10e552da7Schristos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
20e552da7Schristos *
30e552da7Schristos * Permission is hereby granted, free of charge, to any person obtaining a copy
40e552da7Schristos * of this software and associated documentation files (the "Software"), to
50e552da7Schristos * deal in the Software without restriction, including without limitation the
60e552da7Schristos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
70e552da7Schristos * sell copies of the Software, and to permit persons to whom the Software is
80e552da7Schristos * furnished to do so, subject to the following conditions:
90e552da7Schristos *
100e552da7Schristos * The above copyright notice and this permission notice shall be included in
110e552da7Schristos * all copies or substantial portions of the Software.
120e552da7Schristos *
130e552da7Schristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
140e552da7Schristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150e552da7Schristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
160e552da7Schristos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
170e552da7Schristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
180e552da7Schristos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
190e552da7Schristos * IN THE SOFTWARE.
200e552da7Schristos */
210e552da7Schristos
220e552da7Schristos #include "uv.h"
230e552da7Schristos #include "internal.h"
240e552da7Schristos
250e552da7Schristos #include <assert.h>
260e552da7Schristos #include <errno.h>
270e552da7Schristos #include <string.h>
280e552da7Schristos #include <sys/un.h>
290e552da7Schristos #include <unistd.h>
300e552da7Schristos #include <stdlib.h>
310e552da7Schristos
320e552da7Schristos
uv_pipe_init(uv_loop_t * loop,uv_pipe_t * handle,int ipc)330e552da7Schristos int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
340e552da7Schristos uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
350e552da7Schristos handle->shutdown_req = NULL;
360e552da7Schristos handle->connect_req = NULL;
370e552da7Schristos handle->pipe_fname = NULL;
380e552da7Schristos handle->ipc = ipc;
390e552da7Schristos return 0;
400e552da7Schristos }
410e552da7Schristos
420e552da7Schristos
uv_pipe_bind(uv_pipe_t * handle,const char * name)430e552da7Schristos int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
440e552da7Schristos struct sockaddr_un saddr;
450e552da7Schristos const char* pipe_fname;
460e552da7Schristos int sockfd;
470e552da7Schristos int err;
480e552da7Schristos
490e552da7Schristos pipe_fname = NULL;
500e552da7Schristos
510e552da7Schristos /* Already bound? */
520e552da7Schristos if (uv__stream_fd(handle) >= 0)
530e552da7Schristos return UV_EINVAL;
54*5f2f4271Schristos if (uv__is_closing(handle)) {
55*5f2f4271Schristos return UV_EINVAL;
56*5f2f4271Schristos }
570e552da7Schristos /* Make a copy of the file name, it outlives this function's scope. */
580e552da7Schristos pipe_fname = uv__strdup(name);
590e552da7Schristos if (pipe_fname == NULL)
600e552da7Schristos return UV_ENOMEM;
610e552da7Schristos
620e552da7Schristos /* We've got a copy, don't touch the original any more. */
630e552da7Schristos name = NULL;
640e552da7Schristos
650e552da7Schristos err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
660e552da7Schristos if (err < 0)
670e552da7Schristos goto err_socket;
680e552da7Schristos sockfd = err;
690e552da7Schristos
700e552da7Schristos memset(&saddr, 0, sizeof saddr);
710e552da7Schristos uv__strscpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path));
720e552da7Schristos saddr.sun_family = AF_UNIX;
730e552da7Schristos
740e552da7Schristos if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
750e552da7Schristos err = UV__ERR(errno);
760e552da7Schristos /* Convert ENOENT to EACCES for compatibility with Windows. */
770e552da7Schristos if (err == UV_ENOENT)
780e552da7Schristos err = UV_EACCES;
790e552da7Schristos
800e552da7Schristos uv__close(sockfd);
810e552da7Schristos goto err_socket;
820e552da7Schristos }
830e552da7Schristos
840e552da7Schristos /* Success. */
850e552da7Schristos handle->flags |= UV_HANDLE_BOUND;
860e552da7Schristos handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */
870e552da7Schristos handle->io_watcher.fd = sockfd;
880e552da7Schristos return 0;
890e552da7Schristos
900e552da7Schristos err_socket:
910e552da7Schristos uv__free((void*)pipe_fname);
920e552da7Schristos return err;
930e552da7Schristos }
940e552da7Schristos
950e552da7Schristos
uv__pipe_listen(uv_pipe_t * handle,int backlog,uv_connection_cb cb)96*5f2f4271Schristos int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
970e552da7Schristos if (uv__stream_fd(handle) == -1)
980e552da7Schristos return UV_EINVAL;
990e552da7Schristos
1000e552da7Schristos if (handle->ipc)
1010e552da7Schristos return UV_EINVAL;
1020e552da7Schristos
1030e552da7Schristos #if defined(__MVS__) || defined(__PASE__)
1040e552da7Schristos /* On zOS, backlog=0 has undefined behaviour */
1050e552da7Schristos /* On IBMi PASE, backlog=0 leads to "Connection refused" error */
1060e552da7Schristos if (backlog == 0)
1070e552da7Schristos backlog = 1;
1080e552da7Schristos else if (backlog < 0)
1090e552da7Schristos backlog = SOMAXCONN;
1100e552da7Schristos #endif
1110e552da7Schristos
1120e552da7Schristos if (listen(uv__stream_fd(handle), backlog))
1130e552da7Schristos return UV__ERR(errno);
1140e552da7Schristos
1150e552da7Schristos handle->connection_cb = cb;
1160e552da7Schristos handle->io_watcher.cb = uv__server_io;
1170e552da7Schristos uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
1180e552da7Schristos return 0;
1190e552da7Schristos }
1200e552da7Schristos
1210e552da7Schristos
uv__pipe_close(uv_pipe_t * handle)1220e552da7Schristos void uv__pipe_close(uv_pipe_t* handle) {
1230e552da7Schristos if (handle->pipe_fname) {
1240e552da7Schristos /*
1250e552da7Schristos * Unlink the file system entity before closing the file descriptor.
1260e552da7Schristos * Doing it the other way around introduces a race where our process
1270e552da7Schristos * unlinks a socket with the same name that's just been created by
1280e552da7Schristos * another thread or process.
1290e552da7Schristos */
1300e552da7Schristos unlink(handle->pipe_fname);
1310e552da7Schristos uv__free((void*)handle->pipe_fname);
1320e552da7Schristos handle->pipe_fname = NULL;
1330e552da7Schristos }
1340e552da7Schristos
1350e552da7Schristos uv__stream_close((uv_stream_t*)handle);
1360e552da7Schristos }
1370e552da7Schristos
1380e552da7Schristos
uv_pipe_open(uv_pipe_t * handle,uv_file fd)1390e552da7Schristos int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
1400e552da7Schristos int flags;
1410e552da7Schristos int mode;
1420e552da7Schristos int err;
1430e552da7Schristos flags = 0;
1440e552da7Schristos
1450e552da7Schristos if (uv__fd_exists(handle->loop, fd))
1460e552da7Schristos return UV_EEXIST;
1470e552da7Schristos
1480e552da7Schristos do
1490e552da7Schristos mode = fcntl(fd, F_GETFL);
1500e552da7Schristos while (mode == -1 && errno == EINTR);
1510e552da7Schristos
1520e552da7Schristos if (mode == -1)
1530e552da7Schristos return UV__ERR(errno); /* according to docs, must be EBADF */
1540e552da7Schristos
1550e552da7Schristos err = uv__nonblock(fd, 1);
1560e552da7Schristos if (err)
1570e552da7Schristos return err;
1580e552da7Schristos
1590e552da7Schristos #if defined(__APPLE__)
1600e552da7Schristos err = uv__stream_try_select((uv_stream_t*) handle, &fd);
1610e552da7Schristos if (err)
1620e552da7Schristos return err;
1630e552da7Schristos #endif /* defined(__APPLE__) */
1640e552da7Schristos
1650e552da7Schristos mode &= O_ACCMODE;
1660e552da7Schristos if (mode != O_WRONLY)
1670e552da7Schristos flags |= UV_HANDLE_READABLE;
1680e552da7Schristos if (mode != O_RDONLY)
1690e552da7Schristos flags |= UV_HANDLE_WRITABLE;
1700e552da7Schristos
1710e552da7Schristos return uv__stream_open((uv_stream_t*)handle, fd, flags);
1720e552da7Schristos }
1730e552da7Schristos
1740e552da7Schristos
uv_pipe_connect(uv_connect_t * req,uv_pipe_t * handle,const char * name,uv_connect_cb cb)1750e552da7Schristos void uv_pipe_connect(uv_connect_t* req,
1760e552da7Schristos uv_pipe_t* handle,
1770e552da7Schristos const char* name,
1780e552da7Schristos uv_connect_cb cb) {
1790e552da7Schristos struct sockaddr_un saddr;
1800e552da7Schristos int new_sock;
1810e552da7Schristos int err;
1820e552da7Schristos int r;
1830e552da7Schristos
1840e552da7Schristos new_sock = (uv__stream_fd(handle) == -1);
1850e552da7Schristos
1860e552da7Schristos if (new_sock) {
1870e552da7Schristos err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
1880e552da7Schristos if (err < 0)
1890e552da7Schristos goto out;
1900e552da7Schristos handle->io_watcher.fd = err;
1910e552da7Schristos }
1920e552da7Schristos
1930e552da7Schristos memset(&saddr, 0, sizeof saddr);
1940e552da7Schristos uv__strscpy(saddr.sun_path, name, sizeof(saddr.sun_path));
1950e552da7Schristos saddr.sun_family = AF_UNIX;
1960e552da7Schristos
1970e552da7Schristos do {
1980e552da7Schristos r = connect(uv__stream_fd(handle),
1990e552da7Schristos (struct sockaddr*)&saddr, sizeof saddr);
2000e552da7Schristos }
2010e552da7Schristos while (r == -1 && errno == EINTR);
2020e552da7Schristos
2030e552da7Schristos if (r == -1 && errno != EINPROGRESS) {
2040e552da7Schristos err = UV__ERR(errno);
2050e552da7Schristos #if defined(__CYGWIN__) || defined(__MSYS__)
2060e552da7Schristos /* EBADF is supposed to mean that the socket fd is bad, but
2070e552da7Schristos Cygwin reports EBADF instead of ENOTSOCK when the file is
2080e552da7Schristos not a socket. We do not expect to see a bad fd here
2090e552da7Schristos (e.g. due to new_sock), so translate the error. */
2100e552da7Schristos if (err == UV_EBADF)
2110e552da7Schristos err = UV_ENOTSOCK;
2120e552da7Schristos #endif
2130e552da7Schristos goto out;
2140e552da7Schristos }
2150e552da7Schristos
2160e552da7Schristos err = 0;
2170e552da7Schristos if (new_sock) {
2180e552da7Schristos err = uv__stream_open((uv_stream_t*)handle,
2190e552da7Schristos uv__stream_fd(handle),
2200e552da7Schristos UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
2210e552da7Schristos }
2220e552da7Schristos
2230e552da7Schristos if (err == 0)
2240e552da7Schristos uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
2250e552da7Schristos
2260e552da7Schristos out:
2270e552da7Schristos handle->delayed_error = err;
2280e552da7Schristos handle->connect_req = req;
2290e552da7Schristos
2300e552da7Schristos uv__req_init(handle->loop, req, UV_CONNECT);
2310e552da7Schristos req->handle = (uv_stream_t*)handle;
2320e552da7Schristos req->cb = cb;
2330e552da7Schristos QUEUE_INIT(&req->queue);
2340e552da7Schristos
2350e552da7Schristos /* Force callback to run on next tick in case of error. */
2360e552da7Schristos if (err)
2370e552da7Schristos uv__io_feed(handle->loop, &handle->io_watcher);
2380e552da7Schristos
2390e552da7Schristos }
2400e552da7Schristos
2410e552da7Schristos
uv__pipe_getsockpeername(const uv_pipe_t * handle,uv__peersockfunc func,char * buffer,size_t * size)2420e552da7Schristos static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
2430e552da7Schristos uv__peersockfunc func,
2440e552da7Schristos char* buffer,
2450e552da7Schristos size_t* size) {
2460e552da7Schristos struct sockaddr_un sa;
2470e552da7Schristos socklen_t addrlen;
2480e552da7Schristos int err;
2490e552da7Schristos
2500e552da7Schristos addrlen = sizeof(sa);
2510e552da7Schristos memset(&sa, 0, addrlen);
2520e552da7Schristos err = uv__getsockpeername((const uv_handle_t*) handle,
2530e552da7Schristos func,
2540e552da7Schristos (struct sockaddr*) &sa,
2550e552da7Schristos (int*) &addrlen);
2560e552da7Schristos if (err < 0) {
2570e552da7Schristos *size = 0;
2580e552da7Schristos return err;
2590e552da7Schristos }
2600e552da7Schristos
2610e552da7Schristos #if defined(__linux__)
2620e552da7Schristos if (sa.sun_path[0] == 0)
2630e552da7Schristos /* Linux abstract namespace */
2640e552da7Schristos addrlen -= offsetof(struct sockaddr_un, sun_path);
2650e552da7Schristos else
2660e552da7Schristos #endif
2670e552da7Schristos addrlen = strlen(sa.sun_path);
2680e552da7Schristos
2690e552da7Schristos
2700e552da7Schristos if ((size_t)addrlen >= *size) {
2710e552da7Schristos *size = addrlen + 1;
2720e552da7Schristos return UV_ENOBUFS;
2730e552da7Schristos }
2740e552da7Schristos
2750e552da7Schristos memcpy(buffer, sa.sun_path, addrlen);
2760e552da7Schristos *size = addrlen;
2770e552da7Schristos
2780e552da7Schristos /* only null-terminate if it's not an abstract socket */
2790e552da7Schristos if (buffer[0] != '\0')
2800e552da7Schristos buffer[addrlen] = '\0';
2810e552da7Schristos
2820e552da7Schristos return 0;
2830e552da7Schristos }
2840e552da7Schristos
2850e552da7Schristos
uv_pipe_getsockname(const uv_pipe_t * handle,char * buffer,size_t * size)2860e552da7Schristos int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
2870e552da7Schristos return uv__pipe_getsockpeername(handle, getsockname, buffer, size);
2880e552da7Schristos }
2890e552da7Schristos
2900e552da7Schristos
uv_pipe_getpeername(const uv_pipe_t * handle,char * buffer,size_t * size)2910e552da7Schristos int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
2920e552da7Schristos return uv__pipe_getsockpeername(handle, getpeername, buffer, size);
2930e552da7Schristos }
2940e552da7Schristos
2950e552da7Schristos
uv_pipe_pending_instances(uv_pipe_t * handle,int count)2960e552da7Schristos void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
2970e552da7Schristos }
2980e552da7Schristos
2990e552da7Schristos
uv_pipe_pending_count(uv_pipe_t * handle)3000e552da7Schristos int uv_pipe_pending_count(uv_pipe_t* handle) {
3010e552da7Schristos uv__stream_queued_fds_t* queued_fds;
3020e552da7Schristos
3030e552da7Schristos if (!handle->ipc)
3040e552da7Schristos return 0;
3050e552da7Schristos
3060e552da7Schristos if (handle->accepted_fd == -1)
3070e552da7Schristos return 0;
3080e552da7Schristos
3090e552da7Schristos if (handle->queued_fds == NULL)
3100e552da7Schristos return 1;
3110e552da7Schristos
3120e552da7Schristos queued_fds = handle->queued_fds;
3130e552da7Schristos return queued_fds->offset + 1;
3140e552da7Schristos }
3150e552da7Schristos
3160e552da7Schristos
uv_pipe_pending_type(uv_pipe_t * handle)3170e552da7Schristos uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
3180e552da7Schristos if (!handle->ipc)
3190e552da7Schristos return UV_UNKNOWN_HANDLE;
3200e552da7Schristos
3210e552da7Schristos if (handle->accepted_fd == -1)
3220e552da7Schristos return UV_UNKNOWN_HANDLE;
3230e552da7Schristos else
324*5f2f4271Schristos return uv_guess_handle(handle->accepted_fd);
3250e552da7Schristos }
3260e552da7Schristos
3270e552da7Schristos
uv_pipe_chmod(uv_pipe_t * handle,int mode)3280e552da7Schristos int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
3290e552da7Schristos unsigned desired_mode;
3300e552da7Schristos struct stat pipe_stat;
3310e552da7Schristos char* name_buffer;
3320e552da7Schristos size_t name_len;
3330e552da7Schristos int r;
3340e552da7Schristos
3350e552da7Schristos if (handle == NULL || uv__stream_fd(handle) == -1)
3360e552da7Schristos return UV_EBADF;
3370e552da7Schristos
3380e552da7Schristos if (mode != UV_READABLE &&
3390e552da7Schristos mode != UV_WRITABLE &&
3400e552da7Schristos mode != (UV_WRITABLE | UV_READABLE))
3410e552da7Schristos return UV_EINVAL;
3420e552da7Schristos
3430e552da7Schristos /* Unfortunately fchmod does not work on all platforms, we will use chmod. */
3440e552da7Schristos name_len = 0;
3450e552da7Schristos r = uv_pipe_getsockname(handle, NULL, &name_len);
3460e552da7Schristos if (r != UV_ENOBUFS)
3470e552da7Schristos return r;
3480e552da7Schristos
3490e552da7Schristos name_buffer = uv__malloc(name_len);
3500e552da7Schristos if (name_buffer == NULL)
3510e552da7Schristos return UV_ENOMEM;
3520e552da7Schristos
3530e552da7Schristos r = uv_pipe_getsockname(handle, name_buffer, &name_len);
3540e552da7Schristos if (r != 0) {
3550e552da7Schristos uv__free(name_buffer);
3560e552da7Schristos return r;
3570e552da7Schristos }
3580e552da7Schristos
3590e552da7Schristos /* stat must be used as fstat has a bug on Darwin */
3600e552da7Schristos if (stat(name_buffer, &pipe_stat) == -1) {
3610e552da7Schristos uv__free(name_buffer);
3620e552da7Schristos return -errno;
3630e552da7Schristos }
3640e552da7Schristos
3650e552da7Schristos desired_mode = 0;
3660e552da7Schristos if (mode & UV_READABLE)
3670e552da7Schristos desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
3680e552da7Schristos if (mode & UV_WRITABLE)
3690e552da7Schristos desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
3700e552da7Schristos
3710e552da7Schristos /* Exit early if pipe already has desired mode. */
3720e552da7Schristos if ((pipe_stat.st_mode & desired_mode) == desired_mode) {
3730e552da7Schristos uv__free(name_buffer);
3740e552da7Schristos return 0;
3750e552da7Schristos }
3760e552da7Schristos
3770e552da7Schristos pipe_stat.st_mode |= desired_mode;
3780e552da7Schristos
3790e552da7Schristos r = chmod(name_buffer, pipe_stat.st_mode);
3800e552da7Schristos uv__free(name_buffer);
3810e552da7Schristos
3820e552da7Schristos return r != -1 ? 0 : UV__ERR(errno);
3830e552da7Schristos }
384*5f2f4271Schristos
385*5f2f4271Schristos
uv_pipe(uv_os_fd_t fds[2],int read_flags,int write_flags)386*5f2f4271Schristos int uv_pipe(uv_os_fd_t fds[2], int read_flags, int write_flags) {
387*5f2f4271Schristos uv_os_fd_t temp[2];
388*5f2f4271Schristos int err;
389*5f2f4271Schristos #if defined(__FreeBSD__) || defined(__linux__)
390*5f2f4271Schristos int flags = O_CLOEXEC;
391*5f2f4271Schristos
392*5f2f4271Schristos if ((read_flags & UV_NONBLOCK_PIPE) && (write_flags & UV_NONBLOCK_PIPE))
393*5f2f4271Schristos flags |= UV_FS_O_NONBLOCK;
394*5f2f4271Schristos
395*5f2f4271Schristos if (pipe2(temp, flags))
396*5f2f4271Schristos return UV__ERR(errno);
397*5f2f4271Schristos
398*5f2f4271Schristos if (flags & UV_FS_O_NONBLOCK) {
399*5f2f4271Schristos fds[0] = temp[0];
400*5f2f4271Schristos fds[1] = temp[1];
401*5f2f4271Schristos return 0;
402*5f2f4271Schristos }
403*5f2f4271Schristos #else
404*5f2f4271Schristos if (pipe(temp))
405*5f2f4271Schristos return UV__ERR(errno);
406*5f2f4271Schristos
407*5f2f4271Schristos if ((err = uv__cloexec(temp[0], 1)))
408*5f2f4271Schristos goto fail;
409*5f2f4271Schristos
410*5f2f4271Schristos if ((err = uv__cloexec(temp[1], 1)))
411*5f2f4271Schristos goto fail;
412*5f2f4271Schristos #endif
413*5f2f4271Schristos
414*5f2f4271Schristos if (read_flags & UV_NONBLOCK_PIPE)
415*5f2f4271Schristos if ((err = uv__nonblock(temp[0], 1)))
416*5f2f4271Schristos goto fail;
417*5f2f4271Schristos
418*5f2f4271Schristos if (write_flags & UV_NONBLOCK_PIPE)
419*5f2f4271Schristos if ((err = uv__nonblock(temp[1], 1)))
420*5f2f4271Schristos goto fail;
421*5f2f4271Schristos
422*5f2f4271Schristos fds[0] = temp[0];
423*5f2f4271Schristos fds[1] = temp[1];
424*5f2f4271Schristos return 0;
425*5f2f4271Schristos
426*5f2f4271Schristos fail:
427*5f2f4271Schristos uv__close(temp[0]);
428*5f2f4271Schristos uv__close(temp[1]);
429*5f2f4271Schristos return err;
430*5f2f4271Schristos }
431*5f2f4271Schristos
432*5f2f4271Schristos
uv__make_pipe(int fds[2],int flags)433*5f2f4271Schristos int uv__make_pipe(int fds[2], int flags) {
434*5f2f4271Schristos return uv_pipe(fds,
435*5f2f4271Schristos flags & UV_NONBLOCK_PIPE,
436*5f2f4271Schristos flags & UV_NONBLOCK_PIPE);
437*5f2f4271Schristos }
438