Jack2 1.9.6

JackWinNamedPipe.cpp

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