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.

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