From e7c1c757cdf5080b4d971b328ba94635e296b687 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 19 May 2016 12:34:35 +0800 Subject: [PATCH] replace LWS_MAX_SOCKET_IO_BUF with context creation info pt_serv_buf_size This makes it easy for user code to choose the size of the per-thread buffer used by various things in lws, including file transfer chunking. Previously it was 4096, if you leave info.pt_serv_buf_size as zero that is still the default. With some caveats, you can increase transfer efficiency by increasing it to, eg, 128KiB, if that makes sense for your memory situation. Signed-off-by: Andy Green --- lib/client-parser.c | 4 ++-- lib/client.c | 10 +++++----- lib/context.c | 13 +++++++++---- lib/extension-permessage-deflate.c | 4 ++-- lib/header.c | 2 +- lib/libwebsockets.h | 6 ++++++ lib/output.c | 4 ++-- lib/parsers.c | 7 +++---- lib/private-libwebsockets.h | 2 +- lib/server-handshake.c | 4 ++-- lib/server.c | 6 +++--- lib/service.c | 6 +++--- lib/ssl.c | 2 +- 13 files changed, 40 insertions(+), 30 deletions(-) diff --git a/lib/client-parser.c b/lib/client-parser.c index 4036941c..b467aa09 100644 --- a/lib/client-parser.c +++ b/lib/client-parser.c @@ -321,10 +321,10 @@ int lws_client_rx_sm(struct lws *wsi, unsigned char c) /* * if there's no protocol max frame size given, we are - * supposed to default to LWS_MAX_SOCKET_IO_BUF + * supposed to default to context->pt_serv_buf_size */ if (!wsi->protocol->rx_buffer_size && - wsi->u.ws.rx_ubuf_head != LWS_MAX_SOCKET_IO_BUF) + wsi->u.ws.rx_ubuf_head != wsi->context->pt_serv_buf_size) break; if (wsi->protocol->rx_buffer_size && diff --git a/lib/client.c b/lib/client.c index adb27595..4ce50eb5 100644 --- a/lib/client.c +++ b/lib/client.c @@ -107,7 +107,7 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi, return 0; } - n = recv(wsi->sock, sb, LWS_MAX_SOCKET_IO_BUF, 0); + n = recv(wsi->sock, sb, context->pt_serv_buf_size, 0); if (n < 0) { if (LWS_ERRNO == LWS_EAGAIN) { lwsl_debug("Proxy read returned EAGAIN... retrying\n"); @@ -368,11 +368,11 @@ lws_client_interpret_server_handshake(struct lws *wsi) { int n, len, okay = 0, isErrorCodeReceived = 0, port = 0, ssl = 0; int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR; + struct lws_context *context = wsi->context; const char *pc, *prot, *ads = NULL, *path; struct allocated_headers *ah; char *p; #ifndef LWS_NO_EXTENSIONS - struct lws_context *context = wsi->context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; char *sb = (char *)&pt->serv_buf[0]; const struct lws_ext_options *opts; @@ -622,7 +622,7 @@ check_extensions: * and go through matching them or identifying bogons */ - if (lws_hdr_copy(wsi, sb, LWS_MAX_SOCKET_IO_BUF, WSI_TOKEN_EXTENSIONS) < 0) { + if (lws_hdr_copy(wsi, sb, context->pt_serv_buf_size, WSI_TOKEN_EXTENSIONS) < 0) { lwsl_warn("ext list from server failed to copy\n"); goto bail2; } @@ -789,7 +789,7 @@ check_accept: */ n = wsi->protocol->rx_buffer_size; if (!n) - n = LWS_MAX_SOCKET_IO_BUF; + n = context->pt_serv_buf_size; n += LWS_PRE; wsi->u.ws.rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */); if (!wsi->u.ws.rx_ubuf) { @@ -993,7 +993,7 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt) /* give userland a chance to append, eg, cookies */ wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, - wsi->user_space, &p, (pkt + LWS_MAX_SOCKET_IO_BUF) - p - 12); + wsi->user_space, &p, (pkt + context->pt_serv_buf_size) - p - 12); p += sprintf(p, "\x0d\x0a"); diff --git a/lib/context.c b/lib/context.c index bf359265..47976fbb 100644 --- a/lib/context.c +++ b/lib/context.c @@ -272,7 +272,7 @@ static const struct lws_protocols protocols_dummy[] = { "http-only", /* name */ callback_http_dummy, /* callback */ 0, /* per_session_data_size */ - 4096, /* max frame size / rx buffer */ + 0, /* max frame size / rx buffer */ }, /* * the other protocols are provided by lws plugins @@ -598,6 +598,11 @@ lws_create_context(struct lws_context_creation_info *info) return NULL; } + if (info->pt_serv_buf_size) + context->pt_serv_buf_size = info->pt_serv_buf_size; + else + context->pt_serv_buf_size = 4096; + context->time_up = time(NULL); #ifndef LWS_NO_DAEMONIZE if (pid_daemon) { @@ -649,7 +654,7 @@ lws_create_context(struct lws_context_creation_info *info) * and header data pool */ for (n = 0; n < context->count_threads; n++) { - context->pt[n].serv_buf = lws_zalloc(LWS_MAX_SOCKET_IO_BUF); + context->pt[n].serv_buf = lws_zalloc(context->pt_serv_buf_size); if (!context->pt[n].serv_buf) { lwsl_err("OOM\n"); return NULL; @@ -714,10 +719,10 @@ lws_create_context(struct lws_context_creation_info *info) lwsl_info(" mem: context: %5u bytes (%d ctx + (%d thr x %d))\n", sizeof(struct lws_context) + - (context->count_threads * LWS_MAX_SOCKET_IO_BUF), + (context->count_threads * context->pt_serv_buf_size), sizeof(struct lws_context), context->count_threads, - LWS_MAX_SOCKET_IO_BUF); + context->pt_serv_buf_size); lwsl_info(" mem: http hdr rsvd: %5u bytes (%u thr x (%u + %u) x %u))\n", (context->max_http_header_data + diff --git a/lib/extension-permessage-deflate.c b/lib/extension-permessage-deflate.c index 65f28caa..ec9c8092 100644 --- a/lib/extension-permessage-deflate.c +++ b/lib/extension-permessage-deflate.c @@ -49,7 +49,7 @@ lws_extension_pmdeflate_restrict_args(struct lws *wsi, /* cap the RX buf at the nearest power of 2 to protocol rx buf */ - n = LWS_MAX_SOCKET_IO_BUF; + n = wsi->context->pt_serv_buf_size; if (wsi->protocol->rx_buffer_size) n = wsi->protocol->rx_buffer_size; @@ -115,7 +115,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, case LWS_EXT_CB_CLIENT_CONSTRUCT: case LWS_EXT_CB_CONSTRUCT: - n = LWS_MAX_SOCKET_IO_BUF; + n = context->pt_serv_buf_size; if (wsi->protocol->rx_buffer_size) n = wsi->protocol->rx_buffer_size; diff --git a/lib/header.c b/lib/header.c index bacbe978..1a45c95e 100644 --- a/lib/header.c +++ b/lib/header.c @@ -219,7 +219,7 @@ lws_return_http_status(struct lws *wsi, unsigned int code, struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; unsigned char *p = pt->serv_buf + LWS_PRE; unsigned char *start = p, *body = p + 512; - unsigned char *end = p + LWS_MAX_SOCKET_IO_BUF - LWS_PRE; + unsigned char *end = p + context->pt_serv_buf_size - LWS_PRE; int n, m, len; char slen[20]; diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 40cfba71..21debc13 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -1496,6 +1496,11 @@ struct lws_http_mount { * @mounts: VHOST: optional linked list of mounts for this vhost * @server_string: CONTEXT: string used in HTTP headers to identify server * software, if NULL, "libwebsockets". + * @pt_serv_buf_size: CONTEXT: 0 = default of 4096. This buffer is used by + * various service related features including file serving, it + * defines the max chunk of file that can be sent at once. + * At the risk of lws having to buffer failed large sends, it + * can be increased to, eg, 128KiB to improve throughput. */ struct lws_context_creation_info { @@ -1538,6 +1543,7 @@ struct lws_context_creation_info { const char *log_filepath; /* VH */ const struct lws_http_mount *mounts; /* VH */ const char *server_string; /* context */ + unsigned int pt_serv_buf_size; /* context */ /* Add new things just above here ---^ * This is part of the ABI, don't needlessly break compatibility diff --git a/lib/output.c b/lib/output.c index a29cf30e..3398fd13 100644 --- a/lib/output.c +++ b/lib/output.c @@ -129,7 +129,7 @@ int lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) /* limit sending */ n = wsi->protocol->rx_buffer_size; if (!n) - n = LWS_MAX_SOCKET_IO_BUF; + n = context->pt_serv_buf_size; n += LWS_PRE + 4; if (n > len) n = len; @@ -585,7 +585,7 @@ LWS_VISIBLE int lws_serve_http_file_fragment(struct lws *wsi) if (lws_plat_file_read(wsi, wsi->u.http.fd, &amount, pt->serv_buf, - LWS_MAX_SOCKET_IO_BUF) < 0) + context->pt_serv_buf_size) < 0) return -1; /* caller will close */ n = (int)amount; diff --git a/lib/parsers.c b/lib/parsers.c index a23f4c92..0dea47f1 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -1286,12 +1286,11 @@ handle_first: /* * if there's no protocol max frame size given, we are - * supposed to default to LWS_MAX_SOCKET_IO_BUF + * supposed to default to context->pt_serv_buf_size */ if (!wsi->protocol->rx_buffer_size && - wsi->u.ws.rx_ubuf_head != - LWS_MAX_SOCKET_IO_BUF) + wsi->u.ws.rx_ubuf_head != wsi->context->pt_serv_buf_size) break; else if (wsi->protocol->rx_buffer_size && @@ -1517,7 +1516,7 @@ lws_payload_until_length_exhausted(struct lws *wsi, unsigned char **buf, if (wsi->protocol->rx_buffer_size) buffer_size = wsi->protocol->rx_buffer_size; else - buffer_size = LWS_MAX_SOCKET_IO_BUF; + buffer_size = wsi->context->pt_serv_buf_size; avail = buffer_size - wsi->u.ws.rx_ubuf_head; /* do not consume more than we should */ diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index c6998aa1..ab06b9d4 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -352,7 +352,6 @@ extern "C" { #endif #define MAX_WEBSOCKET_04_KEY_LEN 128 -#define LWS_MAX_SOCKET_IO_BUF 4096 #ifndef SYSTEM_RANDOM_FILEPATH #define SYSTEM_RANDOM_FILEPATH "/dev/urandom" @@ -742,6 +741,7 @@ struct lws_context { unsigned int options; unsigned int fd_limit_per_thread; unsigned int timeout_secs; + unsigned int pt_serv_buf_size; /* * set to the Thread ID that's doing the service loop just before entry diff --git a/lib/server-handshake.c b/lib/server-handshake.c index 1d0be11b..ef7c5cec 100644 --- a/lib/server-handshake.c +++ b/lib/server-handshake.c @@ -48,7 +48,7 @@ lws_extension_server_handshake(struct lws *wsi, char **p) * and go through them */ - if (lws_hdr_copy(wsi, (char *)pt->serv_buf, LWS_MAX_SOCKET_IO_BUF, + if (lws_hdr_copy(wsi, (char *)pt->serv_buf, context->pt_serv_buf_size, WSI_TOKEN_EXTENSIONS) < 0) return 1; @@ -191,7 +191,7 @@ handshake_0405(struct lws_context *context, struct lws *wsi) lws_SHA1(pt->serv_buf, n, hash); accept_len = lws_b64_encode_string((char *)hash, 20, (char *)pt->serv_buf, - LWS_MAX_SOCKET_IO_BUF); + context->pt_serv_buf_size); if (accept_len < 0) { lwsl_warn("Base64 encoded hash too long\n"); goto bail; diff --git a/lib/server.c b/lib/server.c index c109585f..52991d07 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1134,7 +1134,7 @@ upgrade_ws: n = wsi->protocol->rx_buffer_size; if (!n) - n = LWS_MAX_SOCKET_IO_BUF; + n = context->pt_serv_buf_size; n += LWS_PRE; wsi->u.ws.rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */); if (!wsi->u.ws.rx_ubuf) { @@ -1612,7 +1612,7 @@ lws_server_socket_service(struct lws_context *context, struct lws *wsi, } len = lws_ssl_capable_read(wsi, pt->serv_buf, - LWS_MAX_SOCKET_IO_BUF); + context->pt_serv_buf_size); lwsl_debug("%s: wsi %p read %d\r\n", __func__, wsi, len); switch (len) { case 0: @@ -1781,7 +1781,7 @@ lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type, char cache_control[50], *cc = "no-store"; unsigned char *response = pt->serv_buf + LWS_PRE; unsigned char *p = response; - unsigned char *end = p + LWS_MAX_SOCKET_IO_BUF - LWS_PRE; + unsigned char *end = p + context->pt_serv_buf_size - LWS_PRE; int ret = 0, cclen = 8; wsi->u.http.fd = lws_plat_file_open(wsi, file, &wsi->u.http.filelen, diff --git a/lib/service.c b/lib/service.c index f6ad73a2..8ef82155 100644 --- a/lib/service.c +++ b/lib/service.c @@ -893,7 +893,7 @@ read: if (wsi->mode != LWSCM_HTTP_CLIENT_ACCEPTED) { eff_buf.token_len = lws_ssl_capable_read(wsi, pt->serv_buf, pending ? pending : - LWS_MAX_SOCKET_IO_BUF); + context->pt_serv_buf_size); switch (eff_buf.token_len) { case 0: lwsl_info("%s: zero length read\n", __func__); @@ -989,8 +989,8 @@ drain: pending = lws_ssl_pending(wsi); if (pending) { - pending = pending > LWS_MAX_SOCKET_IO_BUF ? - LWS_MAX_SOCKET_IO_BUF : pending; + pending = pending > context->pt_serv_buf_size ? + context->pt_serv_buf_size : pending; goto read; } diff --git a/lib/ssl.c b/lib/ssl.c index 685584e0..6b2e575d 100644 --- a/lib/ssl.c +++ b/lib/ssl.c @@ -537,7 +537,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) lws_latency_pre(context, wsi); - n = recv(wsi->sock, (char *)pt->serv_buf, LWS_MAX_SOCKET_IO_BUF, + n = recv(wsi->sock, (char *)pt->serv_buf, context->pt_serv_buf_size, MSG_PEEK); /*