Jack2
1.9.8
|
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 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 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("Connect: 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 occurs. 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 // All pipe instances are busy, so wait for 2 seconds. 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, // default security attribute 00150 TRUE, // manual-reset event 00151 TRUE, // initial state = signaled 00152 NULL); // unnamed event object 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, // default security attribute 00159 TRUE, // manual-reset event 00160 TRUE, // initial state = signaled 00161 NULL); // unnamed event object 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, // handle to pipe 00179 &fOverlap, // OVERLAPPED structure 00180 &ret, // bytes transferred 00181 FALSE); // do not wait 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 // Prepare connection for new client ?? 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 // Server side 00255 int JackWinNamedPipeServer::BindAux() 00256 { 00257 jack_log("Bind: fName %s", fName); 00258 00259 if ((fNamedPipe = CreateNamedPipe(fName, 00260 PIPE_ACCESS_DUPLEX, // read/write access 00261 PIPE_TYPE_MESSAGE | // message type pipe 00262 PIPE_READMODE_MESSAGE | // message-read mode 00263 PIPE_WAIT, // blocking mode 00264 PIPE_UNLIMITED_INSTANCES, // max. instances 00265 BUFSIZE, // output buffer size 00266 BUFSIZE, // input buffer size 00267 INFINITE, // client time-out 00268 NULL)) == INVALID_HANDLE_VALUE) { // no security 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 // Init the pipe to the default value 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 // Server side 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, // read/write access 00346 PIPE_TYPE_MESSAGE | // message type pipe 00347 PIPE_READMODE_MESSAGE | // message-read mode 00348 PIPE_WAIT, // blocking mode 00349 PIPE_UNLIMITED_INSTANCES, // max. instances 00350 BUFSIZE, // output buffer size 00351 BUFSIZE, // input buffer size 00352 INFINITE, // client time-out 00353 NULL)) == INVALID_HANDLE_VALUE) { // no security a 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 } // end of namespace 00400