diff options
Diffstat (limited to 'deps/uv/src/win/tcp.c')
-rw-r--r-- | deps/uv/src/win/tcp.c | 65 |
1 files changed, 41 insertions, 24 deletions
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index ccd7a11e2c..a213ad63e7 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -156,6 +156,7 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) { handle->func_acceptex = NULL; handle->func_connectex = NULL; handle->processed_accepts = 0; + handle->delayed_error = 0; return 0; } @@ -235,6 +236,17 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { } +/* 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 cehck 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, @@ -291,8 +303,7 @@ static int uv_tcp_try_bind(uv_tcp_t* handle, 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; + handle->delayed_error = err; } else { return err; } @@ -517,8 +528,8 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { return WSAEISCONN; } - if (handle->flags & UV_HANDLE_BIND_ERROR) { - return handle->bind_error; + if (handle->delayed_error) { + return handle->delayed_error; } if (!(handle->flags & UV_HANDLE_BOUND)) { @@ -528,6 +539,8 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { 0); if (err) return err; + if (handle->delayed_error) + return handle->delayed_error; } if (!handle->func_acceptex) { @@ -699,8 +712,8 @@ static int uv_tcp_try_connect(uv_connect_t* req, DWORD bytes; int err; - if (handle->flags & UV_HANDLE_BIND_ERROR) { - return handle->bind_error; + if (handle->delayed_error) { + return handle->delayed_error; } if (!(handle->flags & UV_HANDLE_BOUND)) { @@ -714,6 +727,8 @@ static int uv_tcp_try_connect(uv_connect_t* req, err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0); if (err) return err; + if (handle->delayed_error) + return handle->delayed_error; } if (!handle->func_connectex) { @@ -762,8 +777,8 @@ int uv_tcp_getsockname(const uv_tcp_t* handle, return UV_EINVAL; } - if (handle->flags & UV_HANDLE_BIND_ERROR) { - return uv_translate_sys_error(handle->bind_error); + if (handle->delayed_error) { + return uv_translate_sys_error(handle->delayed_error); } result = getsockname(handle->socket, name, namelen); @@ -784,8 +799,8 @@ int uv_tcp_getpeername(const uv_tcp_t* handle, return UV_EINVAL; } - if (handle->flags & UV_HANDLE_BIND_ERROR) { - return uv_translate_sys_error(handle->bind_error); + if (handle->delayed_error) { + return uv_translate_sys_error(handle->delayed_error); } result = getpeername(handle->socket, name, namelen); @@ -839,7 +854,7 @@ int uv_tcp_write(uv_loop_t* loop, uv_insert_pending_req(loop, (uv_req_t*) req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* Request queued by the kernel. */ - req->queued_bytes = uv_count_bufs(bufs, nbufs); + req->queued_bytes = uv__count_bufs(bufs, nbufs); handle->reqs_pending++; handle->write_reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); @@ -1009,8 +1024,12 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, } if (req->cb) { - err = GET_REQ_SOCK_ERROR(req); - req->cb(req, uv_translate_sys_error(err)); + err = uv_translate_sys_error(GET_REQ_SOCK_ERROR(req)); + if (err == UV_ECONNABORTED) { + /* use UV_ECANCELED for consistency with Unix */ + err = UV_ECANCELED; + } + req->cb(req, err); } handle->write_reqs_pending--; @@ -1102,14 +1121,13 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, } -int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info, +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_protocol_info, + &socket_info_ex->socket_info, 0, WSA_FLAG_OVERLAPPED); @@ -1126,7 +1144,7 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info, err = uv_tcp_set_socket(tcp->loop, tcp, socket, - socket_protocol_info->iAddressFamily, + socket_info_ex->socket_info.iAddressFamily, 1); if (err) { closesocket(socket); @@ -1141,6 +1159,8 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info, 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; } @@ -1201,13 +1221,10 @@ int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, return ERROR_INVALID_PARAMETER; } - /* Report any deferred bind errors now. */ - if (handle->flags & UV_HANDLE_BIND_ERROR) { - return handle->bind_error; - } - - if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { - return WSAGetLastError(); + if (!(handle->delayed_error)) { + if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { + handle->delayed_error = WSAGetLastError(); + } } } } |