README updated.
[jack2.git] / windows / JackWinNamedPipe.cpp
blob9d067cd25f0eeed42ff97f1ca85ac445f6895663
1 /*
2 Copyright (C) 2004-2008 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "JackWinNamedPipe.h"
22 #include "JackError.h"
23 #include <assert.h>
24 #include <stdio.h>
26 #define BUFSIZE 4096
28 namespace Jack
31 int JackWinNamedPipe::Read(void* data, int len)
33 DWORD read;
34 BOOL res = ReadFile(fNamedPipe, data, len, &read, NULL);
35 if (res && read == (DWORD)len) {
36 return 0;
37 } else {
38 jack_error("Cannot read named pipe err = %ld", GetLastError());
39 return -1;
43 int JackWinNamedPipe::Write(void* data, int len)
45 DWORD written;
46 BOOL res = WriteFile(fNamedPipe, data, len, &written, NULL);
47 if (res && written == (DWORD)len) {
48 return 0;
49 } else {
50 jack_error("Cannot write named pipe err = %ld", GetLastError());
51 return -1;
55 int JackWinNamedPipeClient::Connect(const char* dir, int which)
57 sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
58 jack_log("Connect: fName %s", fName);
60 fNamedPipe = CreateFile(fName, // pipe name
61 GENERIC_READ | // read and write access
62 GENERIC_WRITE,
63 0, // no sharing
64 NULL, // default security attributes
65 OPEN_EXISTING, // opens existing pipe
66 0, // default attributes
67 NULL); // no template file
69 if (fNamedPipe == INVALID_HANDLE_VALUE) {
70 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
71 return -1;
72 } else {
73 return 0;
77 int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
79 sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
80 jack_log("Connect: fName %s", fName);
82 fNamedPipe = CreateFile(fName, // pipe name
83 GENERIC_READ | // read and write access
84 GENERIC_WRITE,
85 0, // no sharing
86 NULL, // default security attributes
87 OPEN_EXISTING, // opens existing pipe
88 0, // default attributes
89 NULL); // no template file
91 if (fNamedPipe == INVALID_HANDLE_VALUE) {
92 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
93 return -1;
94 } else {
95 return 0;
99 int JackWinNamedPipeClient::Close()
101 if (fNamedPipe != INVALID_HANDLE_VALUE) {
102 CloseHandle(fNamedPipe);
103 fNamedPipe = INVALID_HANDLE_VALUE;
104 return 0;
105 } else {
106 return -1;
110 void JackWinNamedPipeClient::SetReadTimeOut(long sec)
113 void JackWinNamedPipeClient::SetWriteTimeOut(long sec)
116 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient()
117 : JackWinNamedPipeClient(), fPendingIO(false), fIOState(kIdle)
119 fIOState = kIdle;
120 fOverlap.hEvent = CreateEvent(NULL, // default security attribute
121 TRUE, // manual-reset event
122 TRUE, // initial state = signaled
123 NULL); // unnamed event object
126 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient(HANDLE pipe, bool pending)
127 : JackWinNamedPipeClient(pipe), fPendingIO(pending), fIOState(kIdle)
129 fOverlap.hEvent = CreateEvent(NULL, // default security attribute
130 TRUE, // manual-reset event
131 TRUE, // initial state = signaled
132 NULL); // unnamed event object
134 if (!fPendingIO)
135 SetEvent(fOverlap.hEvent);
137 fIOState = (fPendingIO) ? kConnecting : kReading;
140 JackWinAsyncNamedPipeClient::~JackWinAsyncNamedPipeClient()
142 CloseHandle(fOverlap.hEvent);
145 int JackWinAsyncNamedPipeClient::FinishIO()
147 DWORD success, ret;
148 success = GetOverlappedResult(fNamedPipe, // handle to pipe
149 &fOverlap, // OVERLAPPED structure
150 &ret, // bytes transferred
151 FALSE); // do not wait
153 switch (fIOState) {
155 case kConnecting:
156 if (!success) {
157 jack_error("Conection error");
158 return -1;
159 } else {
160 fIOState = kReading;
161 // Prepare connection for new client ??
163 break;
165 case kReading:
166 if (!success || ret == 0) {
167 return -1;
169 fIOState = kWriting;
170 break;
172 case kWriting:
173 if (!success || ret == 0) {
174 return -1;
176 fIOState = kReading;
177 break;
179 default:
180 break;
183 return 0;
186 int JackWinAsyncNamedPipeClient::Read(void* data, int len)
188 DWORD read;
189 jack_log("JackWinNamedPipeClient::Read len = %ld", len);
190 BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap);
191 jack_log("JackWinNamedPipeClient::Read res = %ld read %ld", res, read);
193 if (res && read != 0) {
194 fPendingIO = false;
195 fIOState = kWriting;
196 return 0;
197 } else if (!res && GetLastError() == ERROR_IO_PENDING) {
198 fPendingIO = true;
199 return 0;
200 } else {
201 jack_error("Cannot read named pipe err = %ld", GetLastError());
202 return -1;
206 int JackWinAsyncNamedPipeClient::Write(void* data, int len)
208 DWORD written;
209 jack_log("JackWinNamedPipeClient::Write len = %ld", len);
210 BOOL res = WriteFile(fNamedPipe, data, len, &written, &fOverlap);
212 if (res && written != 0) {
213 fPendingIO = false;
214 fIOState = kWriting;
215 return 0;
216 } else if (!res && GetLastError() == ERROR_IO_PENDING) {
217 fPendingIO = true;
218 return 0;
219 } else {
220 jack_error("Cannot write named pipe err = %ld", GetLastError());
221 return -1;
225 // Server side
227 int JackWinNamedPipeServer::Bind(const char* dir, int which)
229 sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
230 jack_log("Bind: fName %s", fName);
232 if ((fNamedPipe = CreateNamedPipe(fName,
233 PIPE_ACCESS_DUPLEX, // read/write access
234 PIPE_TYPE_MESSAGE | // message type pipe
235 PIPE_READMODE_MESSAGE | // message-read mode
236 PIPE_WAIT, // blocking mode
237 PIPE_UNLIMITED_INSTANCES, // max. instances
238 BUFSIZE, // output buffer size
239 BUFSIZE, // input buffer size
240 INFINITE, // client time-out
241 NULL)) == INVALID_HANDLE_VALUE) { // no security a
242 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
243 return -1;
244 } else {
245 return 0;
249 int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
251 sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
252 jack_log("Bind: fName %s", fName);
254 if ((fNamedPipe = CreateNamedPipe(fName,
255 PIPE_ACCESS_DUPLEX, // read/write access
256 PIPE_TYPE_MESSAGE | // message type pipe
257 PIPE_READMODE_MESSAGE | // message-read mode
258 PIPE_WAIT, // blocking mode
259 PIPE_UNLIMITED_INSTANCES, // max. instances
260 BUFSIZE, // output buffer size
261 BUFSIZE, // input buffer size
262 INFINITE, // client time-out
263 NULL)) == INVALID_HANDLE_VALUE) { // no security a
264 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
265 return -1;
266 } else {
267 return 0;
271 bool JackWinNamedPipeServer::Accept()
273 if (ConnectNamedPipe(fNamedPipe, NULL)) {
274 return true;
275 } else {
276 jack_error("Cannot bind server pipe name = %s err = %ld", fName, GetLastError());
277 if (GetLastError() == ERROR_PIPE_CONNECTED) {
278 jack_error("pipe already connnected = %s ", fName);
279 return true;
280 } else {
281 return false;
286 JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient()
288 if (ConnectNamedPipe(fNamedPipe, NULL)) {
289 JackWinNamedPipeClient* client = new JackWinNamedPipeClient(fNamedPipe);
290 // Init the pipe to the default value
291 fNamedPipe = INVALID_HANDLE_VALUE;
292 return client;
293 } else {
294 switch (GetLastError()) {
296 case ERROR_PIPE_CONNECTED:
297 return new JackWinNamedPipeClient(fNamedPipe);
299 default:
300 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
301 return NULL;
302 break;
307 int JackWinNamedPipeServer::Close()
309 jack_log("JackWinNamedPipeServer::Close");
311 if (fNamedPipe != INVALID_HANDLE_VALUE) {
312 DisconnectNamedPipe(fNamedPipe);
313 CloseHandle(fNamedPipe);
314 fNamedPipe = INVALID_HANDLE_VALUE;
315 return 0;
316 } else {
317 return -1;
321 // Server side
323 int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
325 sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
326 jack_log("Bind: fName %s", fName);
328 if ((fNamedPipe = CreateNamedPipe(fName,
329 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
330 PIPE_TYPE_MESSAGE | // message type pipe
331 PIPE_READMODE_MESSAGE | // message-read mode
332 PIPE_WAIT, // blocking mode
333 PIPE_UNLIMITED_INSTANCES, // max. instances
334 BUFSIZE, // output buffer size
335 BUFSIZE, // input buffer size
336 INFINITE, // client time-out
337 NULL)) == INVALID_HANDLE_VALUE) { // no security a
338 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
339 return -1;
340 } else {
341 return 0;
345 int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
347 sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
348 jack_log("Bind: fName %s", fName);
350 if ((fNamedPipe = CreateNamedPipe(fName,
351 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
352 PIPE_TYPE_MESSAGE | // message type pipe
353 PIPE_READMODE_MESSAGE | // message-read mode
354 PIPE_WAIT, // blocking mode
355 PIPE_UNLIMITED_INSTANCES, // max. instances
356 BUFSIZE, // output buffer size
357 BUFSIZE, // input buffer size
358 INFINITE, // client time-out
359 NULL)) == INVALID_HANDLE_VALUE) { // no security a
360 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
361 return -1;
362 } else {
363 return 0;
367 bool JackWinAsyncNamedPipeServer::Accept()
369 return false;
372 JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
374 if (ConnectNamedPipe(fNamedPipe, NULL)) {
375 return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
376 } else {
377 switch (GetLastError()) {
379 case ERROR_IO_PENDING:
380 return new JackWinAsyncNamedPipeClient(fNamedPipe, true);
382 case ERROR_PIPE_CONNECTED:
383 return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
385 default:
386 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
387 return NULL;
388 break;
393 } // end of namespace