diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index 11c9ad075..22c1111ce 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -63,8 +63,9 @@ * * - 0: LWSSS_SER_TXPRE_STREAMTYPE * - 1: 2-byte MSB-first rest-of-frame length - * - 3: 4 byte MSB-first initial tx credit - * - 7: the streamtype name with no NUL + * - 3: 1-byte Client SSS protocol version (introduced in SSSv1) + * - 4: 4-byte MSB-first initial tx credit + * - 8: the streamtype name with no NUL * * - Proxied tx * @@ -362,7 +363,14 @@ typedef struct lws_ss_info { * In the special case of _lws_smd streamtype, this is used to indicate * the connection's rx class mask. * */ - uint8_t flags; + uint8_t flags; + uint8_t sss_protocol_version; + /**< used in proxy / serialization case to hold the SS serialization + * protocol level to use with this peer... clients automatically request + * the most recent version they were built with + * (LWS_SSS_CLIENT_PROTOCOL_VERSION) and the proxy stores the requested + * version in here + */ } lws_ss_info_t; diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 1014ac649..9df8a0471 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -22,6 +22,9 @@ * IN THE SOFTWARE. */ +/* current SS Serialization protocol version */ +#define LWS_SSS_CLIENT_PROTOCOL_VERSION 1 + /* * Secure Stream state */ @@ -226,6 +229,7 @@ struct lws_ss_serialization_parser { uint8_t slen; uint8_t rsl_pos; uint8_t rsl_idx; + uint8_t protocol_version; }; /* diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index f5655b10c..456ddf0dc 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -248,15 +248,18 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, * We are negotating the opening of a particular * streamtype */ - n = (int)strlen(h->ssi.streamtype) + 4; + n = (int)strlen(h->ssi.streamtype) + 5; s[0] = LWSSS_SER_TXPRE_STREAMTYPE; lws_ser_wu16be(&s[1], (uint16_t)n); - lws_ser_wu32be(&s[3], (uint32_t)h->txc.peer_tx_cr_est); + /* SSSv1: add protocol version byte (initially 1) */ + s[3] = (uint8_t)LWS_SSS_CLIENT_PROTOCOL_VERSION; + lws_ser_wu32be(&s[4], (uint32_t)h->txc.peer_tx_cr_est); //h->txcr_out = txc; - lws_strncpy((char *)&s[7], h->ssi.streamtype, sizeof(s) - 7); + lws_strncpy((char *)&s[8], h->ssi.streamtype, sizeof(s) - 8); n += 3; h->state = LPCSCLI_WAITING_CREATE_RESULT; + break; case LPCSCLI_LOCAL_CONNECTED: diff --git a/lib/secure-streams/secure-streams-serialize.c b/lib/secure-streams/secure-streams-serialize.c index 1783d581e..7909531e7 100644 --- a/lib/secure-streams/secure-streams-serialize.c +++ b/lib/secure-streams/secure-streams-serialize.c @@ -68,6 +68,7 @@ typedef enum { RPAR_RX_TXCR_UPDATE, RPAR_STREAMTYPE, + RPAR_INIT_PROVERS, RPAR_INITTXC0, RPAR_TXCR0, @@ -441,10 +442,9 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, goto hangup; if (*state != LPCSPROX_WAIT_INITIAL_TX) goto hangup; - if (par->rem < 4) + if (par->rem < 1 + 4 + 1) goto hangup; - par->ctr = 0; - par->ps = RPAR_INITTXC0; + par->ps = RPAR_INIT_PROVERS; break; case LWSSS_SER_TXPRE_METADATA: @@ -781,6 +781,31 @@ payload_ff: par->ps = RPAR_TYPE; break; + case RPAR_INIT_PROVERS: + /* Protocol version byte for this connection */ + par->protocol_version = *cp++; + + /* + * So we have to know what versions of the serialization + * protocol we can support at the proxy side, and + * reject anythng we don't know how to deal with + * noisily in the logs. + */ + + if (par->protocol_version != 1) { + lwsl_err("%s: Rejecting client with " + "unsupported SSv%d protocol\n", + __func__, par->protocol_version); + + goto hangup; + } + + if (!--par->rem) + goto hangup; + par->ctr = 0; + par->ps = RPAR_INITTXC0; + break; + case RPAR_INITTXC0: if (!--par->rem) goto hangup; @@ -1086,8 +1111,9 @@ payload_ff: par->ps = RPAR_TYPE; par->streamtype[par->ctr] = '\0'; - lwsl_notice("%s: creating proxied ss '%s', txcr %d\n", - __func__, par->streamtype, par->txcr_out); + lwsl_info("%s: proxy ss '%s', sssv%d, txcr %d\n", + __func__, par->streamtype, + par->protocol_version, par->txcr_out); ssi->streamtype = par->streamtype; if (par->txcr_out) // !!! @@ -1100,6 +1126,7 @@ payload_ff: */ ssi->flags |= LWSSSINFLAGS_PROXIED; + ssi->sss_protocol_version = par->protocol_version; if (lws_ss_create(context, 0, ssi, parconn, pss, NULL, NULL)) { /* diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 39807e25f..796413b7b 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -618,7 +618,13 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, if (!h) return 2; - __lws_lc_tag(&context->lcg[LWSLCG_WSI_SS_CLIENT], &h->lc, ssi->streamtype ? ssi->streamtype : "nostreamtype"); + if (ssi->sss_protocol_version) + __lws_lc_tag(&context->lcg[LWSLCG_WSI_SS_CLIENT], &h->lc, "%s|v%u", + ssi->streamtype ? ssi->streamtype : "nostreamtype", + (unsigned int)ssi->sss_protocol_version); + else + __lws_lc_tag(&context->lcg[LWSLCG_WSI_SS_CLIENT], &h->lc, "%s", + ssi->streamtype ? ssi->streamtype : "nostreamtype"); h->info = *ssi; h->policy = pol;