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.

519 lines
17KB

  1. /*
  2. Copyright (C) 2004-2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. /*
  45. See :
  46. http://answers.google.com/answers/threadview?id=430173
  47. http://msdn.microsoft.com/en-us/library/windows/desktop/aa365800(v=vs.85).aspx
  48. */
  49. int JackWinNamedPipeClient::ConnectAux()
  50. {
  51. jack_log("Connect: fName %s", fName);
  52. while (true) {
  53. fNamedPipe = CreateFile(fName, // pipe name
  54. GENERIC_READ | // read and write access
  55. GENERIC_WRITE,
  56. 0, // no sharing
  57. NULL, // default security attributes
  58. OPEN_EXISTING, // opens existing pipe
  59. 0, // default attributes
  60. NULL); // no template file
  61. // Break if the pipe handle is valid.
  62. if (fNamedPipe != INVALID_HANDLE_VALUE) {
  63. return 0;
  64. }
  65. // Exit if an error other than ERROR_PIPE_BUSY occurs.
  66. if (GetLastError() != ERROR_PIPE_BUSY) {
  67. jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
  68. return -1;
  69. }
  70. // All pipe instances are busy, so wait for 2 seconds.
  71. if (!WaitNamedPipe(fName, 2000)) {
  72. jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
  73. return -1;
  74. }
  75. }
  76. }
  77. int JackWinNamedPipeClient::Connect(const char* dir, int which)
  78. {
  79. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
  80. return ConnectAux();
  81. }
  82. int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
  83. {
  84. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
  85. return ConnectAux();
  86. }
  87. /*
  88. int JackWinNamedPipeClient::Connect(const char* dir, int which)
  89. {
  90. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
  91. jack_log("Connect: fName %s", fName);
  92. fNamedPipe = CreateFile(fName, // pipe name
  93. GENERIC_READ | // read and write access
  94. GENERIC_WRITE,
  95. 0, // no sharing
  96. NULL, // default security attributes
  97. OPEN_EXISTING, // opens existing pipe
  98. 0, // default attributes
  99. NULL); // no template file
  100. if (fNamedPipe == INVALID_HANDLE_VALUE) {
  101. jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
  102. return -1;
  103. } else {
  104. return 0;
  105. }
  106. }
  107. int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
  108. {
  109. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
  110. jack_log("Connect: fName %s", fName);
  111. fNamedPipe = CreateFile(fName, // pipe name
  112. GENERIC_READ | // read and write access
  113. GENERIC_WRITE,
  114. 0, // no sharing
  115. NULL, // default security attributes
  116. OPEN_EXISTING, // opens existing pipe
  117. 0, // default attributes
  118. NULL); // no template file
  119. if (fNamedPipe == INVALID_HANDLE_VALUE) {
  120. jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
  121. return -1;
  122. } else {
  123. return 0;
  124. }
  125. }
  126. */
  127. int JackWinNamedPipeClient::Close()
  128. {
  129. if (fNamedPipe != INVALID_HANDLE_VALUE) {
  130. CloseHandle(fNamedPipe);
  131. fNamedPipe = INVALID_HANDLE_VALUE;
  132. return 0;
  133. } else {
  134. return -1;
  135. }
  136. }
  137. void JackWinNamedPipeClient::SetReadTimeOut(long sec)
  138. {}
  139. void JackWinNamedPipeClient::SetWriteTimeOut(long sec)
  140. {}
  141. JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient()
  142. : JackWinNamedPipeClient(), fPendingIO(false), fIOState(kIdle)
  143. {
  144. fIOState = kIdle;
  145. fOverlap.hEvent = CreateEvent(NULL, // default security attribute
  146. TRUE, // manual-reset event
  147. TRUE, // initial state = signaled
  148. NULL); // unnamed event object
  149. }
  150. JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient(HANDLE pipe, bool pending)
  151. : JackWinNamedPipeClient(pipe), fPendingIO(pending), fIOState(kIdle)
  152. {
  153. fOverlap.hEvent = CreateEvent(NULL, // default security attribute
  154. TRUE, // manual-reset event
  155. TRUE, // initial state = signaled
  156. NULL); // unnamed event object
  157. if (!fPendingIO) {
  158. SetEvent(fOverlap.hEvent);
  159. }
  160. fIOState = (fPendingIO) ? kConnecting : kReading;
  161. }
  162. JackWinAsyncNamedPipeClient::~JackWinAsyncNamedPipeClient()
  163. {
  164. CloseHandle(fOverlap.hEvent);
  165. }
  166. int JackWinAsyncNamedPipeClient::FinishIO()
  167. {
  168. DWORD success, ret;
  169. success = GetOverlappedResult(fNamedPipe, // handle to pipe
  170. &fOverlap, // OVERLAPPED structure
  171. &ret, // bytes transferred
  172. FALSE); // do not wait
  173. switch (fIOState) {
  174. case kConnecting:
  175. if (!success) {
  176. jack_error("Conection error");
  177. return -1;
  178. } else {
  179. fIOState = kReading;
  180. // Prepare connection for new client ??
  181. }
  182. break;
  183. case kReading:
  184. if (!success || ret == 0) {
  185. return -1;
  186. }
  187. fIOState = kWriting;
  188. break;
  189. case kWriting:
  190. if (!success || ret == 0) {
  191. return -1;
  192. }
  193. fIOState = kReading;
  194. break;
  195. default:
  196. break;
  197. }
  198. return 0;
  199. }
  200. int JackWinAsyncNamedPipeClient::Read(void* data, int len)
  201. {
  202. DWORD read;
  203. jack_log("JackWinNamedPipeClient::Read len = %ld", len);
  204. BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap);
  205. if (res && read != 0) {
  206. fPendingIO = false;
  207. fIOState = kWriting;
  208. return 0;
  209. } else if (!res && GetLastError() == ERROR_IO_PENDING) {
  210. fPendingIO = true;
  211. return 0;
  212. } else {
  213. jack_error("Cannot read named pipe err = %ld", GetLastError());
  214. return -1;
  215. }
  216. }
  217. int JackWinAsyncNamedPipeClient::Write(void* data, int len)
  218. {
  219. DWORD written;
  220. jack_log("JackWinNamedPipeClient::Write len = %ld", len);
  221. BOOL res = WriteFile(fNamedPipe, data, len, &written, &fOverlap);
  222. if (res && written != 0) {
  223. fPendingIO = false;
  224. fIOState = kWriting;
  225. return 0;
  226. } else if (!res && GetLastError() == ERROR_IO_PENDING) {
  227. fPendingIO = true;
  228. return 0;
  229. } else {
  230. jack_error("Cannot write named pipe err = %ld", GetLastError());
  231. return -1;
  232. }
  233. }
  234. // Server side
  235. int JackWinNamedPipeServer::BindAux()
  236. {
  237. jack_log("Bind: fName %s", fName);
  238. if ((fNamedPipe = CreateNamedPipe(fName,
  239. PIPE_ACCESS_DUPLEX, // read/write access
  240. PIPE_TYPE_MESSAGE | // message type pipe
  241. PIPE_READMODE_MESSAGE | // message-read mode
  242. PIPE_WAIT, // blocking mode
  243. PIPE_UNLIMITED_INSTANCES, // max. instances
  244. BUFSIZE, // output buffer size
  245. BUFSIZE, // input buffer size
  246. INFINITE, // client time-out
  247. NULL)) == INVALID_HANDLE_VALUE) { // no security
  248. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  249. return -1;
  250. } else {
  251. return 0;
  252. }
  253. }
  254. int JackWinNamedPipeServer::Bind(const char* dir, int which)
  255. {
  256. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
  257. return BindAux();
  258. }
  259. int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
  260. {
  261. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
  262. return BindAux();
  263. }
  264. /*
  265. int JackWinNamedPipeServer::Bind(const char* dir, int which)
  266. {
  267. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
  268. jack_log("Bind: fName %s", fName);
  269. if ((fNamedPipe = CreateNamedPipe(fName,
  270. PIPE_ACCESS_DUPLEX, // read/write access
  271. PIPE_TYPE_MESSAGE | // message type pipe
  272. PIPE_READMODE_MESSAGE | // message-read mode
  273. PIPE_WAIT, // blocking mode
  274. PIPE_UNLIMITED_INSTANCES, // max. instances
  275. BUFSIZE, // output buffer size
  276. BUFSIZE, // input buffer size
  277. INFINITE, // client time-out
  278. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  279. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  280. return -1;
  281. } else {
  282. return 0;
  283. }
  284. }
  285. int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
  286. {
  287. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
  288. jack_log("Bind: fName %s", fName);
  289. if ((fNamedPipe = CreateNamedPipe(fName,
  290. PIPE_ACCESS_DUPLEX, // read/write access
  291. PIPE_TYPE_MESSAGE | // message type pipe
  292. PIPE_READMODE_MESSAGE | // message-read mode
  293. PIPE_WAIT, // blocking mode
  294. PIPE_UNLIMITED_INSTANCES, // max. instances
  295. BUFSIZE, // output buffer size
  296. BUFSIZE, // input buffer size
  297. INFINITE, // client time-out
  298. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  299. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  300. return -1;
  301. } else {
  302. return 0;
  303. }
  304. }
  305. */
  306. bool JackWinNamedPipeServer::Accept()
  307. {
  308. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  309. return true;
  310. } else {
  311. jack_error("Cannot bind server pipe name = %s err = %ld", fName, GetLastError());
  312. if (GetLastError() == ERROR_PIPE_CONNECTED) {
  313. jack_error("pipe already connnected = %s ", fName);
  314. return true;
  315. } else {
  316. return false;
  317. }
  318. }
  319. }
  320. JackWinNamedPipeClient* JackWinNamedPipeServer::AcceptClient()
  321. {
  322. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  323. JackWinNamedPipeClient* client = new JackWinNamedPipeClient(fNamedPipe);
  324. // Init the pipe to the default value
  325. fNamedPipe = INVALID_HANDLE_VALUE;
  326. return client;
  327. } else {
  328. switch (GetLastError()) {
  329. case ERROR_PIPE_CONNECTED:
  330. return new JackWinNamedPipeClient(fNamedPipe);
  331. default:
  332. jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
  333. return NULL;
  334. break;
  335. }
  336. }
  337. }
  338. int JackWinNamedPipeServer::Close()
  339. {
  340. jack_log("JackWinNamedPipeServer::Close");
  341. if (fNamedPipe != INVALID_HANDLE_VALUE) {
  342. DisconnectNamedPipe(fNamedPipe);
  343. CloseHandle(fNamedPipe);
  344. fNamedPipe = INVALID_HANDLE_VALUE;
  345. return 0;
  346. } else {
  347. return -1;
  348. }
  349. }
  350. // Server side
  351. int JackWinAsyncNamedPipeServer::BindAux()
  352. {
  353. jack_log("Bind: fName %s", fName);
  354. if ((fNamedPipe = CreateNamedPipe(fName,
  355. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
  356. PIPE_TYPE_MESSAGE | // message type pipe
  357. PIPE_READMODE_MESSAGE | // message-read mode
  358. PIPE_WAIT, // blocking mode
  359. PIPE_UNLIMITED_INSTANCES, // max. instances
  360. BUFSIZE, // output buffer size
  361. BUFSIZE, // input buffer size
  362. INFINITE, // client time-out
  363. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  364. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  365. return -1;
  366. } else {
  367. return 0;
  368. }
  369. }
  370. int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
  371. {
  372. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
  373. return BindAux();
  374. }
  375. int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
  376. {
  377. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
  378. return BindAux();
  379. }
  380. /*
  381. int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
  382. {
  383. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
  384. jack_log("Bind: fName %s", fName);
  385. if ((fNamedPipe = CreateNamedPipe(fName,
  386. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
  387. PIPE_TYPE_MESSAGE | // message type pipe
  388. PIPE_READMODE_MESSAGE | // message-read mode
  389. PIPE_WAIT, // blocking mode
  390. PIPE_UNLIMITED_INSTANCES, // max. instances
  391. BUFSIZE, // output buffer size
  392. BUFSIZE, // input buffer size
  393. INFINITE, // client time-out
  394. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  395. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  396. return -1;
  397. } else {
  398. return 0;
  399. }
  400. }
  401. int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
  402. {
  403. snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
  404. jack_log("Bind: fName %s", fName);
  405. if ((fNamedPipe = CreateNamedPipe(fName,
  406. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
  407. PIPE_TYPE_MESSAGE | // message type pipe
  408. PIPE_READMODE_MESSAGE | // message-read mode
  409. PIPE_WAIT, // blocking mode
  410. PIPE_UNLIMITED_INSTANCES, // max. instances
  411. BUFSIZE, // output buffer size
  412. BUFSIZE, // input buffer size
  413. INFINITE, // client time-out
  414. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  415. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  416. return -1;
  417. } else {
  418. return 0;
  419. }
  420. }
  421. */
  422. bool JackWinAsyncNamedPipeServer::Accept()
  423. {
  424. return false;
  425. }
  426. JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
  427. {
  428. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  429. return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
  430. } else {
  431. switch (GetLastError()) {
  432. case ERROR_IO_PENDING:
  433. return new JackWinAsyncNamedPipeClient(fNamedPipe, true);
  434. case ERROR_PIPE_CONNECTED:
  435. return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
  436. default:
  437. jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
  438. return NULL;
  439. break;
  440. }
  441. }
  442. }
  443. } // end of namespace