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.

388 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. #define BUFSIZE 4096
  19. namespace Jack
  20. {
  21. int JackWinNamedPipe::Read(void* data, int len)
  22. {
  23. DWORD read;
  24. JackLog("JackWinNamedPipeClient::Read len = %ld\n", len);
  25. BOOL res = ReadFile(fNamedPipe, data, len, &read, NULL);
  26. JackLog("JackWinNamedPipeClient::Read res = %ld read %ld\n", res, read);
  27. if (read != len) {
  28. jack_error("Cannot read named pipe err = %ld", GetLastError());
  29. return -1;
  30. } else {
  31. return 0;
  32. }
  33. }
  34. int JackWinNamedPipe::Write(void* data, int len)
  35. {
  36. DWORD written;
  37. JackLog("JackWinNamedPipeClient::Write len = %ld\n", len);
  38. BOOL res = WriteFile(fNamedPipe, data, len, &written, NULL);
  39. if (written != len) {
  40. jack_error("Cannot write named pipe err = %ld", GetLastError());
  41. return -1;
  42. } else {
  43. return 0;
  44. }
  45. }
  46. int JackWinNamedPipeClient::Connect(const char* dir, int which)
  47. {
  48. sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
  49. JackLog("Connect: fName %s\n", fName);
  50. fNamedPipe = CreateFile(fName, // pipe name
  51. GENERIC_READ | // read and write access
  52. GENERIC_WRITE,
  53. 0, // no sharing
  54. NULL, // default security attributes
  55. OPEN_EXISTING, // opens existing pipe
  56. 0, // default attributes
  57. NULL); // no template file
  58. if (fNamedPipe == INVALID_HANDLE_VALUE) {
  59. jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
  60. return -1;
  61. } else {
  62. return 0;
  63. }
  64. }
  65. int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
  66. {
  67. sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
  68. JackLog("Connect: fName %s\n", fName);
  69. fNamedPipe = CreateFile(fName, // pipe name
  70. GENERIC_READ | // read and write access
  71. GENERIC_WRITE,
  72. 0, // no sharing
  73. NULL, // default security attributes
  74. OPEN_EXISTING, // opens existing pipe
  75. 0, // default attributes
  76. NULL); // no template file
  77. if (fNamedPipe == INVALID_HANDLE_VALUE) {
  78. jack_error("Cannot connect to named pipe = %s err = %ld", fName, GetLastError());
  79. return -1;
  80. } else {
  81. return 0;
  82. }
  83. }
  84. int JackWinNamedPipeClient::Close()
  85. {
  86. if (fNamedPipe != INVALID_HANDLE_VALUE) {
  87. CloseHandle(fNamedPipe);
  88. fNamedPipe = INVALID_HANDLE_VALUE;
  89. return 0;
  90. } else {
  91. return -1;
  92. }
  93. }
  94. void JackWinNamedPipeClient::SetReadTimeOut(long sec)
  95. {}
  96. void JackWinNamedPipeClient::SetWriteTimeOut(long sec)
  97. {}
  98. JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient()
  99. : JackWinNamedPipeClient(), fIOState(kIdle), fPendingIO(false)
  100. {
  101. fIOState = kIdle;
  102. fOverlap.hEvent = CreateEvent(NULL, // default security attribute
  103. TRUE, // manual-reset event
  104. TRUE, // initial state = signaled
  105. NULL); // unnamed event object
  106. }
  107. JackWinAsyncNamedPipeClient::JackWinAsyncNamedPipeClient(HANDLE pipe, bool pending)
  108. : JackWinNamedPipeClient(pipe), fIOState(kIdle), fPendingIO(pending)
  109. {
  110. fOverlap.hEvent = CreateEvent(NULL, // default security attribute
  111. TRUE, // manual-reset event
  112. TRUE, // initial state = signaled
  113. NULL); // unnamed event object
  114. if (!fPendingIO)
  115. SetEvent(fOverlap.hEvent);
  116. fIOState = (fPendingIO) ? kConnecting : kReading;
  117. }
  118. JackWinAsyncNamedPipeClient::~JackWinAsyncNamedPipeClient()
  119. {
  120. CloseHandle(fOverlap.hEvent);
  121. }
  122. int JackWinAsyncNamedPipeClient::FinishIO()
  123. {
  124. DWORD success, ret;
  125. success = GetOverlappedResult(fNamedPipe, // handle to pipe
  126. &fOverlap, // OVERLAPPED structure
  127. &ret, // bytes transferred
  128. FALSE); // do not wait
  129. switch (fIOState) {
  130. case kConnecting:
  131. if (!success) {
  132. jack_error("Conection error");
  133. return -1;
  134. } else {
  135. fIOState = kReading;
  136. // Prepare connection for new client ??
  137. }
  138. break;
  139. case kReading:
  140. if (!success || ret == 0) {
  141. return -1;
  142. }
  143. fIOState = kWriting;
  144. break;
  145. case kWriting:
  146. if (!success || ret == 0) {
  147. return -1;
  148. }
  149. fIOState = kReading;
  150. break;
  151. }
  152. return 0;
  153. }
  154. int JackWinAsyncNamedPipeClient::Read(void* data, int len)
  155. {
  156. DWORD read;
  157. JackLog("JackWinNamedPipeClient::Read len = %ld\n", len);
  158. BOOL res = ReadFile(fNamedPipe, data, len, &read, &fOverlap);
  159. JackLog("JackWinNamedPipeClient::Read res = %ld read %ld\n", 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. JackLog("JackWinNamedPipeClient::Write len = %ld\n", 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. JackLog("Bind: fName %s\n", 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", dir, name);
  213. JackLog("Bind: fName %s\n", 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. } else {
  251. switch (GetLastError()) {
  252. case ERROR_PIPE_CONNECTED:
  253. return new JackWinNamedPipeClient(fNamedPipe);
  254. default:
  255. jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
  256. return NULL;
  257. break;
  258. }
  259. }
  260. }
  261. int JackWinNamedPipeServer::Close()
  262. {
  263. JackLog("JackWinNamedPipeServer::Close\n");
  264. if (fNamedPipe != INVALID_HANDLE_VALUE) {
  265. DisconnectNamedPipe(fNamedPipe);
  266. CloseHandle(fNamedPipe);
  267. fNamedPipe = INVALID_HANDLE_VALUE;
  268. return 0;
  269. } else {
  270. return -1;
  271. }
  272. }
  273. // Server side
  274. int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
  275. {
  276. sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
  277. JackLog("Bind: fName %s\n", fName);
  278. if ((fNamedPipe = CreateNamedPipe(fName,
  279. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
  280. PIPE_TYPE_MESSAGE | // message type pipe
  281. PIPE_READMODE_MESSAGE | // message-read mode
  282. PIPE_WAIT, // blocking mode
  283. PIPE_UNLIMITED_INSTANCES, // max. instances
  284. BUFSIZE, // output buffer size
  285. BUFSIZE, // input buffer size
  286. INFINITE, // client time-out
  287. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  288. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  289. return -1;
  290. } else {
  291. return 0;
  292. }
  293. }
  294. int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
  295. {
  296. sprintf(fName, "\\\\.\\pipe\\%s_jack_%s", dir, name);
  297. JackLog("Bind: fName %s\n", fName);
  298. if ((fNamedPipe = CreateNamedPipe(fName,
  299. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
  300. PIPE_TYPE_MESSAGE | // message type pipe
  301. PIPE_READMODE_MESSAGE | // message-read mode
  302. PIPE_WAIT, // blocking mode
  303. PIPE_UNLIMITED_INSTANCES, // max. instances
  304. BUFSIZE, // output buffer size
  305. BUFSIZE, // input buffer size
  306. INFINITE, // client time-out
  307. NULL)) == INVALID_HANDLE_VALUE) { // no security a
  308. jack_error("Cannot bind server to pipe err = %ld", GetLastError());
  309. return -1;
  310. } else {
  311. return 0;
  312. }
  313. }
  314. JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
  315. {
  316. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  317. return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
  318. } else {
  319. switch (GetLastError()) {
  320. case ERROR_IO_PENDING:
  321. return new JackWinAsyncNamedPipeClient(fNamedPipe, true);
  322. case ERROR_PIPE_CONNECTED:
  323. return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
  324. default:
  325. jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
  326. return NULL;
  327. break;
  328. }
  329. }
  330. }
  331. } // end of namespace