Cleanup
[jack2.git] / windows / JackWinNamedPipe.cpp
blobe2d0b5f9657cec28b5e0e9f811d166c4c82f46ca
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>
24 #define BUFSIZE 4096
26 namespace Jack
29 int JackWinNamedPipe::Read(void* data, int len)
31 DWORD read;
32 BOOL res = ReadFile(fNamedPipe, data, len, &read, NULL);
33 if (read != len) {
34 jack_error("Cannot read named pipe err = %ld", GetLastError());
35 return -1;
36 } else {
37 return 0;
41 int JackWinNamedPipe::Write(void* data, int len)
43 DWORD written;
44 BOOL res = WriteFile(fNamedPipe, data, len, &written, NULL);
45 if (written != len) {
46 jack_error("Cannot write named pipe err = %ld", GetLastError());
47 return -1;
48 } else {
49 return 0;
53 int JackWinNamedPipeClient::Connect(const char* dir, int which)
55 sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
56 JackLog("Connect: fName %s\n", fName);
58 fNamedPipe = CreateFile(fName, // pipe name
59 GENERIC_READ | // read and write access
60 GENERIC_WRITE,
61 0, // no sharing
62 NULL, // default security attributes
63 OPEN_EXISTING, // opens existing pipe
64 0, // default attributes
65 NULL); // no template file
67 if (fNamedPipe == INVALID_HANDLE_VALUE) {
68 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
69 return -1;
70 } else {
71 return 0;
75 int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
77 sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
78 JackLog("Connect: fName %s\n", fName);
80 fNamedPipe = CreateFile(fName, // pipe name
81 GENERIC_READ | // read and write access
82 GENERIC_WRITE,
83 0, // no sharing
84 NULL, // default security attributes
85 OPEN_EXISTING, // opens existing pipe
86 0, // default attributes
87 NULL); // no template file
89 if (fNamedPipe == INVALID_HANDLE_VALUE) {
90 jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
91 return -1;
92 } else {
93 return 0;
97 int JackWinNamedPipeClient::Close()
99 if (fNamedPipe != INVALID_HANDLE_VALUE) {
100 CloseHandle(fNamedPipe);
101 fNamedPipe = INVALID_HANDLE_VALUE;
102 return 0;
103 } else {
104 return -1;
108 void JackWinNamedPipeClient::SetReadTimeOut(long sec)
111 void JackWinNamedPipeClient::SetWriteTimeOut(long sec)
114 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient()
115 : JackWinNamedPipeClient(), fIOState(kIdle), fPendingIO(false)
117 fIOState = kIdle;
118 fOverlap.hEvent = CreateEvent(NULL, // default security attribute
119 TRUE, // manual-reset event
120 TRUE, // initial state = signaled
121 NULL); // unnamed event object
124 JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient(HANDLE pipe, bool pending)
125 : JackWinNamedPipeClient(pipe), fIOState(kIdle), fPendingIO(pending)
127 fOverlap.hEvent = CreateEvent(NULL, // default security attribute
128 TRUE, // manual-reset event
129 TRUE, // initial state = signaled
130 NULL); // unnamed event object
132 if (!fPendingIO)
133 SetEvent(fOverlap.hEvent);
135 fIOState = (fPendingIO) ? kConnecting : kReading;
138 JackWinAsyncNamedPipeClient::~JackWinAsyncNamedPipeClient()
140 CloseHandle(fOverlap.hEvent);
143 int JackWinAsyncNamedPipeClient::FinishIO()
145 DWORD success, ret;
146 success = GetOverlappedResult(fNamedPipe, // handle to pipe
147 &fOverlap, // OVERLAPPED structure
148 &ret, // bytes transferred
149 FALSE); // do not wait
151 switch (fIOState) {
153 case kConnecting:
154 if (!success) {
155 jack_error("Conection error");
156 return -1;
157 } else {
158 fIOState = kReading;
159 // Prepare connection for new client ??
161 break;
163 case kReading:
164 if (!success || ret == 0) {
165 return -1;
167 fIOState = kWriting;
168 break;
170 case kWriting:
171 if (!success || ret == 0) {
172 return -1;
174 fIOState = kReading;
175 break;
178 return 0;
181 int JackWinAsyncNamedPipeClient::Read(void* data, int len)
183 DWORD read;
184 JackLog("JackWinNamedPipeClient::Read len = %ld\n", len);
185 BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap);
186 JackLog("JackWinNamedPipeClient::Read res = %ld read %ld\n", res, read);
188 if (res && read != 0) {
189 fPendingIO = false;
190 fIOState = kWriting;
191 return 0;
192 } else if (!res && GetLastError() == ERROR_IO_PENDING) {
193 fPendingIO = true;
194 return 0;
195 } else {
196 jack_error("Cannot read named pipe err = %ld", GetLastError());
197 return -1;
201 int JackWinAsyncNamedPipeClient::Write(void* data, int len)
203 DWORD written;
204 JackLog("JackWinNamedPipeClient::Write len = %ld\n", len);
205 BOOL res = WriteFile(fNamedPipe, data, len, &written, &fOverlap);
207 if (res && written != 0) {
208 fPendingIO = false;
209 fIOState = kWriting;
210 return 0;
211 } else if (!res && GetLastError() == ERROR_IO_PENDING) {
212 fPendingIO = true;
213 return 0;
214 } else {
215 jack_error("Cannot write named pipe err = %ld", GetLastError());
216 return -1;
220 // Server side
222 int JackWinNamedPipeServer::Bind(const char* dir, int which)
224 sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
225 JackLog("Bind: fName %s\n", fName);
227 if ((fNamedPipe = CreateNamedPipe(fName,
228 PIPE_ACCESS_DUPLEX, // read/write access
229 PIPE_TYPE_MESSAGE | // message type pipe
230 PIPE_READMODE_MESSAGE | // message-read mode
231 PIPE_WAIT, // blocking mode
232 PIPE_UNLIMITED_INSTANCES, // max. instances
233 BUFSIZE, // output buffer size
234 BUFSIZE, // input buffer size
235 INFINITE, // client time-out
236 NULL)) == INVALID_HANDLE_VALUE) { // no security a
237 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
238 return -1;
239 } else {
240 return 0;
244 int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
246 sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
247 JackLog("Bind: fName %s\n", fName);
249 if ((fNamedPipe = CreateNamedPipe(fName,
250 PIPE_ACCESS_DUPLEX, // read/write access
251 PIPE_TYPE_MESSAGE | // message type pipe
252 PIPE_READMODE_MESSAGE | // message-read mode
253 PIPE_WAIT, // blocking mode
254 PIPE_UNLIMITED_INSTANCES, // max. instances
255 BUFSIZE, // output buffer size
256 BUFSIZE, // input buffer size
257 INFINITE, // client time-out
258 NULL)) == INVALID_HANDLE_VALUE) { // no security a
259 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
260 return -1;
261 } else {
262 return 0;
266 bool JackWinNamedPipeServer::Accept()
268 if (ConnectNamedPipe(fNamedPipe, NULL)) {
269 return true;
270 } else {
271 jack_error("Cannot bind server pipe name = %s err = %ld", fName, GetLastError());
272 if (GetLastError() == ERROR_PIPE_CONNECTED) {
273 jack_error("pipe already connnected = %s ", fName);
274 return true;
275 } else {
276 return false;
281 JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient()
283 if (ConnectNamedPipe(fNamedPipe, NULL)) {
284 JackWinNamedPipeClient* client = new JackWinNamedPipeClient(fNamedPipe);
285 // Init the pipe to the default value
286 fNamedPipe = INVALID_HANDLE_VALUE;
287 } else {
288 switch (GetLastError()) {
290 case ERROR_PIPE_CONNECTED:
291 return new JackWinNamedPipeClient(fNamedPipe);
293 default:
294 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
295 return NULL;
296 break;
301 int JackWinNamedPipeServer::Close()
303 JackLog("JackWinNamedPipeServer::Close\n");
305 if (fNamedPipe != INVALID_HANDLE_VALUE) {
306 DisconnectNamedPipe(fNamedPipe);
307 CloseHandle(fNamedPipe);
308 fNamedPipe = INVALID_HANDLE_VALUE;
309 return 0;
310 } else {
311 return -1;
315 // Server side
317 int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
319 sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
320 JackLog("Bind: fName %s\n", fName);
322 if ((fNamedPipe = CreateNamedPipe(fName,
323 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
324 PIPE_TYPE_MESSAGE | // message type pipe
325 PIPE_READMODE_MESSAGE | // message-read mode
326 PIPE_WAIT, // blocking mode
327 PIPE_UNLIMITED_INSTANCES, // max. instances
328 BUFSIZE, // output buffer size
329 BUFSIZE, // input buffer size
330 INFINITE, // client time-out
331 NULL)) == INVALID_HANDLE_VALUE) { // no security a
332 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
333 return -1;
334 } else {
335 return 0;
339 int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
341 sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
342 JackLog("Bind: fName %s\n", fName);
344 if ((fNamedPipe = CreateNamedPipe(fName,
345 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
346 PIPE_TYPE_MESSAGE | // message type pipe
347 PIPE_READMODE_MESSAGE | // message-read mode
348 PIPE_WAIT, // blocking mode
349 PIPE_UNLIMITED_INSTANCES, // max. instances
350 BUFSIZE, // output buffer size
351 BUFSIZE, // input buffer size
352 INFINITE, // client time-out
353 NULL)) == INVALID_HANDLE_VALUE) { // no security a
354 jack_error("Cannot bind server to pipe err = %ld", GetLastError());
355 return -1;
356 } else {
357 return 0;
361 JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
363 if (ConnectNamedPipe(fNamedPipe, NULL)) {
364 return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
365 } else {
366 switch (GetLastError()) {
368 case ERROR_IO_PENDING:
369 return new JackWinAsyncNamedPipeClient(fNamedPipe, true);
371 case ERROR_PIPE_CONNECTED:
372 return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
374 default:
375 jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
376 return NULL;
377 break;
382 } // end of namespace