ext/libuv/src/win/tcp.c in libuv-1.0.0 vs ext/libuv/src/win/tcp.c in libuv-1.0.2
- old
+ new
@@ -154,10 +154,11 @@
handle->socket = INVALID_SOCKET;
handle->reqs_pending = 0;
handle->func_acceptex = NULL;
handle->func_connectex = NULL;
handle->processed_accepts = 0;
+ handle->delayed_error = 0;
return 0;
}
@@ -233,20 +234,31 @@
loop->active_tcp_streams--;
}
}
+/* 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,
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);
@@ -289,12 +301,11 @@
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;
+ handle->delayed_error = err;
} else {
return err;
}
}
@@ -515,21 +526,23 @@
if (handle->flags & UV_HANDLE_READING) {
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)) {
err = uv_tcp_try_bind(handle,
(const struct sockaddr*) &uv_addr_ip4_any_,
sizeof(uv_addr_ip4_any_),
0);
if (err)
return err;
+ if (handle->delayed_error)
+ return handle->delayed_error;
}
if (!handle->func_acceptex) {
if (!uv_get_acceptex_function(handle->socket, &handle->func_acceptex)) {
return WSAEAFNOSUPPORT;
@@ -697,12 +710,12 @@
const struct sockaddr* bind_addr;
BOOL success;
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)) {
if (addrlen == sizeof(uv_addr_ip4_any_)) {
bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
@@ -712,10 +725,12 @@
abort();
}
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) {
if (!uv_get_connectex_function(handle->socket, &handle->func_connectex)) {
return WSAEAFNOSUPPORT;
@@ -760,12 +775,12 @@
if (!(handle->flags & UV_HANDLE_BOUND)) {
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);
if (result != 0) {
return uv_translate_sys_error(WSAGetLastError());
@@ -782,12 +797,12 @@
if (!(handle->flags & UV_HANDLE_BOUND)) {
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);
if (result != 0) {
return uv_translate_sys_error(WSAGetLastError());
@@ -808,11 +823,10 @@
uv_req_init(loop, (uv_req_t*) req);
req->type = UV_WRITE;
req->handle = (uv_stream_t*) handle;
req->cb = cb;
- memset(&req->overlapped, 0, sizeof(req->overlapped));
/* Prepare the overlapped structure. */
memset(&(req->overlapped), 0, sizeof(req->overlapped));
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
req->event_handle = CreateEvent(NULL, 0, 0, NULL);
@@ -838,11 +852,11 @@
handle->write_reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
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);
handle->write_queue_size += req->queued_bytes;
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
@@ -1008,12 +1022,16 @@
req->event_handle = NULL;
}
}
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--;
if (handle->shutdown_req != NULL &&
handle->write_reqs_pending == 0) {
@@ -1101,18 +1119,17 @@
DECREASE_PENDING_REQ_COUNT(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);
if (socket == INVALID_SOCKET) {
return WSAGetLastError();
@@ -1125,11 +1142,11 @@
}
err = uv_tcp_set_socket(tcp->loop,
tcp,
socket,
- socket_protocol_info->iAddressFamily,
+ socket_info_ex->socket_info.iAddressFamily,
1);
if (err) {
closesocket(socket);
return err;
}
@@ -1140,10 +1157,12 @@
}
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;
}
@@ -1200,16 +1219,13 @@
if (!(handle->flags & UV_HANDLE_LISTENING)) {
if (!(handle->flags & UV_HANDLE_BOUND)) {
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();
+ }
}
}
}
if (WSADuplicateSocketW(handle->socket, pid, protocol_info)) {