PageRenderTime 24ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/unix/pipe.c

http://github.com/joyent/libuv
C | 256 lines | 164 code | 50 blank | 42 comment | 38 complexity | 94d9949af796692f9307ca1fe0075d0f MD5 | raw file
Possible License(s): ISC, BSD-2-Clause
  1. /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #include "uv.h"
  22. #include "internal.h"
  23. #include <assert.h>
  24. #include <errno.h>
  25. #include <string.h>
  26. #include <sys/un.h>
  27. #include <unistd.h>
  28. #include <stdlib.h>
  29. static void uv__pipe_accept(uv_loop_t* loop, uv__io_t* w, unsigned int events);
  30. int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
  31. uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
  32. handle->shutdown_req = NULL;
  33. handle->connect_req = NULL;
  34. handle->pipe_fname = NULL;
  35. handle->ipc = ipc;
  36. return 0;
  37. }
  38. int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
  39. struct sockaddr_un saddr;
  40. const char* pipe_fname;
  41. int saved_errno;
  42. int sockfd;
  43. int status;
  44. int bound;
  45. saved_errno = errno;
  46. pipe_fname = NULL;
  47. sockfd = -1;
  48. status = -1;
  49. bound = 0;
  50. /* Already bound? */
  51. if (handle->io_watcher.fd >= 0) {
  52. uv__set_artificial_error(handle->loop, UV_EINVAL);
  53. goto out;
  54. }
  55. /* Make a copy of the file name, it outlives this function's scope. */
  56. if ((pipe_fname = strdup(name)) == NULL) {
  57. uv__set_sys_error(handle->loop, ENOMEM);
  58. goto out;
  59. }
  60. /* We've got a copy, don't touch the original any more. */
  61. name = NULL;
  62. if ((sockfd = uv__socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
  63. uv__set_sys_error(handle->loop, errno);
  64. goto out;
  65. }
  66. memset(&saddr, 0, sizeof saddr);
  67. uv_strlcpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path));
  68. saddr.sun_family = AF_UNIX;
  69. if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
  70. /* Convert ENOENT to EACCES for compatibility with Windows. */
  71. uv__set_sys_error(handle->loop, (errno == ENOENT) ? EACCES : errno);
  72. goto out;
  73. }
  74. bound = 1;
  75. /* Success. */
  76. handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */
  77. handle->io_watcher.fd = sockfd;
  78. status = 0;
  79. out:
  80. /* Clean up on error. */
  81. if (status) {
  82. if (bound) {
  83. /* unlink() before close() to avoid races. */
  84. assert(pipe_fname != NULL);
  85. unlink(pipe_fname);
  86. }
  87. close(sockfd);
  88. free((void*)pipe_fname);
  89. }
  90. errno = saved_errno;
  91. return status;
  92. }
  93. int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
  94. int saved_errno;
  95. int status;
  96. saved_errno = errno;
  97. status = -1;
  98. if (handle->io_watcher.fd == -1) {
  99. uv__set_artificial_error(handle->loop, UV_EINVAL);
  100. goto out;
  101. }
  102. assert(handle->io_watcher.fd >= 0);
  103. if ((status = listen(handle->io_watcher.fd, backlog)) == -1) {
  104. uv__set_sys_error(handle->loop, errno);
  105. } else {
  106. handle->connection_cb = cb;
  107. handle->io_watcher.cb = uv__pipe_accept;
  108. uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN);
  109. }
  110. out:
  111. errno = saved_errno;
  112. return status;
  113. }
  114. void uv__pipe_close(uv_pipe_t* handle) {
  115. if (handle->pipe_fname) {
  116. /*
  117. * Unlink the file system entity before closing the file descriptor.
  118. * Doing it the other way around introduces a race where our process
  119. * unlinks a socket with the same name that's just been created by
  120. * another thread or process.
  121. */
  122. unlink(handle->pipe_fname);
  123. free((void*)handle->pipe_fname);
  124. handle->pipe_fname = NULL;
  125. }
  126. uv__stream_close((uv_stream_t*)handle);
  127. }
  128. int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
  129. return uv__stream_open((uv_stream_t*)handle,
  130. fd,
  131. UV_STREAM_READABLE | UV_STREAM_WRITABLE);
  132. }
  133. void uv_pipe_connect(uv_connect_t* req,
  134. uv_pipe_t* handle,
  135. const char* name,
  136. uv_connect_cb cb) {
  137. struct sockaddr_un saddr;
  138. int saved_errno;
  139. int new_sock;
  140. int err;
  141. int r;
  142. saved_errno = errno;
  143. new_sock = (handle->io_watcher.fd == -1);
  144. err = -1;
  145. if (new_sock)
  146. if ((handle->io_watcher.fd = uv__socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  147. goto out;
  148. memset(&saddr, 0, sizeof saddr);
  149. uv_strlcpy(saddr.sun_path, name, sizeof(saddr.sun_path));
  150. saddr.sun_family = AF_UNIX;
  151. /* We don't check for EINPROGRESS. Think about it: the socket
  152. * is either there or not.
  153. */
  154. do {
  155. r = connect(handle->io_watcher.fd, (struct sockaddr*)&saddr, sizeof saddr);
  156. }
  157. while (r == -1 && errno == EINTR);
  158. if (r == -1)
  159. goto out;
  160. if (new_sock)
  161. if (uv__stream_open((uv_stream_t*)handle,
  162. handle->io_watcher.fd,
  163. UV_STREAM_READABLE | UV_STREAM_WRITABLE))
  164. goto out;
  165. uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN | UV__POLLOUT);
  166. err = 0;
  167. out:
  168. handle->delayed_error = err ? errno : 0; /* Passed to callback. */
  169. handle->connect_req = req;
  170. uv__req_init(handle->loop, req, UV_CONNECT);
  171. req->handle = (uv_stream_t*)handle;
  172. req->cb = cb;
  173. ngx_queue_init(&req->queue);
  174. /* Run callback on next tick. */
  175. uv__io_feed(handle->loop, &handle->io_watcher);
  176. /* Mimic the Windows pipe implementation, always
  177. * return 0 and let the callback handle errors.
  178. */
  179. errno = saved_errno;
  180. }
  181. /* TODO merge with uv__server_io()? */
  182. static void uv__pipe_accept(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
  183. uv_pipe_t* pipe;
  184. int saved_errno;
  185. int sockfd;
  186. saved_errno = errno;
  187. pipe = container_of(w, uv_pipe_t, io_watcher);
  188. assert(pipe->type == UV_NAMED_PIPE);
  189. sockfd = uv__accept(pipe->io_watcher.fd);
  190. if (sockfd == -1) {
  191. if (errno != EAGAIN && errno != EWOULDBLOCK) {
  192. uv__set_sys_error(pipe->loop, errno);
  193. pipe->connection_cb((uv_stream_t*)pipe, -1);
  194. }
  195. } else {
  196. pipe->accepted_fd = sockfd;
  197. pipe->connection_cb((uv_stream_t*)pipe, 0);
  198. if (pipe->accepted_fd == sockfd) {
  199. /* The user hasn't called uv_accept() yet */
  200. uv__io_stop(pipe->loop, &pipe->io_watcher, UV__POLLIN);
  201. }
  202. }
  203. errno = saved_errno;
  204. }
  205. void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
  206. }