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.

389 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. #if defined(HAVE_CONFIG_H)
  16. #include "config.h"
  17. #endif
  18. #include "JackWinNamedPipe.h"
  19. #include "JackError.h"
  20. #include <assert.h>
  21. #define BUFSIZE 4096
  22. namespace Jack
  23. {
  24. int JackWinNamedPipe::Read(void* data, int len)
  25. {
  26. DWORD read;
  27. BOOL res = ReadFile(fNamedPipe, data, len, &read, NULL);
  28. if (read != len) {
  29. jack_error("Cannot read named pipe err = %ld", GetLastError());
  30. return -1;
  31. } else {
  32. return 0;
  33. }
  34. }
  35. int JackWinNamedPipe::Write(void* data, int len)
  36. {
  37. DWORD written;
  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. jack_log("Connect: fName %s", 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_%d", dir, name, which);
  68. jack_log("Connect: fName %s", 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. 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. JackWinNamedPipeClient* JackWinAsyncNamedPipeServer::AcceptClient()
  316. {
  317. if (ConnectNamedPipe(fNamedPipe, NULL)) {
  318. return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
  319. } else {
  320. switch (GetLastError()) {
  321. case ERROR_IO_PENDING:
  322. return new JackWinAsyncNamedPipeClient(fNamedPipe, true);
  323. case ERROR_PIPE_CONNECTED:
  324. return new JackWinAsyncNamedPipeClient(fNamedPipe, false);
  325. default:
  326. jack_error("Cannot connect server pipe name = %s err = %ld", fName, GetLastError());
  327. return NULL;
  328. break;
  329. }
  330. }
  331. }
  332. } // end of namespace