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); /*