1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

TCP_FASTOPEN

This commit is contained in:
Andy Green 2021-05-25 06:09:01 +01:00
parent f9ae34c320
commit ad3aa5339e
8 changed files with 96 additions and 13 deletions

View file

@ -0,0 +1,32 @@
# `TCP_FASTOPEN` support in lws
Lws supports enabling TCP_FASTOPEN oper-vhost for listen sockets.
## Enabling per vhost serving
Set the `info.fo_listen_queue` to nonzero at vhost creation. Different
platforms interpret this number differently, zero always disables it
but on Linux, the number is interpreted as a SYN queue length.
On FreeBSD, OSX and Windows, the number is basically a bool, with the
extra restriction OSX and Windows only allows 0 or 1.
## Enabling Linux for serving with TCP_FASTOPEN
To configure the kernel for listening socket TCP_FASTOPEN, you need
```
# sysctl -w net.ipv4.tcp_fastopen=3
```
## Enabling BSD for serving with TCP_FASTOPEN
At least on FreeBSD, you need to set the net.inet.tcp.fastopen.enabled
sysctl to 1
## Enabling Windows for serving with TCP_FASTOPEN
```
> netsh int tcp set global fastopenfallback=disabled
> netsh int tcp show global
```

View file

@ -854,16 +854,22 @@ struct lws_context_creation_info {
#if defined(LWS_WITH_SYS_METRICS)
const struct lws_metric_policy *metrics_policies;
/**< non-SS policy metrics policies */
/**< CONTEXT: non-SS policy metrics policies */
const char *metrics_prefix;
/**< prefix for this context's metrics, used to distinguish metrics
* pooled from different processes / applications, so, eg what would
* be "cpu.svc" if this is NULL becomes "myapp.cpu.svc" is this is
/**< CONTEXT: prefix for this context's metrics, used to distinguish
* metrics pooled from different processes / applications, so, eg what
* would be "cpu.svc" if this is NULL becomes "myapp.cpu.svc" is this is
* set to "myapp". Policies are applied using the name with the prefix,
* if present.
*/
#endif
int fo_listen_queue;
/**< VHOST: 0 = no TCP_FASTOPEN, nonzero = enable TCP_FASTOPEN if the
* platform supports it, with the given queue length for the listen
* socket.
*/
/* Add new things just above here ---^
* This is part of the ABI, don't needlessly break compatibility
*

View file

@ -535,6 +535,7 @@ struct lws_vhost {
int keepalive_timeout;
int timeout_secs_ah_idle;
int connect_timeout_secs;
int fo_listen_queue;
int count_bound_wsi;

View file

@ -659,15 +659,16 @@ lws_create_vhost(struct lws_context *context,
vh->count_protocols++)
;
vh->options = info->options;
vh->pvo = info->pvo;
vh->headers = info->headers;
vh->user = info->user;
vh->finalize = info->finalize;
vh->finalize_arg = info->finalize_arg;
vh->listen_accept_role = info->listen_accept_role;
vh->listen_accept_protocol = info->listen_accept_protocol;
vh->unix_socket_perms = info->unix_socket_perms;
vh->options = info->options;
vh->pvo = info->pvo;
vh->headers = info->headers;
vh->user = info->user;
vh->finalize = info->finalize;
vh->finalize_arg = info->finalize_arg;
vh->listen_accept_role = info->listen_accept_role;
vh->listen_accept_protocol = info->listen_accept_protocol;
vh->unix_socket_perms = info->unix_socket_perms;
vh->fo_listen_queue = info->fo_listen_queue;
LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
if (lws_rops_fidx(ar, LWS_ROPS_init_vhost) &&

View file

@ -220,6 +220,16 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
int en;
#endif
#if 0
#if defined(TCP_FASTOPEN_CONNECT)
optval = 1;
if (setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, (void *)&optval,
sizeof(optval)))
lwsl_warn("%s: FASTOPEN_CONNECT failed\n", __func__);
optval = (int)pri;
#endif
#endif
#if !defined(__APPLE__) && \
!defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && \
!defined(__NetBSD__) && \

View file

@ -119,6 +119,7 @@ static const char * const paths_vhosts[] = {
"vhosts[].ignore-missing-cert",
"vhosts[].error-document-404",
"vhosts[].alpn",
"vhosts[].fo-listen-queue",
"vhosts[].ssl-client-option-set",
"vhosts[].ssl-client-option-clear",
"vhosts[].tls13-ciphers",
@ -187,6 +188,7 @@ enum lejp_vhost_paths {
LEJPVP_IGNORE_MISSING_CERT,
LEJPVP_ERROR_DOCUMENT_404,
LEJPVP_ALPN,
LWJPVP_FO_LISTEN_QUEUE,
LEJPVP_SSL_CLIENT_OPTION_SET,
LEJPVP_SSL_CLIENT_OPTION_CLEAR,
LEJPVP_TLS13_CIPHERS,
@ -693,6 +695,9 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
case LEJPVP_CGI_TIMEOUT:
a->m.cgi_timeout = atoi(ctx->buf);
return 0;
case LWJPVP_FO_LISTEN_QUEUE:
a->info->fo_listen_queue = atoi(ctx->buf);
return 0;
case LEJPVP_KEEPALIVE_TIMEOUT:
a->info->keepalive_timeout = atoi(ctx->buf);
return 0;

View file

@ -24,6 +24,10 @@
#include "private-lib-core.h"
#if !defined(SOL_TCP) && defined(IPPROTO_TCP)
#define SOL_TCP IPPROTO_TCP
#endif
const char * const method_names[] = {
"GET", "POST",
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS)
@ -345,6 +349,29 @@ done_list:
vhost->lserv_wsi = wsi;
lws_pt_unlock(pt);
#if defined(WIN32) && defined(TCP_FASTOPEN)
if (vhost->fo_listen_queue) {
int optval = 1;
if (setsockopt(wsi->desc.sockfd, IPPROTO_TCP,
TCP_FASTOPEN,
(const char*)&optval, sizeof(optval)) < 0) {
int error = LWS_ERRNO;
lwsl_warn("%s: TCP_NODELAY failed with error %d\n",
__func__, error);
}
}
#else
#if defined(TCP_FASTOPEN)
if (vhost->fo_listen_queue) {
int qlen = vhost->fo_listen_queue;
if (setsockopt(wsi->desc.sockfd, SOL_TCP, TCP_FASTOPEN,
&qlen, sizeof(qlen)))
lwsl_warn("%s: TCP_FASTOPEN failed\n", __func__);
}
#endif
#endif
n = listen(wsi->desc.sockfd, LWS_SOMAXCONN);
if (n < 0) {
lwsl_err("listen failed with error %d\n", LWS_ERRNO);

View file

@ -126,6 +126,7 @@ int main(int argc, const char **argv)
LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE;
info.ssl_cert_filepath = "localhost-100y.cert";
info.ssl_private_key_filepath = "localhost-100y.key";
info.fo_listen_queue = 32;
#if defined(LWS_WITH_PLUGINS)
info.plugin_dirs = plugin_dirs;