int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) { int domain; /* Use the lower 8 bits for the domain */ domain = flags & 0xFF; if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) return -EINVAL; if (flags & ~0xFF) return -EINVAL; uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP); /* If anything fails beyond this point we need to remove the handle from * the handle queue, since it was added by uv__handle_init in uv_stream_init. */ if (domain != AF_UNSPEC) { int err = maybe_new_socket(tcp, domain, 0); if (err) { QUEUE_REMOVE(&tcp->handle_queue); return err; } } return 0; }
int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); loop->counters.pipe_init++; handle->pipe_fname = NULL; handle->ipc = ipc; return 0; }
int uv_device_open(uv_loop_t* loop, uv_device_t* device, uv_os_fd_t fd, int flags) { int err; int stream_flags = 0; assert(device); if (flags != O_RDONLY && flags != O_WRONLY && flags != O_RDWR) { return -EINVAL; } uv__stream_init(loop, (uv_stream_t*) device, UV_DEVICE); if (flags & O_RDONLY) { stream_flags |= UV_STREAM_READABLE; } else if (flags & O_WRONLY) { stream_flags |= UV_STREAM_WRITABLE; } else if (flags & O_RDWR) { stream_flags |= UV_STREAM_READABLE | UV_STREAM_WRITABLE; } err = uv__nonblock(fd, 1); if (err) { return err; } err = uv__stream_open((uv_stream_t*) device, fd, stream_flags); if (err) { return err; } return 0; }
int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); handle->shutdown_req = NULL; handle->connect_req = NULL; handle->pipe_fname = NULL; handle->ipc = ipc; return 0; }
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { int flags; int newfd; int r; uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY); /* Reopen the file descriptor when it refers to a tty. This lets us put the * tty in non-blocking mode without affecting other processes that share it * with us. * * Example: `node | cat` - if we put our fd 0 in non-blocking mode, it also * affects fd 1 of `cat` because both file descriptors refer to the same * struct file in the kernel. When we reopen our fd 0, it points to a * different struct file, hence changing its properties doesn't affect * other processes. */ if (isatty(fd)) { newfd = open("/dev/tty", O_RDWR); if (newfd == -1) return uv__set_sys_error(loop, errno); do r = dup2(newfd, fd); while (r == -1 && (errno == EINTR || errno == EBUSY)); /* EINVAL means newfd == fd which could conceivably happen if another * thread called close(fd) between our calls to isatty() and open(). * That's a rather unlikely event but let's handle it anyway. */ if (r == -1 && errno != EINVAL) { close(newfd); return uv__set_sys_error(loop, errno); } fd = newfd; } if (readable) flags = UV_STREAM_READABLE; else flags = UV_STREAM_WRITABLE; uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*)tty, fd, flags); tty->mode = 0; return 0; }
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY); if (readable) { uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_READABLE); } else { /* Note: writable tty we set to blocking mode. */ uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_WRITABLE); tty->flags |= UV_STREAM_BLOCKING; } tty->mode = 0; return 0; }
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY); if (readable) { uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*)tty, fd, UV_READABLE); } else { /* Note: writable tty we set to blocking mode. */ uv__stream_open((uv_stream_t*)tty, fd, UV_WRITABLE); tty->blocking = 1; } loop->counters.tty_init++; tty->mode = 0; return 0; }
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY); #if defined(__APPLE__) if (uv__stream_try_select((uv_stream_t*) tty, &fd)) return -1; #endif /* defined(__APPLE__) */ if (readable) { uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_READABLE); } else { /* Note: writable tty we set to blocking mode. */ uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_WRITABLE); tty->flags |= UV_STREAM_BLOCKING; } tty->mode = 0; return 0; }
int uv_device_init(uv_loop_t* loop, uv_device_t* device, const char*path, int flags) { int fd, err; int stream_flags; if (flags != O_RDONLY && flags != O_WRONLY && flags != O_RDWR) return -EINVAL; uv__stream_init(loop, (uv_stream_t*) device, UV_DEVICE); fd = open(path, flags); if (fd < 0) return -errno; stream_flags = 0; if (flags & O_RDONLY) stream_flags |= UV_STREAM_READABLE; else if (flags & O_WRONLY) stream_flags |= UV_STREAM_WRITABLE; else if (flags & O_RDWR) stream_flags |= UV_STREAM_READABLE | UV_STREAM_WRITABLE; err = uv__nonblock(fd, 1); if (err) { close(fd); return err; } err = uv__stream_open((uv_stream_t*)device, fd, stream_flags); if (err) { close(fd); return err; } return 0; }
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) { uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP); loop->counters.tcp_init++; return 0; }
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { int flags; int newfd; int r; flags = 0; newfd = -1; uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY); /* Reopen the file descriptor when it refers to a tty. This lets us put the * tty in non-blocking mode without affecting other processes that share it * with us. * * Example: `node | cat` - if we put our fd 0 in non-blocking mode, it also * affects fd 1 of `cat` because both file descriptors refer to the same * struct file in the kernel. When we reopen our fd 0, it points to a * different struct file, hence changing its properties doesn't affect * other processes. */ if (isatty(fd)) { r = uv__open_cloexec("/dev/tty", O_RDWR); if (r < 0) { /* fallback to using blocking writes */ if (!readable) flags |= UV_STREAM_BLOCKING; goto skip; } newfd = r; r = uv__dup2_cloexec(newfd, fd); if (r < 0 && r != -EINVAL) { /* EINVAL means newfd == fd which could conceivably happen if another * thread called close(fd) between our calls to isatty() and open(). * That's a rather unlikely event but let's handle it anyway. */ uv__close(newfd); return r; } fd = newfd; } skip: #if defined(__APPLE__) r = uv__stream_try_select((uv_stream_t*) tty, &fd); if (r) { if (newfd != -1) uv__close(newfd); return r; } #endif if (readable) flags |= UV_STREAM_READABLE; else flags |= UV_STREAM_WRITABLE; if (!(flags & UV_STREAM_BLOCKING)) uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*) tty, fd, flags); tty->mode = UV_TTY_MODE_NORMAL; return 0; }
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) { uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP); return 0; }
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { uv_handle_type type; int flags; int newfd; int r; int saved_flags; char path[256]; /* File descriptors that refer to files cannot be monitored with epoll. * That restriction also applies to character devices like /dev/random * (but obviously not /dev/tty.) */ type = uv_guess_handle(fd); if (type == UV_FILE || type == UV_UNKNOWN_HANDLE) return UV_EINVAL; flags = 0; newfd = -1; /* Reopen the file descriptor when it refers to a tty. This lets us put the * tty in non-blocking mode without affecting other processes that share it * with us. * * Example: `node | cat` - if we put our fd 0 in non-blocking mode, it also * affects fd 1 of `cat` because both file descriptors refer to the same * struct file in the kernel. When we reopen our fd 0, it points to a * different struct file, hence changing its properties doesn't affect * other processes. */ if (type == UV_TTY) { /* Reopening a pty in master mode won't work either because the reopened * pty will be in slave mode (*BSD) or reopening will allocate a new * master/slave pair (Linux). Therefore check if the fd points to a * slave device. */ if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0) r = uv__open_cloexec(path, O_RDWR); else r = -1; if (r < 0) { /* fallback to using blocking writes */ if (!readable) flags |= UV_HANDLE_BLOCKING_WRITES; goto skip; } newfd = r; r = uv__dup2_cloexec(newfd, fd); if (r < 0 && r != UV_EINVAL) { /* EINVAL means newfd == fd which could conceivably happen if another * thread called close(fd) between our calls to isatty() and open(). * That's a rather unlikely event but let's handle it anyway. */ uv__close(newfd); return r; } fd = newfd; } #if defined(__APPLE__) /* Save the fd flags in case we need to restore them due to an error. */ do saved_flags = fcntl(fd, F_GETFL); while (saved_flags == -1 && errno == EINTR); if (saved_flags == -1) { if (newfd != -1) uv__close(newfd); return UV__ERR(errno); } #endif /* Pacify the compiler. */ (void) &saved_flags; skip: uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY); /* If anything fails beyond this point we need to remove the handle from * the handle queue, since it was added by uv__handle_init in uv_stream_init. */ if (!(flags & UV_HANDLE_BLOCKING_WRITES)) uv__nonblock(fd, 1); #if defined(__APPLE__) r = uv__stream_try_select((uv_stream_t*) tty, &fd); if (r) { int rc = r; if (newfd != -1) uv__close(newfd); QUEUE_REMOVE(&tty->handle_queue); do r = fcntl(fd, F_SETFL, saved_flags); while (r == -1 && errno == EINTR); return rc; } #endif if (readable) flags |= UV_HANDLE_READABLE; else flags |= UV_HANDLE_WRITABLE; uv__stream_open((uv_stream_t*) tty, fd, flags); tty->mode = UV_TTY_MODE_NORMAL; return 0; }
int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) { uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP); tcp->idle_handle = NULL; return 0; }