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.

391 lines
13KB

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