Merge branch 'master' into server_no_deadlock
[jack2.git] / windows / JackWinNamedPipe.cpp
blobd3329055f5425a088f15806fc293b7f9ce1f0cd3
1 /*
2 Copyright (C) 2004-2006 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "JackWinNamedPipe.h"
21 #include "JackError.h"
22 #include <assert.h>
23 #include <stdio.h>
25 #define BUFSIZE 4096
27 namespace Jack
30 int JackWinNamedPipe::Read(void* data, int len)
32 DWORD read;
33 BOOL res = ReadFile(fNamedPipe, data, len, &read, NULL);
34 if (res && read == (DWORD)len) {
35 return 0;
36 } else {
37 jack_error("Cannot read named pipe err = %ld", GetLastError());
38 return -1;
42 int JackWinNamedPipe::Write(void* data, int len)
44 DWORD written;
45 BOOL res = WriteFile(fNamedPipe, data, len, &written, NULL);
46 if (res && written == (DWORD)len) {
47 return 0;
48 } else {
49 jack_error("Cannot write named pipe err = %ld", GetLastError());
50 return -1;
54 int JackWinNamedPipeClient::Connect(const char* dir, int which)
56 sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
57 jack_log("Connect: fName %s", fName);
59 fNamedPipe = CreateFile(fName, // pipe name
60 GENERIC_READ | // read and write access
61 GENERIC_WRITE,
62 0, // no sharing
63 NULL, // default security attributes
64 OPEN_EXISTING, // opens existing pipe
65 0, // default attributes
66 NULL); // no template file
68 if (fNamedPipe == INVALID_HANDLE_VALUE) {
69 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
70 return -1;
71 } else {
72 return 0;
76 int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
78 sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
79 jack_log("Connect: fName %s", fName);
81 fNamedPipe = CreateFile(fName, // pipe name
82 GENERIC_READ | // read and write access
83 GENERIC_WRITE,
84 0, // no sharing
85 NULL, // default security attributes
86 OPEN_EXISTING, // opens existing pipe
87 0, // default attributes
88 NULL); // no template file
90 if (fNamedPipe == INVALID_HANDLE_VALUE) {
91 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
92 return -1;
93 } else {
94 return 0;
98 int JackWinNamedPipeClient::Close()
100 if (fNamedPipe != INVALID_HANDLE_VALUE) {
101 CloseHandle(fNamedPipe);
102 fNamedPipe = INVALID_HANDLE_VALUE;
103 return 0;
104 } else {
105 return -1;
109 void JackWinNamedPipeClient::SetReadTimeOut(long sec)
112 void JackWinNamedPipeClient::SetWriteTimeOut(long sec)
115 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient()
116 : JackWinNamedPipeClient(), fPendingIO(false), fIOState(kIdle)
118 fIOState = kIdle;
119 fOverlap.hEvent = CreateEvent(NULL, // default security attribute
120 TRUE, // manual-reset event
121 TRUE, // initial state = signaled
122 NULL); // unnamed event object
125 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient(HANDLE pipe, bool pending)
126 : JackWinNamedPipeClient(pipe), fPendingIO(pending), fIOState(kIdle)
128 fOverlap.hEvent = CreateEvent(NULL, // default security attribute
129 TRUE, // manual-reset event
130 TRUE, // initial state = signaled
131 NULL); // unnamed event object
133 if (!fPendingIO)
134 SetEvent(fOverlap.hEvent);
136 fIOState = (fPendingIO) ? kConnecting : kReading;
139 JackWinAsyncNamedPipeClient::~JackWinAsyncNamedPipeClient()
141 CloseHandle(fOverlap.hEvent);
144 int JackWinAsyncNamedPipeClient::FinishIO()
146 DWORD success, ret;
147 success = GetOverlappedResult(fNamedPipe, // handle to pipe
148 &fOverlap, // OVERLAPPED structure
149 &ret, // bytes transferred
150 FALSE); // do not wait
152 switch (fIOState) {
154 case kConnecting:
155 if (!success) {
156 jack_error("Conection error");
157 return -1;
158 } else {
159 fIOState = kReading;
160 // Prepare connection for new client ??
162 break;
164 case kReading:
165 if (!success || ret == 0) {
166 return -1;
168 fIOState = kWriting;
169 break;
171 case kWriting:
172 if (!success || ret == 0) {
173 return -1;
175 fIOState = kReading;
176 break;
178 default:
179 break;
182 return 0;
185 int JackWinAsyncNamedPipeClient::Read(void* data, int len)
187 DWORD read;
188 jack_log("JackWinNamedPipeClient::Read len = %ld", len);
189 BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap);
190 jack_log("JackWinNamedPipeClient::Read res = %ld read %ld", res, read);
192 if (res && read != 0) {
193 fPendingIO = false;
194 fIOState = kWriting;
195 return 0;
196 } else if (!res && GetLastError() == ERROR_IO_PENDING) {
197 fPendingIO = true;
198 return 0;
199 } else {
200 jack_error("Cannot read named pipe err = %ld", GetLastError());
201 return -1;
205 int JackWinAsyncNamedPipeClient::Write(void* data, int len)
207 DWORD written;
208 jack_log("JackWinNamedPipeClient::Write len = %ld", len);
209 BOOL res = WriteFile(fNamedPipe, data, len, &written, &fOverlap);
211 if (res && written != 0) {
212 fPendingIO = false;
213 fIOState = kWriting;
214 return 0;
215 } else if (!res && GetLastError() == ERROR_IO_PENDING) {
216 fPendingIO = true;
217 return 0;
218 } else {
219 jack_error("Cannot write named pipe err = %ld", GetLastError());
220 return -1;
224 // Server side
226 int JackWinNamedPipeServer::Bind(const char* dir, int which)
228 sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
229 jack_log("Bind: fName %s", fName);
231 if ((fNamedPipe = CreateNamedPipe(fName,
232 PIPE_ACCESS_DUPLEX, // read/write access
233 PIPE_TYPE_MESSAGE | // message type pipe
234 PIPE_READMODE_MESSAGE | // message-read mode
235 PIPE_WAIT, // blocking mode
236 PIPE_UNLIMITED_INSTANCES, // max. instances
237 BUFSIZE, // output buffer size
238 BUFSIZE, // input buffer size
239 INFINITE, // client time-out
240 NULL)) == INVALID_HANDLE_VALUE) { // no security a
241 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
242 return -1;
243 } else {
244 return 0;
248 int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
250 sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
251 jack_log("Bind: fName %s", fName);
253 if ((fNamedPipe = CreateNamedPipe(fName,
254 PIPE_ACCESS_DUPLEX, // read/write access
255 PIPE_TYPE_MESSAGE | // message type pipe
256 PIPE_READMODE_MESSAGE | // message-read mode
257 PIPE_WAIT, // blocking mode
258 PIPE_UNLIMITED_INSTANCES, // max. instances
259 BUFSIZE, // output buffer size
260 BUFSIZE, // input buffer size
261 INFINITE, // client time-out
262 NULL)) == INVALID_HANDLE_VALUE) { // no security a
263 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
264 return -1;
265 } else {
266 return 0;
270 bool JackWinNamedPipeServer::Accept()
272 if (ConnectNamedPipe(fNamedPipe, NULL)) {
273 return true;
274 } else {
275 jack_error("Cannot bind server pipe name = %s err = %ld", fName, GetLastError());
276 if (GetLastError() == ERROR_PIPE_CONNECTED) {
277 jack_error("pipe already connnected = %s ", fName);
278 return true;
279 } else {
280 return false;
285 JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient()
287 if (ConnectNamedPipe(fNamedPipe, NULL)) {
288 JackWinNamedPipeClient* client = new JackWinNamedPipeClient(fNamedPipe);
289 // Init the pipe to the default value
290 fNamedPipe = INVALID_HANDLE_VALUE;
291 return client;
292 } else {
293 switch (GetLastError()) {
295 case ERROR_PIPE_CONNECTED:
296 return new JackWinNamedPipeClient(fNamedPipe);
298 default:
299 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
300 return NULL;
301 break;
306 int JackWinNamedPipeServer::Close()
308 jack_log("JackWinNamedPipeServer::Close");
310 if (fNamedPipe != INVALID_HANDLE_VALUE) {
311 DisconnectNamedPipe(fNamedPipe);
312 CloseHandle(fNamedPipe);
313 fNamedPipe = INVALID_HANDLE_VALUE;
314 return 0;
315 } else {
316 return -1;
320 // Server side
322 int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
324 sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
325 jack_log("Bind: fName %s", fName);
327 if ((fNamedPipe = CreateNamedPipe(fName,
328 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
329 PIPE_TYPE_MESSAGE | // message type pipe
330 PIPE_READMODE_MESSAGE | // message-read mode
331 PIPE_WAIT, // blocking mode
332 PIPE_UNLIMITED_INSTANCES, // max. instances
333 BUFSIZE, // output buffer size
334 BUFSIZE, // input buffer size
335 INFINITE, // client time-out
336 NULL)) == INVALID_HANDLE_VALUE) { // no security a
337 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
338 return -1;
339 } else {
340 return 0;
344 int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
346 sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
347 jack_log("Bind: fName %s", fName);
349 if ((fNamedPipe = CreateNamedPipe(fName,
350 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
351 PIPE_TYPE_MESSAGE | // message type pipe
352 PIPE_READMODE_MESSAGE | // message-read mode
353 PIPE_WAIT, // blocking mode
354 PIPE_UNLIMITED_INSTANCES, // max. instances
355 BUFSIZE, // output buffer size
356 BUFSIZE, // input buffer size
357 INFINITE, // client time-out
358 NULL)) == INVALID_HANDLE_VALUE) { // no security a
359 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
360 return -1;
361 } else {
362 return 0;
366 bool JackWinAsyncNamedPipeServer::Accept()
368 return false;
371 JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
373 if (ConnectNamedPipe(fNamedPipe, NULL)) {
374 return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
375 } else {
376 switch (GetLastError()) {
378 case ERROR_IO_PENDING:
379 return new JackWinAsyncNamedPipeClient(fNamedPipe, true);
381 case ERROR_PIPE_CONNECTED:
382 return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
384 default:
385 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
386 return NULL;
387 break;
392 } // end of namespace