From 629ccd4db8f2657222fc49f3b1257d88d24f4f15 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 31 Dec 2020 15:08:48 +0000 Subject: [PATCH] sspc: ssv1: return policy about client dsh allocation Let's allow the proxy to pass back what the policy says about the size of dsh buffer the client side of this streamtype should have. Defer clientsize dsh generation until we got the info back from the proxy in the response to the initial packet. If it's zero / unset in the policy, just go with 32KB. --- .../libwebsockets/lws-secure-streams-policy.h | 1 + include/libwebsockets/lws-secure-streams.h | 6 ++-- lib/core-net/lws-dsh.c | 1 + lib/secure-streams/README.md | 9 ++++- lib/secure-streams/policy-json.c | 6 ++++ lib/secure-streams/secure-streams-client.c | 10 +++--- lib/secure-streams/secure-streams-process.c | 5 ++- lib/secure-streams/secure-streams-serialize.c | 34 ++++++++++++++++--- 8 files changed, 58 insertions(+), 14 deletions(-) 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;