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

Generated on Thu Feb 14 11:16:02 2008 for Jackdmp by  doxygen 1.5.1