mirror of
https://github.com/libevent/libevent.git
synced 2025-01-09 00:56:20 +08:00
Optimize preprocessor directives on Solaris for evutil_set_tcp_keepalive (#1536)
Changes: - Optimize preprocessor directives on Solaris for evutil_set_tcp_keepalive - Reduce the amount of code being compiled and trim trailing whitespace in passing. - Move comments for Solaris under its macro - Refactor the control flow
This commit is contained in:
parent
76460fbe66
commit
9d4853b363
80
evutil.c
80
evutil.c
@ -438,7 +438,7 @@ evutil_ersatz_socketpair_(int family, int type, int protocol,
|
||||
ev_socklen_t size;
|
||||
int saved_errno = -1;
|
||||
int family_test;
|
||||
|
||||
|
||||
family_test = family != AF_INET;
|
||||
#ifdef AF_UNIX
|
||||
family_test = family_test && (family != AF_UNIX);
|
||||
@ -447,7 +447,7 @@ evutil_ersatz_socketpair_(int family, int type, int protocol,
|
||||
EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (!fd) {
|
||||
EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL));
|
||||
return -1;
|
||||
@ -625,9 +625,9 @@ evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock)
|
||||
int one = 1;
|
||||
|
||||
/* TCP_DEFER_ACCEPT tells the kernel to call defer accept() only after data
|
||||
* has arrived and ready to read */
|
||||
* has arrived and ready to read */
|
||||
return setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &one,
|
||||
(ev_socklen_t)sizeof(one));
|
||||
(ev_socklen_t)sizeof(one));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -3043,80 +3043,80 @@ evutil_set_tcp_keepalive(evutil_socket_t fd, int on, int timeout)
|
||||
(void) intvl;
|
||||
(void) cnt;
|
||||
|
||||
if (timeout <= 0)
|
||||
if (timeout <= 0)
|
||||
return 0;
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
|
||||
return -1;
|
||||
if (!on)
|
||||
if (!on)
|
||||
return 0;
|
||||
|
||||
/* Unlike Unix-like OS's, TCP keep-alive mechanism on Windows is kind of a mess,
|
||||
/* Unlike Unix-like OS's, TCP keep-alive mechanism on Windows is kind of a mess,
|
||||
* setting TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT on Windows could be a bit tricky.
|
||||
* Check out https://learn.microsoft.com/en-us/windows/win32/winsock/sio-keepalive-vals,
|
||||
* https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options.
|
||||
* These three options are not available until Windows 10, version 1709 where we set them
|
||||
* by `setsockopt` (slightly different from Unix-like OS's pattern), while on older Windows,
|
||||
* by `setsockopt` (slightly different from Unix-like OS's pattern), while on older Windows,
|
||||
* we have to use `WSAIoctl` instead.
|
||||
* Therefore, we skip setting those three options on Windows for now.
|
||||
* TODO(panjf2000): enable the full TCP keep-alive mechanism on Windows when we find a feasible way to do it.
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
|
||||
/* The implementation of TCP keep-alive on Solaris/SmartOS is a bit unusual
|
||||
* compared to other Unix-like systems.
|
||||
* Thus, we need to specialize it on Solaris.
|
||||
*/
|
||||
#ifdef __sun
|
||||
/* There are two keep-alive mechanisms on Solaris:
|
||||
* - By default, the first keep-alive probe is sent out after a TCP connection is idle for two hours.
|
||||
* If the peer does not respond to the probe within eight minutes, the TCP connection is aborted.
|
||||
* You can alter the interval for sending out the first probe using the socket option TCP_KEEPALIVE_THRESHOLD
|
||||
/* The implementation of TCP keep-alive on Solaris/SmartOS is a bit unusual
|
||||
* compared to other Unix-like systems.
|
||||
* Thus, we need to specialize it on Solaris.
|
||||
*
|
||||
* There are two keep-alive mechanisms on Solaris:
|
||||
* - By default, the first keep-alive probe is sent out after a TCP connection is idle for two hours.
|
||||
* If the peer does not respond to the probe within eight minutes, the TCP connection is aborted.
|
||||
* You can alter the interval for sending out the first probe using the socket option TCP_KEEPALIVE_THRESHOLD
|
||||
* in milliseconds or TCP_KEEPIDLE in seconds.
|
||||
* The system default is controlled by the TCP ndd parameter tcp_keepalive_interval. The minimum value is ten seconds.
|
||||
* The maximum is ten days, while the default is two hours. If you receive no response to the probe,
|
||||
* The system default is controlled by the TCP ndd parameter tcp_keepalive_interval. The minimum value is ten seconds.
|
||||
* The maximum is ten days, while the default is two hours. If you receive no response to the probe,
|
||||
* you can use the TCP_KEEPALIVE_ABORT_THRESHOLD socket option to change the time threshold for aborting a TCP connection.
|
||||
* The option value is an unsigned integer in milliseconds. The value zero indicates that TCP should never time out and
|
||||
* abort the connection when probing. The system default is controlled by the TCP ndd parameter tcp_keepalive_abort_interval.
|
||||
* The option value is an unsigned integer in milliseconds. The value zero indicates that TCP should never time out and
|
||||
* abort the connection when probing. The system default is controlled by the TCP ndd parameter tcp_keepalive_abort_interval.
|
||||
* The default is eight minutes.
|
||||
*
|
||||
* - The second implementation is activated if socket option TCP_KEEPINTVL and/or TCP_KEEPCNT are set.
|
||||
* The time between each consequent probes is set by TCP_KEEPINTVL in seconds.
|
||||
* The minimum value is ten seconds. The maximum is ten days, while the default is two hours.
|
||||
* - The second implementation is activated if socket option TCP_KEEPINTVL and/or TCP_KEEPCNT are set.
|
||||
* The time between each consequent probes is set by TCP_KEEPINTVL in seconds.
|
||||
* The minimum value is ten seconds. The maximum is ten days, while the default is two hours.
|
||||
* The TCP connection will be aborted after certain amount of probes, which is set by TCP_KEEPCNT, without receiving response.
|
||||
*/
|
||||
|
||||
idle = timeout;
|
||||
/* Kernel expects at least 10 seconds. */
|
||||
if (idle < 10)
|
||||
if (idle < 10)
|
||||
idle = 10;
|
||||
/* Kernel expects at most 10 days. */
|
||||
if (idle > 10*24*60*60)
|
||||
idle = 10*24*60*60;
|
||||
|
||||
/* `TCP_KEEPIDLE`, `TCP_KEEPINTVL`, and `TCP_KEEPCNT` were not available on Solaris
|
||||
if (idle > 10*24*60*60)
|
||||
idle = 10*24*60*60;
|
||||
|
||||
/* `TCP_KEEPIDLE`, `TCP_KEEPINTVL`, and `TCP_KEEPCNT` were not available on Solaris
|
||||
* until version 11.4, but let's gamble here.
|
||||
*/
|
||||
#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT)
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)))
|
||||
return -1;
|
||||
|
||||
intvl = idle/3;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
|
||||
return -1;
|
||||
|
||||
cnt = 3;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
|
||||
return -1;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/* Fall back to the first implementation of tcp-alive mechanism for older Solaris,
|
||||
#else
|
||||
/* Fall back to the first implementation of tcp-alive mechanism for older Solaris,
|
||||
* simulate the tcp-alive mechanism on other platforms via `TCP_KEEPALIVE_THRESHOLD` + `TCP_KEEPALIVE_ABORT_THRESHOLD`.
|
||||
*/
|
||||
idle *= 1000; /* kernel expects milliseconds */
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD, &idle, sizeof(idle)))
|
||||
return -1;
|
||||
|
||||
/* Note that the consequent probes will not be sent at equal intervals on Solaris,
|
||||
/* Note that the consequent probes will not be sent at equal intervals on Solaris,
|
||||
* but will be sent using the exponential backoff algorithm.
|
||||
*/
|
||||
intvl = idle/3;
|
||||
@ -3124,10 +3124,10 @@ evutil_set_tcp_keepalive(evutil_socket_t fd, int on, int timeout)
|
||||
int time_to_abort = intvl * cnt;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, &time_to_abort, sizeof(time_to_abort)))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#else /* !__sun */
|
||||
|
||||
#ifdef TCP_KEEPIDLE
|
||||
idle = timeout;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)))
|
||||
@ -3140,12 +3140,12 @@ evutil_set_tcp_keepalive(evutil_socket_t fd, int on, int timeout)
|
||||
#endif
|
||||
|
||||
#ifdef TCP_KEEPINTVL
|
||||
/* Set the interval between individual keep-alive probes as timeout / 3
|
||||
* and the maximum number of keepalive probes as 3 to make it double timeout
|
||||
* before aborting a dead connection.
|
||||
/* Set the interval between individual keep-alive probes as timeout / 3
|
||||
* and the maximum number of keepalive probes as 3 to make it double timeout
|
||||
* before aborting a dead connection.
|
||||
*/
|
||||
intvl = timeout/3;
|
||||
if (intvl == 0)
|
||||
if (intvl == 0)
|
||||
intvl = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
|
||||
return -1;
|
||||
@ -3160,6 +3160,8 @@ evutil_set_tcp_keepalive(evutil_socket_t fd, int on, int timeout)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#endif /* !__sun */
|
||||
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
return 0;
|
||||
|
@ -473,7 +473,7 @@ int evutil_closesocket(evutil_socket_t sock);
|
||||
|
||||
/** Do platform-specific operations, if possible, to make a tcp listener
|
||||
* socket defer accept()s until there is data to read.
|
||||
*
|
||||
*
|
||||
* Not all platforms support this. You don't want to do this for every
|
||||
* listener socket: only the ones that implement a protocol where the
|
||||
* client transmits before the server needs to respond.
|
||||
@ -481,19 +481,19 @@ int evutil_closesocket(evutil_socket_t sock);
|
||||
* @param sock The listening socket to to make deferred
|
||||
* @return 0 on success (whether the operation is supported or not),
|
||||
* -1 on failure
|
||||
*/
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock);
|
||||
|
||||
/** Do platform-specific operations to set/unset TCP keep-alive options
|
||||
* TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT on a socket.
|
||||
*
|
||||
* @param sock The socket to be set TCP keep-alive
|
||||
* @param on nonzero value to enable TCP keep-alive, 0 to disable
|
||||
* @param timeout The timeout in seconds with no activity until
|
||||
*
|
||||
* @param sock The socket to be set TCP keep-alive
|
||||
* @param on Nonzero value to enable TCP keep-alive, 0 to disable
|
||||
* @param timeout The timeout in seconds with no activity until
|
||||
* the first keepalive probe is sent
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evutil_set_tcp_keepalive(evutil_socket_t sock, int on, int timeout);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user