diff --git a/include/libwebsockets/lws-secure-streams-client.h b/include/libwebsockets/lws-secure-streams-client.h index b7244158a..35cb88730 100644 --- a/include/libwebsockets/lws-secure-streams-client.h +++ b/include/libwebsockets/lws-secure-streams-client.h @@ -163,7 +163,7 @@ lws_sspc_rideshare(struct lws_sspc_handle *h); */ LWS_VISIBLE LWS_EXTERN int lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, - void *value, size_t len); + const void *value, size_t len); LWS_VISIBLE LWS_EXTERN int lws_sspc_add_peer_tx_credit(struct lws_sspc_handle *h, int32_t add); diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index afd8bee19..f0b2b4032 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -463,7 +463,7 @@ lws_ss_rideshare(struct lws_ss_handle *h); */ LWS_VISIBLE LWS_EXTERN int lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, - void *value, size_t len); + const void *value, size_t len); /** diff --git a/lib/core/context.c b/lib/core/context.c index 5b5bb1c9e..27b1d11f1 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -949,7 +949,9 @@ lws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result) cx->captive_portal_detect = (uint8_t)result; /* if nothing is there to intercept anything, go all the way */ - lws_state_transition_steps(&cx->mgr_system, LWS_SYSTATE_OPERATIONAL); + if (cx->mgr_system.state != LWS_SYSTATE_POLICY_INVALID) + lws_state_transition_steps(&cx->mgr_system, + LWS_SYSTATE_OPERATIONAL); } lws_cpd_result_t diff --git a/lib/secure-streams/policy.c b/lib/secure-streams/policy.c index d12f6f801..6991e5281 100644 --- a/lib/secure-streams/policy.c +++ b/lib/secure-streams/policy.c @@ -242,7 +242,7 @@ lws_ss_policy_metadata_index(const lws_ss_policy_t *p, size_t index) int lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, - void *value, size_t len) + const void *value, size_t len) { lws_ss_metadata_t *omd = lws_ss_policy_metadata(h->policy, name); @@ -252,7 +252,7 @@ lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, } h->metadata[omd->length].name = name; - h->metadata[omd->length].value = value; + h->metadata[omd->length].value = (void *)value; h->metadata[omd->length].length = len; return 0; diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 1de0868f3..81065a334 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -543,10 +543,16 @@ secstream_connect_munge_h1(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *pbasis = h->policy->u.http.url; size_t used_in, used_out; lws_strexp_t exp; - if (!h->policy->u.http.url) + /* i.path on entry is used to override the policy urlpath if not "" */ + + if (i->path[0]) + pbasis = i->path; + + if (!pbasis) return 0; #if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2) @@ -564,8 +570,7 @@ secstream_connect_munge_h1(lws_ss_handle_t *h, char *buf, size_t len, lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); - if (lws_strexp_expand(&exp, h->policy->u.http.url, - strlen(h->policy->u.http.url), + if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), &used_in, &used_out) != LSTRX_DONE) return 1; diff --git a/lib/secure-streams/protocols/ss-h2.c b/lib/secure-streams/protocols/ss-h2.c index 941183c1c..063324855 100644 --- a/lib/secure-streams/protocols/ss-h2.c +++ b/lib/secure-streams/protocols/ss-h2.c @@ -112,6 +112,15 @@ secstream_connect_munge_h2(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *pbasis = h->policy->u.http.url; + size_t used_in, used_out; + lws_strexp_t exp; + + /* i.path on entry is used to override the policy urlpath if not "" */ + + if (i->path[0]) + pbasis = i->path; + if (h->policy->flags & LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM) i->ssl_connection |= LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; @@ -137,13 +146,19 @@ secstream_connect_munge_h2(lws_ss_handle_t *h, char *buf, size_t len, i->manual_initial_tx_credit); } - if (!h->policy->u.http.url) + if (!pbasis) return 0; /* protocol aux is the path part */ i->path = buf; - lws_snprintf(buf, len, "/%s", h->policy->u.http.url); + buf[0] = '/'; + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); + + if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), + &used_in, &used_out) != LSTRX_DONE) + return 1; return 0; } diff --git a/lib/secure-streams/protocols/ss-ws.c b/lib/secure-streams/protocols/ss-ws.c index ac1dc32ab..91d36a580 100644 --- a/lib/secure-streams/protocols/ss-ws.c +++ b/lib/secure-streams/protocols/ss-ws.c @@ -143,15 +143,30 @@ secstream_connect_munge_ws(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct) { + const char *pbasis = h->policy->u.http.url; + size_t used_in, used_out; + lws_strexp_t exp; + lwsl_notice("%s\n", __func__); - if (!h->policy->u.http.url) + /* i.path on entry is used to override the policy urlpath if not "" */ + + if (i->path[0]) + pbasis = i->path; + + if (!pbasis) return 0; /* protocol aux is the path part ; ws subprotocol name */ - i->path = h->policy->u.http.url; - lws_snprintf(buf, len, "/%s", h->policy->u.http.url); + i->path = buf; + buf[0] = '/'; + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); + + if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), + &used_in, &used_out) != LSTRX_DONE) + return 1; i->protocol = h->policy->u.http.u.ws.subprotocol; diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index 67d73be67..57d7ca0d8 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -493,7 +493,7 @@ lws_sspc_rideshare(struct lws_sspc_handle *h) static int _lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, - void *value, size_t len, int tx_cr_adjust) + const void *value, size_t len, int tx_cr_adjust) { lws_sspc_metadata_t *md; @@ -555,7 +555,7 @@ _lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, int lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, - void *value, size_t len) + const void *value, size_t len) { return _lws_sspc_set_metadata(h, name, value, len, 0); } diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index f8e7b2ae3..b93158aca 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -185,11 +185,13 @@ lws_ss_backoff(lws_ss_handle_t *h) int lws_ss_client_connect(lws_ss_handle_t *h) { + const char *prot, *_prot, *ipath, *_ipath, *ads, *_ads; struct lws_client_connect_info i; const struct ss_pcols *ssp; size_t used_in, used_out; union lws_ss_contemp ct; char path[128], ep[96]; + int port, _port, tls; lws_strexp_t exp; if (!h->policy) { @@ -205,10 +207,53 @@ lws_ss_client_connect(lws_ss_handle_t *h) if (h->h_sink) return 0; + /* + * We're going to substitute ${metadata} in the endpoint at connection- + * time, so this can be set dynamically... + */ + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, ep, sizeof(ep)); + + if (lws_strexp_expand(&exp, h->policy->endpoint, + strlen(h->policy->endpoint), + &used_in, &used_out) != LSTRX_DONE) { + lwsl_err("%s: address strexp failed\n", __func__); + + return -1; + } + + /* + * ... in some cases, we might want the user to be able to override + * some policy settings by what he provided in there. For example, + * if he set the endpoint to "https://myendpoint.com:4443/mypath" it + * might be quite convenient to override the policy to follow the info + * that was given for at least server, port and the url path. + */ + + _port = port = h->policy->port; + _prot = prot = NULL; + _ipath = ipath = ""; + _ads = ads = ep; + + if (strchr(ep, ':') && + !lws_parse_uri(ep, &_prot, &_ads, &_port, &_ipath)) { + lwsl_debug("%s: using uri parse results '%s' '%s' %d '%s'\n", + __func__, _prot, _ads, _port, _ipath); + prot = _prot; + ads = _ads; + port = _port; + ipath = _ipath; + } + memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */ i.context = h->context; + tls = !!(h->policy->flags & LWSSSPOLF_TLS); - if (h->policy->flags & LWSSSPOLF_TLS) { + if (prot && (!strcmp(prot, "http") || !strcmp(prot, "ws") || + !strcmp(prot, "mqtt"))) + tls = 0; + + if (tls) { lwsl_info("%s: using tls\n", __func__); i.ssl_connection = LCCSCF_USE_SSL; @@ -228,28 +273,19 @@ lws_ss_client_connect(lws_ss_handle_t *h) } } - /* expand metadata ${symbols} that may be inside the endpoint string */ + i.address = ads; + i.port = port; + i.host = i.address; + i.origin = i.address; + i.opaque_user_data = h; + i.seq = h->seq; + i.retry_and_idle_policy = h->policy->retry_bo; + i.sys_tls_client_cert = h->policy->client_cert; - lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, ep, sizeof(ep)); - - if (lws_strexp_expand(&exp, h->policy->endpoint, - strlen(h->policy->endpoint), - &used_in, &used_out) != LSTRX_DONE) { - lwsl_err("%s: address strexp failed\n", __func__); - - return -1; - } - - i.address = ep; - i.port = h->policy->port; - i.host = i.address; - i.origin = i.address; - i.opaque_user_data = h; - i.seq = h->seq; - i.retry_and_idle_policy = h->policy->retry_bo; - i.sys_tls_client_cert = h->policy->client_cert; - - i.path = ""; + i.path = ipath; + /* if this is not "", munge should use it instead of policy + * url path + */ ssp = ss_pcols[(int)h->policy->protocol]; if (!ssp) { diff --git a/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c index 1481ec14d..d9214801e 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-metadata/minimal-secure-streams.c @@ -40,6 +40,7 @@ static int interrupted, bad = 1, force_cpd_fail_portal, force_cpd_fail_no_internet; static lws_state_notify_link_t nl; +static const char *server_name_or_url = "warmcat.com"; /* * If the -proxy app is fulfilling our connection, then we don't need to have @@ -223,7 +224,9 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: - lws_ss_set_metadata(m->ss, "servername", "warmcat.com", 11); + lwsl_notice("%s: CREATING: setting servername metadata to %s\n", + __func__, server_name_or_url); + lws_ss_set_metadata(m->ss, "servername", server_name_or_url, strlen(server_name_or_url)); lws_ss_client_connect(m->ss); break; case LWSSSCS_ALL_RETRIES_FAILED: @@ -296,6 +299,7 @@ int main(int argc, const char **argv) { struct lws_context_creation_info info; struct lws_context *context; + const char *p; int n = 0; signal(SIGINT, sigint_handler); @@ -318,30 +322,30 @@ int main(int argc, const char **argv) #if defined(LWS_SS_USE_SSPC) info.protocols = lws_sspc_protocols; - { - const char *p; - /* connect to ssproxy via UDS by default, else via - * tcp connection to this port */ - if ((p = lws_cmdline_option(argc, argv, "-p"))) - info.ss_proxy_port = atoi(p); + /* connect to ssproxy via UDS by default, else via + * tcp connection to this port */ + if ((p = lws_cmdline_option(argc, argv, "-p"))) + info.ss_proxy_port = atoi(p); - /* UDS "proxy.ss.lws" in abstract namespace, else this socket - * path; when -p given this can specify the network interface - * to bind to */ - if ((p = lws_cmdline_option(argc, argv, "-i"))) - info.ss_proxy_bind = p; + /* UDS "proxy.ss.lws" in abstract namespace, else this socket + * path; when -p given this can specify the network interface + * to bind to */ + if ((p = lws_cmdline_option(argc, argv, "-i"))) + info.ss_proxy_bind = p; - /* if -p given, -a specifies the proxy address to connect to */ - if ((p = lws_cmdline_option(argc, argv, "-a"))) - info.ss_proxy_address = p; - } + /* if -p given, -a specifies the proxy address to connect to */ + if ((p = lws_cmdline_option(argc, argv, "-a"))) + info.ss_proxy_address = p; #else info.pss_policies_json = default_ss_policy; info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; #endif + if ((p = lws_cmdline_option(argc, argv, "-u"))) + server_name_or_url = p; + /* integrate us with lws system state management when context created */ nl.name = "app";