Jack2 1.9.10
|
00001 /* 00002 Copyright (C) 2004-2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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 JackWinNamedPipeAux::ReadAux(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_log("Cannot read named pipe name = %s err = %ld", fName, GetLastError()); 00039 return -1; 00040 } 00041 } 00042 00043 int JackWinNamedPipeAux::WriteAux(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_log("Cannot write named pipe name = %s err = %ld", fName, GetLastError()); 00051 return -1; 00052 } 00053 } 00054 00055 /* 00056 See : 00057 http://answers.google.com/answers/threadview?id=430173 00058 http://msdn.microsoft.com/en-us/library/windows/desktop/aa365800(v=vs.85).aspx 00059 */ 00060 00061 /* 00062 int JackWinNamedPipeClient::ConnectAux() 00063 { 00064 fNamedPipe = CreateFile(fName, // pipe name 00065 GENERIC_READ | // read and write access 00066 GENERIC_WRITE, 00067 0, // no sharing 00068 NULL, // default security attributes 00069 OPEN_EXISTING, // opens existing pipe 00070 0, // default attributes 00071 NULL); // no template file 00072 00073 if (fNamedPipe == INVALID_HANDLE_VALUE) { 00074 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError()); 00075 return -1; 00076 } else { 00077 return 0; 00078 } 00079 } 00080 */ 00081 00082 int JackWinNamedPipeClient::ConnectAux() 00083 { 00084 jack_log("JackWinNamedPipeClient::ConnectAux : fName %s", fName); 00085 00086 while (true) { 00087 00088 fNamedPipe = CreateFile(fName, // pipe name 00089 GENERIC_READ | // read and write access 00090 GENERIC_WRITE, 00091 0, // no sharing 00092 NULL, // default security attributes 00093 OPEN_EXISTING, // opens existing pipe 00094 0, // default attributes 00095 NULL); // no template file 00096 00097 // Break if the pipe handle is valid. 00098 if (fNamedPipe != INVALID_HANDLE_VALUE) { 00099 return 0; 00100 } 00101 00102 // Exit if an error other than ERROR_PIPE_BUSY or ERROR_FILE_NOT_FOUND occurs. 00103 if ((GetLastError() != ERROR_PIPE_BUSY) && (GetLastError() != ERROR_FILE_NOT_FOUND)) { 00104 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError()); 00105 return -1; 00106 } 00107 00108 // All pipe instances are busy, so wait for 2 seconds. 00109 if (!WaitNamedPipe(fName, 2000)) { 00110 jack_error("Cannot connect to named pipe after wait = %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 COMMTIMEOUTS timeout; 00143 if (GetCommTimeouts(fNamedPipe, &timeout)) { 00144 jack_info("JackWinNamedPipeClient::SetReadTimeOut ReadIntervalTimeout = %d", timeout.ReadIntervalTimeout); 00145 jack_info("JackWinNamedPipeClient::SetReadTimeOut ReadTotalTimeoutMultiplier = %d", timeout.ReadTotalTimeoutMultiplier); 00146 jack_info("JackWinNamedPipeClient::SetReadTimeOut ReadTotalTimeoutConstant = %d", timeout.ReadTotalTimeoutConstant); 00147 } else { 00148 jack_error("JackWinNamedPipeClient::SetReadTimeOut err %d", GetLastError()); 00149 } 00150 */ 00151 } 00152 00153 void JackWinNamedPipeClient::SetWriteTimeOut(long sec) 00154 { 00155 /* 00156 COMMTIMEOUTS timeout; 00157 if (GetCommTimeouts(fNamedPipe, &timeout)) { 00158 jack_info("JackWinNamedPipeClient::SetWriteTimeOut WriteTotalTimeoutMultiplier = %d", timeout.WriteTotalTimeoutMultiplier); 00159 jack_info("JackWinNamedPipeClient::SetWriteTimeOut WriteTotalTimeoutConstant = %d", timeout.WriteTotalTimeoutConstant); 00160 } 00161 */ 00162 } 00163 00164 void JackWinNamedPipeClient::SetNonBlocking(bool onoff) 00165 {} 00166 00167 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient() 00168 : JackWinNamedPipeClient(), fPendingIO(false), fIOState(kIdle) 00169 { 00170 fIOState = kIdle; 00171 fOverlap.hEvent = CreateEvent(NULL, // default security attribute 00172 TRUE, // manual-reset event 00173 TRUE, // initial state = signaled 00174 NULL); // unnamed event object 00175 } 00176 00177 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient(HANDLE pipe, const char* name, bool pending) 00178 : JackWinNamedPipeClient(pipe, name), fPendingIO(pending), fIOState(kIdle) 00179 { 00180 fOverlap.hEvent = CreateEvent(NULL, // default security attribute 00181 TRUE, // manual-reset event 00182 TRUE, // initial state = signaled 00183 NULL); // unnamed event object 00184 00185 if (!fPendingIO) { 00186 SetEvent(fOverlap.hEvent); 00187 } 00188 00189 fIOState = (fPendingIO) ? kConnecting : kReading; 00190 } 00191 00192 JackWinAsyncNamedPipeClient::~JackWinAsyncNamedPipeClient() 00193 { 00194 CloseHandle(fOverlap.hEvent); 00195 } 00196 00197 int JackWinAsyncNamedPipeClient::FinishIO() 00198 { 00199 DWORD success, ret; 00200 success = GetOverlappedResult(fNamedPipe, // handle to pipe 00201 &fOverlap, // OVERLAPPED structure 00202 &ret, // bytes transferred 00203 FALSE); // do not wait 00204 00205 switch (fIOState) { 00206 00207 case kConnecting: 00208 if (!success) { 00209 jack_error("Conection error"); 00210 return -1; 00211 } else { 00212 fIOState = kReading; 00213 // Prepare connection for new client ?? 00214 } 00215 break; 00216 00217 case kReading: 00218 if (!success || ret == 0) { 00219 return -1; 00220 } 00221 fIOState = kWriting; 00222 break; 00223 00224 case kWriting: 00225 if (!success || ret == 0) { 00226 return -1; 00227 } 00228 fIOState = kReading; 00229 break; 00230 00231 default: 00232 break; 00233 } 00234 00235 return 0; 00236 } 00237 00238 int JackWinAsyncNamedPipeClient::Read(void* data, int len) 00239 { 00240 DWORD read; 00241 jack_log("JackWinNamedPipeClient::Read len = %ld", len); 00242 BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap); 00243 00244 if (res && read != 0) { 00245 fPendingIO = false; 00246 fIOState = kWriting; 00247 return 0; 00248 } else if (!res && GetLastError() == ERROR_IO_PENDING) { 00249 fPendingIO = true; 00250 return 0; 00251 } else { 00252 jack_error("Cannot read named pipe err = %ld", GetLastError()); 00253 return -1; 00254 } 00255 } 00256 00257 int JackWinAsyncNamedPipeClient::Write(void* data, int len) 00258 { 00259 DWORD written; 00260 jack_log("JackWinNamedPipeClient::Write len = %ld", len); 00261 BOOL res = WriteFile(fNamedPipe, data, len, &written, &fOverlap); 00262 00263 if (res && written != 0) { 00264 fPendingIO = false; 00265 fIOState = kWriting; 00266 return 0; 00267 } else if (!res && GetLastError() == ERROR_IO_PENDING) { 00268 fPendingIO = true; 00269 return 0; 00270 } else { 00271 jack_error("Cannot write named pipe err = %ld", GetLastError()); 00272 return -1; 00273 } 00274 } 00275 00276 // Server side 00277 int JackWinNamedPipeServer::BindAux() 00278 { 00279 jack_log("JackWinNamedPipeServer::BindAux : fName %s", fName); 00280 00281 if ((fNamedPipe = CreateNamedPipe(fName, 00282 PIPE_ACCESS_DUPLEX, // read/write access 00283 PIPE_TYPE_MESSAGE | // message type pipe 00284 PIPE_READMODE_MESSAGE | // message-read mode 00285 PIPE_WAIT, // blocking mode 00286 PIPE_UNLIMITED_INSTANCES, // max. instances 00287 BUFSIZE, // output buffer size 00288 BUFSIZE, // input buffer size 00289 INFINITE, // client time-out 00290 NULL)) == INVALID_HANDLE_VALUE) { // no security 00291 jack_error("Cannot bind server to pipe err = %ld", GetLastError()); 00292 return -1; 00293 } else { 00294 return 0; 00295 } 00296 } 00297 00298 int JackWinNamedPipeServer::Bind(const char* dir, int which) 00299 { 00300 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which); 00301 return BindAux(); 00302 } 00303 00304 int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which) 00305 { 00306 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which); 00307 return BindAux(); 00308 } 00309 00310 bool JackWinNamedPipeServer::Accept() 00311 { 00312 if (ConnectNamedPipe(fNamedPipe, NULL)) { 00313 return true; 00314 } else { 00315 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError()); 00316 if (GetLastError() == ERROR_PIPE_CONNECTED) { 00317 jack_error("Pipe already connnected = %s", fName); 00318 return true; 00319 } else { 00320 return false; 00321 } 00322 } 00323 } 00324 00325 JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient() 00326 { 00327 if (ConnectNamedPipe(fNamedPipe, NULL)) { 00328 JackWinNamedPipeClient* client = new JackWinNamedPipeClient(fNamedPipe, fName); 00329 // Init the pipe to the default value 00330 fNamedPipe = INVALID_HANDLE_VALUE; 00331 return client; 00332 } else { 00333 switch (GetLastError()) { 00334 00335 case ERROR_PIPE_CONNECTED: 00336 return new JackWinNamedPipeClient(fNamedPipe, fName); 00337 00338 default: 00339 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError()); 00340 return NULL; 00341 } 00342 } 00343 } 00344 00345 int JackWinNamedPipeServer::Close() 00346 { 00347 jack_log("JackWinNamedPipeServer::Close"); 00348 00349 if (fNamedPipe != INVALID_HANDLE_VALUE) { 00350 DisconnectNamedPipe(fNamedPipe); 00351 CloseHandle(fNamedPipe); 00352 fNamedPipe = INVALID_HANDLE_VALUE; 00353 return 0; 00354 } else { 00355 return -1; 00356 } 00357 } 00358 00359 // Server side 00360 00361 int JackWinAsyncNamedPipeServer::BindAux() 00362 { 00363 jack_log("JackWinAsyncNamedPipeServer::BindAux : fName %s", fName); 00364 00365 if ((fNamedPipe = CreateNamedPipe(fName, 00366 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access 00367 PIPE_TYPE_MESSAGE | // message type pipe 00368 PIPE_READMODE_MESSAGE | // message-read mode 00369 PIPE_WAIT, // blocking mode 00370 PIPE_UNLIMITED_INSTANCES, // max. instances 00371 BUFSIZE, // output buffer size 00372 BUFSIZE, // input buffer size 00373 INFINITE, // client time-out 00374 NULL)) == INVALID_HANDLE_VALUE) { // no security a 00375 jack_error("Cannot bind server to pipe err = %ld", GetLastError()); 00376 return -1; 00377 } else { 00378 return 0; 00379 } 00380 } 00381 00382 int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which) 00383 { 00384 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which); 00385 return BindAux(); 00386 } 00387 00388 int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which) 00389 { 00390 snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which); 00391 return BindAux(); 00392 } 00393 00394 bool JackWinAsyncNamedPipeServer::Accept() 00395 { 00396 return false; 00397 } 00398 00399 JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient() 00400 { 00401 if (ConnectNamedPipe(fNamedPipe, NULL)) { 00402 return new JackWinAsyncNamedPipeClient(fNamedPipe, fName, false); 00403 } else { 00404 switch (GetLastError()) { 00405 00406 case ERROR_IO_PENDING: 00407 return new JackWinAsyncNamedPipeClient(fNamedPipe, fName, true); 00408 00409 case ERROR_PIPE_CONNECTED: 00410 return new JackWinAsyncNamedPipeClient(fNamedPipe, fName, false); 00411 00412 default: 00413 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError()); 00414 return NULL; 00415 break; 00416 } 00417 } 00418 } 00419 00420 } // end of namespace 00421