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.

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