summaryrefslogtreecommitdiff
path: root/deps/uv/src/win/tcp.c
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2021-02-13 13:03:10 -0500
committerAntoine du Hamel <duhamelantoine1995@gmail.com>2021-02-15 23:09:54 +0100
commit78d6e62fd07ad500f84f1dad8a2509be597dcfc1 (patch)
tree7fa9f0e433f77bd1e7de52e21652fcc03e9ed215 /deps/uv/src/win/tcp.c
parent0f29587757a782973b0aeabdee255b79c30780a2 (diff)
downloadnode-new-78d6e62fd07ad500f84f1dad8a2509be597dcfc1.tar.gz
deps: upgrade to libuv 1.41.0
Notable changes: - The IBM i platform has been promoted to a Tier 2 platform. - libuv is now built with `-fno-strict-aliasing`, and recommends that projects using libuv do the same. - `uv_fs_mkdir()` now returns `UV_EINVAL` for invalid directory names on Windows. - `uv_uptime()` now returns the correct value on OpenVZ containers. - Windows 8 is the new minimum supported version of Windows. - Bind errors are now reported from `uv_tcp_connect()`. - The `uv_pipe()` function has been added. - The `uv_socketpair()` function has been added. - `uv_read_start()` error handling has been unified across Windows and Unix. PR-URL: https://github.com/nodejs/node/pull/37360 Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Diffstat (limited to 'deps/uv/src/win/tcp.c')
-rw-r--r--deps/uv/src/win/tcp.c143
1 files changed, 137 insertions, 6 deletions
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index 0dcaa97df7..517700e66d 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -800,9 +800,8 @@ static int uv_tcp_try_connect(uv_connect_t* req,
if (err)
return err;
- if (handle->delayed_error) {
- return handle->delayed_error;
- }
+ if (handle->delayed_error != 0)
+ goto out;
if (!(handle->flags & UV_HANDLE_BOUND)) {
if (addrlen == sizeof(uv_addr_ip4_any_)) {
@@ -815,8 +814,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->delayed_error != 0)
+ goto out;
}
if (!handle->tcp.conn.func_connectex) {
@@ -844,11 +843,21 @@ static int uv_tcp_try_connect(uv_connect_t* req,
NULL);
}
+out:
+
UV_REQ_INIT(req, UV_CONNECT);
req->handle = (uv_stream_t*) handle;
req->cb = cb;
memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
+ if (handle->delayed_error != 0) {
+ /* Process the req without IOCP. */
+ handle->reqs_pending++;
+ REGISTER_HANDLE_REQ(loop, handle, req);
+ uv_insert_pending_req(loop, (uv_req_t*)req);
+ return 0;
+ }
+
success = handle->tcp.conn.func_connectex(handle->socket,
(const struct sockaddr*) &converted,
addrlen,
@@ -1215,7 +1224,14 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
UNREGISTER_HANDLE_REQ(loop, handle, req);
err = 0;
- if (REQ_SUCCESS(req)) {
+ if (handle->delayed_error) {
+ /* To smooth over the differences between unixes errors that
+ * were reported synchronously on the first connect can be delayed
+ * until the next tick--which is now.
+ */
+ err = handle->delayed_error;
+ handle->delayed_error = 0;
+ } else if (REQ_SUCCESS(req)) {
if (handle->flags & UV_HANDLE_CLOSING) {
/* use UV_ECANCELED for consistency with Unix */
err = ERROR_OPERATION_ABORTED;
@@ -1571,3 +1587,118 @@ int uv__tcp_connect(uv_connect_t* req,
return 0;
}
+
+#ifndef WSA_FLAG_NO_HANDLE_INHERIT
+/* Added in Windows 7 SP1. Specify this to avoid race conditions, */
+/* but also manually clear the inherit flag in case this failed. */
+#define WSA_FLAG_NO_HANDLE_INHERIT 0x80
+#endif
+
+int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) {
+ SOCKET server = INVALID_SOCKET;
+ SOCKET client0 = INVALID_SOCKET;
+ SOCKET client1 = INVALID_SOCKET;
+ SOCKADDR_IN name;
+ LPFN_ACCEPTEX func_acceptex;
+ WSAOVERLAPPED overlap;
+ char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32];
+ int namelen;
+ int err;
+ DWORD bytes;
+ DWORD flags;
+ DWORD client0_flags = WSA_FLAG_NO_HANDLE_INHERIT;
+ DWORD client1_flags = WSA_FLAG_NO_HANDLE_INHERIT;
+
+ if (flags0 & UV_NONBLOCK_PIPE)
+ client0_flags |= WSA_FLAG_OVERLAPPED;
+ if (flags1 & UV_NONBLOCK_PIPE)
+ client1_flags |= WSA_FLAG_OVERLAPPED;
+
+ server = WSASocketW(AF_INET, type, protocol, NULL, 0,
+ WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);
+ if (server == INVALID_SOCKET)
+ goto wsaerror;
+ if (!SetHandleInformation((HANDLE) server, HANDLE_FLAG_INHERIT, 0))
+ goto error;
+ name.sin_family = AF_INET;
+ name.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ name.sin_port = 0;
+ if (bind(server, (SOCKADDR*) &name, sizeof(name)) != 0)
+ goto wsaerror;
+ if (listen(server, 1) != 0)
+ goto wsaerror;
+ namelen = sizeof(name);
+ if (getsockname(server, (SOCKADDR*) &name, &namelen) != 0)
+ goto wsaerror;
+ client0 = WSASocketW(AF_INET, type, protocol, NULL, 0, client0_flags);
+ if (client0 == INVALID_SOCKET)
+ goto wsaerror;
+ if (!SetHandleInformation((HANDLE) client0, HANDLE_FLAG_INHERIT, 0))
+ goto error;
+ if (connect(client0, (SOCKADDR*) &name, sizeof(name)) != 0)
+ goto wsaerror;
+ client1 = WSASocketW(AF_INET, type, protocol, NULL, 0, client1_flags);
+ if (client1 == INVALID_SOCKET)
+ goto wsaerror;
+ if (!SetHandleInformation((HANDLE) client1, HANDLE_FLAG_INHERIT, 0))
+ goto error;
+ if (!uv_get_acceptex_function(server, &func_acceptex)) {
+ err = WSAEAFNOSUPPORT;
+ goto cleanup;
+ }
+ memset(&overlap, 0, sizeof(overlap));
+ if (!func_acceptex(server,
+ client1,
+ accept_buffer,
+ 0,
+ sizeof(struct sockaddr_storage),
+ sizeof(struct sockaddr_storage),
+ &bytes,
+ &overlap)) {
+ err = WSAGetLastError();
+ if (err == ERROR_IO_PENDING) {
+ /* Result should complete immediately, since we already called connect,
+ * but emperically, we sometimes have to poll the kernel a couple times
+ * until it notices that. */
+ while (!WSAGetOverlappedResult(client1, &overlap, &bytes, FALSE, &flags)) {
+ err = WSAGetLastError();
+ if (err != WSA_IO_INCOMPLETE)
+ goto cleanup;
+ SwitchToThread();
+ }
+ }
+ else {
+ goto cleanup;
+ }
+ }
+ if (setsockopt(client1, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
+ (char*) &server, sizeof(server)) != 0) {
+ goto wsaerror;
+ }
+
+ closesocket(server);
+
+ fds[0] = client0;
+ fds[1] = client1;
+
+ return 0;
+
+ wsaerror:
+ err = WSAGetLastError();
+ goto cleanup;
+
+ error:
+ err = GetLastError();
+ goto cleanup;
+
+ cleanup:
+ if (server != INVALID_SOCKET)
+ closesocket(server);
+ if (client0 != INVALID_SOCKET)
+ closesocket(client0);
+ if (client1 != INVALID_SOCKET)
+ closesocket(client1);
+
+ assert(err);
+ return uv_translate_sys_error(err);
+}