diff --git a/include/libwebsockets/lws-secure-streams-policy.h b/include/libwebsockets/lws-secure-streams-policy.h index d53408f62..26766b9d6 100644 --- a/include/libwebsockets/lws-secure-streams-policy.h +++ b/include/libwebsockets/lws-secure-streams-policy.h @@ -316,6 +316,7 @@ typedef struct lws_ss_policy { const lws_retry_bo_t *retry_bo; /**< retry policy to use */ uint32_t proxy_buflen; /**< max dsh alloc for proxy */ + uint32_t client_buflen; /**< max dsh alloc for client */ uint32_t timeout_ms; /**< default message response * timeout in ms */ uint32_t flags; /**< stream attribute flags */ diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index 884d21373..a0bf5977c 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -115,8 +115,10 @@ * - 0: LWSSS_SER_RXPRE_CREATE_RESULT * - 1: 2 byte MSB-first rest-of-frame length (usually 00, 03) * - 3: 1 byte result, 0 = success. On failure, proxy will close connection. - * - 4: 2 byte MSB-first initial tx credit - * - 6: if present, comma-sep list of rideshare types from policy + * - 4: 4 byte client dsh allocation recommended for stream type, from policy + * (introduced in SSSv1) + * - 8: 2 byte MSB-first initial tx credit + * - 10: if present, comma-sep list of rideshare types from policy * * - Proxied rx * diff --git a/lib/core-net/lws-dsh.c b/lib/core-net/lws-dsh.c index 46aec64dd..3391b1c85 100644 --- a/lib/core-net/lws-dsh.c +++ b/lib/core-net/lws-dsh.c @@ -59,6 +59,7 @@ lws_dsh_create(lws_dll2_owner_t *owner, size_t buf_len, int count_kinds) assert(buf_len); assert(count_kinds > 1); + assert(buf_len > sizeof(lws_dsh_t) + oha_len); dsh = lws_malloc(sizeof(lws_dsh_t) + buf_len + oha_len, __func__); if (!dsh) diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index aabea6d86..6e1c8b1d7 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -376,7 +376,14 @@ schedule. Only used when the streamtype is proxied... sets the maximum size of the payload buffering (in bytes) the proxy will hold for this type of stream. If the endpoint dumps a lot of data without any flow control, this may need to -be correspondingly large. Default is 16KB. +be correspondingly large. Default is 32KB. + +### `client_buflen` + +Only used when the streamtype is proxied... sets the maximum size of the +payload buffering (in bytes) the client will hold for this type of stream. If +the client sends a lot of data without any flow control, this may need to +be correspondingly large. Default is 32KB. ### `metadata` diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index 5f14f7c6d..f91e92842 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -58,6 +58,7 @@ static const char * const lejp_tokens_policy[] = { "s[].*.timeout_ms", "s[].*.tls_trust_store", "s[].*.proxy_buflen", + "s[].*.client_buflen", "s[].*.metadata", "s[].*.metadata[].*", "s[].*.http_resp_map", @@ -142,6 +143,7 @@ typedef enum { LSSPPT_DEFAULT_TIMEOUT_MS, LSSPPT_TRUST, LSSPPT_PROXY_BUFLEN, + LSSPPT_CLIENT_BUFLEN, LSSPPT_METADATA, LSSPPT_METADATA_ITEM, LSSPPT_HTTPRESPMAP, @@ -575,6 +577,10 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->proxy_buflen = (uint32_t)atol(ctx->buf); break; + case LSSPPT_CLIENT_BUFLEN: + a->curr[LTY_POLICY].p->client_buflen = (uint32_t)atol(ctx->buf); + break; + case LSSPPT_HTTP_METHOD: pp = (char **)&a->curr[LTY_POLICY].p->u.http.method; goto string2; diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index 475f53ebb..0f3ca2234 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -142,12 +142,10 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, lwsl_info("%s: CONNECTED (%s)\n", __func__, h->ssi.streamtype); h->state = LPCSCLI_SENDING_INITIAL_TX; - if (!h->dsh) { - h->dsh = lws_dsh_create(NULL, (LWS_PRE + LWS_SS_MTU) * 160, 1); - if (!h->dsh) - return -1; - } - + /* + * We create the dsh at the response to the initial tx, which + * will let us know the policy's max size for it + */ lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, 3); lws_callback_on_writable(wsi); break; diff --git a/lib/secure-streams/secure-streams-process.c b/lib/secure-streams/secure-streams-process.c index 724d4b16b..af428674b 100644 --- a/lib/secure-streams/secure-streams-process.c +++ b/lib/secure-streams/secure-streams-process.c @@ -479,6 +479,7 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, n = 0; pay = 0; + s[3] = 0; cp = (const uint8_t *)s; switch (conn->state) { @@ -490,7 +491,9 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, s[1] = 0; s[2] = 1; - n = 4; + n = 8; + + lws_ser_wu32be((uint8_t *)&s[4], conn->ss->policy->client_buflen); /* * If there's rideshare sequencing, it's added after the diff --git a/lib/secure-streams/secure-streams-serialize.c b/lib/secure-streams/secure-streams-serialize.c index af8682c80..ec1d75260 100644 --- a/lib/secure-streams/secure-streams-serialize.c +++ b/lib/secure-streams/secure-streams-serialize.c @@ -57,6 +57,7 @@ typedef enum { RPAR_RIDESHARE_LEN, RPAR_RIDESHARE, + RPAR_RESULT_CREATION_DSH, RPAR_RESULT_CREATION_RIDESHARE, RPAR_METADATA_NAMELEN, @@ -1189,14 +1190,33 @@ payload_ff: goto hangup; } + if (--par->rem < 4) + goto hangup; + + par->ps = RPAR_RESULT_CREATION_DSH; + par->ctr = 0; + break; + + case RPAR_RESULT_CREATION_DSH: + + par->temp32 = (par->temp32 << 8) | (*cp++); + if (!par->rem--) + goto hangup; + if (++par->ctr < 4) + break; + + /* - * Client + * Client (par->temp32 == dsh alloc) */ lws_ss_serialize_state_transition(state, LPCSCLI_LOCAL_CONNECTED); h = lws_container_of(par, lws_sspc_handle_t, parser); + if (h->dsh) + goto hangup; + /* * This is telling us that the streamtype could be (and * was) created at the proxy. It's not telling us that @@ -1230,6 +1250,11 @@ payload_ff: return LWSSSSRET_DESTROY_ME; } + h->dsh = lws_dsh_create(NULL, (size_t)(par->temp32 ? + par->temp32 : 32768), 1); + if (!h->dsh) + goto hangup; + if (h->cwsi) lws_callback_on_writable(h->cwsi); @@ -1240,9 +1265,10 @@ payload_ff: h->rideshare_list[0] = '\0'; h->rsidx = 0; - if (!--par->rem) - par->ps = RPAR_TYPE; - else { + /* no rideshare data is OK */ + par->ps = RPAR_TYPE; + + if (par->rem) { par->ps = RPAR_RESULT_CREATION_RIDESHARE; if (par->rem >= sizeof(h->rideshare_list)) goto hangup;