win/tcp: make uv_tcp_set_socket set UV_HANDLE_IPV6
This makes uv_tcp_set_socket responsible for setting the UV_HANDLE_IPV6 flag. This fixes a couple of situations where the the fact that a socket is an IPv6 socket is not taken into account when deciding whether a call to SetFileCompletionNotificationModes is appropriate. It also fixes the issue that uv_tcp_open would never set this flag at all.
This commit is contained in:
parent
cfe14452ae
commit
40c60cfc54
@ -81,7 +81,7 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign
|
||||
|
||||
|
||||
static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
SOCKET socket, int imported) {
|
||||
SOCKET socket, int family, int imported) {
|
||||
DWORD yes = 1;
|
||||
int non_ifs_lsp;
|
||||
|
||||
@ -107,8 +107,11 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
}
|
||||
}
|
||||
|
||||
non_ifs_lsp = (handle->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
|
||||
uv_tcp_non_ifs_lsp_ipv4;
|
||||
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 && !non_ifs_lsp) {
|
||||
if (pSetFileCompletionNotificationModes((HANDLE) socket,
|
||||
@ -134,6 +137,12 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
|
||||
handle->socket = socket;
|
||||
|
||||
if (family == AF_INET6) {
|
||||
handle->flags |= UV_HANDLE_IPV6;
|
||||
} else {
|
||||
assert(!(handle->flags & UV_HANDLE_IPV6));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -230,14 +239,14 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
|
||||
|
||||
static int uv__bind(uv_tcp_t* handle,
|
||||
int domain,
|
||||
int family,
|
||||
struct sockaddr* addr,
|
||||
int addrsize) {
|
||||
DWORD err;
|
||||
int r;
|
||||
|
||||
if (handle->socket == INVALID_SOCKET) {
|
||||
SOCKET sock = socket(domain, SOCK_STREAM, 0);
|
||||
SOCKET sock = socket(family, SOCK_STREAM, 0);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
uv__set_sys_error(handle->loop, WSAGetLastError());
|
||||
return -1;
|
||||
@ -250,7 +259,7 @@ static int uv__bind(uv_tcp_t* handle,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uv_tcp_set_socket(handle->loop, handle, sock, 0) == -1) {
|
||||
if (uv_tcp_set_socket(handle->loop, handle, sock, family, 0) < 0) {
|
||||
closesocket(sock);
|
||||
return -1;
|
||||
}
|
||||
@ -285,17 +294,10 @@ int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) {
|
||||
|
||||
|
||||
int uv__tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) {
|
||||
if (uv_allow_ipv6) {
|
||||
handle->flags |= UV_HANDLE_IPV6;
|
||||
return uv__bind(handle,
|
||||
AF_INET6,
|
||||
(struct sockaddr*)&addr,
|
||||
sizeof(struct sockaddr_in6));
|
||||
|
||||
} else {
|
||||
uv__set_sys_error(handle->loop, WSAEAFNOSUPPORT);
|
||||
return -1;
|
||||
}
|
||||
return uv__bind(handle,
|
||||
AF_INET6,
|
||||
(struct sockaddr*)&addr,
|
||||
sizeof(struct sockaddr_in6));
|
||||
}
|
||||
|
||||
|
||||
@ -584,6 +586,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
|
||||
int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
|
||||
uv_loop_t* loop = server->loop;
|
||||
int rv = 0;
|
||||
int family;
|
||||
|
||||
uv_tcp_accept_t* req = server->pending_accepts;
|
||||
|
||||
@ -598,7 +601,17 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uv_tcp_set_socket(client->loop, client, req->accept_socket, 0) == -1) {
|
||||
if (server->flags & UV_HANDLE_IPV6) {
|
||||
family = AF_INET6;
|
||||
} else {
|
||||
family = AF_INET;
|
||||
}
|
||||
|
||||
if (uv_tcp_set_socket(client->loop,
|
||||
client,
|
||||
req->accept_socket,
|
||||
family,
|
||||
0) < 0) {
|
||||
closesocket(req->accept_socket);
|
||||
rv = -1;
|
||||
} else {
|
||||
@ -1148,7 +1161,11 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uv_tcp_set_socket(tcp->loop, tcp, socket, 1) != 0) {
|
||||
if (uv_tcp_set_socket(tcp->loop,
|
||||
tcp,
|
||||
socket,
|
||||
socket_protocol_info->iAddressFamily,
|
||||
1) < 0) {
|
||||
closesocket(socket);
|
||||
return -1;
|
||||
}
|
||||
@ -1161,10 +1178,6 @@ 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;
|
||||
|
||||
if (socket_protocol_info->iAddressFamily == AF_INET6) {
|
||||
tcp->flags |= UV_HANDLE_IPV6;
|
||||
}
|
||||
|
||||
tcp->loop->active_tcp_streams++;
|
||||
return 0;
|
||||
}
|
||||
@ -1381,13 +1394,31 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
|
||||
|
||||
|
||||
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
|
||||
WSAPROTOCOL_INFOW protocol_info;
|
||||
int opt_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) {
|
||||
uv__set_sys_error(handle->loop, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
if (uv_tcp_set_socket(handle->loop,
|
||||
handle,
|
||||
sock,
|
||||
protocol_info.iAddressFamily,
|
||||
1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user