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-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. 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