00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "JackWinNamedPipe.h"
00022 #include "JackError.h"
00023 #include <assert.h>
00024 #include <stdio.h>
00025
00026 #define BUFSIZE 4096
00027
00028 namespace Jack
00029 {
00030
00031 int JackWinNamedPipe::Read(void* data, int len)
00032 {
00033 DWORD read;
00034 BOOL res = ReadFile(fNamedPipe, data, len, &read, NULL);
00035 if (res && read == (DWORD)len) {
00036 return 0;
00037 } else {
00038 jack_error("Cannot read named pipe name = %s err = %ld", fName, GetLastError());
00039 return -1;
00040 }
00041 }
00042
00043 int JackWinNamedPipe::Write(void* data, int len)
00044 {
00045 DWORD written;
00046 BOOL res = WriteFile(fNamedPipe, data, len, &written, NULL);
00047 if (res && written == (DWORD)len) {
00048 return 0;
00049 } else {
00050 jack_error("Cannot write named pipe name = %s err = %ld", fName, GetLastError());
00051 return -1;
00052 }
00053 }
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 int JackWinNamedPipeClient::ConnectAux()
00083 {
00084 jack_log("Connect: fName %s", fName);
00085
00086 while (true) {
00087
00088 fNamedPipe = CreateFile(fName,
00089 GENERIC_READ |
00090 GENERIC_WRITE,
00091 0,
00092 NULL,
00093 OPEN_EXISTING,
00094 0,
00095 NULL);
00096
00097
00098 if (fNamedPipe != INVALID_HANDLE_VALUE) {
00099 return 0;
00100 }
00101
00102
00103 if (GetLastError() != ERROR_PIPE_BUSY) {
00104 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
00105 return -1;
00106 }
00107
00108
00109 if (!WaitNamedPipe(fName, 2000)) {
00110 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
00111 return -1;
00112 }
00113 }
00114 }
00115
00116 int JackWinNamedPipeClient::Connect(const char* dir, int which)
00117 {
00118 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
00119 return ConnectAux();
00120 }
00121
00122 int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
00123 {
00124 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
00125 return ConnectAux();
00126 }
00127
00128 int JackWinNamedPipeClient::Close()
00129 {
00130 if (fNamedPipe != INVALID_HANDLE_VALUE) {
00131 CloseHandle(fNamedPipe);
00132 fNamedPipe = INVALID_HANDLE_VALUE;
00133 return 0;
00134 } else {
00135 return -1;
00136 }
00137 }
00138
00139 void JackWinNamedPipeClient::SetReadTimeOut(long sec)
00140 {}
00141
00142 void JackWinNamedPipeClient::SetWriteTimeOut(long sec)
00143 {}
00144
00145 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient()
00146 : JackWinNamedPipeClient(), fPendingIO(false), fIOState(kIdle)
00147 {
00148 fIOState = kIdle;
00149 fOverlap.hEvent = CreateEvent(NULL,
00150 TRUE,
00151 TRUE,
00152 NULL);
00153 }
00154
00155 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient(HANDLE pipe, const char* name, bool pending)
00156 : JackWinNamedPipeClient(pipe, name), fPendingIO(pending), fIOState(kIdle)
00157 {
00158 fOverlap.hEvent = CreateEvent(NULL,
00159 TRUE,
00160 TRUE,
00161 NULL);
00162
00163 if (!fPendingIO) {
00164 SetEvent(fOverlap.hEvent);
00165 }
00166
00167 fIOState = (fPendingIO) ? kConnecting : kReading;
00168 }
00169
00170 JackWinAsyncNamedPipeClient::~JackWinAsyncNamedPipeClient()
00171 {
00172 CloseHandle(fOverlap.hEvent);
00173 }
00174
00175 int JackWinAsyncNamedPipeClient::FinishIO()
00176 {
00177 DWORD success, ret;
00178 success = GetOverlappedResult(fNamedPipe,
00179 &fOverlap,
00180 &ret,
00181 FALSE);
00182
00183 switch (fIOState) {
00184
00185 case kConnecting:
00186 if (!success) {
00187 jack_error("Conection error");
00188 return -1;
00189 } else {
00190 fIOState = kReading;
00191
00192 }
00193 break;
00194
00195 case kReading:
00196 if (!success || ret == 0) {
00197 return -1;
00198 }
00199 fIOState = kWriting;
00200 break;
00201
00202 case kWriting:
00203 if (!success || ret == 0) {
00204 return -1;
00205 }
00206 fIOState = kReading;
00207 break;
00208
00209 default:
00210 break;
00211 }
00212
00213 return 0;
00214 }
00215
00216 int JackWinAsyncNamedPipeClient::Read(void* data, int len)
00217 {
00218 DWORD read;
00219 jack_log("JackWinNamedPipeClient::Read len = %ld", len);
00220 BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap);
00221
00222 if (res && read != 0) {
00223 fPendingIO = false;
00224 fIOState = kWriting;
00225 return 0;
00226 } else if (!res && GetLastError() == ERROR_IO_PENDING) {
00227 fPendingIO = true;
00228 return 0;
00229 } else {
00230 jack_error("Cannot read named pipe err = %ld", GetLastError());
00231 return -1;
00232 }
00233 }
00234
00235 int JackWinAsyncNamedPipeClient::Write(void* data, int len)
00236 {
00237 DWORD written;
00238 jack_log("JackWinNamedPipeClient::Write len = %ld", len);
00239 BOOL res = WriteFile(fNamedPipe, data, len, &written, &fOverlap);
00240
00241 if (res && written != 0) {
00242 fPendingIO = false;
00243 fIOState = kWriting;
00244 return 0;
00245 } else if (!res && GetLastError() == ERROR_IO_PENDING) {
00246 fPendingIO = true;
00247 return 0;
00248 } else {
00249 jack_error("Cannot write named pipe err = %ld", GetLastError());
00250 return -1;
00251 }
00252 }
00253
00254
00255 int JackWinNamedPipeServer::BindAux()
00256 {
00257 jack_log("Bind: fName %s", fName);
00258
00259 if ((fNamedPipe = CreateNamedPipe(fName,
00260 PIPE_ACCESS_DUPLEX,
00261 PIPE_TYPE_MESSAGE |
00262 PIPE_READMODE_MESSAGE |
00263 PIPE_WAIT,
00264 PIPE_UNLIMITED_INSTANCES,
00265 BUFSIZE,
00266 BUFSIZE,
00267 INFINITE,
00268 NULL)) == INVALID_HANDLE_VALUE) {
00269 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
00270 return -1;
00271 } else {
00272 return 0;
00273 }
00274 }
00275
00276 int JackWinNamedPipeServer::Bind(const char* dir, int which)
00277 {
00278 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
00279 return BindAux();
00280 }
00281
00282 int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
00283 {
00284 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
00285 return BindAux();
00286 }
00287
00288 bool JackWinNamedPipeServer::Accept()
00289 {
00290 if (ConnectNamedPipe(fNamedPipe, NULL)) {
00291 return true;
00292 } else {
00293 jack_error("Cannot bind server pipe name = %s err = %ld", fName, GetLastError());
00294 if (GetLastError() == ERROR_PIPE_CONNECTED) {
00295 jack_error("pipe already connnected = %s ", fName);
00296 return true;
00297 } else {
00298 return false;
00299 }
00300 }
00301 }
00302
00303 JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient()
00304 {
00305 if (ConnectNamedPipe(fNamedPipe, NULL)) {
00306 JackWinNamedPipeClient* client = new JackWinNamedPipeClient(fNamedPipe, fName);
00307
00308 fNamedPipe = INVALID_HANDLE_VALUE;
00309 return client;
00310 } else {
00311 switch (GetLastError()) {
00312
00313 case ERROR_PIPE_CONNECTED:
00314 return new JackWinNamedPipeClient(fNamedPipe, fName);
00315
00316 default:
00317 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
00318 return NULL;
00319 break;
00320 }
00321 }
00322 }
00323
00324 int JackWinNamedPipeServer::Close()
00325 {
00326 jack_log("JackWinNamedPipeServer::Close");
00327
00328 if (fNamedPipe != INVALID_HANDLE_VALUE) {
00329 DisconnectNamedPipe(fNamedPipe);
00330 CloseHandle(fNamedPipe);
00331 fNamedPipe = INVALID_HANDLE_VALUE;
00332 return 0;
00333 } else {
00334 return -1;
00335 }
00336 }
00337
00338
00339
00340 int JackWinAsyncNamedPipeServer::BindAux()
00341 {
00342 jack_log("Bind: fName %s", fName);
00343
00344 if ((fNamedPipe = CreateNamedPipe(fName,
00345 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
00346 PIPE_TYPE_MESSAGE |
00347 PIPE_READMODE_MESSAGE |
00348 PIPE_WAIT,
00349 PIPE_UNLIMITED_INSTANCES,
00350 BUFSIZE,
00351 BUFSIZE,
00352 INFINITE,
00353 NULL)) == INVALID_HANDLE_VALUE) {
00354 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
00355 return -1;
00356 } else {
00357 return 0;
00358 }
00359 }
00360
00361 int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
00362 {
00363 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
00364 return BindAux();
00365 }
00366
00367 int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
00368 {
00369 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
00370 return BindAux();
00371 }
00372
00373 bool JackWinAsyncNamedPipeServer::Accept()
00374 {
00375 return false;
00376 }
00377
00378 JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
00379 {
00380 if (ConnectNamedPipe(fNamedPipe, NULL)) {
00381 return new JackWinAsyncNamedPipeClient(fNamedPipe, fName, false);
00382 } else {
00383 switch (GetLastError()) {
00384
00385 case ERROR_IO_PENDING:
00386 return new JackWinAsyncNamedPipeClient(fNamedPipe, fName, true);
00387
00388 case ERROR_PIPE_CONNECTED:
00389 return new JackWinAsyncNamedPipeClient(fNamedPipe, fName, false);
00390
00391 default:
00392 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
00393 return NULL;
00394 break;
00395 }
00396 }
00397 }
00398
00399 }
00400