JackWinNamedPipe.cpp

00001 /*
00002 Copyright (C) 2004-2006 Grame  
00003 
00004 This program is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 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 General Public License for more details.
00013 
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 
00018 */
00019 
00020 #include "JackWinNamedPipe.h"
00021 #include "JackError.h"
00022 #include <assert.h>
00023 
00024 #define BUFSIZE 4096
00025 
00026 namespace Jack
00027 {
00028 
00029 int JackWinNamedPipe::Read(void* data, int len)
00030 {
00031     DWORD read;
00032     JackLog("JackWinNamedPipeClient::Read len = %ld\n", len);
00033     BOOL res = ReadFile(fNamedPipe, data, len, &read, NULL);
00034     JackLog("JackWinNamedPipeClient::Read res = %ld read %ld\n", res, read);
00035     if (read != len) {
00036         jack_error("Cannot read named pipe err = %ld", GetLastError());
00037         return -1;
00038     } else {
00039         return 0;
00040     }
00041 }
00042 
00043 int JackWinNamedPipe::Write(void* data, int len)
00044 {
00045     DWORD written;
00046     JackLog("JackWinNamedPipeClient::Write len = %ld\n", len);
00047     BOOL res = WriteFile(fNamedPipe, data, len, &written, NULL);
00048     if (written != len) {
00049         jack_error("Cannot write named pipe err = %ld", GetLastError());
00050         return -1;
00051     } else {
00052         return 0;
00053     }
00054 }
00055 
00056 int JackWinNamedPipeClient::Connect(const char* dir, int which)
00057 {
00058     sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
00059     JackLog("Connect: fName %s\n", fName);
00060 
00061     fNamedPipe = CreateFile(fName,                       // pipe name
00062                             GENERIC_READ |   // read and write access
00063                             GENERIC_WRITE,
00064                             0,               // no sharing
00065                             NULL,            // default security attributes
00066                             OPEN_EXISTING,   // opens existing pipe
00067                             0,               // default attributes
00068                             NULL);          // no template file
00069 
00070     if (fNamedPipe == INVALID_HANDLE_VALUE) {
00071         jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
00072         return -1;
00073     } else {
00074         return 0;
00075     }
00076 }
00077 
00078 int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
00079 {
00080     sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
00081     JackLog("Connect: fName %s\n", fName);
00082 
00083     fNamedPipe = CreateFile(fName,                       // pipe name
00084                             GENERIC_READ |   // read and write access
00085                             GENERIC_WRITE,
00086                             0,               // no sharing
00087                             NULL,            // default security attributes
00088                             OPEN_EXISTING,   // opens existing pipe
00089                             0,               // default attributes
00090                             NULL);          // no template file
00091 
00092     if (fNamedPipe == INVALID_HANDLE_VALUE) {
00093         jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
00094         return -1;
00095     } else {
00096         return 0;
00097     }
00098 }
00099 
00100 int JackWinNamedPipeClient::Close()
00101 {
00102         if (fNamedPipe != INVALID_HANDLE_VALUE) {
00103                 CloseHandle(fNamedPipe);
00104                 fNamedPipe = INVALID_HANDLE_VALUE;
00105                 return 0;
00106         } else {
00107                 return -1;
00108         }
00109 }
00110 
00111 void JackWinNamedPipeClient::SetReadTimeOut(long sec)
00112 {}
00113 
00114 void JackWinNamedPipeClient::SetWriteTimeOut(long sec)
00115 {}
00116 
00117 
00118 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient()
00119         : JackWinNamedPipeClient(), fIOState(kIdle), fPendingIO(false)
00120 {
00121     fIOState = kIdle;
00122     fOverlap.hEvent = CreateEvent(NULL,     // default security attribute
00123                                   TRUE,     // manual-reset event
00124                                   TRUE,     // initial state = signaled
00125                                   NULL);   // unnamed event object
00126 }
00127 
00128 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient(HANDLE pipe, bool pending)
00129         : JackWinNamedPipeClient(pipe), fIOState(kIdle), fPendingIO(pending)
00130 {
00131     fOverlap.hEvent = CreateEvent(NULL,     // default security attribute
00132                                   TRUE,     // manual-reset event
00133                                   TRUE,     // initial state = signaled
00134                                   NULL);        // unnamed event object
00135 
00136     if (!fPendingIO)
00137         SetEvent(fOverlap.hEvent);
00138 
00139     fIOState = (fPendingIO) ? kConnecting : kReading;
00140 }
00141 
00142 JackWinAsyncNamedPipeClient::~JackWinAsyncNamedPipeClient()
00143 {
00144     CloseHandle(fOverlap.hEvent);
00145 }
00146 
00147 int JackWinAsyncNamedPipeClient::FinishIO()
00148 {
00149     DWORD success, ret;
00150     success = GetOverlappedResult(fNamedPipe,   // handle to pipe
00151                                   &fOverlap,    // OVERLAPPED structure
00152                                   &ret,         // bytes transferred
00153                                   FALSE);       // do not wait
00154 
00155     switch (fIOState) {
00156 
00157         case kConnecting:
00158             if (!success) {
00159                 jack_error("Conection error");
00160                 return -1;
00161             } else {
00162                 fIOState = kReading;
00163                 // Prepare connection for new client ??
00164             }
00165             break;
00166 
00167         case kReading:
00168             if (!success || ret == 0) {
00169                 return -1;
00170             }
00171             fIOState = kWriting;
00172             break;
00173 
00174         case kWriting:
00175             if (!success || ret == 0) {
00176                 return -1;
00177             }
00178             fIOState = kReading;
00179             break;
00180     }
00181 
00182     return 0;
00183 }
00184 
00185 int JackWinAsyncNamedPipeClient::Read(void* data, int len)
00186 {
00187     DWORD read;
00188     JackLog("JackWinNamedPipeClient::Read len = %ld\n", len);
00189     BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap);
00190     JackLog("JackWinNamedPipeClient::Read res = %ld read %ld\n", res, read);
00191 
00192     if (res && read != 0) {
00193         fPendingIO = false;
00194         fIOState = kWriting;
00195         return 0;
00196     } else if (!res && GetLastError() == ERROR_IO_PENDING) {
00197         fPendingIO = true;
00198         return 0;
00199     } else {
00200         jack_error("Cannot read named pipe err = %ld", GetLastError());
00201         return -1;
00202     }
00203 }
00204 
00205 int JackWinAsyncNamedPipeClient::Write(void* data, int len)
00206 {
00207     DWORD written;
00208     JackLog("JackWinNamedPipeClient::Write len = %ld\n", len);
00209     BOOL res = WriteFile(fNamedPipe, data, len, &written, &fOverlap);
00210 
00211     if (res && written != 0) {
00212         fPendingIO = false;
00213         fIOState = kWriting;
00214         return 0;
00215     } else if (!res && GetLastError() == ERROR_IO_PENDING) {
00216         fPendingIO = true;
00217         return 0;
00218     } else {
00219         jack_error("Cannot write named pipe err = %ld", GetLastError());
00220         return -1;
00221     }
00222 }
00223 
00224 // Server side
00225 
00226 int JackWinNamedPipeServer::Bind(const char* dir, int which)
00227 {
00228     sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
00229     JackLog("Bind: fName %s\n", fName);
00230 
00231     if ((fNamedPipe = CreateNamedPipe(fName,
00232                                       PIPE_ACCESS_DUPLEX,  // read/write access
00233                                       PIPE_TYPE_MESSAGE |  // message type pipe
00234                                       PIPE_READMODE_MESSAGE |  // message-read mode
00235                                       PIPE_WAIT,  // blocking mode
00236                                       PIPE_UNLIMITED_INSTANCES,  // max. instances
00237                                       BUFSIZE,  // output buffer size
00238                                       BUFSIZE,  // input buffer size
00239                                       INFINITE,  // client time-out
00240                                       NULL)) == INVALID_HANDLE_VALUE) { // no security a
00241         jack_error("Cannot bind server to pipe err = %ld", GetLastError());
00242         return -1;
00243     } else {
00244         return 0;
00245     }
00246 }
00247 
00248 int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
00249 {
00250     sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
00251     JackLog("Bind: fName %s\n", fName);
00252 
00253     if ((fNamedPipe = CreateNamedPipe(fName,
00254                                       PIPE_ACCESS_DUPLEX,  // read/write access
00255                                       PIPE_TYPE_MESSAGE |  // message type pipe
00256                                       PIPE_READMODE_MESSAGE |  // message-read mode
00257                                       PIPE_WAIT,  // blocking mode
00258                                       PIPE_UNLIMITED_INSTANCES,  // max. instances
00259                                       BUFSIZE,  // output buffer size
00260                                       BUFSIZE,  // input buffer size
00261                                       INFINITE,  // client time-out
00262                                       NULL)) == INVALID_HANDLE_VALUE) { // no security a
00263         jack_error("Cannot bind server to pipe err = %ld", GetLastError());
00264         return -1;
00265     } else {
00266         return 0;
00267     }
00268 }
00269 
00270 bool JackWinNamedPipeServer::Accept()
00271 {
00272     if (ConnectNamedPipe(fNamedPipe, NULL)) {
00273         return true;
00274     } else {
00275         jack_error("Cannot bind server pipe name = %s err = %ld", fName, GetLastError());
00276         if (GetLastError() == ERROR_PIPE_CONNECTED) {
00277             jack_error("pipe already connnected = %s ", fName);
00278             return true;
00279         } else {
00280             return false;
00281         }
00282     }
00283 }
00284 
00285 JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient()
00286 {
00287     if (ConnectNamedPipe(fNamedPipe, NULL)) {
00288                 JackWinNamedPipeClient* client = new JackWinNamedPipeClient(fNamedPipe);
00289                 // Init the pipe to the default value
00290         fNamedPipe = INVALID_HANDLE_VALUE;
00291     } else {
00292         switch (GetLastError()) {
00293 
00294             case ERROR_PIPE_CONNECTED:
00295                 return new JackWinNamedPipeClient(fNamedPipe);
00296 
00297             default:
00298                 jack_error("Cannot connect server pipe name = %s  err = %ld", fName, GetLastError());
00299                 return NULL;
00300                 break;
00301         }
00302     }
00303 }
00304 
00305 int JackWinNamedPipeServer::Close()
00306 {
00307         JackLog("JackWinNamedPipeServer::Close\n");
00308 
00309         if (fNamedPipe != INVALID_HANDLE_VALUE) {
00310                 DisconnectNamedPipe(fNamedPipe);
00311                 CloseHandle(fNamedPipe);
00312                 fNamedPipe = INVALID_HANDLE_VALUE;
00313                 return 0;
00314         } else {
00315                 return -1;
00316         }
00317 }
00318 
00319 // Server side
00320 
00321 int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
00322 {
00323     sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
00324     JackLog("Bind: fName %s\n", fName);
00325 
00326     if ((fNamedPipe = CreateNamedPipe(fName,
00327                                       PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,  // read/write access
00328                                       PIPE_TYPE_MESSAGE |  // message type pipe
00329                                       PIPE_READMODE_MESSAGE |  // message-read mode
00330                                       PIPE_WAIT,  // blocking mode
00331                                       PIPE_UNLIMITED_INSTANCES,  // max. instances
00332                                       BUFSIZE,  // output buffer size
00333                                       BUFSIZE,  // input buffer size
00334                                       INFINITE,  // client time-out
00335                                       NULL)) == INVALID_HANDLE_VALUE) { // no security a
00336         jack_error("Cannot bind server to pipe err = %ld", GetLastError());
00337         return -1;
00338     } else {
00339         return 0;
00340     }
00341 }
00342 
00343 int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
00344 {
00345     sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
00346     JackLog("Bind: fName %s\n", fName);
00347 
00348     if ((fNamedPipe = CreateNamedPipe(fName,
00349                                       PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,  // read/write access
00350                                       PIPE_TYPE_MESSAGE |  // message type pipe
00351                                       PIPE_READMODE_MESSAGE |  // message-read mode
00352                                       PIPE_WAIT,  // blocking mode
00353                                       PIPE_UNLIMITED_INSTANCES,  // max. instances
00354                                       BUFSIZE,  // output buffer size
00355                                       BUFSIZE,  // input buffer size
00356                                       INFINITE,  // client time-out
00357                                       NULL)) == INVALID_HANDLE_VALUE) { // no security a
00358         jack_error("Cannot bind server to pipe err = %ld", GetLastError());
00359         return -1;
00360     } else {
00361         return 0;
00362     }
00363 }
00364 
00365 JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
00366 {
00367     if (ConnectNamedPipe(fNamedPipe, NULL)) {
00368         return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
00369     } else {
00370         switch (GetLastError()) {
00371 
00372             case ERROR_IO_PENDING:
00373                 return new JackWinAsyncNamedPipeClient(fNamedPipe, true);
00374 
00375             case ERROR_PIPE_CONNECTED:
00376                 return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
00377 
00378             default:
00379                 jack_error("Cannot connect server pipe name = %s  err = %ld", fName, GetLastError());
00380                 return NULL;
00381                 break;
00382         }
00383     }
00384 }
00385 
00386 } // end of namespace
00387 

Generated on Wed Jan 10 11:42:47 2007 for Jackdmp by  doxygen 1.4.5