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.

394 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 (res && read == (DWORD)len) {
  27. return 0;
  28. } else {
  29. jack_error("Cannot read named pipe err = %ld", GetLastError());
  30. return -1;
  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 (res && written == (DWORD)len) {
  38. return 0;
  39. } else {
  40. jack_error("Cannot write named pipe err = %ld", GetLastError());
  41. return -1;
  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(), fPendingIO(false), fIOState(kIdle)
  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), fPendingIO(pending), fIOState(kIdle)
  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. default:
  150. break;
  151. }
  152. return 0;
  153. }
  154. int JackWinAsyncNamedPipeClient::Read(void* data, int len)
  155. {
  156. DWORD read;
  157. jack_log("JackWinNamedPipeClient::Read len = %ld", len);
  158. BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap);
  159. jack_log("JackWinNamedPipeClient::Read res = %ld read %ld", res, read);
  160. if (res && read != 0) {
  161. fPendingIO = false;
  162. fIOState = kWriting;
  163. return 0;
  164. } else if (!res && GetLastError() == ERROR_IO_PENDING) {
  165. fPendingIO = true;
  166. return 0;
  167. } else {
  168. jack_error("Cannot read named pipe err = %ld", GetLastError());
  169. return -1;
  170. }
  171. }
  172. int JackWinAsyncNamedPipeClient::Write(void* data, int len)
  173. {
  174. DWORD written;
  175. jack_log("JackWinNamedPipeClient::Write len = %ld", len);
  176. BOOL res = WriteFile(fNamedPipe, data, len, &written, &fOverlap);
  177. if (res && written != 0) {
  178. fPendingIO = false;
  179. fIOState = kWriting;
  180. return 0;
  181. } else if (!res && GetLastError() == ERROR_IO_PENDING) {
  182. fPendingIO = true;
  183. return 0;
  184. } else {
  185. jack_error("Cannot write named pipe err = %ld", GetLastError());
  186. return -1;
  187. }
  188. }
  189. // Server side
  190. int JackWinNamedPipeServer::Bind(const char* dir, int which)
  191. {
  192. sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
  193. jack_log("Bind: fName %s", fName);
  194. if ((fNamedPipe = CreateNamedPipe(fName,
  195. PIPE_ACCESS_DUPLEX, // read/write access
  196. PIPE_TYPE_MESSAGE | // message type pipe
  197. PIPE_READMODE_MESSAGE | // message-read mode
  198. PIPE_WAIT, // blocking mode
  199. PIPE_UNLIMITED_INSTANCES, // max. instances
  200. BUFSIZE, // output buffer size
  201. BUFSIZE, // input buffer size
  202. INFINITE, // client time-out
  203. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  204. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  205. return -1;
  206. } else {
  207. return 0;
  208. }
  209. }
  210. int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
  211. {
  212. sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
  213. jack_log("Bind: fName %s", fName);
  214. if ((fNamedPipe = CreateNamedPipe(fName,
  215. PIPE_ACCESS_DUPLEX, // read/write access
  216. PIPE_TYPE_MESSAGE | // message type pipe
  217. PIPE_READMODE_MESSAGE | // message-read mode
  218. PIPE_WAIT, // blocking mode
  219. PIPE_UNLIMITED_INSTANCES, // max. instances
  220. BUFSIZE, // output buffer size
  221. BUFSIZE, // input buffer size
  222. INFINITE, // client time-out
  223. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  224. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  225. return -1;
  226. } else {
  227. return 0;
  228. }
  229. }
  230. bool JackWinNamedPipeServer::Accept()
  231. {
  232. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  233. return true;
  234. } else {
  235. jack_error("Cannot bind server pipe name = %s err = %ld", fName, GetLastError());
  236. if (GetLastError() == ERROR_PIPE_CONNECTED) {
  237. jack_error("pipe already connnected = %s ", fName);
  238. return true;
  239. } else {
  240. return false;
  241. }
  242. }
  243. }
  244. JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient()
  245. {
  246. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  247. JackWinNamedPipeClient* client = new JackWinNamedPipeClient(fNamedPipe);
  248. // Init the pipe to the default value
  249. fNamedPipe = INVALID_HANDLE_VALUE;
  250. return client;
  251. } else {
  252. switch (GetLastError()) {
  253. case ERROR_PIPE_CONNECTED:
  254. return new JackWinNamedPipeClient(fNamedPipe);
  255. default:
  256. jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
  257. return NULL;
  258. break;
  259. }
  260. }
  261. }
  262. int JackWinNamedPipeServer::Close()
  263. {
  264. jack_log("JackWinNamedPipeServer::Close");
  265. if (fNamedPipe != INVALID_HANDLE_VALUE) {
  266. DisconnectNamedPipe(fNamedPipe);
  267. CloseHandle(fNamedPipe);
  268. fNamedPipe = INVALID_HANDLE_VALUE;
  269. return 0;
  270. } else {
  271. return -1;
  272. }
  273. }
  274. // Server side
  275. int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
  276. {
  277. sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
  278. jack_log("Bind: fName %s", fName);
  279. if ((fNamedPipe = CreateNamedPipe(fName,
  280. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
  281. PIPE_TYPE_MESSAGE | // message type pipe
  282. PIPE_READMODE_MESSAGE | // message-read mode
  283. PIPE_WAIT, // blocking mode
  284. PIPE_UNLIMITED_INSTANCES, // max. instances
  285. BUFSIZE, // output buffer size
  286. BUFSIZE, // input buffer size
  287. INFINITE, // client time-out
  288. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  289. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  290. return -1;
  291. } else {
  292. return 0;
  293. }
  294. }
  295. int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
  296. {
  297. sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
  298. jack_log("Bind: fName %s", fName);
  299. if ((fNamedPipe = CreateNamedPipe(fName,
  300. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
  301. PIPE_TYPE_MESSAGE | // message type pipe
  302. PIPE_READMODE_MESSAGE | // message-read mode
  303. PIPE_WAIT, // blocking mode
  304. PIPE_UNLIMITED_INSTANCES, // max. instances
  305. BUFSIZE, // output buffer size
  306. BUFSIZE, // input buffer size
  307. INFINITE, // client time-out
  308. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  309. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  310. return -1;
  311. } else {
  312. return 0;
  313. }
  314. }
  315. bool JackWinAsyncNamedPipeServer::Accept()
  316. {
  317. return false;
  318. }
  319. JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
  320. {
  321. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  322. return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
  323. } else {
  324. switch (GetLastError()) {
  325. case ERROR_IO_PENDING:
  326. return new JackWinAsyncNamedPipeClient(fNamedPipe, true);
  327. case ERROR_PIPE_CONNECTED:
  328. return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
  329. default:
  330. jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
  331. return NULL;
  332. break;
  333. }
  334. }
  335. }
  336. } // end of namespace