int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { WSAPROTOCOL_INFOW protocol_info; int opt_len; int err; /* Detect the address family of the socket. */ opt_len = (int) sizeof protocol_info; if (getsockopt(sock, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &protocol_info, &opt_len) == SOCKET_ERROR) { return uv_translate_sys_error(GetLastError()); } /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) { return uv_translate_sys_error(GetLastError()); } err = uv_tcp_set_socket(handle->loop, handle, sock, protocol_info.iAddressFamily, 1); if (err) { return uv_translate_sys_error(err); } return 0; }
int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info, int tcp_connection) { SOCKET socket = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_IP, socket_protocol_info, 0, WSA_FLAG_OVERLAPPED); if (socket == INVALID_SOCKET) { uv__set_sys_error(tcp->loop, WSAGetLastError()); return -1; } tcp->flags |= UV_HANDLE_BOUND; tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET; if (tcp_connection) { uv_connection_init((uv_stream_t*)tcp); } if (socket_protocol_info->iAddressFamily == AF_INET6) { tcp->flags |= UV_HANDLE_IPV6; } if (uv_tcp_set_socket(tcp->loop, tcp, socket, 1) != 0) { return -1; } tcp->loop->active_tcp_streams++; return 0; }
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { WSAPROTOCOL_INFOW protocol_info; int opt_len; int err; /* Detect the address family of the socket. */ opt_len = (int) sizeof protocol_info; if (getsockopt(sock, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &protocol_info, &opt_len) == SOCKET_ERROR) { return uv_translate_sys_error(GetLastError()); } err = uv_tcp_set_socket(handle->loop, handle, sock, protocol_info.iAddressFamily, 1); if (err) { return uv_translate_sys_error(err); } return 0; }
/* Unlike on Unix, here we don't set SO_REUSEADDR, because it doesn't just * allow binding to addresses that are in use by sockets in TIME_WAIT, it * effectively allows 'stealing' a port which is in use by another application. * * SO_EXCLUSIVEADDRUSE is also not good here because it does check all sockets, * regardless of state, so we'd get an error even if the port is in use by a * socket in TIME_WAIT state. * * See issue #1360. * */ static int uv_tcp_try_bind(uv_tcp_t* handle, const struct sockaddr* addr, unsigned int addrlen, unsigned int flags) { DWORD err; int r; if (handle->socket == INVALID_SOCKET) { SOCKET sock; /* Cannot set IPv6-only mode on non-IPv6 socket. */ if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) return ERROR_INVALID_PARAMETER; sock = socket(addr->sa_family, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { return WSAGetLastError(); } err = uv_tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0); if (err) { closesocket(sock); return err; } } #ifdef IPV6_V6ONLY if (addr->sa_family == AF_INET6) { int on; on = (flags & UV_TCP_IPV6ONLY) != 0; /* TODO: how to handle errors? This may fail if there is no ipv4 stack * available, or when run on XP/2003 which have no support for dualstack * sockets. For now we're silently ignoring the error. */ setsockopt(handle->socket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof on); } #endif r = bind(handle->socket, addr, addrlen); if (r == SOCKET_ERROR) { err = WSAGetLastError(); if (err == WSAEADDRINUSE) { /* Some errors are not to be reported until connect() or listen() */ handle->delayed_error = err; } else { return err; } } handle->flags |= UV_HANDLE_BOUND; return 0; }
int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { uv_loop_t* loop = server->loop; int rv = 0; uv_tcp_accept_t* req = server->pending_accepts; if (!req) { /* No valid connections found, so we error out. */ uv__set_sys_error(loop, WSAEWOULDBLOCK); return -1; } if (req->accept_socket == INVALID_SOCKET) { uv__set_sys_error(loop, WSAENOTCONN); return -1; } if (uv_tcp_set_socket(client->loop, client, req->accept_socket, 0) == -1) { closesocket(req->accept_socket); rv = -1; } else { uv_connection_init((uv_stream_t*) client); /* AcceptEx() implicitly binds the accepted socket. */ client->flags |= UV_HANDLE_BOUND; } /* Prepare the req to pick up a new connection */ server->pending_accepts = req->next_pending; req->next_pending = NULL; req->accept_socket = INVALID_SOCKET; if (!(server->flags & UV_HANDLE_CLOSING)) { /* Check if we're in a middle of changing the number of pending accepts. */ if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) { uv_tcp_queue_accept(server, req); } else { /* We better be switching to a single pending accept. */ assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT); server->processed_accepts++; if (server->processed_accepts >= uv_simultaneous_server_accepts) { server->processed_accepts = 0; /* * All previously queued accept requests are now processed. * We now switch to queueing just a single accept. */ uv_tcp_queue_accept(server, &server->accept_reqs[0]); server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING; server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; } } } active_tcp_streams++; return rv; }
static int uv__bind(uv_tcp_t* handle, int family, struct sockaddr* addr, int addrsize) { DWORD err; int r; int on; if (handle->socket == INVALID_SOCKET) { SOCKET sock = socket(family, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) { uv__set_sys_error(handle->loop, GetLastError()); closesocket(sock); return -1; } if (uv_tcp_set_socket(handle->loop, handle, sock, family, 0) < 0) { closesocket(sock); return -1; } if (handle->flags & UV_HANDLE_TCP_V6ONLY) { on = 1; if (setsockopt(handle->socket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&on, sizeof(on)) != 0) { closesocket(sock); return -1; } } } r = bind(handle->socket, addr, addrsize); if (r == SOCKET_ERROR) { err = WSAGetLastError(); if (err == WSAEADDRINUSE) { /* Some errors are not to be reported until connect() or listen() */ handle->bind_error = err; handle->flags |= UV_HANDLE_BIND_ERROR; } else { uv__set_sys_error(handle->loop, err); return -1; } } handle->flags |= UV_HANDLE_BOUND; return 0; }
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) { uv__set_sys_error(handle->loop, GetLastError()); return -1; } if (uv_tcp_set_socket(handle->loop, handle, sock, 0) == -1) { return -1; } return 0; }
int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, 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 UV_EINVAL; if (flags & ~0xFF) return UV_EINVAL; uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP); handle->tcp.serv.accept_reqs = NULL; handle->tcp.serv.pending_accepts = NULL; handle->socket = INVALID_SOCKET; handle->reqs_pending = 0; handle->tcp.serv.func_acceptex = NULL; handle->tcp.conn.func_connectex = NULL; handle->tcp.serv.processed_accepts = 0; handle->delayed_error = 0; /* 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) { SOCKET sock; DWORD err; sock = socket(domain, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { err = WSAGetLastError(); QUEUE_REMOVE(&handle->handle_queue); return uv_translate_sys_error(err); } err = uv_tcp_set_socket(handle->loop, handle, sock, domain, 0); if (err) { closesocket(sock); QUEUE_REMOVE(&handle->handle_queue); return uv_translate_sys_error(err); } } return 0; }
int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) { SOCKET socket = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_IP, socket_protocol_info, 0, WSA_FLAG_OVERLAPPED); if (socket == INVALID_SOCKET) { uv__set_sys_error(tcp->loop, WSAGetLastError()); return -1; } tcp->flags |= UV_HANDLE_BOUND; return uv_tcp_set_socket(tcp->loop, tcp, socket, 1); }
static int uv__bind(uv_tcp_t* handle, int domain, struct sockaddr* addr, int addrsize) { DWORD err; int r; if (handle->socket == INVALID_SOCKET) { SOCKET sock = socket(domain, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) { uv__set_sys_error(handle->loop, GetLastError()); closesocket(sock); return -1; } if (uv_tcp_set_socket(handle->loop, handle, sock, 0) == -1) { closesocket(sock); return -1; } } r = bind(handle->socket, addr, addrsize); if (r == SOCKET_ERROR) { err = WSAGetLastError(); if (err == WSAEADDRINUSE) { /* Some errors are not to be reported until connect() or listen() */ handle->bind_error = err; handle->flags |= UV_HANDLE_BIND_ERROR; } else { uv__set_sys_error(handle->loop, err); return -1; } } handle->flags |= UV_HANDLE_BOUND; return 0; }
static int uv_tcp_try_bind(uv_tcp_t* handle, const struct sockaddr* addr, unsigned int addrlen) { DWORD err; int r; if (handle->socket == INVALID_SOCKET) { SOCKET sock = socket(addr->sa_family, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { return WSAGetLastError(); } /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) { err = GetLastError(); closesocket(sock); return err; } err = uv_tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0); if (err) { closesocket(sock); return err; } } r = bind(handle->socket, addr, addrlen); if (r == SOCKET_ERROR) { err = WSAGetLastError(); if (err == WSAEADDRINUSE) { /* Some errors are not to be reported until connect() or listen() */ handle->bind_error = err; handle->flags |= UV_HANDLE_BIND_ERROR; } else { return err; } } handle->flags |= UV_HANDLE_BOUND; return 0; }
int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info, int tcp_connection) { int err; SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, socket_protocol_info, 0, WSA_FLAG_OVERLAPPED); if (socket == INVALID_SOCKET) { return WSAGetLastError(); } if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0)) { err = GetLastError(); closesocket(socket); return err; } err = uv_tcp_set_socket(tcp->loop, tcp, socket, socket_protocol_info->iAddressFamily, 1); if (err) { closesocket(socket); return err; } if (tcp_connection) { uv_connection_init((uv_stream_t*)tcp); tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } tcp->flags |= UV_HANDLE_BOUND; tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET; tcp->loop->active_tcp_streams++; return 0; }
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { WSAPROTOCOL_INFOW protocol_info; int opt_len; int err; struct sockaddr_storage saddr; int saddr_len; /* Detect the address family of the socket. */ opt_len = (int) sizeof protocol_info; if (getsockopt(sock, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &protocol_info, &opt_len) == SOCKET_ERROR) { return uv_translate_sys_error(GetLastError()); } err = uv_tcp_set_socket(handle->loop, handle, sock, protocol_info.iAddressFamily, 1); if (err) { return uv_translate_sys_error(err); } /* Support already active socket. */ saddr_len = sizeof(saddr); if (!uv_tcp_getsockname(handle, (struct sockaddr*) &saddr, &saddr_len)) { /* Socket is already bound. */ handle->flags |= UV_HANDLE_BOUND; saddr_len = sizeof(saddr); if (!uv_tcp_getpeername(handle, (struct sockaddr*) &saddr, &saddr_len)) { /* Socket is already connected. */ uv_connection_init((uv_stream_t*) handle); handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } } return 0; }
int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info, int tcp_connection) { SOCKET socket = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_IP, socket_protocol_info, 0, WSA_FLAG_OVERLAPPED); if (socket == INVALID_SOCKET) { uv__set_sys_error(tcp->loop, WSAGetLastError()); return -1; } if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0)) { uv__set_sys_error(tcp->loop, GetLastError()); closesocket(socket); return -1; } if (uv_tcp_set_socket(tcp->loop, tcp, socket, socket_protocol_info->iAddressFamily, 1) < 0) { closesocket(socket); return -1; } if (tcp_connection) { uv_connection_init((uv_stream_t*)tcp); tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } tcp->flags |= UV_HANDLE_BOUND; tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET; tcp->loop->active_tcp_streams++; return 0; }
int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { uv_loop_t* loop = server->loop; int rv = 0; uv_tcp_accept_t* req = server->pending_accepts; if (!req) { /* No valid connections found, so we error out. */ uv__set_sys_error(loop, WSAEWOULDBLOCK); return -1; } if (req->accept_socket == INVALID_SOCKET) { uv__set_sys_error(loop, WSAENOTCONN); return -1; } if (uv_tcp_set_socket(client->loop, client, req->accept_socket) == -1) { closesocket(req->accept_socket); rv = -1; } else { uv_connection_init((uv_stream_t*) client); /* AcceptEx() implicitly binds the accepted socket. */ client->flags |= UV_HANDLE_BOUND; } /* Prepare the req to pick up a new connection */ server->pending_accepts = req->next_pending; req->next_pending = NULL; req->accept_socket = INVALID_SOCKET; if (!(server->flags & UV_HANDLE_CLOSING)) { uv_tcp_queue_accept(server, req); } active_tcp_streams++; return rv; }
int uv__tcp_xfer_import(uv_tcp_t* tcp, uv__ipc_socket_xfer_type_t xfer_type, uv__ipc_socket_xfer_info_t* xfer_info) { int err; SOCKET socket; assert(xfer_type == UV__IPC_SOCKET_XFER_TCP_SERVER || xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION); socket = WSASocketW(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &xfer_info->socket_info, 0, WSA_FLAG_OVERLAPPED); if (socket == INVALID_SOCKET) { return WSAGetLastError(); } err = uv_tcp_set_socket( tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1); if (err) { closesocket(socket); return err; } tcp->delayed_error = xfer_info->delayed_error; tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET; if (xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION) { uv_connection_init((uv_stream_t*)tcp); tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } tcp->loop->active_tcp_streams++; return 0; }
static int uv__bind(uv_loop_t* loop, uv_tcp_t* handle, int domain, struct sockaddr* addr, int addrsize) { DWORD err; int r; SOCKET sock; if (handle->socket == INVALID_SOCKET) { sock = socket(domain, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { uv_set_sys_error(loop, WSAGetLastError()); return -1; } if (uv_tcp_set_socket(loop, handle, sock) == -1) { closesocket(sock); return -1; } } r = bind(handle->socket, addr, addrsize); if (r == SOCKET_ERROR) { err = WSAGetLastError(); if (err == WSAEADDRINUSE) { /* Some errors are not to be reported until connect() or listen() */ handle->bind_error = uv_new_sys_error(err); handle->flags |= UV_HANDLE_BIND_ERROR; } else { uv_set_sys_error(loop, err); return -1; } } handle->flags |= UV_HANDLE_BOUND; return 0; }
int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex, int tcp_connection) { int err; SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &socket_info_ex->socket_info, 0, WSA_FLAG_OVERLAPPED); if (socket == INVALID_SOCKET) { return WSAGetLastError(); } err = uv_tcp_set_socket(tcp->loop, tcp, socket, socket_info_ex->socket_info.iAddressFamily, 1); if (err) { closesocket(socket); return err; } if (tcp_connection) { uv_connection_init((uv_stream_t*)tcp); tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } tcp->flags |= UV_HANDLE_BOUND; tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET; tcp->delayed_error = socket_info_ex->delayed_error; tcp->loop->active_tcp_streams++; return 0; }