int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { int err; if (handle->socket != INVALID_SOCKET) { err = uv__tcp_keepalive(handle, handle->socket, enable, delay); if (err) return err; } if (enable) { handle->flags |= UV_HANDLE_TCP_KEEPALIVE; } else { handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE; } /* TODO: Store delay if handle->socket isn't created yet. */ return 0; }
int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) { int err; if (uv__stream_fd(handle) != -1) { err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay); if (err) return err; } if (on) handle->flags |= UV_TCP_KEEPALIVE; else handle->flags &= ~UV_TCP_KEEPALIVE; /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge * uv_tcp_t with an int that's almost never used... */ return 0; }
int uv__stream_open(uv_stream_t* stream, int fd, int flags) { socklen_t yes; assert(fd >= 0); stream->fd = fd; stream->flags |= flags; if (stream->type == UV_TCP) { /* Reuse the port address if applicable. */ yes = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1) { uv__set_sys_error(stream->loop, errno); return -1; } if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay((uv_tcp_t*)stream, 1)) { return -1; } /* TODO Use delay the user passed in. */ if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive((uv_tcp_t*)stream, 1, 60)) { return -1; } } #if defined(__APPLE__) if (uv__stream_try_select(stream, fd) == 0) { /* Use fake fd */ fd = ((uv__stream_select_t*) stream->select)->fake_fd; } #endif /* defined(__APPLE__) */ /* Associate the fd with each watcher. */ uv__io_set(&stream->read_watcher, uv__stream_io, fd, UV__IO_READ); uv__io_set(&stream->write_watcher, uv__stream_io, fd, UV__IO_WRITE); return 0; }
int uv__stream_open(uv_stream_t* stream, int fd, int flags) { socklen_t yes; assert(fd >= 0); stream->fd = fd; stream->flags |= flags; if (stream->type == UV_TCP) { /* Reuse the port address if applicable. */ yes = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1) { uv__set_sys_error(stream->loop, errno); return -1; } if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay((uv_tcp_t*)stream, 1)) { return -1; } /* TODO Use delay the user passed in. */ if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive((uv_tcp_t*)stream, 1, 60)) { return -1; } } /* Associate the fd with each ev_io watcher. */ ev_io_set(&stream->read_watcher, fd, EV_READ); ev_io_set(&stream->write_watcher, fd, EV_WRITE); /* These should have been set up by uv_tcp_init or uv_pipe_init. */ assert(stream->read_watcher.cb == uv__stream_io); assert(stream->write_watcher.cb == uv__stream_io); return 0; }
static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, SOCKET socket, int family, int imported) { DWORD yes = 1; int non_ifs_lsp; int err; assert(handle->socket == INVALID_SOCKET); /* Set the socket to nonblocking mode */ if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { return WSAGetLastError(); } /* Associate it with the I/O completion port. */ /* Use uv_handle_t pointer as completion key. */ if (CreateIoCompletionPort((HANDLE)socket, loop->iocp, (ULONG_PTR)socket, 0) == NULL) { if (imported) { handle->flags |= UV_HANDLE_EMULATE_IOCP; } else { return GetLastError(); } } if (family == AF_INET6) { non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv6; } else { non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4; } if (pSetFileCompletionNotificationModes && !(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) { if (pSetFileCompletionNotificationModes((HANDLE) socket, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; } else if (GetLastError() != ERROR_INVALID_FUNCTION) { return GetLastError(); } } if (handle->flags & UV_HANDLE_TCP_NODELAY) { err = uv__tcp_nodelay(handle, socket, 1); if (err) return err; } /* TODO: Use stored delay. */ if (handle->flags & UV_HANDLE_TCP_KEEPALIVE) { err = uv__tcp_keepalive(handle, socket, 1, 60); if (err) return err; } handle->socket = socket; if (family == AF_INET6) { handle->flags |= UV_HANDLE_IPV6; } else { assert(!(handle->flags & UV_HANDLE_IPV6)); } return 0; }
static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, SOCKET socket, int imported) { DWORD yes = 1; int non_ifs_lsp; assert(handle->socket == INVALID_SOCKET); /* Set the socket to nonblocking mode */ if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { uv__set_sys_error(loop, WSAGetLastError()); return -1; } /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) { uv__set_sys_error(loop, GetLastError()); return -1; } /* Associate it with the I/O completion port. */ /* Use uv_handle_t pointer as completion key. */ if (CreateIoCompletionPort((HANDLE)socket, loop->iocp, (ULONG_PTR)socket, 0) == NULL) { if (imported) { handle->flags |= UV_HANDLE_EMULATE_IOCP; } else { uv__set_sys_error(loop, GetLastError()); return -1; } } non_ifs_lsp = (handle->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 : uv_tcp_non_ifs_lsp_ipv4; if (pSetFileCompletionNotificationModes && !non_ifs_lsp) { if (pSetFileCompletionNotificationModes((HANDLE) socket, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; } else if (GetLastError() != ERROR_INVALID_FUNCTION) { uv__set_sys_error(loop, GetLastError()); return -1; } } if ((handle->flags & UV_HANDLE_TCP_NODELAY) && uv__tcp_nodelay(handle, socket, 1)) { return -1; } /* TODO: Use stored delay. */ if ((handle->flags & UV_HANDLE_TCP_KEEPALIVE) && uv__tcp_keepalive(handle, socket, 1, 60)) { return -1; } handle->socket = socket; return 0; }