jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

374 lines
12KB

  1. /*
  2. Copyright (C) 2004-2006 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackWinNamedPipe.h"
  16. #include "JackError.h"
  17. #include <assert.h>
  18. #define BUFSIZE 4096
  19. namespace Jack
  20. {
  21. int JackWinNamedPipe::Read(void* data, int len)
  22. {
  23. DWORD read;
  24. JackLog("JackWinNamedPipeClient::Read len = %ld\n", len);
  25. BOOL res = ReadFile(fNamedPipe, data, len, &read, NULL);
  26. JackLog("JackWinNamedPipeClient::Read res = %ld read %ld\n", res, read);
  27. if (read != len) {
  28. jack_error("Cannot read named pipe err = %ld", GetLastError());
  29. return -1;
  30. } else {
  31. return 0;
  32. }
  33. }
  34. int JackWinNamedPipe::Write(void* data, int len)
  35. {
  36. DWORD written;
  37. JackLog("JackWinNamedPipeClient::Write len = %ld\n", len);
  38. BOOL res = WriteFile(fNamedPipe, data, len, &written, NULL);
  39. if (written != len) {
  40. jack_error("Cannot write named pipe err = %ld", GetLastError());
  41. return -1;
  42. } else {
  43. return 0;
  44. }
  45. }
  46. int JackWinNamedPipeClient::Connect(const char* dir, int which)
  47. {
  48. sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
  49. JackLog("Connect: fName %s\n", fName);
  50. fNamedPipe = CreateFile(fName, // pipe name
  51. GENERIC_READ | // read and write access
  52. GENERIC_WRITE,
  53. 0, // no sharing
  54. NULL, // default security attributes
  55. OPEN_EXISTING, // opens existing pipe
  56. 0, // default attributes
  57. NULL); // no template file
  58. if (fNamedPipe == INVALID_HANDLE_VALUE) {
  59. jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
  60. return -1;
  61. } else {
  62. return 0;
  63. }
  64. }
  65. int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
  66. {
  67. sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
  68. JackLog("Connect: fName %s\n", fName);
  69. fNamedPipe = CreateFile(fName, // pipe name
  70. GENERIC_READ | // read and write access
  71. GENERIC_WRITE,
  72. 0, // no sharing
  73. NULL, // default security attributes
  74. OPEN_EXISTING, // opens existing pipe
  75. 0, // default attributes
  76. NULL); // no template file
  77. if (fNamedPipe == INVALID_HANDLE_VALUE) {
  78. jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
  79. return -1;
  80. } else {
  81. return 0;
  82. }
  83. }
  84. int JackWinNamedPipeClient::Close()
  85. {
  86. CloseHandle(fNamedPipe);
  87. return 0;
  88. }
  89. void JackWinNamedPipeClient::SetReadTimeOut(long sec)
  90. {}
  91. void JackWinNamedPipeClient::SetWriteTimeOut(long sec)
  92. {}
  93. JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient()
  94. : JackWinNamedPipeClient(), fIOState(kIdle), fPendingIO(false)
  95. {
  96. fIOState = kIdle;
  97. fOverlap.hEvent = CreateEvent(NULL, // default security attribute
  98. TRUE, // manual-reset event
  99. TRUE, // initial state = signaled
  100. NULL); // unnamed event object
  101. }
  102. JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient(HANDLE pipe, bool pending)
  103. : JackWinNamedPipeClient(pipe), fIOState(kIdle), fPendingIO(pending)
  104. {
  105. fOverlap.hEvent = CreateEvent(NULL, // default security attribute
  106. TRUE, // manual-reset event
  107. TRUE, // initial state = signaled
  108. NULL); // unnamed event object
  109. if (!fPendingIO)
  110. SetEvent(fOverlap.hEvent);
  111. fIOState = (fPendingIO) ? kConnecting : kReading;
  112. }
  113. JackWinAsyncNamedPipeClient::~JackWinAsyncNamedPipeClient()
  114. {
  115. CloseHandle(fOverlap.hEvent);
  116. }
  117. int JackWinAsyncNamedPipeClient::FinishIO()
  118. {
  119. DWORD success, ret;
  120. success = GetOverlappedResult(fNamedPipe, // handle to pipe
  121. &fOverlap, // OVERLAPPED structure
  122. &ret, // bytes transferred
  123. FALSE); // do not wait
  124. switch (fIOState) {
  125. case kConnecting:
  126. if (!success) {
  127. jack_error("Conection error");
  128. return -1;
  129. } else {
  130. fIOState = kReading;
  131. // Prepare connection for new client ??
  132. }
  133. break;
  134. case kReading:
  135. if (!success || ret == 0) {
  136. return -1;
  137. }
  138. fIOState = kWriting;
  139. break;
  140. case kWriting:
  141. if (!success || ret == 0) {
  142. return -1;
  143. }
  144. fIOState = kReading;
  145. break;
  146. }
  147. return 0;
  148. }
  149. int JackWinAsyncNamedPipeClient::Read(void* data, int len)
  150. {
  151. DWORD read;
  152. JackLog("JackWinNamedPipeClient::Read len = %ld\n", len);
  153. BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap);
  154. JackLog("JackWinNamedPipeClient::Read res = %ld read %ld\n", res, read);
  155. if (res && read != 0) {
  156. fPendingIO = false;
  157. fIOState = kWriting;
  158. return 0;
  159. } else if (!res && GetLastError() == ERROR_IO_PENDING) {
  160. fPendingIO = true;
  161. return 0;
  162. } else {
  163. jack_error("Cannot read named pipe err = %ld", GetLastError());
  164. return -1;
  165. }
  166. }
  167. int JackWinAsyncNamedPipeClient::Write(void* data, int len)
  168. {
  169. DWORD written;
  170. JackLog("JackWinNamedPipeClient::Write len = %ld\n", len);
  171. BOOL res = WriteFile(fNamedPipe, data, len, &written, &fOverlap);
  172. if (res && written != 0) {
  173. fPendingIO = false;
  174. fIOState = kWriting;
  175. return 0;
  176. } else if (!res && GetLastError() == ERROR_IO_PENDING) {
  177. fPendingIO = true;
  178. return 0;
  179. } else {
  180. jack_error("Cannot write named pipe err = %ld", GetLastError());
  181. return -1;
  182. }
  183. }
  184. // Server side
  185. int JackWinNamedPipeServer::Bind(const char* dir, int which)
  186. {
  187. sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
  188. JackLog("Bind: fName %s\n", fName);
  189. if ((fNamedPipe = CreateNamedPipe(fName,
  190. PIPE_ACCESS_DUPLEX, // read/write access
  191. PIPE_TYPE_MESSAGE | // message type pipe
  192. PIPE_READMODE_MESSAGE | // message-read mode
  193. PIPE_WAIT, // blocking mode
  194. PIPE_UNLIMITED_INSTANCES, // max. instances
  195. BUFSIZE, // output buffer size
  196. BUFSIZE, // input buffer size
  197. INFINITE, // client time-out
  198. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  199. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  200. return -1;
  201. } else {
  202. return 0;
  203. }
  204. }
  205. int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
  206. {
  207. sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
  208. JackLog("Bind: fName %s\n", fName);
  209. if ((fNamedPipe = CreateNamedPipe(fName,
  210. PIPE_ACCESS_DUPLEX, // read/write access
  211. PIPE_TYPE_MESSAGE | // message type pipe
  212. PIPE_READMODE_MESSAGE | // message-read mode
  213. PIPE_WAIT, // blocking mode
  214. PIPE_UNLIMITED_INSTANCES, // max. instances
  215. BUFSIZE, // output buffer size
  216. BUFSIZE, // input buffer size
  217. INFINITE, // client time-out
  218. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  219. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  220. return -1;
  221. } else {
  222. return 0;
  223. }
  224. }
  225. bool JackWinNamedPipeServer::Accept()
  226. {
  227. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  228. return true;
  229. } else {
  230. jack_error("Cannot bind server pipe name = %s err = %ld", fName, GetLastError());
  231. if (GetLastError() == ERROR_PIPE_CONNECTED) {
  232. jack_error("pipe already connnected = %s ", fName);
  233. return true;
  234. } else {
  235. return false;
  236. }
  237. }
  238. }
  239. JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient()
  240. {
  241. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  242. return new JackWinNamedPipeClient(fNamedPipe);
  243. } else {
  244. switch (GetLastError()) {
  245. case ERROR_PIPE_CONNECTED:
  246. return new JackWinNamedPipeClient(fNamedPipe);
  247. default:
  248. jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
  249. return NULL;
  250. break;
  251. }
  252. }
  253. }
  254. int JackWinNamedPipeServer::Close()
  255. {
  256. DisconnectNamedPipe(fNamedPipe);
  257. CloseHandle(fNamedPipe);
  258. return 0;
  259. }
  260. // Server side
  261. int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
  262. {
  263. sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
  264. JackLog("Bind: fName %s\n", fName);
  265. if ((fNamedPipe = CreateNamedPipe(fName,
  266. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
  267. PIPE_TYPE_MESSAGE | // message type pipe
  268. PIPE_READMODE_MESSAGE | // message-read mode
  269. PIPE_WAIT, // blocking mode
  270. PIPE_UNLIMITED_INSTANCES, // max. instances
  271. BUFSIZE, // output buffer size
  272. BUFSIZE, // input buffer size
  273. INFINITE, // client time-out
  274. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  275. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  276. return -1;
  277. } else {
  278. return 0;
  279. }
  280. }
  281. int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
  282. {
  283. sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
  284. JackLog("Bind: fName %s\n", fName);
  285. if ((fNamedPipe = CreateNamedPipe(fName,
  286. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
  287. PIPE_TYPE_MESSAGE | // message type pipe
  288. PIPE_READMODE_MESSAGE | // message-read mode
  289. PIPE_WAIT, // blocking mode
  290. PIPE_UNLIMITED_INSTANCES, // max. instances
  291. BUFSIZE, // output buffer size
  292. BUFSIZE, // input buffer size
  293. INFINITE, // client time-out
  294. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  295. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  296. return -1;
  297. } else {
  298. return 0;
  299. }
  300. }
  301. JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
  302. {
  303. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  304. return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
  305. } else {
  306. switch (GetLastError()) {
  307. case ERROR_IO_PENDING:
  308. return new JackWinAsyncNamedPipeClient(fNamedPipe, true);
  309. case ERROR_PIPE_CONNECTED:
  310. return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
  311. default:
  312. jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
  313. return NULL;
  314. break;
  315. }
  316. }
  317. }
  318. } // end of namespace