Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c6ccbd7

Browse filesBrowse files
panjf2000aduh95
authored andcommitted
deps: libuv: reapply 3a9a6e3e6b
Original commit message: tcp: support customizing TCP_KEEPINTVL and TCP_KEEPCNT Implement `uv_tcp_keepalive_ex` function that extends `uv_tcp_keepalive` to support `TCP_KEEPINTVL` and `TCP_KEEPCN` socket options in addition to TCP_KEEPIDLE. Refs: libuv/libuv@3a9a6e3 PR-URL: #62561 Reviewed-By: René <contact.9a5d6388@renegade334.me.uk> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
1 parent 5b9cb10 commit c6ccbd7
Copy full SHA for c6ccbd7

8 files changed

+199-59Lines changed: 199 additions & 59 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎deps/uv/docs/src/tcp.rst‎

Copy file name to clipboardExpand all lines: deps/uv/docs/src/tcp.rst
+29Lines changed: 29 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,35 @@ API
9191
9292
.. versionchanged:: 1.49.0 If `delay` is less than 1 then ``UV_EINVAL``` is returned.
9393
94+
.. c:function:: int uv_tcp_keepalive_ex(uv_tcp_t* handle, int on, unsigned int idle, unsigned int intvl, unsigned int cnt)
95+
96+
Enable / disable TCP keep-alive with all socket options: `TCP_KEEPIDLE`, `TCP_KEEPINTVL` and `TCP_KEEPCNT`.
97+
`idle` is the value for `TCP_KEEPIDLE`, `intvl` is the value for `TCP_KEEPINTVL`,
98+
`cnt` is the value for `TCP_KEEPCNT`, ignored when `on` is zero.
99+
100+
With TCP keep-alive enabled, `idle` is the time (in seconds) the connection needs to remain idle before
101+
TCP starts sending keep-alive probes. `intvl` is the time (in seconds) between individual keep-alive probes.
102+
TCP will drop the connection after sending `cnt` probes without getting any replies from the peer, then the
103+
handle is destroyed with a ``UV_ETIMEDOUT`` error passed to the corresponding callback.
104+
105+
If one of `idle`, `intvl`, or `cnt` is less than 1, ``UV_EINVAL`` is returned.
106+
107+
.. versionchanged:: 1.52.0 added support of setting `TCP_KEEPINTVL` and `TCP_KEEPCNT` socket options.
108+
109+
.. note::
110+
Ensure that the socket options are supported by the underlying operating system.
111+
Currently supported platforms:
112+
- AIX
113+
- DragonFlyBSD
114+
- FreeBSD
115+
- HP-UX
116+
- illumos
117+
- Linux
118+
- macOS
119+
- NetBSD
120+
- Solaris
121+
- Windows
122+
94123
.. c:function:: int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable)
95124
96125
Enable / disable simultaneous asynchronous accept requests that are
Collapse file

‎deps/uv/include/uv.h‎

Copy file name to clipboardExpand all lines: deps/uv/include/uv.h
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,11 @@ UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
602602
UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,
603603
int enable,
604604
unsigned int delay);
605+
UV_EXTERN int uv_tcp_keepalive_ex(uv_tcp_t* handle,
606+
int on,
607+
unsigned int idle,
608+
unsigned int intvl,
609+
unsigned int cnt);
605610
UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);
606611

607612
enum uv_tcp_flags {
Collapse file

‎deps/uv/src/unix/internal.h‎

Copy file name to clipboardExpand all lines: deps/uv/src/unix/internal.h
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,11 @@ int uv__slurp(const char* filename, char* buf, size_t len);
359359
/* tcp */
360360
int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
361361
int uv__tcp_nodelay(int fd, int on);
362-
int uv__tcp_keepalive(int fd, int on, unsigned int delay);
362+
int uv__tcp_keepalive(int fd,
363+
int on,
364+
unsigned int idle,
365+
unsigned int intvl,
366+
unsigned int cnt);
363367

364368
/* tty */
365369
void uv__tty_close(uv_tty_t* handle);
Collapse file

‎deps/uv/src/unix/stream.c‎

Copy file name to clipboardExpand all lines: deps/uv/src/unix/stream.c
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
416416

417417
/* TODO Use delay the user passed in. */
418418
if ((stream->flags & UV_HANDLE_TCP_KEEPALIVE) &&
419-
uv__tcp_keepalive(fd, 1, 60)) {
419+
uv__tcp_keepalive(fd, 1, 60, 1, 10)) {
420420
return UV__ERR(errno);
421421
}
422422
}
Collapse file

‎deps/uv/src/unix/tcp.c‎

Copy file name to clipboardExpand all lines: deps/uv/src/unix/tcp.c
+25-22Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -465,22 +465,18 @@ int uv__tcp_nodelay(int fd, int on) {
465465
#else
466466
#define UV_KEEPALIVE_FACTOR(x)
467467
#endif
468-
int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
469-
int idle;
470-
int intvl;
471-
int cnt;
472-
473-
(void) &idle;
474-
(void) &intvl;
475-
(void) &cnt;
476-
468+
int uv__tcp_keepalive(int fd,
469+
int on,
470+
unsigned int idle,
471+
unsigned int intvl,
472+
unsigned int cnt) {
477473
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
478474
return UV__ERR(errno);
479475

480476
if (!on)
481477
return 0;
482478

483-
if (delay < 1)
479+
if (idle < 1 || intvl < 1 || cnt < 1)
484480
return UV_EINVAL;
485481

486482
#ifdef __sun
@@ -506,13 +502,16 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
506502
* The TCP connection will be aborted after certain amount of probes, which is set by TCP_KEEPCNT, without receiving response.
507503
*/
508504

509-
idle = delay;
510-
/* Kernel expects at least 10 seconds. */
505+
/* Kernel expects at least 10 seconds for TCP_KEEPIDLE and TCP_KEEPINTVL. */
511506
if (idle < 10)
512507
idle = 10;
513-
/* Kernel expects at most 10 days. */
508+
if (intvl < 10)
509+
intvl = 10;
510+
/* Kernel expects at most 10 days for TCP_KEEPIDLE and TCP_KEEPINTVL. */
514511
if (idle > 10*24*60*60)
515512
idle = 10*24*60*60;
513+
if (intvl > 10*24*60*60)
514+
intvl = 10*24*60*60;
516515

517516
UV_KEEPALIVE_FACTOR(idle);
518517

@@ -522,12 +521,10 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
522521
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)))
523522
return UV__ERR(errno);
524523

525-
intvl = 10; /* required at least 10 seconds */
526524
UV_KEEPALIVE_FACTOR(intvl);
527525
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
528526
return UV__ERR(errno);
529527

530-
cnt = 1; /* 1 retry, ensure (TCP_KEEPINTVL * TCP_KEEPCNT) is 10 seconds */
531528
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
532529
return UV__ERR(errno);
533530
#else
@@ -539,15 +536,14 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
539536

540537
/* Note that the consequent probes will not be sent at equal intervals on Solaris,
541538
* but will be sent using the exponential backoff algorithm. */
542-
int time_to_abort = 10; /* 10 seconds */
539+
unsigned int time_to_abort = intvl * cnt;
543540
UV_KEEPALIVE_FACTOR(time_to_abort);
544541
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, &time_to_abort, sizeof(time_to_abort)))
545542
return UV__ERR(errno);
546543
#endif
547544

548545
#else /* !defined(__sun) */
549546

550-
idle = delay;
551547
UV_KEEPALIVE_FACTOR(idle);
552548
#ifdef TCP_KEEPIDLE
553549
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)))
@@ -559,14 +555,12 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
559555
#endif
560556

561557
#ifdef TCP_KEEPINTVL
562-
intvl = 1; /* 1 second; same as default on Win32 */
563558
UV_KEEPALIVE_FACTOR(intvl);
564559
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
565560
return UV__ERR(errno);
566561
#endif
567562

568563
#ifdef TCP_KEEPCNT
569-
cnt = 10; /* 10 retries; same as hardcoded on Win32 */
570564
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
571565
return UV__ERR(errno);
572566
#endif
@@ -594,11 +588,20 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
594588
}
595589

596590

597-
int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
591+
int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int idle) {
592+
return uv_tcp_keepalive_ex(handle, on, idle, 1, 10);
593+
}
594+
595+
596+
int uv_tcp_keepalive_ex(uv_tcp_t* handle,
597+
int on,
598+
unsigned int idle,
599+
unsigned int intvl,
600+
unsigned int cnt) {
598601
int err;
599602

600603
if (uv__stream_fd(handle) != -1) {
601-
err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay);
604+
err = uv__tcp_keepalive(uv__stream_fd(handle), on, idle, intvl, cnt);
602605
if (err)
603606
return err;
604607
}
@@ -608,7 +611,7 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
608611
else
609612
handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
610613

611-
/* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
614+
/* TODO Store idle if uv__stream_fd(handle) == -1 but don't want to enlarge
612615
* uv_tcp_t with an int that's almost never used...
613616
*/
614617

Collapse file

‎deps/uv/src/win/tcp.c‎

Copy file name to clipboardExpand all lines: deps/uv/src/win/tcp.c
+95-31Lines changed: 95 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -49,29 +49,99 @@ static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) {
4949
}
5050

5151

52-
static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) {
52+
/*
53+
* Check if Windows version is 10.0.16299 (Windows 10, version 1709) or later.
54+
*/
55+
static int minimal_windows10_version1709(void) {
56+
OSVERSIONINFOW os_info;
57+
if (!pRtlGetVersion)
58+
return 0;
59+
pRtlGetVersion(&os_info);
60+
if (os_info.dwMajorVersion < 10)
61+
return 0;
62+
if (os_info.dwMajorVersion > 10)
63+
return 1;
64+
if (os_info.dwMinorVersion > 0)
65+
return 1;
66+
return os_info.dwBuildNumber >= 16299;
67+
}
68+
69+
70+
static int uv__tcp_keepalive(uv_tcp_t* handle,
71+
SOCKET socket,
72+
int on,
73+
unsigned int idle,
74+
unsigned int intvl,
75+
unsigned int cnt) {
5376
if (setsockopt(socket,
5477
SOL_SOCKET,
5578
SO_KEEPALIVE,
56-
(const char*)&enable,
57-
sizeof enable) == -1) {
79+
(const char*)&on,
80+
sizeof on) == -1) {
5881
return WSAGetLastError();
5982
}
6083

61-
if (!enable)
84+
if (!on)
6285
return 0;
6386

64-
if (delay < 1)
87+
if (idle < 1 || intvl < 1 || cnt < 1)
6588
return UV_EINVAL;
6689

67-
if (setsockopt(socket,
68-
IPPROTO_TCP,
69-
TCP_KEEPALIVE,
70-
(const char*)&delay,
71-
sizeof delay) == -1) {
72-
return WSAGetLastError();
90+
/* Windows 10, version 1709 (build 10.0.16299) and later require second units
91+
* for TCP keepalive options. */
92+
if (minimal_windows10_version1709()) {
93+
if (setsockopt(socket,
94+
IPPROTO_TCP,
95+
TCP_KEEPIDLE,
96+
(const char*)&idle,
97+
sizeof idle) == -1) {
98+
return WSAGetLastError();
99+
}
100+
101+
if (setsockopt(socket,
102+
IPPROTO_TCP,
103+
TCP_KEEPINTVL,
104+
(const char*)&intvl,
105+
sizeof intvl) == -1) {
106+
return WSAGetLastError();
107+
}
108+
109+
if (setsockopt(socket,
110+
IPPROTO_TCP,
111+
TCP_KEEPCNT,
112+
(const char*)&cnt,
113+
sizeof cnt) == -1) {
114+
return WSAGetLastError();
115+
}
116+
117+
return 0;
73118
}
74119

120+
/* For those versions prior to Windows 10 version 1709,
121+
* we fall back to SIO_KEEPALIVE_VALS that expects millisecond units.
122+
* The SIO_KEEPALIVE_VALS IOCTL is supported on Windows 2000
123+
* and later versions of the operating system. */
124+
struct tcp_keepalive keepalive;
125+
keepalive.onoff = on;
126+
keepalive.keepalivetime = idle * 1000;
127+
keepalive.keepaliveinterval = intvl * 1000;
128+
/* On Windows Vista and later, the number of keep-alive probes
129+
* (data retransmissions) is set to 10 and cannot be changed.
130+
* On Windows Server 2003, Windows XP, and Windows 2000, the default setting
131+
* for number of keep-alive probes is 5 and cannot be changed programmatically.
132+
*/
133+
DWORD dummy;
134+
if (WSAIoctl(socket,
135+
SIO_KEEPALIVE_VALS,
136+
(LPVOID) &keepalive,
137+
sizeof keepalive,
138+
NULL,
139+
0,
140+
&dummy,
141+
NULL,
142+
NULL) == -1)
143+
return WSAGetLastError();
144+
75145
return 0;
76146
}
77147

@@ -132,7 +202,7 @@ static int uv__tcp_set_socket(uv_loop_t* loop,
132202

133203
/* TODO: Use stored delay. */
134204
if (handle->flags & UV_HANDLE_TCP_KEEPALIVE) {
135-
err = uv__tcp_keepalive(handle, socket, 1, 60);
205+
err = uv__tcp_keepalive(handle, socket, 1, 60, 1, 10);
136206
if (err)
137207
return err;
138208
}
@@ -749,20 +819,6 @@ static int uv__is_loopback(const struct sockaddr_storage* storage) {
749819
return 0;
750820
}
751821

752-
// Check if Windows version is 10.0.16299 or later
753-
static int uv__is_fast_loopback_fail_supported(void) {
754-
OSVERSIONINFOW os_info;
755-
if (!pRtlGetVersion)
756-
return 0;
757-
pRtlGetVersion(&os_info);
758-
if (os_info.dwMajorVersion < 10)
759-
return 0;
760-
if (os_info.dwMajorVersion > 10)
761-
return 1;
762-
if (os_info.dwMinorVersion > 0)
763-
return 1;
764-
return os_info.dwBuildNumber >= 16299;
765-
}
766822

767823
static int uv__tcp_try_connect(uv_connect_t* req,
768824
uv_tcp_t* handle,
@@ -809,7 +865,7 @@ static int uv__tcp_try_connect(uv_connect_t* req,
809865
* is not reachable, instead of waiting for 2s. We do not care if this fails.
810866
* This only works on Windows version 10.0.16299 and later.
811867
*/
812-
if (uv__is_fast_loopback_fail_supported() && uv__is_loopback(&converted)) {
868+
if (minimal_windows10_version1709() && uv__is_loopback(&converted)) {
813869
memset(&retransmit_ioctl, 0, sizeof(retransmit_ioctl));
814870
retransmit_ioctl.Rtt = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;
815871
retransmit_ioctl.MaxSynRetransmissions = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;
@@ -1335,22 +1391,30 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int enable) {
13351391
}
13361392

13371393

1338-
int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
1394+
int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int idle) {
1395+
return uv_tcp_keepalive_ex(handle, on, idle, 1, 10);
1396+
}
1397+
1398+
int uv_tcp_keepalive_ex(uv_tcp_t* handle,
1399+
int on,
1400+
unsigned int idle,
1401+
unsigned int intvl,
1402+
unsigned int cnt) {
13391403
int err;
13401404

13411405
if (handle->socket != INVALID_SOCKET) {
1342-
err = uv__tcp_keepalive(handle, handle->socket, enable, delay);
1406+
err = uv__tcp_keepalive(handle, handle->socket, on, idle, intvl, cnt);
13431407
if (err)
13441408
return uv_translate_sys_error(err);
13451409
}
13461410

1347-
if (enable) {
1411+
if (on) {
13481412
handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
13491413
} else {
13501414
handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
13511415
}
13521416

1353-
/* TODO: Store delay if handle->socket isn't created yet. */
1417+
/* TODO: Store idle if handle->socket isn't created yet. */
13541418

13551419
return 0;
13561420
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.