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.

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