From 3d7d180eb84cd551ba1521f3b932644869e2dd75 Mon Sep 17 00:00:00 2001 From: Kenneth Mastro Date: Wed, 6 Oct 2021 06:25:03 +0100 Subject: [PATCH 001/275] wolfssl: adapt SNI for recent changes It seems WOLFSSL_SNI_HOST_NAME is an enum in later wolfssl, use the wolfssl define HAVE_SNI as well --- lib/tls/openssl/openssl-client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index aa1c5df16b..d8c56c518f 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -343,9 +343,9 @@ lws_ssl_client_bio_create(struct lws *wsi) strlen(hostname)); #endif #else -#ifdef WOLFSSL_SNI_HOST_NAME +#if defined(WOLFSSL_SNI_HOST_NAME) || defined(HAVE_SNI) wolfSSL_UseSNI(wsi->tls.ssl, WOLFSSL_SNI_HOST_NAME, hostname, - strlen(hostname)); + (unsigned short)strlen(hostname)); #endif #endif #else From 3b90c89bab1387db9689e3fcdc80f3f495ea1ada Mon Sep 17 00:00:00 2001 From: Tero Turtiainen Date: Wed, 6 Oct 2021 09:21:27 +0100 Subject: [PATCH 002/275] tls: clear unused warning on WITHOUT_SERVER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I’ve got an error when compiling libwebsockets on Mac with -DLWS_WITHOUT_SERVER=ON: libwebsockets/lib/tls/tls.c:98:22: error: unused variable 'cx' [-Werror,-Wunused-variable] --- lib/tls/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tls/tls.c b/lib/tls/tls.c index 6afc76400a..b5b43859fb 100644 --- a/lib/tls/tls.c +++ b/lib/tls/tls.c @@ -95,12 +95,12 @@ lws_tls_restrict_borrow(struct lws *wsi) static void _lws_tls_restrict_return(struct lws *wsi) { +#if defined(LWS_WITH_SERVER) struct lws_context *cx = wsi->a.context; assert(cx->simultaneous_ssl_handshake >= 0); assert(cx->simultaneous_ssl >= 0); -#if defined(LWS_WITH_SERVER) lws_gate_accepts(cx, (cx->simultaneous_ssl_restriction && cx->simultaneous_ssl == cx->simultaneous_ssl_restriction) || From 6decd5a7e7770090f1d86e0b3900e8b94234f3af Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Wed, 6 Oct 2021 19:20:47 -0700 Subject: [PATCH 003/275] ss-mqtt: Skip SUBSCRIBE when MQTT session is resumed --- lib/roles/mqtt/mqtt.c | 3 + lib/roles/mqtt/private-lib-roles-mqtt.h | 1 + lib/secure-streams/protocols/ss-mqtt.c | 208 ++++++++++++++---------- 3 files changed, 130 insertions(+), 82 deletions(-) diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index baad7f73bc..2a73d6f5e1 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -2272,6 +2272,9 @@ lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub) return 1; } + if (wsi->mqtt->inside_resume_session) + return 0; + if (lws_write(nwsi, start, lws_ptr_diff_size_t(p, start), LWS_WRITE_BINARY) != lws_ptr_diff(p, start)) return 1; diff --git a/lib/roles/mqtt/private-lib-roles-mqtt.h b/lib/roles/mqtt/private-lib-roles-mqtt.h index a1f5d23c32..779e2971c6 100644 --- a/lib/roles/mqtt/private-lib-roles-mqtt.h +++ b/lib/roles/mqtt/private-lib-roles-mqtt.h @@ -371,6 +371,7 @@ struct _lws_mqtt_related { uint8_t inside_payload:1; uint8_t inside_subscribe:1; uint8_t inside_unsubscribe:1; + uint8_t inside_resume_session:1; uint8_t send_puback:1; uint8_t send_pubrel:1; uint8_t send_pubrec:1; diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 2c3c522221..1cd7d09bff 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -46,6 +46,100 @@ secstream_mqtt_cleanup(lws_ss_handle_t *h) } } +static int +secstream_mqtt_subscribe(struct lws *wsi) +{ + size_t used_in, used_out, topic_limit; + lws_strexp_t exp; + char* expbuf; + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + + if (!h || !h->policy) + return -1; + + if (h->policy->u.mqtt.aws_iot) + topic_limit = LWS_MQTT_MAX_AWSIOT_TOPICLEN; + else + topic_limit = LWS_MQTT_MAX_TOPICLEN; + + if (!h->policy->u.mqtt.subscribe || wsi->mqtt->done_subscribe) + return 0; + + lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, NULL, + topic_limit); + /* + * Expand with no output first to calculate the size of + * expanded string then, allocate new buffer and expand + * again with the buffer + */ + if (lws_strexp_expand(&exp, h->policy->u.mqtt.subscribe, + strlen(h->policy->u.mqtt.subscribe), &used_in, + &used_out) != LSTRX_DONE) { + lwsl_err( + "%s, failed to expand MQTT subscribe" + " topic with no output\n", + __func__); + return 1; + } + + expbuf = lws_malloc(used_out + 1, __func__); + if (!expbuf) { + lwsl_err( + "%s, failed to allocate MQTT subscribe" + "topic", + __func__); + return 1; + } + + lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, expbuf, + used_out + 1); + + if (lws_strexp_expand(&exp, h->policy->u.mqtt.subscribe, + strlen(h->policy->u.mqtt.subscribe), &used_in, + &used_out) != LSTRX_DONE) { + lwsl_err("%s, failed to expand MQTT subscribe topic\n", + __func__); + lws_free(expbuf); + return 1; + } + lwsl_notice("%s, expbuf - %s\n", __func__, expbuf); + h->u.mqtt.sub_top.name = expbuf; + + /* + * The policy says to subscribe to something, and we + * haven't done it yet. Do it using the pre-prepared + * string-substituted version of the policy string. + */ + + lwsl_notice("%s: subscribing %s\n", __func__, + h->u.mqtt.sub_top.name); + + h->u.mqtt.sub_top.qos = h->policy->u.mqtt.qos; + memset(&h->u.mqtt.sub_info, 0, sizeof(h->u.mqtt.sub_info)); + h->u.mqtt.sub_info.num_topics = 1; + h->u.mqtt.sub_info.topic = &h->u.mqtt.sub_top; + h->u.mqtt.sub_info.topic = + lws_malloc(sizeof(lws_mqtt_topic_elem_t), __func__); + h->u.mqtt.sub_info.topic[0].name = lws_strdup(expbuf); + h->u.mqtt.sub_info.topic[0].qos = h->policy->u.mqtt.qos; + + if (lws_mqtt_client_send_subcribe(wsi, &h->u.mqtt.sub_info)) { + lwsl_notice("%s: unable to subscribe", __func__); + lws_free(expbuf); + h->u.mqtt.sub_top.name = NULL; + return -1; + } + lws_free(expbuf); + h->u.mqtt.sub_top.name = NULL; + + /* Expect a SUBACK */ + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { + lwsl_err("%s: Unable to set LWS_POLLIN\n", __func__); + return -1; + } + return 0; +} + static int secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -120,13 +214,32 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->wsi = wsi; h->retry = 0; h->seqstate = SSSEQ_CONNECTED; - /* - * If a subscribe is pending on the stream, then make - * sure the SUBSCRIBE is done before signaling the - * user application. - */ - if (h->policy->u.mqtt.subscribe && - !wsi->mqtt->done_subscribe) { + + if (!h->policy->u.mqtt.subscribe || + !h->policy->u.mqtt.subscribe[0]) { + /* + * If subscribe is empty in the policy, then, + * skip sending SUBSCRIBE and signal the user + * application. + */ + wsi->mqtt->done_subscribe = 1; + } else if (!h->policy->u.mqtt.clean_start && + wsi->mqtt->session_resumed) { + wsi->mqtt->inside_resume_session = 1; + /* + * If the previous session is resumed and Server has + * stored session, then, do not subscribe. + */ + if (!secstream_mqtt_subscribe(wsi)) + wsi->mqtt->done_subscribe = 1; + wsi->mqtt->inside_resume_session = 0; + } else if (h->policy->u.mqtt.subscribe && + !wsi->mqtt->done_subscribe) { + /* + * If a subscribe is pending on the stream, then make + * sure the SUBSCRIBE is done before signaling the + * user application. + */ lws_callback_on_writable(wsi); break; } @@ -208,79 +321,8 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, else topic_limit = LWS_MQTT_MAX_TOPICLEN; - if (h->policy->u.mqtt.subscribe && - !wsi->mqtt->done_subscribe) { - lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, - NULL, topic_limit); - /* - * Expand with no output first to calculate the size of - * expanded string then, allocate new buffer and expand - * again with the buffer - */ - if (lws_strexp_expand(&exp, h->policy->u.mqtt.subscribe, - strlen(h->policy->u.mqtt.subscribe), - &used_in, &used_out) != LSTRX_DONE) { - lwsl_err("%s, failed to expand MQTT subscribe" - " topic with no output\n", __func__); - return 1; - } - - expbuf = lws_malloc(used_out + 1, __func__); - if (!expbuf) { - lwsl_err("%s, failed to allocate MQTT subscribe" - "topic", __func__); - return 1; - } - - lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, - expbuf, used_out + 1); - - if (lws_strexp_expand(&exp, h->policy->u.mqtt.subscribe, - strlen(h->policy->u.mqtt.subscribe), - &used_in, &used_out) != LSTRX_DONE) { - lwsl_err("%s, failed to expand MQTT subscribe topic\n", - __func__); - lws_free(expbuf); - return 1; - } - lwsl_notice("%s, expbuf - %s\n", __func__, expbuf); - h->u.mqtt.sub_top.name = expbuf; - - /* - * The policy says to subscribe to something, and we - * haven't done it yet. Do it using the pre-prepared - * string-substituted version of the policy string. - */ - - lwsl_notice("%s: subscribing %s\n", __func__, - h->u.mqtt.sub_top.name); - - h->u.mqtt.sub_top.qos = h->policy->u.mqtt.qos; - memset(&h->u.mqtt.sub_info, 0, sizeof(h->u.mqtt.sub_info)); - h->u.mqtt.sub_info.num_topics = 1; - h->u.mqtt.sub_info.topic = &h->u.mqtt.sub_top; - h->u.mqtt.sub_info.topic = lws_malloc(sizeof(lws_mqtt_topic_elem_t), - __func__); - h->u.mqtt.sub_info.topic[0].name = lws_strdup(expbuf); - h->u.mqtt.sub_info.topic[0].qos = h->policy->u.mqtt.qos; - - if (lws_mqtt_client_send_subcribe(wsi, &h->u.mqtt.sub_info)) { - lwsl_notice("%s: unable to subscribe", __func__); - lws_free(expbuf); - h->u.mqtt.sub_top.name = NULL; - return -1; - } - lws_free(expbuf); - h->u.mqtt.sub_top.name = NULL; - /* Expect a SUBACK */ - if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { - lwsl_err("%s: Unable to set LWS_POLLIN\n", __func__); - return -1; - } - - return 0; - } - + if (!wsi->mqtt->done_subscribe && h->policy->u.mqtt.subscribe) + return secstream_mqtt_subscribe(wsi); buflen = sizeof(buf) - LWS_PRE; r = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, @@ -308,8 +350,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); memset(&mqpp, 0, sizeof(mqpp)); - /* this is the string-substituted h->policy->u.mqtt.topic */ - mqpp.topic = (char *)h->u.mqtt.topic_qos.name; + lws_strexp_init(&exp, h, lws_ss_exp_cb_metadata, NULL, topic_limit); @@ -513,6 +554,9 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, */ for (n = 0; n < (int)LWS_ARRAY_SIZE(sources); n++) { + if (!sources[n]) + continue; + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, NULL, (size_t)-1); if (lws_strexp_expand(&exp, sources[n], strlen(sources[n]), From bf5744ab0742d820b4f5ce01d4da75f1fd3430de Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Wed, 6 Oct 2021 20:09:40 -0700 Subject: [PATCH 004/275] ss-mqtt: Add support for Birth message This provides Birth message on SS policy. The Birth message is a message published just after the MQTT connection has been established. --- include/libwebsockets/lws-mqtt.h | 7 + .../libwebsockets/lws-secure-streams-policy.h | 5 + lib/roles/mqtt/mqtt.c | 17 +- lib/roles/mqtt/private-lib-roles-mqtt.h | 2 + lib/secure-streams/policy-json.c | 23 ++ lib/secure-streams/protocols/ss-mqtt.c | 196 +++++++++++------- 6 files changed, 164 insertions(+), 86 deletions(-) diff --git a/include/libwebsockets/lws-mqtt.h b/include/libwebsockets/lws-mqtt.h index 71193e6628..eb9dcbb2a7 100644 --- a/include/libwebsockets/lws-mqtt.h +++ b/include/libwebsockets/lws-mqtt.h @@ -81,6 +81,13 @@ typedef struct lws_mqtt_client_connect_param_s { uint8_t retain; } will_param; /* MQTT LWT parameters */ + struct { + const char *topic; + const char *message; + lws_mqtt_qos_levels_t qos; + uint8_t retain; + } birth_param; /* MQTT Birth + parameters */ const char *username; const char *password; uint8_t aws_iot; diff --git a/include/libwebsockets/lws-secure-streams-policy.h b/include/libwebsockets/lws-secure-streams-policy.h index f84edec993..863140d74b 100644 --- a/include/libwebsockets/lws-secure-streams-policy.h +++ b/include/libwebsockets/lws-secure-streams-policy.h @@ -312,11 +312,16 @@ typedef struct lws_ss_policy { const char *will_topic; const char *will_message; + const char *birth_topic; + const char *birth_message; + uint16_t keep_alive; uint8_t qos; uint8_t clean_start; uint8_t will_qos; uint8_t will_retain; + uint8_t birth_qos; + uint8_t birth_retain; uint8_t aws_iot; } mqtt; diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index 2a73d6f5e1..b661343622 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -2038,17 +2038,12 @@ lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, return 1; } } - /* - * A non-empty Payload is expected and a chunk - * is present - */ - if (pub->payload_len && len) { - p = lws_mqtt_str_next(&mqtt_vh_payload, NULL); - memcpy(p, buf, len); - if (lws_mqtt_str_advance(&mqtt_vh_payload, (int)len)) - return 1; - p = lws_mqtt_str_next(&mqtt_vh_payload, NULL); - } + + p = lws_mqtt_str_next(&mqtt_vh_payload, NULL); + memcpy(p, buf, len); + if (lws_mqtt_str_advance(&mqtt_vh_payload, (int)len)) + return 1; + p = lws_mqtt_str_next(&mqtt_vh_payload, NULL); if (!is_complete) nwsi->mqtt->inside_payload = wsi->mqtt->inside_payload = 1; diff --git a/lib/roles/mqtt/private-lib-roles-mqtt.h b/lib/roles/mqtt/private-lib-roles-mqtt.h index 779e2971c6..d89f371879 100644 --- a/lib/roles/mqtt/private-lib-roles-mqtt.h +++ b/lib/roles/mqtt/private-lib-roles-mqtt.h @@ -371,6 +371,7 @@ struct _lws_mqtt_related { uint8_t inside_payload:1; uint8_t inside_subscribe:1; uint8_t inside_unsubscribe:1; + uint8_t inside_birth:1; uint8_t inside_resume_session:1; uint8_t send_puback:1; uint8_t send_pubrel:1; @@ -380,6 +381,7 @@ struct _lws_mqtt_related { uint8_t unacked_pubrel:1; uint8_t done_subscribe:1; + uint8_t done_birth:1; }; /* diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index c49879e1eb..3427ae6d44 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -117,6 +117,10 @@ static const char * const lejp_tokens_policy[] = { "s[].*.mqtt_will_message", "s[].*.mqtt_will_qos", "s[].*.mqtt_will_retain", + "s[].*.mqtt_birth_topic", + "s[].*.mqtt_birth_message", + "s[].*.mqtt_birth_qos", + "s[].*.mqtt_birth_retain", "s[].*.aws_iot", "s[].*.swake_validity", "s[].*.use_auth", @@ -220,6 +224,10 @@ typedef enum { LSSPPT_MQTT_WILL_MESSAGE, LSSPPT_MQTT_WILL_QOS, LSSPPT_MQTT_WILL_RETAIN, + LSSPPT_MQTT_BIRTH_TOPIC, + LSSPPT_MQTT_BIRTH_MESSAGE, + LSSPPT_MQTT_BIRTH_QOS, + LSSPPT_MQTT_BIRTH_RETAIN, LSSPPT_MQTT_AWS_IOT, LSSPPT_SWAKE_VALIDITY, LSSPPT_USE_AUTH, @@ -1035,6 +1043,21 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->u.mqtt.will_retain = reason == LEJPCB_VAL_TRUE; break; + case LSSPPT_MQTT_BIRTH_TOPIC: + pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.birth_topic; + goto string2; + + case LSSPPT_MQTT_BIRTH_MESSAGE: + pp = (char **)&a->curr[LTY_POLICY].p->u.mqtt.birth_message; + goto string2; + + case LSSPPT_MQTT_BIRTH_QOS: + a->curr[LTY_POLICY].p->u.mqtt.birth_qos = (uint8_t)atoi(ctx->buf); + break; + case LSSPPT_MQTT_BIRTH_RETAIN: + a->curr[LTY_POLICY].p->u.mqtt.birth_retain = + reason == LEJPCB_VAL_TRUE; + break; case LSSPPT_MQTT_AWS_IOT: if (reason == LEJPCB_VAL_TRUE) a->curr[LTY_POLICY].p->u.mqtt.aws_iot = diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 1cd7d09bff..f13eea4a57 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -140,15 +140,85 @@ secstream_mqtt_subscribe(struct lws *wsi) return 0; } +static int +secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buflen, + const char* topic, + lws_mqtt_qos_levels_t qos, int f) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + size_t used_in, used_out, topic_limit; + lws_strexp_t exp; + char *expbuf; + lws_mqtt_publish_param_t mqpp; + + if (h->policy->u.mqtt.aws_iot) + topic_limit = LWS_MQTT_MAX_AWSIOT_TOPICLEN; + else + topic_limit = LWS_MQTT_MAX_TOPICLEN; + + memset(&mqpp, 0, sizeof(mqpp)); + + lws_strexp_init(&exp, h, lws_ss_exp_cb_metadata, NULL, + topic_limit); + + if (lws_strexp_expand(&exp, topic, strlen(topic), &used_in, + &used_out) != LSTRX_DONE) { + lwsl_err("%s, failed to expand MQTT publish" + " topic with no output\n", __func__); + return 1; + } + expbuf = lws_malloc(used_out + 1, __func__); + if (!expbuf) { + lwsl_err("%s, failed to allocate MQTT publish topic", + __func__); + return 1; + } + + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, expbuf, + used_out + 1); + + if (lws_strexp_expand(&exp, topic, strlen(topic), &used_in, + &used_out) != LSTRX_DONE) { + lws_free(expbuf); + return 1; + } + lwsl_notice("%s, expbuf - %s\n", __func__, expbuf); + mqpp.topic = (char *)expbuf; + + mqpp.topic_len = (uint16_t)strlen(mqpp.topic); + mqpp.packet_id = (uint16_t)(h->txord - 1); + mqpp.payload = buf; + if (h->writeable_len) + mqpp.payload_len = (uint32_t)h->writeable_len; + else + mqpp.payload_len = (uint32_t)buflen; + + lwsl_notice("%s: payload len %d\n", __func__, + (int)mqpp.payload_len); + + mqpp.qos = h->policy->u.mqtt.qos; + + if (lws_mqtt_client_send_publish(wsi, &mqpp, + (const char *)buf, + (uint32_t)buflen, + f & LWSSS_FLAG_EOM)) { + lwsl_notice("%s: failed to publish\n", __func__); + lws_free(expbuf); + return -1; + } + lws_free(expbuf); + return 0; +} + static int secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); - lws_mqtt_publish_param_t mqpp, *pmqpp; + lws_mqtt_publish_param_t *pmqpp; uint8_t buf[LWS_PRE + 1400]; lws_ss_state_return_t r; - size_t buflen; + size_t buflen = sizeof(buf) - LWS_PRE; int f = 0; switch (reason) { @@ -288,8 +358,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_sul_cancel(&h->sul); r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); if (r != LWSSSSRET_OK) - return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, - wsi, &h); + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); } wsi->mqtt->done_subscribe = 1; lws_callback_on_writable(wsi); @@ -297,6 +366,14 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_MQTT_ACK: lws_sul_cancel(&h->sul_timeout); + if (wsi->mqtt->inside_birth) { + /* + * Skip LWSSSCS_QOS_ACK_REMOTE for birth topic. + */ + wsi->mqtt->inside_birth = 0; + wsi->mqtt->done_birth = 1; + break; + } r = lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE); if (r != LWSSSSRET_OK) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); @@ -304,10 +381,6 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_MQTT_CLIENT_WRITEABLE: { - size_t used_in, used_out, topic_limit; - lws_strexp_t exp; - char *expbuf; - if (!h || !h->info.tx) return 0; lwsl_notice("%s: %s: WRITEABLE\n", __func__, lws_ss_tag(h)); @@ -316,17 +389,29 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, lwsl_warn("%s: seqstate %d\n", __func__, h->seqstate); break; } - if (h->policy->u.mqtt.aws_iot) - topic_limit = LWS_MQTT_MAX_AWSIOT_TOPICLEN; - else - topic_limit = LWS_MQTT_MAX_TOPICLEN; if (!wsi->mqtt->done_subscribe && h->policy->u.mqtt.subscribe) return secstream_mqtt_subscribe(wsi); - buflen = sizeof(buf) - LWS_PRE; + if (!wsi->mqtt->done_birth && h->policy->u.mqtt.birth_topic) { + lws_strexp_t exp; + size_t used_in, used_out = 0; + if (h->policy->u.mqtt.birth_message) { + lws_strexp_init(&exp, h, lws_ss_exp_cb_metadata, + (char *)(buf + LWS_PRE), buflen); + if (lws_strexp_expand(&exp, h->policy->u.mqtt.birth_message, + strlen(h->policy->u.mqtt.birth_message), + &used_in, &used_out) != LSTRX_DONE) { + return 1; + } + } + wsi->mqtt->inside_birth = 1; + return secstream_mqtt_publish(wsi, buf + LWS_PRE, + used_out, h->policy->u.mqtt.birth_topic, + h->policy->u.mqtt.birth_qos, LWSSS_FLAG_EOM); + } r = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, - &buflen, &f); + &buflen, &f); if (r == LWSSSSRET_TX_DONT_SEND) return 0; @@ -349,62 +434,9 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (r < 0) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); - memset(&mqpp, 0, sizeof(mqpp)); - - lws_strexp_init(&exp, h, lws_ss_exp_cb_metadata, NULL, - topic_limit); - - if (lws_strexp_expand(&exp, h->policy->u.mqtt.topic, - strlen(h->policy->u.mqtt.topic), - &used_in, &used_out) != LSTRX_DONE) { - lwsl_err("%s, failed to expand MQTT publish" - " topic with no output\n", __func__); - return 1; - } - expbuf = lws_malloc(used_out + 1, __func__); - if (!expbuf) { - lwsl_err("%s, failed to allocate MQTT publish topic", - __func__); - return 1; - } - - lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, expbuf, - used_out + 1); - - if (lws_strexp_expand(&exp, h->policy->u.mqtt.topic, - strlen(h->policy->u.mqtt.topic), &used_in, - &used_out) != LSTRX_DONE) { - lws_free(expbuf); - return 1; - } - lwsl_notice("%s, expbuf - %s\n", __func__, expbuf); - mqpp.topic = (char *)expbuf; - - mqpp.topic_len = (uint16_t)strlen(mqpp.topic); - mqpp.packet_id = (uint16_t)(h->txord - 1); - mqpp.payload = buf + LWS_PRE; - if (h->writeable_len) - mqpp.payload_len = (uint32_t)h->writeable_len; - else - mqpp.payload_len = (uint32_t)buflen; - - lwsl_notice("%s: payload len %d\n", __func__, - (int)mqpp.payload_len); - - mqpp.qos = h->policy->u.mqtt.qos; - - if (lws_mqtt_client_send_publish(wsi, &mqpp, - (const char *)buf + LWS_PRE, - (uint32_t)buflen, - f & LWSSS_FLAG_EOM)) { - lwsl_notice("%s: failed to publish\n", __func__); - lws_free(expbuf); - - return -1; - } - lws_free(expbuf); - - return 0; + return secstream_mqtt_publish(wsi, buf + LWS_PRE, buflen, + h->policy->u.mqtt.topic, + h->policy->u.mqtt.qos, f); } case LWS_CALLBACK_MQTT_UNSUBSCRIBED: @@ -450,7 +482,9 @@ enum { SSCMM_STRSUB_WILL_TOPIC, SSCMM_STRSUB_WILL_MESSAGE, SSCMM_STRSUB_SUBSCRIBE, - SSCMM_STRSUB_TOPIC + SSCMM_STRSUB_TOPIC, + SSCMM_STRSUB_BIRTH_TOPIC, + SSCMM_STRSUB_BIRTH_MESSAGE }; static int @@ -458,16 +492,18 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, struct lws_client_connect_info *i, union lws_ss_contemp *ct) { - const char *sources[4] = { + const char *sources[6] = { /* we're going to string-substitute these before use */ h->policy->u.mqtt.will_topic, h->policy->u.mqtt.will_message, h->policy->u.mqtt.subscribe, - h->policy->u.mqtt.topic + h->policy->u.mqtt.topic, + h->policy->u.mqtt.birth_topic, + h->policy->u.mqtt.birth_message }; - size_t used_in, olen[4] = { 0, 0, 0, 0 }, tot = 0; + size_t used_in, olen[6] = { 0, 0, 0, 0, 0, 0 }, tot = 0; lws_strexp_t exp; - char *ps[4]; + char *ps[6]; uint8_t *p = NULL; int n = -1; size_t blen; @@ -485,6 +521,8 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, return -1; } p = (uint8_t *)lws_zalloc(blen+1, __func__); + if (!p) + return -1; n = lws_system_blob_get(b, p, &blen, 0); if (n) { ct->ccp.client_id = NULL; @@ -504,6 +542,8 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, /* If LWS_SYSBLOB_TYPE_MQTT_USERNAME is set */ if (b && (blen = lws_system_blob_get_size(b))) { p = (uint8_t *)lws_zalloc(blen+1, __func__); + if (!p) + return -1; n = lws_system_blob_get(b, p, &blen, 0); if (n) { ct->ccp.username = NULL; @@ -520,6 +560,8 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, /* If LWS_SYSBLOB_TYPE_MQTT_PASSWORD is set */ if (b && (blen = lws_system_blob_get_size(b))) { p = (uint8_t *)lws_zalloc(blen+1, __func__); + if (!p) + return -1; n = lws_system_blob_get(b, p, &blen, 0); if (n) { ct->ccp.password = NULL; @@ -534,6 +576,8 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, ct->ccp.clean_start = (h->policy->u.mqtt.clean_start & 1u); ct->ccp.will_param.qos = h->policy->u.mqtt.will_qos; ct->ccp.will_param.retain = h->policy->u.mqtt.will_retain; + ct->ccp.birth_param.qos = h->policy->u.mqtt.birth_qos; + ct->ccp.birth_param.retain = h->policy->u.mqtt.birth_retain; ct->ccp.aws_iot = h->policy->u.mqtt.aws_iot; h->u.mqtt.topic_qos.qos = h->policy->u.mqtt.qos; @@ -608,6 +652,8 @@ secstream_connect_munge_mqtt(lws_ss_handle_t *h, char *buf, size_t len, h->u.mqtt.subscribe_to = ps[SSCMM_STRSUB_SUBSCRIBE]; h->u.mqtt.subscribe_to_len = olen[SSCMM_STRSUB_SUBSCRIBE]; h->u.mqtt.topic_qos.name = ps[SSCMM_STRSUB_TOPIC]; + ct->ccp.birth_param.topic = ps[SSCMM_STRSUB_BIRTH_TOPIC]; + ct->ccp.birth_param.message = ps[SSCMM_STRSUB_BIRTH_MESSAGE]; i->method = "MQTT"; i->mqtt_cp = &ct->ccp; From a75fc1aae86adb2affd977cf76a12e8929ed81c1 Mon Sep 17 00:00:00 2001 From: caobug <7737673+caobug@users.noreply.github.com> Date: Thu, 7 Oct 2021 11:01:00 +0100 Subject: [PATCH 005/275] uv: handle uv_poll_init failure --- lib/event-libs/libuv/libuv.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/event-libs/libuv/libuv.c b/lib/event-libs/libuv/libuv.c index 6ae5d3eed3..dad371aac3 100644 --- a/lib/event-libs/libuv/libuv.c +++ b/lib/event-libs/libuv/libuv.c @@ -424,7 +424,8 @@ static int elops_wsi_logical_close_uv(struct lws *wsi) { if (!lws_socket_is_valid(wsi->desc.sockfd) && - wsi->role_ops && strcmp(wsi->role_ops->name, "raw-file")) + wsi->role_ops && strcmp(wsi->role_ops->name, "raw-file") && + !wsi_to_priv_uv(wsi)->w_read.pwatcher) return 0; if (wsi->listener || wsi->event_pipe) { @@ -495,6 +496,7 @@ elops_accept_uv(struct lws *wsi) struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt); struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read; + int n; if (!ptpriv->thread_valid) { /* record the thread id that gave us our first event */ @@ -509,12 +511,20 @@ elops_accept_uv(struct lws *wsi) return -1; if (wsi->role_ops->file_handle) - uv_poll_init(pt_to_priv_uv(pt)->io_loop, w_read->pwatcher, + n = uv_poll_init(pt_to_priv_uv(pt)->io_loop, w_read->pwatcher, (int)(lws_intptr_t)wsi->desc.filefd); else - uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop, + n = uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop, w_read->pwatcher, wsi->desc.sockfd); + if (n) { + lwsl_wsi_err(wsi, "uv_poll_init failed %d, sockfd=%p", n, + (void *)(lws_intptr_t)wsi->desc.sockfd); + lws_free(w_read->pwatcher); + w_read->pwatcher = NULL; + return -1; + } + ((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi; ptpriv->extant_handles++; From 05e9362df225d196cd9ea3b196f69dfc4890e542 Mon Sep 17 00:00:00 2001 From: Pavel Otchertsov Date: Thu, 7 Oct 2021 14:29:01 +0300 Subject: [PATCH 006/275] context: fix compilation error --- lib/core/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core/context.c b/lib/core/context.c index c517294a30..ab6afa382c 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -688,7 +688,7 @@ lws_create_context(const struct lws_context_creation_info *info) context->lcg[LWSLCG_WSI_SERVER].tag_prefix = "wsisrv"; /* adopted */ #if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT) - context->lcg[LWSLCG_WSI_MUX].tag_prefix = "mux", /* a mux child wsi */ + context->lcg[LWSLCG_WSI_MUX].tag_prefix = "mux"; /* a mux child wsi */ #endif #if defined(LWS_WITH_CLIENT) From df008ef6ce219696046198654fa4999e1537da61 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 8 Oct 2021 09:18:30 +0100 Subject: [PATCH 007/275] freertos: suppress return check on xSemaphoreTake With the timeout set to portMAX_DELAY, there is no timeout and so no way for the api to return failure. https://www.freertos.org/a00122.html However Coverity doesn't understand this, and futher, Coverity usually ignores (void) result casts. So add needless checks and the corresponding needless unwinding to the 10 uses of lws_mutex_lock() in smd.c. Invert the return value to align it with pthreads mutex lock return semantics. --- lib/plat/freertos/private-lib-plat-freertos.h | 2 +- lib/system/smd/smd.c | 44 +++++++++++++------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/lib/plat/freertos/private-lib-plat-freertos.h b/lib/plat/freertos/private-lib-plat-freertos.h index 9589f98855..d544e2b112 100644 --- a/lib/plat/freertos/private-lib-plat-freertos.h +++ b/lib/plat/freertos/private-lib-plat-freertos.h @@ -76,7 +76,7 @@ gai_strerror(int); typedef SemaphoreHandle_t lws_mutex_t; #define lws_mutex_init(x) x = xSemaphoreCreateMutex() #define lws_mutex_destroy(x) vSemaphoreDelete(x) -#define lws_mutex_lock(x) xSemaphoreTake(x, portMAX_DELAY) +#define lws_mutex_lock(x) (!xSemaphoreTake(x, portMAX_DELAY)) /*0 = OK */ #define lws_mutex_unlock(x) xSemaphoreGive(x) #include diff --git a/lib/system/smd/smd.c b/lib/system/smd/smd.c index de7af193a7..89421d4f19 100644 --- a/lib/system/smd/smd.c +++ b/lib/system/smd/smd.c @@ -206,8 +206,9 @@ _lws_smd_msg_send(struct lws_context *ctx, void *pay, struct lws_smd_peer *exc) return 1; } - if (!ctx->smd.delivering) - lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + if (!ctx->smd.delivering && + lws_mutex_lock(ctx->smd.lock_peers)) /* +++++++++++++++ peers */ + return 1; /* For Coverity */ msg->refcount = (uint16_t)_lws_smd_msg_assess_peers_interested( &ctx->smd, msg, exc); @@ -224,7 +225,8 @@ _lws_smd_msg_send(struct lws_context *ctx, void *pay, struct lws_smd_peer *exc) /* let's add him on the queue... */ - lws_mutex_lock(ctx->smd.lock_messages); /* +++++++++++++++++ messages */ + if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++++++++++ messages */ + goto bail; lws_dll2_add_tail(&msg->list, &ctx->smd.owner_messages); /* @@ -252,6 +254,7 @@ _lws_smd_msg_send(struct lws_context *ctx, void *pay, struct lws_smd_peer *exc) lws_mutex_unlock(ctx->smd.lock_messages); /* --------------- messages */ +bail: if (!ctx->smd.delivering) lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ @@ -455,7 +458,8 @@ _lws_smd_peer_destroy(lws_smd_peer_t *pr) lws_smd_t *smd = lws_container_of(pr->list.owner, lws_smd_t, owner_peers); - lws_mutex_lock(smd->lock_messages); /* +++++++++ messages */ + if (lws_mutex_lock(smd->lock_messages)) /* +++++++++ messages */ + return; /* For Coverity */ lws_dll2_remove(&pr->list); @@ -546,7 +550,9 @@ _lws_smd_msg_deliver_peer(struct lws_context *ctx, lws_smd_peer_t *pr) /* tail message has to actually be of interest to the peer */ assert(!pr->tail || (pr->tail->_class & pr->_class_filter)); - lws_mutex_lock(ctx->smd.lock_messages); /* +++++++++ messages */ + if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++ messages */ + return 1; /* For Coverity */ + if (!--msg->refcount) _lws_smd_msg_destroy(ctx, &ctx->smd, msg); lws_mutex_unlock(ctx->smd.lock_messages); /* messages ------- */ @@ -573,7 +579,8 @@ lws_smd_msg_distribute(struct lws_context *ctx) do { more = 0; - lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + if (lws_mutex_lock(ctx->smd.lock_peers)) /* +++++++++++++++ peers */ + return 1; /* For Coverity */ lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, ctx->smd.owner_peers.head) { @@ -605,14 +612,21 @@ lws_smd_register(struct lws_context *ctx, void *opaque, int flags, pr->_class_filter = _class_filter; pr->ctx = ctx; - if (!ctx->smd.delivering) - lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++ peers */ + if (!ctx->smd.delivering && + lws_mutex_lock(ctx->smd.lock_peers)) { /* +++++++++++++++ peers */ + lws_free(pr); + return NULL; /* For Coverity */ + } /* * Let's lock the message list before adding this peer... because... */ - lws_mutex_lock(ctx->smd.lock_messages); /* +++++++++ messages */ + if (lws_mutex_lock(ctx->smd.lock_messages)) { /* +++++++++ messages */ + lws_free(pr); + pr = NULL; + goto bail1; /* For Coverity */ + } lws_dll2_add_tail(&pr->list, &ctx->smd.owner_peers); @@ -642,6 +656,7 @@ lws_smd_register(struct lws_context *ctx, void *opaque, int flags, lwsl_cx_info(ctx, "peer %p (count %u) registered", pr, (unsigned int)ctx->smd.owner_peers.count); +bail1: if (!ctx->smd.delivering) lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ @@ -653,8 +668,9 @@ lws_smd_unregister(struct lws_smd_peer *pr) { lws_smd_t *smd = lws_container_of(pr->list.owner, lws_smd_t, owner_peers); - if (!smd->delivering) - lws_mutex_lock(smd->lock_peers); /* +++++++++++++++++++ peers */ + if (!smd->delivering && + lws_mutex_lock(smd->lock_peers)) /* +++++++++++++++++++ peers */ + return; /* For Coverity */ lwsl_cx_notice(pr->ctx, "destroying peer %p", pr); _lws_smd_peer_destroy(pr); if (!smd->delivering) @@ -679,8 +695,10 @@ lws_smd_message_pending(struct lws_context *ctx) * have been hanging around too long */ - lws_mutex_lock(ctx->smd.lock_peers); /* +++++++++++++++++++++++ peers */ - lws_mutex_lock(ctx->smd.lock_messages); /* +++++++++++++++++ messages */ + if (lws_mutex_lock(ctx->smd.lock_peers)) /* +++++++++++++++++++++++ peers */ + return 1; /* For Coverity */ + if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++++++++++ messages */ + goto bail; /* For Coverity */ lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, ctx->smd.owner_messages.head) { From 361a07c8f49590e0094ecf9db909bdaa96652638 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 9 Oct 2021 07:36:37 +0100 Subject: [PATCH 008/275] minimal: esp32: wrover display: increase smd timeout to cover delays in display --- .../embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c | 1 + 1 file changed, 1 insertion(+) diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c b/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c index db891ebdcb..5843317b68 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c @@ -209,6 +209,7 @@ app_main(void) info->early_smd_class_filter = LWSSMDCL_INTERACTION | LWSSMDCL_SYSTEM_STATE | LWSSMDCL_NETWORK; + info->smd_ttl_us = 20 * LWS_USEC_PER_SEC; /* we can spend a long time in display */ context = lws_create_context(info); if (!context) { From 3b4c9aaeb31a407eb9a03a6f2a945eca2286ef27 Mon Sep 17 00:00:00 2001 From: Yichen Gu Date: Mon, 11 Oct 2021 09:04:46 +0100 Subject: [PATCH 009/275] lecp: remove extra struct lws_lec_pctx fwd definitions C++ compilers set to less than C11 may choke on it, it's anyway not needed any more since no references between that and the actual definition. --- include/libwebsockets/lws-lecp.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/libwebsockets/lws-lecp.h b/include/libwebsockets/lws-lecp.h index 04de86add1..8133e4b148 100644 --- a/include/libwebsockets/lws-lecp.h +++ b/include/libwebsockets/lws-lecp.h @@ -300,9 +300,6 @@ struct lecp_ctx { char buf[LECP_STRING_CHUNK + 1]; }; -struct lws_lec_pctx; -typedef struct lws_lec_pctx lws_lec_pctx_t; - enum lws_lec_pctx_ret { LWS_LECPCTX_RET_FINISHED = 0, LWS_LECPCTX_RET_AGAIN, /* call again to continue writing buffer */ From fad2bdbeeabda9f02a1fb9c0ae9ff047105d2cc1 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Mon, 11 Oct 2021 11:16:01 -0400 Subject: [PATCH 010/275] Teach client-ws.c about log contexts. --- lib/roles/ws/client-ws.c | 93 +++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 50 deletions(-) diff --git a/lib/roles/ws/client-ws.c b/lib/roles/ws/client-ws.c index afacb4962d..bc2a84682a 100644 --- a/lib/roles/ws/client-ws.c +++ b/lib/roles/ws/client-ws.c @@ -51,7 +51,7 @@ lws_create_client_ws_object(const struct lws_client_connect_info *i, /* allocate the ws struct for the wsi */ wsi->ws = lws_zalloc(sizeof(*wsi->ws), "client ws struct"); if (!wsi->ws) { - lwsl_notice("OOM\n"); + lwsl_wsi_notice(wsi, "OOM"); return 1; } @@ -77,14 +77,14 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) !lwsi_role_client(wsi)) return 0; - lwsl_debug("%s: hs client feels it has %d in\n", __func__, (int)len); + lwsl_wsi_debug(wsi, "hs client feels it has %d in", (int)len); while (len) { /* * we were accepting input but now we stopped doing so */ if (lws_is_flowcontrolled(wsi)) { - lwsl_debug("%s: caching %ld\n", __func__, (long)len); + lwsl_wsi_debug(wsi, "caching %ld", (long)len); /* * Since we cached the remaining available input, we * can say we "consumed" it. @@ -103,8 +103,7 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) * indicate we didn't use anything to the caller * so he doesn't do any consumed processing */ - lwsl_info("%s: trimming inside rxflow cache\n", - __func__); + lwsl_wsi_info(wsi, "trimming inside rxflow cache"); *buf = bufin; } else *buf += len; @@ -115,7 +114,7 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) if (wsi->ws->rx_draining_ext) { int m; - lwsl_info("%s: draining ext\n", __func__); + lwsl_wsi_info(wsi, "draining ext"); if (lwsi_role_client(wsi)) m = lws_ws_client_rx_sm(wsi, 0); else @@ -131,13 +130,13 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) */ if (lws_ws_client_rx_sm(wsi, *(*buf)++)) { - lwsl_info("%s: client_rx_sm exited, DROPPING %d\n", - __func__, (int)len); + lwsl_wsi_info(wsi, "client_rx_sm exited, DROPPING %d", + (int)len); return -1; } len--; } - // lwsl_notice("%s: finished with %ld\n", __func__, (long)len); + // lwsl_wsi_notice(wsi, "finished with %ld", (long)len); return 0; } @@ -157,7 +156,7 @@ lws_generate_client_ws_handshake(struct lws *wsi, char *p, const char *conn1) * create the random key */ if (lws_get_random(wsi->a.context, hash, 16) != 16) { - lwsl_err("Unable to read from random dev %s\n", + lwsl_wsi_err(wsi, "Unable to read from random dev %s", SYSTEM_RANDOM_FILEPATH); return NULL; } @@ -252,44 +251,40 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) #endif if (wsi->client_mux_substream) {/* !!! client ws-over-h2 not there yet */ - lwsl_warn("%s: client ws-over-h2 upgrade not supported yet\n", - __func__); + lwsl_wsi_warn(wsi, "client ws-over-h2 upgrade not supported yet"); *cce = "HS: h2 / ws upgrade unsupported"; goto bail3; } if (wsi->http.ah->http_response == 401) { - lwsl_warn( - "lws_client_handshake: got bad HTTP response '%d'\n", - wsi->http.ah->http_response); + lwsl_wsi_warn(wsi, "got bad HTTP response '%d'", + wsi->http.ah->http_response); *cce = "HS: ws upgrade unauthorized"; goto bail3; } if (wsi->http.ah->http_response != 101) { - lwsl_warn( - "lws_client_handshake: got bad HTTP response '%d'\n", - wsi->http.ah->http_response); + lwsl_wsi_warn(wsi, "got bad HTTP response '%d'", + wsi->http.ah->http_response); *cce = "HS: ws upgrade response not 101"; goto bail3; } if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) { - lwsl_info("no ACCEPT\n"); + lwsl_wsi_info(wsi, "no ACCEPT"); *cce = "HS: ACCEPT missing"; goto bail3; } p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE); if (!p) { - lwsl_info("no UPGRADE\n"); + lwsl_wsi_info(wsi, "no UPGRADE"); *cce = "HS: UPGRADE missing"; goto bail3; } strtolower(p); if (strcmp(p, "websocket")) { - lwsl_warn( - "lws_client_handshake: got bad Upgrade header '%s'\n", p); + lwsl_wsi_warn(wsi, "got bad Upgrade header '%s'", p); *cce = "HS: Upgrade to something other than websocket"; goto bail3; } @@ -316,8 +311,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) default: /* includes ENDED found by the tokenizer itself */ bad_conn_format: - lwsl_info("%s: malfored connection '%s'\n", - __func__, buf); + lwsl_wsi_info(wsi, "malformed connection '%s'", buf); *cce = "HS: UPGRADE malformed"; goto bail3; } @@ -325,10 +319,10 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS); #if defined(_DEBUG) - if (!pc) { - lwsl_parser("lws_client_int_s_hs: no protocol list\n"); - } else - lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc); + if (!pc) + lwsl_wsi_parser(wsi, "lws_client_int_s_hs: no protocol list"); + else + lwsl_wsi_parser(wsi, "lws_client_int_s_hs: protocol list '%s'", pc); #endif /* @@ -338,7 +332,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL); if (!len) { - lwsl_info("%s: WSI_TOKEN_PROTOCOL is null\n", __func__); + lwsl_wsi_info(wsi, "WSI_TOKEN_PROTOCOL is null"); /* * no protocol name to work from, if we don't already have one * default to first protocol @@ -372,7 +366,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) } if (!okay) { - lwsl_info("%s: got bad protocol %s\n", __func__, p); + lwsl_wsi_info(wsi, "got bad protocol %s", p); *cce = "HS: PROTOCOL malformed"; goto bail2; } @@ -404,7 +398,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) if (n == wsi->a.vhost->count_protocols) { /* no match */ /* if server, that's already fatal */ if (!lwsi_role_client(wsi)) { - lwsl_info("%s: fail protocol %s\n", __func__, p); + lwsl_wsi_info(wsi, "fail protocol %s", p); *cce = "HS: Cannot match protocol"; goto bail2; } @@ -423,16 +417,16 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) if (!wsi->a.vhost->protocols[n].callback) { if (wsi->a.protocol) - lwsl_err("Failed to match protocol %s\n", + lwsl_wsi_err(wsi, "Failed to match protocol %s", wsi->a.protocol->name); else - lwsl_err("No protocol on client\n"); + lwsl_wsi_err(wsi, "No protocol on client"); *cce = "ws protocol no match"; goto bail2; } } - lwsl_debug("Selected protocol %s\n", wsi->a.protocol ? + lwsl_wsi_debug(wsi, "Selected protocol %s", wsi->a.protocol ? wsi->a.protocol->name : "no pcol"); check_extensions: @@ -450,7 +444,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) /* instantiate the accepted extensions */ if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) { - lwsl_ext("no client extensions allowed by server\n"); + lwsl_wsi_ext(wsi, "no client extensions allowed by server"); goto check_accept; } @@ -461,7 +455,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) if (lws_hdr_copy(wsi, sb, (int)context->pt_serv_buf_size, WSI_TOKEN_EXTENSIONS) < 0) { - lwsl_warn("ext list from server failed to copy\n"); + lwsl_wsi_warn(wsi, "ext list from server failed to copy"); *cce = "HS: EXT: list too big"; goto bail2; } @@ -500,7 +494,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) /* check we actually support it */ - lwsl_notice("checking client ext %s\n", ext_name); + lwsl_wsi_notice(wsi, "checking client ext %s", ext_name); n = 0; ext = wsi->a.vhost->ws.extensions; @@ -511,7 +505,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) } n = 1; - lwsl_notice("instantiating client ext %s\n", ext_name); + lwsl_wsi_notice(wsi, "instantiating client ext %s", ext_name); /* instantiate the extension on this conn */ @@ -524,7 +518,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) (void *)&wsi->ws->act_ext_user[ wsi->ws->count_act_ext], (void *)&opts, 0)) { - lwsl_info(" ext %s failed construction\n", + lwsl_wsi_info(wsi, " ext %s failed construction", ext_name); ext++; continue; @@ -549,8 +543,8 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) wsi->ws->count_act_ext], opts, ext_name, (int)strlen(ext_name))) { - lwsl_err("%s: unable to parse user defaults '%s'", - __func__, ext_name); + lwsl_wsi_err(wsi, "unable to parse user defaults '%s'", + ext_name); *cce = "HS: EXT: failed parsing defaults"; goto bail2; } @@ -562,8 +556,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) wsi->ws->act_ext_user[ wsi->ws->count_act_ext], opts, a, lws_ptr_diff(c, a))) { - lwsl_err("%s: unable to parse remote def '%s'", - __func__, a); + lwsl_wsi_err(wsi, "unable to parse remote def '%s'", a); *cce = "HS: EXT: failed parsing options"; goto bail2; } @@ -572,8 +565,8 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) LWS_EXT_CB_OPTION_CONFIRM, wsi->ws->act_ext_user[wsi->ws->count_act_ext], NULL, 0)) { - lwsl_err("%s: ext %s rejects server options %s", - __func__, ext->name, a); + lwsl_wsi_err(wsi, "ext %s rejects server options %s", + ext->name, a); *cce = "HS: EXT: Rejects server options"; goto bail2; } @@ -584,7 +577,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) } if (n == 0) { - lwsl_warn("Unknown ext '%s'!\n", ext_name); + lwsl_wsi_warn(wsi, "Unknown ext '%s'!", ext_name); *cce = "HS: EXT: unknown ext"; goto bail2; } @@ -602,7 +595,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT); if (strcmp(p, wsi->http.ah->initial_handshake_hash_base64)) { - lwsl_warn("lws_client_int_s_hs: accept '%s' wrong vs '%s'\n", p, + lwsl_wsi_warn(wsi, "lws_client_int_s_hs: accept '%s' wrong vs '%s'", p, wsi->http.ah->initial_handshake_hash_base64); *cce = "HS: Accept hash wrong"; goto bail2; @@ -610,7 +603,7 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) /* allocate the per-connection user memory (if any) */ if (lws_ensure_user_space(wsi)) { - lwsl_err("Problem allocating wsi user mem\n"); + lwsl_wsi_err(wsi, "Problem allocating wsi user mem"); *cce = "HS: OOM"; goto bail2; } @@ -649,13 +642,13 @@ lws_client_ws_upgrade(struct lws *wsi, const char **cce) wsi->ws->rx_ubuf = lws_malloc((unsigned int)n + 4 /* 0x0000ffff zlib */, "client frame buffer"); if (!wsi->ws->rx_ubuf) { - lwsl_err("Out of Mem allocating rx buffer %d\n", n); + lwsl_wsi_err(wsi, "OOM allocating rx buffer %d", n); *cce = "HS: OOM"; goto bail2; } wsi->ws->rx_ubuf_alloc = (unsigned int)n; - lwsl_debug("handshake OK for protocol %s\n", wsi->a.protocol->name); + lwsl_wsi_debug(wsi, "handshake OK for protocol %s", wsi->a.protocol->name); /* call him back to inform him he is up */ From 8d4526c780dd4f7d605496da764c614f0b580eaf Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 12 Oct 2021 09:14:31 +0100 Subject: [PATCH 011/275] smd: take message lock earlier --- lib/system/smd/smd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/system/smd/smd.c b/lib/system/smd/smd.c index 89421d4f19..13ccadb46b 100644 --- a/lib/system/smd/smd.c +++ b/lib/system/smd/smd.c @@ -210,10 +210,15 @@ _lws_smd_msg_send(struct lws_context *ctx, void *pay, struct lws_smd_peer *exc) lws_mutex_lock(ctx->smd.lock_peers)) /* +++++++++++++++ peers */ return 1; /* For Coverity */ + if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++++++++++ messages */ + goto bail; + msg->refcount = (uint16_t)_lws_smd_msg_assess_peers_interested( &ctx->smd, msg, exc); if (!msg->refcount) { /* possible, condsidering exc and no other participants */ + lws_mutex_unlock(ctx->smd.lock_messages); /* --------------- messages */ + lws_free(msg); if (!ctx->smd.delivering) lws_mutex_unlock(ctx->smd.lock_peers); /* ------------- peers */ @@ -225,8 +230,6 @@ _lws_smd_msg_send(struct lws_context *ctx, void *pay, struct lws_smd_peer *exc) /* let's add him on the queue... */ - if (lws_mutex_lock(ctx->smd.lock_messages)) /* +++++++++++++++++ messages */ - goto bail; lws_dll2_add_tail(&msg->list, &ctx->smd.owner_messages); /* From c226da3e108176b00b151b4154e187aa4db9e52f Mon Sep 17 00:00:00 2001 From: Orefkov Aleksander Date: Tue, 12 Oct 2021 10:13:18 +0300 Subject: [PATCH 012/275] cmake: wrong miniz include dir + mbed link on windows --- CMakeLists.txt | 2 +- lib/tls/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e428af8ff..c062be6f3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -865,7 +865,7 @@ if (LWS_WITH_ZLIB) if (NOT ZLIB_FOUND) if (LWS_WITH_MINIZ) find_package(Miniz REQUIRED) - set(ZLIB_INCLUDE_DIRS ${MINIZ_INCLUDE_DIRS}) + set(ZLIB_INCLUDE_DIRS ${MINIZ_INCLUDE_DIR}) set(ZLIB_LIBRARIES ${MINIZ_LIBRARIES}) else() find_package(ZLIB REQUIRED) diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index fdf9cb1d4b..91ca8be93f 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -367,6 +367,7 @@ if (LWS_WITH_MBEDTLS) # not supported in esp-idf openssl wrapper yet, but is in our version set(LWS_HAVE_X509_VERIFY_PARAM_set1_host 1 PARENT_SCOPE) endif() + set(CMAKE_REQUIRED_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${MBEDTLS_INCLUDE_DIRS}) CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct mbedtls_x509_crt c; c.authority_key_id.keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; return c.authority_key_id.keyIdentifier.tag; }\n" LWS_HAVE_MBEDTLS_AUTH_KEY_ID) From 00b922041bedf679c156551984f6a039fd0fc045 Mon Sep 17 00:00:00 2001 From: Orefkov Aleksander Date: Tue, 12 Oct 2021 10:21:49 +0300 Subject: [PATCH 013/275] mbedtls: set length even when LWS_HAVE_mbedtls_ssl_get_alpn_protocol --- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index f67da544f8..04354f6b47 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -888,6 +888,8 @@ void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, *len = (unsigned int)strlen(alp); else *len = 0; +#else + *len = 0; #endif } From 413ce239cd5b8e5db38ad2329f3f670c5f4081e5 Mon Sep 17 00:00:00 2001 From: Orefkov Aleksander Date: Tue, 12 Oct 2021 17:18:01 +0300 Subject: [PATCH 014/275] mbedtls: windows: add define to be compatible with the latest versions of mbedtls --- lib/plat/windows/windows-sockets.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/plat/windows/windows-sockets.c b/lib/plat/windows/windows-sockets.c index 2619fad278..ce9b7192e9 100644 --- a/lib/plat/windows/windows-sockets.c +++ b/lib/plat/windows/windows-sockets.c @@ -25,6 +25,7 @@ #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS #define _WINSOCK_DEPRECATED_NO_WARNINGS #endif +#define MBEDTLS_ALLOW_PRIVATE_ACCESS #include "private-lib-core.h" #if defined(LWS_WITH_MBEDTLS) From b53a09f61c1fd14499e7312b47a2815429082e3e Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Wed, 13 Oct 2021 01:47:40 -0400 Subject: [PATCH 015/275] logs: migrate client-parser-ws.c to contextual logging --- CMakeLists.txt | 2 + lib/roles/ws/client-parser-ws.c | 81 ++++++++++++++++----------------- 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c062be6f3b..4020645692 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -836,6 +836,8 @@ if (MSVC) add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) # Fail the build if any warnings add_compile_options(/W3 /WX) + # Unbreak MSVC broken preprocessor __VA_ARGS__ behaviour + add_compile_options(/Zc:preprocessor /experimental:preprocessor /wd5105) endif(MSVC) if (MINGW) diff --git a/lib/roles/ws/client-parser-ws.c b/lib/roles/ws/client-parser-ws.c index 24c38a5df0..09e681f921 100644 --- a/lib/roles/ws/client-parser-ws.c +++ b/lib/roles/ws/client-parser-ws.c @@ -51,7 +51,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) lws_remove_wsi_from_draining_ext_list(wsi); rx_draining_ext = 1; - lwsl_debug("%s: doing draining flow\n", __func__); + lwsl_wsi_debug(wsi, "doing draining flow"); goto drain_extension; } @@ -100,7 +100,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) break; case LWSWSOPC_CONTINUATION: if (!wsi->ws->continuation_possible) { - lwsl_info("disordered continuation\n"); + lwsl_wsi_info(wsi, "disordered continuation"); return -1; } wsi->ws->first_fragment = 0; @@ -119,7 +119,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) case 0xd: case 0xe: case 0xf: - lwsl_info("illegal opcode\n"); + lwsl_wsi_info(wsi, "illegal opcode"); return -1; default: wsi->ws->defeat_check_utf8 = 1; @@ -132,17 +132,17 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) !wsi->ws->count_act_ext && #endif wsi->ws->rsv) { - lwsl_info("illegal rsv bits set\n"); + lwsl_wsi_info(wsi, "illegal rsv bits set"); return -1; } wsi->ws->final = !!((c >> 7) & 1); - lwsl_ext("%s: This RX frame Final %d\n", __func__, + lwsl_wsi_ext(wsi, " This RX frame Final %d", wsi->ws->final); if (wsi->ws->owed_a_fin && (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME || wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)) { - lwsl_info("hey you owed us a FIN\n"); + lwsl_wsi_info(wsi, "hey you owed us a FIN"); return -1; } if ((!(wsi->ws->opcode & 8)) && wsi->ws->final) { @@ -151,7 +151,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) } if ((wsi->ws->opcode & 8) && !wsi->ws->final) { - lwsl_info("control msg can't be fragmented\n"); + lwsl_wsi_info(wsi, "control msg can't be fragmented"); return -1; } if (!wsi->ws->final) @@ -168,7 +168,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) break; default: - lwsl_err("unknown spec version %02d\n", + lwsl_wsi_err(wsi, "unknown spec version %02d", wsi->ws->ietf_spec_revision); break; } @@ -231,7 +231,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) case LWS_RXPS_04_FRAME_HDR_LEN64_8: if (c & 0x80) { - lwsl_warn("b63 of length must be zero\n"); + lwsl_wsi_warn(wsi, "b63 of length must be zero"); /* kill the connection */ return -1; } @@ -350,8 +350,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) if (--wsi->ws->rx_packet_length == 0) { /* spill because we have the whole frame */ wsi->lws_rx_parse_state = LWS_RXPS_NEW; - lwsl_debug("%s: spilling as we have the whole frame\n", - __func__); + lwsl_wsi_debug(wsi, "spilling as we have the whole frame"); goto spill; } @@ -369,8 +368,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) /* spill because we filled our rx buffer */ - lwsl_debug("%s: spilling as we filled our rx buffer\n", - __func__); + lwsl_wsi_debug(wsi, "spilling as we filled our rx buffer"); spill: handled = 0; @@ -396,11 +394,11 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) * fine he has told us he is closing too, let's * finish our close */ - lwsl_parser("seen server's close ack\n"); + lwsl_wsi_parser(wsi, "seen server's close ack"); return -1; } - lwsl_parser("client sees server close len = %d\n", + lwsl_wsi_parser(wsi, "client sees server close len = %d", (int)wsi->ws->rx_ubuf_head); if (wsi->ws->rx_ubuf_head >= 2) { close_code = (unsigned short)((pp[0] << 8) | pp[1]); @@ -426,8 +424,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) wsi->ws->close_in_ping_buffer_len = (uint8_t)wsi->ws->rx_ubuf_head; - lwsl_info("%s: scheduling return close as ack\n", - __func__); + lwsl_wsi_info(wsi, "scheduling return close as ack"); __lws_change_pollfd(wsi, LWS_POLLIN, 0); lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_SEND, 3); wsi->waiting_to_send_close_frame = 1; @@ -438,7 +435,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) break; case LWSWSOPC_PING: - lwsl_info("received %d byte ping, sending pong\n", + lwsl_wsi_info(wsi, "received %d byte ping, sending pong", (int)wsi->ws->rx_ubuf_head); /* he set a close reason on this guy, ignore PING */ @@ -450,13 +447,13 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) * there is already a pending pong payload * we should just log and drop */ - lwsl_parser("DROP PING since one pending\n"); + lwsl_wsi_parser(wsi, "DROP PING since one pending"); goto ping_drop; } /* control packets can only be < 128 bytes long */ if (wsi->ws->rx_ubuf_head > 128 - 3) { - lwsl_parser("DROP PING payload too large\n"); + lwsl_wsi_parser(wsi, "DROP PING payload too large"); goto ping_drop; } @@ -476,8 +473,8 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) break; case LWSWSOPC_PONG: - lwsl_info("%s: %s received pong\n", __func__, lws_wsi_tag(wsi)); - lwsl_hexdump(&wsi->ws->rx_ubuf[LWS_PRE], + lwsl_wsi_info(wsi, "Received pong"); + lwsl_hexdump_wsi_debug(wsi, &wsi->ws->rx_ubuf[LWS_PRE], wsi->ws->rx_ubuf_head); lws_validity_confirmed(wsi); @@ -492,7 +489,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) default: /* not handled or failed */ - lwsl_ext("Unhandled ext opc 0x%x\n", wsi->ws->opcode); + lwsl_wsi_ext(wsi, "Unhandled ext opc 0x%x", wsi->ws->opcode); wsi->ws->rx_ubuf_head = 0; return -1; @@ -522,26 +519,26 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) pmdrx.eb_out = pmdrx.eb_in; - lwsl_debug("%s: starting disbursal of %d deframed rx\n", - __func__, (int)wsi->ws->rx_ubuf_head); + lwsl_wsi_debug(wsi, "starting disbursal of %d deframed rx", + (int)wsi->ws->rx_ubuf_head); #if !defined(LWS_WITHOUT_EXTENSIONS) drain_extension: #endif do { - // lwsl_notice("%s: pmdrx.eb_in.len: %d\n", __func__, + // lwsl_wsi_notice("pmdrx.eb_in.len: %d", // (int)pmdrx.eb_in.len); n = PMDR_DID_NOTHING; #if !defined(LWS_WITHOUT_EXTENSIONS) - lwsl_ext("%s: +++ passing %d %p to ext\n", __func__, + lwsl_wsi_ext(wsi, "+++ passing %d %p to ext", pmdrx.eb_in.len, pmdrx.eb_in.token); n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &pmdrx, 0); - lwsl_ext("Ext RX returned %d\n", n); + lwsl_wsi_ext(wsi, "Ext RX returned %d", n); if (n < 0) { wsi->socket_is_permanently_unusable = 1; return -1; @@ -550,23 +547,21 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) /* ie, not PMDR_NOTHING_WE_SHOULD_DO */ break; #endif - lwsl_ext("%s: post inflate ebuf in len %d / out len %d\n", - __func__, pmdrx.eb_in.len, pmdrx.eb_out.len); + lwsl_wsi_ext(wsi, "post inflate ebuf in len %d / out len %d", + pmdrx.eb_in.len, pmdrx.eb_out.len); #if !defined(LWS_WITHOUT_EXTENSIONS) if (rx_draining_ext && !pmdrx.eb_out.len) { - lwsl_debug(" --- ending drain on 0 read result\n"); + lwsl_wsi_debug(wsi, " --- ending drain on 0 read result"); goto already_done; } if (n == PMDR_HAS_PENDING) { /* 1 means stuff to drain */ /* extension had more... main loop will come back */ - lwsl_ext("%s: adding to draining ext list\n", - __func__); + lwsl_wsi_ext(wsi, "adding to draining ext list"); lws_add_wsi_to_draining_ext_list(wsi); } else { - lwsl_ext("%s: removing from draining ext list\n", - __func__); + lwsl_wsi_ext(wsi, "removing from draining ext list"); lws_remove_wsi_from_draining_ext_list(wsi); } rx_draining_ext = wsi->ws->rx_draining_ext; @@ -591,13 +586,13 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) && (n == PMDR_EMPTY_FINAL || n == PMDR_UNKNOWN) #endif ) { - lwsl_info("FINAL utf8 error\n"); + lwsl_wsi_info(wsi, "FINAL utf8 error"); lws_close_reason(wsi, LWS_CLOSE_STATUS_INVALID_PAYLOAD, (uint8_t *)"partial utf8", 12); utf8_fail: - lwsl_info("utf8 error\n"); - lwsl_hexdump_info(pmdrx.eb_out.token, + lwsl_wsi_info(wsi, "utf8 error"); + lwsl_hexdump_wsi_info(wsi, pmdrx.eb_out.token, (unsigned int)pmdrx.eb_out.len); return -1; @@ -617,7 +612,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) goto already_done; if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG) - lwsl_info("Client doing pong callback\n"); + lwsl_wsi_info(wsi, "Client doing pong callback"); #if !defined(LWS_WITHOUT_EXTENSIONS) if (n == PMDR_HAS_PENDING) @@ -652,8 +647,8 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) wsi->ws->first_fragment = 0; - lwsl_debug("%s: bulk ws rx: inp used %d, output %d\n", - __func__, (int)wsi->ws->rx_ubuf_head, + lwsl_wsi_debug(wsi, "bulk ws rx: inp used %d, output %d", + (int)wsi->ws->rx_ubuf_head, (int)pmdrx.eb_out.len); /* if user code wants to close, let caller know */ @@ -670,14 +665,14 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) wsi->ws->rx_ubuf_head = 0; break; default: - lwsl_err("client rx illegal state\n"); + lwsl_wsi_err(wsi, "client rx illegal state"); return 1; } return 0; illegal_ctl_length: - lwsl_warn("Control frame asking for extended length is illegal\n"); + lwsl_wsi_warn(wsi, "Control frame asking for extended length is illegal"); /* kill the connection */ return -1; From 7fb6a450e8eed9d3391733ba74d96c86ece1d5b6 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Wed, 13 Oct 2021 02:03:56 -0400 Subject: [PATCH 016/275] logs: migrate ws extension code to contextual logging --- .../ws/ext/extension-permessage-deflate.c | 91 +++++++++---------- lib/roles/ws/ext/extension.c | 21 ++--- 2 files changed, 55 insertions(+), 57 deletions(-) diff --git a/lib/roles/ws/ext/extension-permessage-deflate.c b/lib/roles/ws/ext/extension-permessage-deflate.c index c442f7c1a0..79c70ea955 100644 --- a/lib/roles/ws/ext/extension-permessage-deflate.c +++ b/lib/roles/ws/ext/extension-permessage-deflate.c @@ -62,7 +62,7 @@ lws_extension_pmdeflate_restrict_args(struct lws *wsi, if (extra < priv->args[PMD_RX_BUF_PWR2]) { priv->args[PMD_RX_BUF_PWR2] = (unsigned char)extra; - lwsl_info(" Capping pmd rx to %d\n", 1 << extra); + lwsl_wsi_info(wsi, " Capping pmd rx to %d", 1 << extra); } } @@ -89,8 +89,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, oa = in; if (!oa->option_name) break; - lwsl_ext("%s: named option set: %s\n", __func__, - oa->option_name); + lwsl_wsi_ext(wsi, "named option set: %s", oa->option_name); for (n = 0; n < (int)LWS_ARRAY_SIZE(lws_ext_pm_deflate_options); n++) if (!strcmp(lws_ext_pm_deflate_options[n].name, @@ -105,7 +104,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, case LWS_EXT_CB_OPTION_SET: oa = in; - lwsl_ext("%s: option set: idx %d, %s, len %d\n", __func__, + lwsl_wsi_ext(wsi, "option set: idx %d, %s, len %d", oa->option_index, oa->start, oa->len); if (oa->start) priv->args[oa->option_index] = (unsigned char)atoi(oa->start); @@ -134,8 +133,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, n = (int)wsi->a.protocol->rx_buffer_size; if (n < 128) { - lwsl_info(" permessage-deflate requires the protocol " - "(%s) to have an RX buffer >= 128\n", + lwsl_wsi_info(wsi, " permessage-deflate requires the protocol " + "(%s) to have an RX buffer >= 128", wsi->a.protocol->name); return -1; } @@ -143,7 +142,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, /* fill in **user */ priv = lws_zalloc(sizeof(*priv), "pmd priv"); *((void **)user) = priv; - lwsl_ext("%s: LWS_EXT_CB_*CONSTRUCT\n", __func__); + lwsl_wsi_ext(wsi, "LWS_EXT_CB_*CONSTRUCT"); memset(priv, 0, sizeof(*priv)); /* fill in pointer to options list */ @@ -173,7 +172,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, break; case LWS_EXT_CB_DESTROY: - lwsl_ext("%s: LWS_EXT_CB_DESTROY\n", __func__); + lwsl_wsi_ext(wsi, "LWS_EXT_CB_DESTROY"); lws_free(priv->buf_rx_inflated); lws_free(priv->buf_tx_deflated); if (priv->rx_init) @@ -189,8 +188,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, /* * ie, we are INFLATING */ - lwsl_ext(" %s: LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d\n", - __func__, pmdrx->eb_in.len, priv->rx.avail_in); + lwsl_wsi_ext(wsi, " LWS_EXT_CB_PAYLOAD_RX: in %d, existing in %d", + pmdrx->eb_in.len, priv->rx.avail_in); /* * If this frame is not marked as compressed, @@ -216,8 +215,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, pmdrx->eb_out.len = 0; - lwsl_ext("%s: LWS_EXT_CB_PAYLOAD_RX: in %d, " - "existing avail in %d, pkt fin: %d\n", __func__, + lwsl_wsi_ext(wsi, "LWS_EXT_CB_PAYLOAD_RX: in %d, " + "existing avail in %d, pkt fin: %d", pmdrx->eb_in.len, priv->rx.avail_in, wsi->ws->final); /* if needed, initialize the inflator */ @@ -225,7 +224,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, if (!priv->rx_init) { if (inflateInit2(&priv->rx, -priv->args[PMD_SERVER_MAX_WINDOW_BITS]) != Z_OK) { - lwsl_err("%s: iniflateInit failed\n", __func__); + lwsl_wsi_err(wsi, "iniflateInit failed"); return PMDR_FAILED; } priv->rx_init = 1; @@ -235,7 +234,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, (1 << priv->args[PMD_RX_BUF_PWR2])), "pmd rx inflate buf"); if (!priv->buf_rx_inflated) { - lwsl_err("%s: OOM\n", __func__); + lwsl_wsi_err(wsi, "OOM"); return PMDR_FAILED; } } @@ -248,8 +247,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, if (priv->rx.avail_in && pmdrx->eb_in.token && pmdrx->eb_in.len) { - lwsl_warn("%s: priv->rx.avail_in %d while getting new in\n", - __func__, priv->rx.avail_in); + lwsl_wsi_warn(wsi, "priv->rx.avail_in %d while getting new in", + priv->rx.avail_in); // assert(0); } #endif @@ -277,7 +276,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, wsi->ws->final && !wsi->ws->rx_packet_length && wsi->ws->pmd_trailer_application) { - lwsl_ext("%s: trailer apply 1\n", __func__); + lwsl_wsi_ext(wsi, "trailer apply 1"); was_fin = 1; wsi->ws->pmd_trailer_application = 0; priv->rx.next_in = trail; @@ -293,15 +292,15 @@ lws_extension_callback_pm_deflate(struct lws_context *context, return PMDR_DID_NOTHING; n = inflate(&priv->rx, was_fin ? Z_SYNC_FLUSH : Z_NO_FLUSH); - lwsl_ext("inflate ret %d, avi %d, avo %d, wsifinal %d\n", n, + lwsl_wsi_ext(wsi, "inflate ret %d, avi %d, avo %d, wsifinal %d", n, priv->rx.avail_in, priv->rx.avail_out, wsi->ws->final); switch (n) { case Z_NEED_DICT: case Z_STREAM_ERROR: case Z_DATA_ERROR: case Z_MEM_ERROR: - lwsl_err("%s: zlib error inflate %d: \"%s\"\n", - __func__, n, priv->rx.msg); + lwsl_wsi_err(wsi, "zlib error inflate %d: \"%s\"", + n, priv->rx.msg); return PMDR_FAILED; } @@ -313,7 +312,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, ((unsigned int)pmdrx->eb_in.len - (unsigned int)priv->rx.avail_in); pmdrx->eb_in.len = (int)priv->rx.avail_in; - lwsl_debug("%s: %d %d %d %d %d\n", __func__, + lwsl_wsi_debug(wsi, "%d %d %d %d %d", priv->rx.avail_in, wsi->ws->final, (int)wsi->ws->rx_packet_length, @@ -325,7 +324,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, !wsi->ws->rx_packet_length && !was_fin && wsi->ws->pmd_trailer_application) { - lwsl_ext("%s: RX trailer apply 2\n", __func__); + lwsl_wsi_ext(wsi, "RX trailer apply 2"); /* we overallocated just for this situation where * we might issue something */ @@ -336,14 +335,14 @@ lws_extension_callback_pm_deflate(struct lws_context *context, priv->rx.next_in = trail; priv->rx.avail_in = sizeof(trail); n = inflate(&priv->rx, Z_SYNC_FLUSH); - lwsl_ext("RX trailer infl ret %d, avi %d, avo %d\n", + lwsl_wsi_ext(wsi, "RX trailer infl ret %d, avi %d, avo %d", n, priv->rx.avail_in, priv->rx.avail_out); switch (n) { case Z_NEED_DICT: case Z_STREAM_ERROR: case Z_DATA_ERROR: case Z_MEM_ERROR: - lwsl_info("zlib error inflate %d: %s\n", + lwsl_wsi_info(wsi, "zlib error inflate %d: %s", n, priv->rx.msg); return -1; } @@ -355,16 +354,16 @@ lws_extension_callback_pm_deflate(struct lws_context *context, pmdrx->eb_out.token); priv->count_rx_between_fin = priv->count_rx_between_fin + (size_t)pmdrx->eb_out.len; - lwsl_ext(" %s: RX leaving with new effbuff len %d, " - "rx.avail_in=%d, TOTAL RX since FIN %lu\n", - __func__, pmdrx->eb_out.len, priv->rx.avail_in, + lwsl_wsi_ext(wsi, " RX leaving with new effbuff len %d, " + "rx.avail_in=%d, TOTAL RX since FIN %lu", + pmdrx->eb_out.len, priv->rx.avail_in, (unsigned long)priv->count_rx_between_fin); if (was_fin) { - lwsl_ext("%s: was_fin\n", __func__); + lwsl_wsi_ext(wsi, "was_fin"); priv->count_rx_between_fin = 0; if (priv->args[PMD_SERVER_NO_CONTEXT_TAKEOVER]) { - lwsl_ext("PMD_SERVER_NO_CONTEXT_TAKEOVER\n"); + lwsl_wsi_ext(wsi, "PMD_SERVER_NO_CONTEXT_TAKEOVER"); (void)inflateEnd(&priv->rx); priv->rx_init = 0; } @@ -393,7 +392,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, priv->args[PMD_MEM_LEVEL], Z_DEFAULT_STRATEGY); if (n != Z_OK) { - lwsl_ext("inflateInit2 failed %d\n", n); + lwsl_wsi_ext(wsi, "inflateInit2 failed %d", n); return PMDR_FAILED; } priv->tx_init = 1; @@ -404,7 +403,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, (1 << priv->args[PMD_TX_BUF_PWR2])), "pmd tx deflate buf"); if (!priv->buf_tx_deflated) { - lwsl_err("%s: OOM\n", __func__); + lwsl_wsi_err(wsi, "OOM"); return PMDR_FAILED; } @@ -415,8 +414,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, assert(!priv->tx.avail_in); priv->count_tx_between_fin = priv->count_tx_between_fin + (size_t)pmdrx->eb_in.len; - lwsl_ext("%s: TX: eb_in length %d, " - "TOTAL TX since FIN: %d\n", __func__, + lwsl_wsi_ext(wsi, "TX: eb_in length %d, " + "TOTAL TX since FIN: %d", pmdrx->eb_in.len, (int)priv->count_tx_between_fin); priv->tx.next_in = (unsigned char *)pmdrx->eb_in.token; @@ -433,7 +432,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, pen = pen | (unsigned int)penbits; if (!priv->tx.avail_in && (len & LWS_WRITE_NO_FIN)) { - lwsl_ext("%s: no available in, pen: %u\n", __func__, pen); + lwsl_wsi_ext(wsi, "no available in, pen: %u", pen); if (!pen) return PMDR_DID_NOTHING; @@ -441,20 +440,20 @@ lws_extension_callback_pm_deflate(struct lws_context *context, m = Z_NO_FLUSH; if (!(len & LWS_WRITE_NO_FIN)) { - lwsl_ext("%s: deflate with SYNC_FLUSH, pkt len %d\n", - __func__, (int)wsi->ws->rx_packet_length); + lwsl_wsi_ext(wsi, "deflate with SYNC_FLUSH, pkt len %d", + (int)wsi->ws->rx_packet_length); m = Z_SYNC_FLUSH; } n = deflate(&priv->tx, m); if (n == Z_STREAM_ERROR) { - lwsl_notice("%s: Z_STREAM_ERROR\n", __func__); + lwsl_wsi_notice(wsi, "Z_STREAM_ERROR"); return PMDR_FAILED; } pen = (!priv->tx.avail_out) && n != Z_STREAM_END; - lwsl_ext("%s: deflate ret %d, len 0x%x\n", __func__, n, + lwsl_wsi_ext(wsi, "deflate ret %d, len 0x%x", n, (unsigned int)len); if ((len & 0xf) == LWS_WRITE_TEXT) @@ -467,8 +466,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, if (m == Z_SYNC_FLUSH && !(len & LWS_WRITE_NO_FIN) && !pen && pmdrx->eb_out.len < 4) { - lwsl_err("%s: FAIL want to trim out length %d\n", - __func__, (int)pmdrx->eb_out.len); + lwsl_wsi_err(wsi, "FAIL want to trim out length %d", + (int)pmdrx->eb_out.len); assert(0); } @@ -476,7 +475,7 @@ lws_extension_callback_pm_deflate(struct lws_context *context, m == Z_SYNC_FLUSH && !pen && pmdrx->eb_out.len >= 4) { - // lwsl_err("%s: Trimming 4 from end of write\n", __func__); + // lwsl_wsi_err(wsi, "Trimming 4 from end of write"); priv->tx.next_out -= 4; priv->tx.avail_out += 4; priv->count_tx_between_fin = 0; @@ -500,8 +499,8 @@ lws_extension_callback_pm_deflate(struct lws_context *context, pmdrx->eb_out.len = lws_ptr_diff(priv->tx.next_out, pmdrx->eb_out.token); - lwsl_ext(" TX rewritten with new eb_in len %d, " - "eb_out len %d, deflatePending %d\n", + lwsl_wsi_ext(wsi, " TX rewritten with new eb_in len %d, " + "eb_out len %d, deflatePending %d", pmdrx->eb_in.len, pmdrx->eb_out.len, pen); if (pmdrx->eb_in.len || pen) @@ -538,13 +537,13 @@ lws_extension_callback_pm_deflate(struct lws_context *context, if (n == LWSWSOPC_TEXT_FRAME || n == LWSWSOPC_BINARY_FRAME) *pmdrx->eb_in.token |= 0x40; - lwsl_ext("%s: PRESEND compressed: ws frame 0x%02X, len %d\n", - __func__, ((*pmdrx->eb_in.token) & 0xff), + lwsl_wsi_ext(wsi, "PRESEND compressed: ws frame 0x%02X, len %d", + ((*pmdrx->eb_in.token) & 0xff), pmdrx->eb_in.len); if (((*pmdrx->eb_in.token) & 0x80) && /* fin */ priv->args[PMD_CLIENT_NO_CONTEXT_TAKEOVER]) { - lwsl_debug("PMD_CLIENT_NO_CONTEXT_TAKEOVER\n"); + lwsl_wsi_debug(wsi, "PMD_CLIENT_NO_CONTEXT_TAKEOVER"); (void)deflateEnd(&priv->tx); priv->tx_init = 0; } diff --git a/lib/roles/ws/ext/extension.c b/lib/roles/ws/ext/extension.c index 38fd299530..dd6539b71e 100644 --- a/lib/roles/ws/ext/extension.c +++ b/lib/roles/ws/ext/extension.c @@ -30,7 +30,7 @@ void lws_context_init_extensions(const struct lws_context_creation_info *info, struct lws_context *context) { - lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE); + lwsl_cx_info(context, " LWS_MAX_EXTENSIONS_ACTIVE: %u", LWS_MAX_EXTENSIONS_ACTIVE); } enum lws_ext_option_parser_states { @@ -56,7 +56,7 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, while (opts[count_options].name) count_options++; while (len) { - lwsl_ext("'%c' %d", *in, leap); + lwsl_wsi_ext(wsi, "'%c' %d", *in, leap); switch (leap) { case LEAPS_SEEK_NAME: if (*in == ' ') @@ -83,12 +83,12 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, n++; continue; } - lwsl_ext(" m=%d, n=%d, w=%d\n", m, n, w); + lwsl_wsi_ext(wsi, " m=%d, n=%d, w=%d", m, n, w); if (*in == opts[n].name[w]) { if (!opts[n].name[w + 1]) { oa.option_index = (int)n; - lwsl_ext("hit %d\n", + lwsl_wsi_ext(wsi, "hit %d", oa.option_index); leap = LEAPS_SEEK_VAL; if (len == 1) @@ -98,7 +98,7 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, } else { match_map &= (unsigned int)~(1 << n); if (!match_map) { - lwsl_ext("empty match map\n"); + lwsl_wsi_ext(wsi, "empty match map"); return -1; } } @@ -200,7 +200,7 @@ int lws_ext_cb_active(struct lws *wsi, int reason, void *arg, int len) lws_get_context(wsi), wsi->ws->active_extensions[n], wsi, (enum lws_extension_callback_reasons)reason, wsi->ws->act_ext_user[n], arg, (size_t)len); if (m < 0) { - lwsl_ext("Ext '%s' failed to handle callback %d!\n", + lwsl_wsi_ext(wsi, "Ext '%s' failed to handle callback %d!", wsi->ws->active_extensions[n]->name, reason); return -1; } @@ -229,7 +229,7 @@ int lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi, m = ext->callback(context, ext, wsi, (enum lws_extension_callback_reasons)reason, (void *)(lws_intptr_t)n, arg, (size_t)len); if (m < 0) { - lwsl_ext("Ext '%s' failed to handle callback %d!\n", + lwsl_wsi_ext(wsi, "Ext '%s' failed to handle callback %d!", wsi->ws->active_extensions[n]->name, reason); return -1; } @@ -284,7 +284,7 @@ lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len) if (ebuf.len) { n = lws_issue_raw(wsi, ebuf.token, (size_t)ebuf.len); if (n < 0) { - lwsl_info("closing from ext access\n"); + lwsl_wsi_info(wsi, "closing from ext access"); return -1; } @@ -292,8 +292,7 @@ lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len) if (wsi->ws->clean_buffer) len = (size_t)n; - lwsl_ext("%s: written %d bytes to client\n", - __func__, n); + lwsl_wsi_ext(wsi, "written %d bytes to client", n); } /* no extension has more to spill? Then we can go */ @@ -315,7 +314,7 @@ lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len) /* no we could add more, lets's do that */ continue; - lwsl_debug("choked\n"); + lwsl_wsi_debug(wsi, "choked"); /* * Yes, he's choked. Don't spill the rest now get a callback From 61c2e3291f64b2a0fe5285b4bd6418a8ef92cb0d Mon Sep 17 00:00:00 2001 From: Yichen Gu Date: Wed, 13 Oct 2021 15:52:33 +0100 Subject: [PATCH 017/275] mqtt: protect printing debug only vars --- lib/roles/mqtt/mqtt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index b661343622..7170b2e32e 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -2362,8 +2362,10 @@ lws_mqtt_client_send_unsubcribe(struct lws *wsi, wsi->mqtt->sub_size = (uint16_t)rem_len; +#if defined(_DEBUG) lwsl_debug("%s: Number of topics = %d, Remaining len = %d\n", __func__, (int)tops, (int)rem_len); +#endif p += lws_mqtt_vbi_encode(rem_len, p); From 9b56baca8f210dc5d3c708b4b1627b276a5efd54 Mon Sep 17 00:00:00 2001 From: Yichen Gu Date: Wed, 13 Oct 2021 15:50:15 +0100 Subject: [PATCH 018/275] ss: static policy generator: fix filepath detection --- lib/secure-streams/policy-json.c | 3 ++- lib/secure-streams/private-lib-secure-streams.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index 3427ae6d44..7e5656f675 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -1246,10 +1246,11 @@ lws_ss_policy_parse(struct lws_context *context, const uint8_t *buf, size_t len) int m; #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) - if (args->jctx.line < 2 && buf[0] != '{') + if (args->jctx.line < 2 && buf[0] != '{' && !args->parse_data) return lws_ss_policy_parse_file(context, (const char *)buf); #endif + args->parse_data = 1; m = lejp_parse(&args->jctx, buf, (int)len); if (m == LEJP_CONTINUE || m >= 0) return m; diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index ebfa7efa0f..70de42f0e7 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -401,6 +401,8 @@ struct policy_cb_args { int count; char pending_respmap; + + uint8_t parse_data:1; }; #if defined(LWS_WITH_SYS_SMD) From ff5257e19347f7467c461c32b66d2e609538acfb Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Fri, 15 Oct 2021 08:44:57 -0400 Subject: [PATCH 019/275] logs: migrate more to log context --- lib/core/context.c | 8 ++++---- lib/core/logs.c | 8 ++++---- lib/tls/tls-network.c | 12 +++++------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index ab6afa382c..fb684e5118 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -782,7 +782,7 @@ lws_create_context(const struct lws_context_creation_info *info) #endif /* network */ - lwsl_notice("LWS: %s, %s%s\n", library_version, opts_str, s); + lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s); #if defined(LWS_WITH_NETWORK) lwsl_cx_info(context, "Event loop: %s", plev->ops->name); #endif @@ -1402,7 +1402,7 @@ lws_create_context(const struct lws_context_creation_info *info) context->l1 = lws_cache_create(&ci); if (!context->l1) { - lwsl_err("Failed to init cookiejar"); + lwsl_cx_err(context, "Failed to init cookiejar"); goto bail; } } @@ -1991,7 +1991,7 @@ lws_context_destroy(struct lws_context *context) vh = context->vhost_list; while (vh) { vh1 = vh->vhost_next; - // lwsl_debug("%s: vh %s destroy2\n", __func__, vh->name); + // lwsl_vhost_debug(vh, "vh %s destroy2", vh->name); __lws_vhost_destroy2(vh); vh = vh1; } @@ -2223,7 +2223,7 @@ lws_context_destroy(struct lws_context *context) #if defined(LWS_WITH_NETWORK) bail: #endif - lwsl_info("%s: leaving\n", __func__); + lwsl_cx_info(context, "leaving"); context->inside_context_destroy = 0; lws_context_unlock(context); } diff --git a/lib/core/logs.c b/lib/core/logs.c index 377dcb08a0..a13c84194b 100644 --- a/lib/core/logs.c +++ b/lib/core/logs.c @@ -124,7 +124,7 @@ __lws_lc_tag(struct lws_context *context, lws_lifecycle_group_t *grp, lwsl_refcount_cx(lc->log_cx, 1); #if defined(LWS_LOG_TAG_LIFECYCLE) - lwsl_notice(" ++ %s (%d)\n", lc->gutag, (int)grp->owner.count); + lwsl_cx_notice(context, " ++ %s (%d)", lc->gutag, (int)grp->owner.count); #endif } @@ -166,13 +166,13 @@ __lws_lc_untag(struct lws_context *context, lws_lifecycle_t *lc) char buf[24]; if (!lc->gutag[0]) { /* we never tagged this object... */ - lwsl_err("%s: %s never tagged\n", __func__, lc->gutag); + lwsl_cx_err(context, "%s never tagged", lc->gutag); assert(0); return; } if (!lc->list.owner) { /* we already untagged this object... */ - lwsl_err("%s: %s untagged twice\n", __func__, lc->gutag); + lwsl_cx_err(context, "%s untagged twice", lc->gutag); assert(0); return; } @@ -184,7 +184,7 @@ __lws_lc_untag(struct lws_context *context, lws_lifecycle_t *lc) humanize_schema_us); #if defined(LWS_LOG_TAG_LIFECYCLE) - lwsl_notice(" -- %s (%d) %s", lc->gutag, + lwsl_cx_notice(context, " -- %s (%d) %s", lc->gutag, (int)lc->list.owner->count - 1, buf); #endif diff --git a/lib/tls/tls-network.c b/lib/tls/tls-network.c index b2038d5371..ef404aff72 100644 --- a/lib/tls/tls-network.c +++ b/lib/tls/tls-network.c @@ -90,10 +90,10 @@ lws_tls_check_cert_lifetime(struct lws_vhost *v) return 1; life = (ir.time - now) / (24 * 3600); - lwsl_notice(" vhost %s: cert expiry: %dd\n", v->name, + lwsl_vhost_notice(v, " vhost %s: cert expiry: %dd", v->name, (int)life); } else - lwsl_info(" vhost %s: no cert\n", v->name); + lwsl_vhost_info(v, " vhost %s: no cert", v->name); memset(&caa, 0, sizeof(caa)); caa.vh = v; @@ -151,7 +151,7 @@ lws_tls_generic_cert_checks(struct lws_vhost *vhost, const char *cert, if ((n == LWS_TLS_EXTANT_NO || m == LWS_TLS_EXTANT_NO) && (vhost->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) { - lwsl_notice("Ignoring missing %s or %s\n", cert, private_key); + lwsl_vhost_notice(vhost, "Ignoring missing %s or %s", cert, private_key); vhost->tls.skipped_certs = 1; return LWS_TLS_EXTANT_NO; @@ -188,8 +188,7 @@ lws_tls_cert_updated(struct lws_context *context, const char *certpath, mem_privkey, len_mem_privkey); if (v->tls.skipped_certs) - lwsl_notice("%s: vhost %s: cert unset\n", - __func__, v->name); + lwsl_vhost_notice(v, "vhost %s: cert unset", v->name); } } lws_end_foreach_ll(v, vhost_next); @@ -217,8 +216,7 @@ lws_gate_accepts(struct lws_context *context, int on) if (v->tls.use_ssl && lws_change_pollfd(wsi, on ? LWS_POLLIN : 0, on ? 0 : LWS_POLLIN)) - lwsl_notice("%s: Unable to set POLLIN %d\n", - __func__, on); + lwsl_cx_notice(context, "Unable to set POLLIN %d", on); } lws_end_foreach_dll(d); v = v->vhost_next; From 826b221e3821b4ae547fe52ea1e46d5ff86f2ee9 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Fri, 15 Oct 2021 08:49:03 -0400 Subject: [PATCH 020/275] client: fix nxdomain CCE --- lib/core-net/client/connect2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core-net/client/connect2.c b/lib/core-net/client/connect2.c index 5ac11e6b10..0ccb3cb559 100644 --- a/lib/core-net/client/connect2.c +++ b/lib/core-net/client/connect2.c @@ -352,7 +352,7 @@ lws_client_connect_2_dnsreq(struct lws *wsi) */ wsi->client_suppress_CONNECTION_ERROR = 0; lws_inform_client_conn_fail(wsi, (void *)dns_nxdomain, - sizeof(*dns_nxdomain)); + strlen(dns_nxdomain)); goto failed1; } #endif From 06bc1d897171c43e9b5dca4ff0dafc9db54dd8b7 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 15 Oct 2021 19:06:15 +0100 Subject: [PATCH 021/275] freertos: no need to freak out if service_adjust_to is 0 If lws_s_a_t() is zero, there's a path where n stays -1 from its declaration and we return -1. --- lib/plat/freertos/freertos-service.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/plat/freertos/freertos-service.c b/lib/plat/freertos/freertos-service.c index 3c60d0bd27..0732be8bbe 100644 --- a/lib/plat/freertos/freertos-service.c +++ b/lib/plat/freertos/freertos-service.c @@ -102,6 +102,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) * is there anybody with pending stuff that needs service forcing? */ again: + n = 0; if (lws_service_adjust_timeout(context, 1, tsi)) { a = 0; From 65faeab1bdfef577b3edb7b31d937707e5896187 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Fri, 15 Oct 2021 11:44:53 -0400 Subject: [PATCH 022/275] logs: log context: async_dns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Of note: A single use of lwsl_debug() remains because the function in question is documented as a public API, but the passed-in parameter doesn’t offer a path to a logging context. --- lib/system/async-dns/async-dns.c | 84 ++++++++++++++++---------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/lib/system/async-dns/async-dns.c b/lib/system/async-dns/async-dns.c index b134d639dc..9e301b584f 100644 --- a/lib/system/async-dns/async-dns.c +++ b/lib/system/async-dns/async-dns.c @@ -92,8 +92,8 @@ lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c) lws_dll2_remove(d); if (c && c->results) { - lwsl_debug("%s: q: %p, c: %p, refcount %d -> %d\n", - __func__, q, c, c->refcount, c->refcount + 1); + lwsl_wsi_debug(w, "q: %p, c: %p, refcount %d -> %d", + q, c, c->refcount, c->refcount + 1); c->refcount++; } lws_set_timeout(w, NO_PENDING_TIMEOUT, 0); @@ -102,7 +102,7 @@ lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c) */ if (w->adns_cb(w, (const char *)&q[1], c ? c->results : NULL, 0, q->opaque) == NULL) - lwsl_info("%s: failed\n", __func__); + lwsl_wsi_info(w, "failed"); // lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS, // "adopt udp2 fail"); @@ -111,8 +111,8 @@ lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c) if (q->standalone_cb) { if (c && c->results) { - lwsl_debug("%s: q: %p, c: %p, refcount %d -> %d\n", - __func__, q, c, c->refcount, c->refcount + 1); + lwsl_wsi_debug(q->dns ? q->dns->wsi : NULL, "q: %p, c: %p, refcount %d -> %d", + q, c, c->refcount, c->refcount + 1); c->refcount++; } @@ -130,7 +130,7 @@ lws_async_dns_sul_cb_retry(struct lws_sorted_usec_list *sul) { lws_adns_q_t *q = lws_container_of(sul, lws_adns_q_t, sul); - lwsl_info("%s\n", __func__); + lwsl_wsi_info(q->dns ? q->dns->wsi : NULL, ""); lws_adns_dump(q->dns); if (q->dns && q->dns->wsi) { @@ -177,7 +177,7 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) lws_retry_sul_schedule_retry_wsi(wsi, &q->sul, lws_async_dns_sul_cb_retry, &q->retry)) { /* we have reached the end of our concealed retries */ - lwsl_info("%s: failing query\n", __func__); + lwsl_wsi_info(wsi, "failing query"); /* * our policy is to force reloading the dns server info * if our connection ever timed out, in case it or the @@ -206,7 +206,7 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) q->asked = 1; #endif - lwsl_info("%s: %s, which %d\n", __func__, name, which); + lwsl_wsi_info(wsi, "%s, which %d", name, which); /* we hack b0 of the tid to be 0 = A, 1 = AAAA */ @@ -237,7 +237,7 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) if (p + 6 >= e) { assert(0); - lwsl_err("%s: name too big\n", __func__); + lwsl_wsi_err(wsi, "name too big"); goto qfail; } @@ -252,14 +252,14 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) m = lws_write(wsi, pkt + LWS_PRE, (unsigned int)n, 0); if (m != n) { - lwsl_notice("%s: dns write failed %d %d errno %d\n", __func__, + lwsl_wsi_notice(wsi, "dns write failed %d %d errno %d", m, n, errno); goto qfail; } #if defined(LWS_WITH_IPV6) if (!q->responded && q->sent[0] != q->sent[1]) { - lwsl_debug("%s: request writeable for ipv6\n", __func__); + lwsl_wsi_debug(wsi, "request writeable for ipv6"); lws_callback_on_writable(wsi); } #endif @@ -267,14 +267,14 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) return; qfail: - lwsl_warn("%s: failing query doing NULL completion\n", __func__); + lwsl_wsi_warn(wsi, "failing query doing NULL completion"); /* * in ipv6 case, we made a cache entry for the first response but * evidently the second response didn't come in time, purge the * incomplete cache entry */ if (q->firstcache) { - lwsl_debug("%s: destroy firstcache\n", __func__); + lwsl_wsi_debug(wsi, "destroy firstcache"); lws_adns_cache_destroy(q->firstcache); q->firstcache = NULL; } @@ -293,21 +293,21 @@ callback_async_dns(struct lws *wsi, enum lws_callback_reasons reason, /* callbacks related to raw socket descriptor */ case LWS_CALLBACK_RAW_ADOPT: - //lwsl_user("LWS_CALLBACK_RAW_ADOPT\n"); + //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_ADOPT"); break; case LWS_CALLBACK_RAW_CLOSE: - //lwsl_user("LWS_CALLBACK_RAW_CLOSE\n"); + //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_CLOSE"); break; case LWS_CALLBACK_RAW_RX: - //lwsl_user("LWS_CALLBACK_RAW_RX (%d)\n", (int)len); - // lwsl_hexdump_level(LLL_NOTICE, in, len); + //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_RX (%d)", (int)len); + // lwsl_hexdump_wsi_notice(wsi, in, len); lws_adns_parse_udp(dns, in, len); break; case LWS_CALLBACK_RAW_WRITEABLE: - //lwsl_user("LWS_CALLBACK_RAW_WRITEABLE\n"); + //lwsl_wsi_user(wsi, "LWS_CALLBACK_RAW_WRITEABLE"); lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, dns->waiting.head) { lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, @@ -341,7 +341,7 @@ lws_async_dns_init(struct lws_context *context) return 0; if (!context->vhost_list) { /* coverity... system vhost always present */ - lwsl_err("%s: no system vhost\n", __func__); + lwsl_cx_err(context, "no system vhost"); return 1; } @@ -354,7 +354,7 @@ lws_async_dns_init(struct lws_context *context) n = lws_plat_asyncdns_init(context, &dns->sa46); if (n < 0) { - lwsl_warn("%s: no valid dns server, retry\n", __func__); + lwsl_cx_warn(context, "no valid dns server, retry"); return 1; } @@ -373,7 +373,7 @@ lws_async_dns_init(struct lws_context *context) lws_async_dns_protocol.name, NULL, NULL, NULL, &retry_policy, "asyncdns"); if (!dns->wsi) { - lwsl_err("%s: foreign socket adoption failed\n", __func__); + lwsl_cx_err(context, "foreign socket adoption failed"); return 1; } @@ -398,7 +398,7 @@ lws_adns_get_cache(lws_async_dns_t *dns, const char *name) lws_dll2_get_head(&dns->cached)) { c = lws_container_of(d, lws_adns_cache_t, list); - // lwsl_notice("%s vs %s (inc %d)\n", name, c->name, c->incomplete); + // lwsl_wsi_notice(dns->wsi, "%s vs %s (inc %d)", name, c->name, c->incomplete); if (!c->incomplete && !strcasecmp(name, c->name)) { /* Keep sorted by LRU: move to the head */ @@ -421,15 +421,15 @@ lws_adns_dump(lws_async_dns_t *dns) if (!dns) return; - lwsl_info("%s: ADNS cache %u entries\n", __func__, + lwsl_wsi_info(dns->wsi, "ADNS cache %u entries", (unsigned int)dns->cached.count); lws_start_foreach_dll(struct lws_dll2 *, d, lws_dll2_get_head(&dns->cached)) { c = lws_container_of(d, lws_adns_cache_t, list); - lwsl_info("%s: cache: '%s', exp: %lldus, incomp %d, " - "fl 0x%x, refc %d, res %p\n", __func__, c->name, + lwsl_wsi_info(dns->wsi, "cache: '%s', exp: %lldus, incomp %d, " + "fl 0x%x, refc %d, res %p\n", c->name, (long long)(c->sul.us - lws_now_usecs()), c->incomplete, c->flags, c->refcount, c->results); } lws_end_foreach_dll(d); @@ -438,8 +438,8 @@ lws_adns_dump(lws_async_dns_t *dns) lws_dll2_get_head(&dns->waiting)) { lws_adns_q_t *q = lws_container_of(d, lws_adns_q_t, list); - lwsl_info("%s: q: '%s', sent %d, resp %d\n", - __func__, (const char *)&q[1], q->sent[0], + lwsl_wsi_info(dns->wsi, "q: '%s', sent %d, resp %d", + (const char *)&q[1], q->sent[0], q->responded); } lws_end_foreach_dll(d); } @@ -482,7 +482,7 @@ sul_cb_write(struct lws_sorted_usec_list *sul) * the query and everyone riding on it... */ - lwsl_info("%s: failing\n", __func__); + lwsl_wsi_info(q->dns ? q->dns->wsi : NULL, "failing"); lws_adns_dump(q->dns); lws_async_dns_complete(q, NULL); /* no cache to relate to */ @@ -531,8 +531,8 @@ lws_async_dns_trim_cache(lws_async_dns_t *dns) c1 = lws_container_of(lws_dll2_get_tail(&dns->cached), lws_adns_cache_t, list); if (c1->refcount) - lwsl_info("%s: acache %p: refcount %d on purge\n", - __func__, c1, c1->refcount); + lwsl_wsi_info(dns->wsi, "acache %p: refcount %d on purge", + c1, c1->refcount); else lws_adns_cache_destroy(c1); } @@ -553,7 +553,7 @@ lws_async_dns_deinit(lws_async_dns_t *dns) lws_dll2_foreach_safe(&dns->cached, NULL, cache_clean); if (dns->wsi && !dns->dns_server_connected) { - lwsl_notice("%s: late free of incomplete dns wsi\n", __func__); + lwsl_wsi_notice(dns->wsi, "late free of incomplete dns wsi"); __lws_lc_untag(dns->wsi->a.context, &dns->wsi->lc); #if defined(LWS_WITH_SYS_METRICS) lws_metrics_tags_destroy(&dns->wsi->cal_conn.mtags_owner); @@ -634,7 +634,7 @@ lws_async_dns_get_new_tid(struct lws_context *context, lws_adns_q_t *q) } while (budget--); - lwsl_err("%s: unable to get unique tid\n", __func__); + lwsl_cx_err(context, "unable to get unique tid"); return -1; } @@ -660,12 +660,12 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, char *p; int m; - lwsl_info("%s: entry %s\n", __func__, name); + lwsl_cx_info(context, "entry %s", name); lws_adns_dump(dns); #if !defined(LWS_WITH_IPV6) if (qtype == LWS_ADNS_RECORD_AAAA) { - lwsl_err("%s: ipv6 not enabled\n", __func__); + lwsl_cx_err(context, "ipv6 not enabled"); goto failed; } #endif @@ -688,7 +688,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, if (wsi) { if (!lws_dll2_is_detached(&wsi->adns)) { - lwsl_err("%s: %s already bound to query %p\n", __func__, + lwsl_cx_err(context, "%s already bound to query %p", lws_wsi_tag(wsi), wsi->adns.owner); goto failed; } @@ -699,7 +699,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, c = lws_adns_get_cache(dns, name); if (c) { - lwsl_info("%s: %s: using cached, c->results %p\n", __func__, + lwsl_cx_info(context, "%s: using cached, c->results %p", name, c->results); m = c->results ? LADNS_RET_FOUND : LADNS_RET_FAILED; if (c->results) @@ -714,7 +714,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, return m; } else - lwsl_info("%s: %s uncached\n", __func__, name); + lwsl_cx_info(context, "%s uncached", name); #if defined(LWS_WITH_SYS_METRICS) lws_metric_event(context->mt_adns_cache, METRES_NOGO, 0); @@ -799,7 +799,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, if (!context->async_dns.dns_server_set && lws_async_dns_init(context)) { - lwsl_notice("%s: init failed\n", __func__); + lwsl_cx_notice(context, "init failed"); goto failed; } @@ -807,7 +807,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, q = lws_adns_get_query(dns, qtype, &dns->waiting, 0, name); if (q) { - lwsl_debug("%s: dns piggybacking: %d:%s\n", __func__, + lwsl_cx_debug(context, "dns piggybacking: %d:%s", qtype, name); if (wsi) lws_dll2_add_head(&wsi->adns, &q->wsi_adns); @@ -847,7 +847,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, q->qtype = (uint16_t)qtype; if (lws_async_dns_get_new_tid(context, q)) { - lwsl_err("%s: tid fail\n", __func__); + lwsl_cx_err(context, "tid fail"); goto failed; } @@ -890,13 +890,13 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, q->go_nogo = METRES_NOGO; /* caliper is reported in lws_adns_q_destroy */ - lwsl_info("%s: created new query: %s\n", __func__, name); + lwsl_cx_info(context, "created new query: %s", name); lws_adns_dump(dns); return LADNS_RET_CONTINUING; failed: - lwsl_notice("%s: failed\n", __func__); + lwsl_cx_notice(context, "failed"); if (!cb(wsi, NULL, NULL, LADNS_RET_FAILED, opaque)) return LADNS_RET_FAILED_WSI_CLOSED; From dcb115694a2ae8583ef61678681be71fff35629d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 16 Oct 2021 04:44:36 +0100 Subject: [PATCH 023/275] logs: log context: async_dns: no empty format string --- lib/system/async-dns/async-dns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system/async-dns/async-dns.c b/lib/system/async-dns/async-dns.c index 9e301b584f..7ad80bf8ed 100644 --- a/lib/system/async-dns/async-dns.c +++ b/lib/system/async-dns/async-dns.c @@ -130,7 +130,7 @@ lws_async_dns_sul_cb_retry(struct lws_sorted_usec_list *sul) { lws_adns_q_t *q = lws_container_of(sul, lws_adns_q_t, sul); - lwsl_wsi_info(q->dns ? q->dns->wsi : NULL, ""); + lwsl_wsi_info(q->dns ? q->dns->wsi : NULL, "in"); lws_adns_dump(q->dns); if (q->dns && q->dns->wsi) { From c95b0222a4701466563269e529db3635ad488ac4 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 16 Oct 2021 05:02:45 +0100 Subject: [PATCH 024/275] cmake: add inclusion of CheckIncludeFile in req --- cmake/LwsCheckRequirements.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/LwsCheckRequirements.cmake b/cmake/LwsCheckRequirements.cmake index 9b371c3bda..fa3fb9fdd6 100644 --- a/cmake/LwsCheckRequirements.cmake +++ b/cmake/LwsCheckRequirements.cmake @@ -4,6 +4,9 @@ # If we are being built externally, confirm installed lws was configured to # support reqconfig, else error out with a helpful message about the problem. # + +include(CheckIncludeFile) + MACRO(require_lws_config reqconfig _val result) if (DEFINED ${reqconfig}) From acb05eb1ca156d2f41366c72274ef12498c01bd8 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 16 Oct 2021 05:07:31 +0100 Subject: [PATCH 025/275] bind: use vhost log ctx since wsi optional --- lib/core-net/network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core-net/network.c b/lib/core-net/network.c index 507977af76..6c155302be 100644 --- a/lib/core-net/network.c +++ b/lib/core-net/network.c @@ -397,7 +397,7 @@ lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, lws_sa46_write_numeric_address((lws_sockaddr46 *)psin, buf, sizeof(buf)); - lwsl_wsi_notice(wsi, "source ads %s", buf); + lwsl_vhost_notice(vhost, "source ads %s", buf); } return port; From 55a7c6a0f4ebb7e080b7f0d511d0826094a0863c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 16 Oct 2021 05:28:37 +0100 Subject: [PATCH 026/275] http: sse: check POLLIN during DOING_TRANSACTION When the client goes away, on some platforms all we get is POLLIN revent stuck on... we have to read it to find out a zero length result and understand it's gone. Add SSE mode's DOING_TRANSACTION to the list of states we will read for. --- lib/roles/h1/ops-h1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c index 1b5ea66535..4590a49757 100644 --- a/lib/roles/h1/ops-h1.c +++ b/lib/roles/h1/ops-h1.c @@ -367,6 +367,7 @@ lws_h1_server_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) if ((lwsi_state(wsi) == LRS_ESTABLISHED || lwsi_state(wsi) == LRS_ISSUING_FILE || lwsi_state(wsi) == LRS_HEADERS || + lwsi_state(wsi) == LRS_DOING_TRANSACTION || /* at least, SSE */ lwsi_state(wsi) == LRS_DISCARD_BODY || lwsi_state(wsi) == LRS_BODY)) { From 50f7bd4f6e757ce18c0b51c8896935628d5e9331 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 16 Oct 2021 08:28:20 +0100 Subject: [PATCH 027/275] logs: unconvert adns wsi deref after potential close --- lib/system/async-dns/async-dns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system/async-dns/async-dns.c b/lib/system/async-dns/async-dns.c index 7ad80bf8ed..e722214f1f 100644 --- a/lib/system/async-dns/async-dns.c +++ b/lib/system/async-dns/async-dns.c @@ -102,7 +102,7 @@ lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c) */ if (w->adns_cb(w, (const char *)&q[1], c ? c->results : NULL, 0, q->opaque) == NULL) - lwsl_wsi_info(w, "failed"); + lwsl_info("%s: failed\n", __func__); // lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS, // "adopt udp2 fail"); From 36af26600107ec744413c811cdce7fad24450195 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 16 Oct 2021 07:37:36 +0100 Subject: [PATCH 028/275] adns: fix label limit check --- lib/system/async-dns/async-dns-parse.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/system/async-dns/async-dns-parse.c b/lib/system/async-dns/async-dns-parse.c index 17e95aa20f..bdfe205037 100644 --- a/lib/system/async-dns/async-dns-parse.c +++ b/lib/system/async-dns/async-dns-parse.c @@ -81,7 +81,8 @@ lws_adns_parse_label(const uint8_t *pkt, int len, const uint8_t *ls, int budget, return -1; } - if (ll > budget) { + + if (ls + ll > ols + budget) { lwsl_notice("%s: label too long %d vs %d\n", __func__, ll, budget); return -1; From d77a6c397ec84a94c581d055704af05e8e277467 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 19 Oct 2021 06:31:58 +0100 Subject: [PATCH 029/275] client: connect_check fail just log once --- lib/core-net/client/connect3.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/core-net/client/connect3.c b/lib/core-net/client/connect3.c index 4b1f0c4ba1..e4d4cd23db 100644 --- a/lib/core-net/client/connect3.c +++ b/lib/core-net/client/connect3.c @@ -95,8 +95,10 @@ lws_client_connect_check(struct lws *wsi) return LCCCR_CONNECTED; } - lwsl_wsi_notice(wsi, "getsockopt fd %d says err %d", + lwsl_wsi_notice(wsi, "getsockopt fd %d says e %d", wsi->desc.sockfd, e); + + return LCCCR_FAILED; } #else From 9efc32ab4932f6dc58ac69323dc0f210139a4da4 Mon Sep 17 00:00:00 2001 From: Orefkov Aleksander Date: Tue, 19 Oct 2021 06:37:10 +0100 Subject: [PATCH 030/275] plugins: sshd: sc25519 must handle last bit This was originally commented because Coverity objected to it. --- plugins/ssh-base/crypto/sc25519.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/ssh-base/crypto/sc25519.c b/plugins/ssh-base/crypto/sc25519.c index a12995bc46..53acc3e40f 100644 --- a/plugins/ssh-base/crypto/sc25519.c +++ b/plugins/ssh-base/crypto/sc25519.c @@ -68,8 +68,8 @@ static void barrett_reduce(sc25519 *r, const uint32_t x[64]) if(i+j >= 31) q2[i+j] += mu[i]*x[j+31]; carry = q2[31] >> 8; q2[32] += carry; - //carry = q2[32] >> 8; - //q2[33] += carry; + carry = q2[32] >> 8; + q2[33] += carry; for(i=0;i<33;i++)r1[i] = x[i]; for(i=0;i<32;i++) From 957bfae5c8c9467fe879f53125734719aad22a09 Mon Sep 17 00:00:00 2001 From: Orefkov Aleksander Date: Tue, 19 Oct 2021 02:01:59 +0300 Subject: [PATCH 031/275] plugins: sshd: mbedtls 3 extra adaptation In fresh mbedtls rsa public decrypt is deprecated and not work on public keys. Replaced by lws_genrsa_hash_sig_verify. --- plugins/ssh-base/sshd.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/plugins/ssh-base/sshd.c b/plugins/ssh-base/sshd.c index f90c500823..be5b0356aa 100644 --- a/plugins/ssh-base/sshd.c +++ b/plugins/ssh-base/sshd.c @@ -533,7 +533,10 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l struct lws_genrsa_ctx ctx; struct lws_ssh_channel *ch; struct lws_subprotocol_scp *scp; - uint8_t *pp, *ps, hash[64], *otmp; + uint8_t *pp, *ps, hash[64]; +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 + uint8_t *otmp = NULL; +#endif uint32_t m; int n; @@ -1256,6 +1259,7 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l m = lws_g32(&pp); pp += m; m = lws_g32(&pp); +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 /* * decrypt it, resulting in an error, or some ASN1 @@ -1290,6 +1294,12 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l } free(otmp); + #else + ctx.ctx->MBEDTLS_PRIVATE(len) = m; + n = lws_genrsa_hash_sig_verify(&ctx, hash, + (enum lws_genhash_types)rsa_hash_alg_from_ident(pss->ua->alg), + pp, m) == 0 ? 1 : 0; + #endif lws_genrsa_destroy(&ctx); /* @@ -1822,7 +1832,9 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l pss->parser_state = SSH_KEX_STATE_SKIP; break; +#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000 ua_fail1: +#endif lws_genrsa_destroy(&ctx); ua_fail: write_task(pss, NULL, SSH_WT_UA_FAILURE); From 6c7798eef44446b3bc9a1bf6663affbf934a1e75 Mon Sep 17 00:00:00 2001 From: Orefkov Aleksander Date: Tue, 19 Oct 2021 02:01:59 +0300 Subject: [PATCH 032/275] plugins: sshd: channel fixes In responses with channel numbers, the sender's channel number is sent instead of the recipient's channel number. See for example https://datatracker.ietf.org/doc/html/rfc4254#section-5.1 Putty uses channel 256 for session, and existing code break it with "Received SSH2_MSG_CHANNEL_OPEN_CONFIRMATION for nonexistent channel 0" error. --- plugins/ssh-base/sshd.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/plugins/ssh-base/sshd.c b/plugins/ssh-base/sshd.c index be5b0356aa..cb02f02294 100644 --- a/plugins/ssh-base/sshd.c +++ b/plugins/ssh-base/sshd.c @@ -1250,7 +1250,6 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l LGRSAM_PKCS1_1_5, LWS_GENHASH_TYPE_UNKNOWN)) goto ua_fail; - /* * point to the encrypted signature payload we * were sent @@ -2269,10 +2268,10 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CH_OPEN_CONF: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_OPEN_CONFIRMATION; - lws_p32(pp, pss->ch_temp->server_ch); - pp += 4; lws_p32(pp, pss->ch_temp->sender_ch); pp += 4; + lws_p32(pp, pss->ch_temp->server_ch); + pp += 4; /* tx initial window size towards us */ lws_p32(pp, LWS_SSH_INITIAL_WINDOW); pp += 4; @@ -2287,10 +2286,10 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CH_FAILURE: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_OPEN_FAILURE; - lws_p32(pp, ch->server_ch); - pp += 4; lws_p32(pp, ch->sender_ch); pp += 4; + lws_p32(pp, ch->server_ch); + pp += 4; lws_cstr(&pp, "reason", 64); lws_cstr(&pp, "en/US", 64); lwsl_info("SSH_WT_CH_FAILURE\n"); @@ -2299,7 +2298,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CHRQ_SUCC: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_SUCCESS; - lws_p32(pp, ch->server_ch); + lws_p32(pp, ch->sender_ch); lwsl_info("SSH_WT_CHRQ_SUCC\n"); pp += 4; goto pac; @@ -2307,7 +2306,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CHRQ_FAILURE: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_FAILURE; - lws_p32(pp, ch->server_ch); + lws_p32(pp, ch->sender_ch); pp += 4; lwsl_info("SSH_WT_CHRQ_FAILURE\n"); goto pac; @@ -2315,7 +2314,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CH_CLOSE: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_CLOSE; - lws_p32(pp, ch->server_ch); + lws_p32(pp, ch->sender_ch); lwsl_info("SSH_WT_CH_CLOSE\n"); pp += 4; goto pac; @@ -2323,7 +2322,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case SSH_WT_CH_EOF: pp = ps + 5; *pp++ = SSH_MSG_CHANNEL_EOF; - lws_p32(pp, ch->server_ch); + lws_p32(pp, ch->sender_ch); lwsl_info("SSH_WT_CH_EOF\n"); pp += 4; goto pac; @@ -2405,7 +2404,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, else *pp++ = SSH_MSG_CHANNEL_EXTENDED_DATA; /* ps + 6 */ - lws_p32(pp, pss->ch_list->server_ch); + lws_p32(pp, pss->ch_list->sender_ch); m = 14; if (n == LWS_STDERR) { pp += 4; From e9c92ec161b4069e4f47a88f6a37f8ce84b3ea87 Mon Sep 17 00:00:00 2001 From: Jin Wang Date: Tue, 19 Oct 2021 10:45:26 +0100 Subject: [PATCH 033/275] metrics: ss: skip tagging if no ss streamtypename --- lib/secure-streams/secure-streams.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 4f56bcdc5b..53cdce00a9 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -863,11 +863,12 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw) #if defined(LWS_WITH_SYS_METRICS) /* possibly already hanging connect retry... */ - if (!h->cal_txn.mt) { + if (!h->cal_txn.mt) lws_metrics_caliper_bind(h->cal_txn, h->context->mth_ss_conn); - } - lws_metrics_tag_add(&h->cal_txn.mtags_owner, "ss", h->policy->streamtype); + if (h->policy->streamtype) + lws_metrics_tag_add(&h->cal_txn.mtags_owner, "ss", + h->policy->streamtype); #endif h->txn_ok = 0; From 63db023f585dc4f312ee9f9ef8da90b9910e69ca Mon Sep 17 00:00:00 2001 From: Orefkov Aleksander Date: Tue, 19 Oct 2021 13:39:33 +0300 Subject: [PATCH 034/275] pugins: sshd: handle window-change request Added processing of window-change request, according to RFC 4254 6.7 https://datatracker.ietf.org/doc/html/rfc4254#section-6.7 For processing called callback pty_req with empty terminal and modes. --- plugins/ssh-base/include/lws-ssh.h | 5 +++++ plugins/ssh-base/sshd.c | 34 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/plugins/ssh-base/include/lws-ssh.h b/plugins/ssh-base/include/lws-ssh.h index 029d2fc060..6b1dbf8175 100644 --- a/plugins/ssh-base/include/lws-ssh.h +++ b/plugins/ssh-base/include/lws-ssh.h @@ -275,6 +275,11 @@ enum { SSHS_NVC_CHRQ_SUBSYSTEM, + SSHS_NVC_CHRQ_WNDCHANGE_TW, + SSHS_NVC_CHRQ_WNDCHANGE_TH, + SSHS_NVC_CHRQ_WNDCHANGE_TWP, + SSHS_NVC_CHRQ_WNDCHANGE_THP, + SSHS_NVC_CH_EOF, SSHS_NVC_CH_CLOSE, diff --git a/plugins/ssh-base/sshd.c b/plugins/ssh-base/sshd.c index cb02f02294..fb5afffe86 100644 --- a/plugins/ssh-base/sshd.c +++ b/plugins/ssh-base/sshd.c @@ -1483,6 +1483,12 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l SSHS_NVC_CHRQ_SUBSYSTEM); break; } + if (!strcmp(pss->name, "window-change")) { + lwsl_info("%s: window-change\n", __func__); + state_get_u32(pss, + SSHS_NVC_CHRQ_WNDCHANGE_TW); + break; + } if (pss->rq_want_reply) goto chrq_fail; @@ -1638,6 +1644,34 @@ lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t l break; #endif + /* CHRQ window-change */ + + case SSHS_NVC_CHRQ_WNDCHANGE_TW: + pss->args.pty.width_ch = pss->len; + state_get_u32(pss, SSHS_NVC_CHRQ_WNDCHANGE_TH); + break; + case SSHS_NVC_CHRQ_WNDCHANGE_TH: + pss->args.pty.height_ch = pss->len; + state_get_u32(pss, SSHS_NVC_CHRQ_WNDCHANGE_TWP); + break; + case SSHS_NVC_CHRQ_WNDCHANGE_TWP: + pss->args.pty.width_px = pss->len; + state_get_u32(pss, SSHS_NVC_CHRQ_WNDCHANGE_THP); + break; + case SSHS_NVC_CHRQ_WNDCHANGE_THP: + pss->args.pty.height_px = pss->len; + pss->args.pty.term[0] = 0; + pss->args.pty.modes = NULL; + pss->args.pty.modes_len = 0; + n = 0; + if (pss->vhd->ops && pss->vhd->ops->pty_req) + n = pss->vhd->ops->pty_req(pss->ch_temp->priv, + &pss->args.pty); + if (n) + goto chrq_fail; + pss->parser_state = SSHS_MSG_EAT_PADDING; + break; + /* SSH_MSG_CHANNEL_DATA */ case SSHS_NVC_CD_RECIP: From b43f90a8ed4da95c6cf5c4550e3dffca6018b85e Mon Sep 17 00:00:00 2001 From: Jin Wang Date: Thu, 21 Oct 2021 14:44:33 +0100 Subject: [PATCH 035/275] ss: policy: adaptations for dynamic policy --- lib/core-net/private-lib-core-net.h | 2 +- lib/secure-streams/policy-common.c | 4 ++-- lib/secure-streams/private-lib-secure-streams.h | 2 +- lib/secure-streams/secure-streams.c | 13 +++++++++++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 3f5073110f..2d3f73abb1 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -524,7 +524,7 @@ struct lws_vhost { uint32_t tls_session_cache_max; #endif -#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP) int8_t ss_refcount; /**< refcount of number of ss connections with streamtypes using this * trust store */ diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c index 8399df1541..b782c1e5bb 100644 --- a/lib/secure-streams/policy-common.c +++ b/lib/secure-streams/policy-common.c @@ -367,7 +367,7 @@ lws_ss_policy_ref_trust_store(struct lws_context *context, } accepted: -#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP) if (doref) v->ss_refcount++; #endif @@ -375,7 +375,7 @@ lws_ss_policy_ref_trust_store(struct lws_context *context, return v; } -#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP) int lws_ss_policy_unref_trust_store(struct lws_context *context, const lws_ss_policy_t *pol) diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 70de42f0e7..6af59e4707 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -541,7 +541,7 @@ lws_ss_cancel_notify_dll(struct lws_dll2 *d, void *user); int lws_sspc_cancel_notify_dll(struct lws_dll2 *d, void *user); -#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) +#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP) int lws_ss_policy_unref_trust_store(struct lws_context *context, const lws_ss_policy_t *pol); diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 53cdce00a9..9d02d5a6f4 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -1283,6 +1283,14 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, lwsl_err("%s: unable to get vhost / trust store\n", __func__); goto fail_creation; } +#else +#if defined(LWS_WITH_SECURE_STREAMS_CPP) + if (!ssi->streamtype && + !lws_ss_policy_ref_trust_store(context, h->policy, 1 /* do the ref */)) { + lwsl_err("%s: unable to get vhost / trust store\n", __func__); + goto fail_creation; + } +#endif #endif r = lws_ss_event_helper(h, LWSSSCS_CREATING); @@ -1487,6 +1495,11 @@ lws_ss_destroy(lws_ss_handle_t **ppss) if (h->policy) lws_ss_policy_unref_trust_store(h->context, h->policy); +#else +#if defined(LWS_WITH_SECURE_STREAMS_CPP) + if (!h->info.streamtype || !*(h->info.streamtype)) + lws_ss_policy_unref_trust_store(h->context, h->policy); +#endif #endif #if defined(LWS_WITH_SERVER) From 1a69afaf6ec8c78ee6537293336b962e0cd4d695 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 24 Oct 2021 06:21:51 +0100 Subject: [PATCH 036/275] raw-file: clear POLLOUT before handling --- lib/roles/raw-file/ops-raw-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/raw-file/ops-raw-file.c b/lib/roles/raw-file/ops-raw-file.c index 37e21256bd..0f753272be 100644 --- a/lib/roles/raw-file/ops-raw-file.c +++ b/lib/roles/raw-file/ops-raw-file.c @@ -31,11 +31,11 @@ rops_handle_POLLIN_raw_file(struct lws_context_per_thread *pt, struct lws *wsi, int n; if (pollfd->revents & LWS_POLLOUT) { - n = lws_callback_as_writeable(wsi); if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { lwsl_wsi_info(wsi, "failed at set pollfd"); return LWS_HPI_RET_WSI_ALREADY_DIED; } + n = lws_callback_as_writeable(wsi); if (n) return LWS_HPI_RET_PLEASE_CLOSE_ME; } From 26f5cb71e767e581cca33b36de131f873b63e012 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Mon, 25 Oct 2021 15:01:58 -0400 Subject: [PATCH 037/275] docs: client: Add UNIX socket connection notes for clients --- include/libwebsockets/lws-client.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h index 8727cf56ba..4b7fa8cd69 100644 --- a/include/libwebsockets/lws-client.h +++ b/include/libwebsockets/lws-client.h @@ -114,7 +114,8 @@ struct lws_client_connect_info { int ssl_connection; /**< 0, or a combination of LCCSCF_ flags */ const char *path; - /**< uri path */ + /**< URI path. Prefix with + for a UNIX socket. (+@ for + * a Linux abstract-namespace socket) */ const char *host; /**< content of host header */ const char *origin; From 00b7fa23d059743986ce573a62545ca67a8fb902 Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Sun, 24 Oct 2021 18:48:48 -0700 Subject: [PATCH 038/275] plat: freertos: selectively use old service looping --- lib/plat/freertos/freertos-service.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/plat/freertos/freertos-service.c b/lib/plat/freertos/freertos-service.c index 0732be8bbe..41f55fcbe9 100644 --- a/lib/plat/freertos/freertos-service.c +++ b/lib/plat/freertos/freertos-service.c @@ -101,9 +101,14 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* * is there anybody with pending stuff that needs service forcing? */ +#if !defined(LWS_AMAZON_RTOS) again: +#endif n = 0; if (lws_service_adjust_timeout(context, 1, tsi)) { +#if defined(LWS_AMAZON_RTOS) +again: +#endif /* LWS_AMAZON_RTOS */ a = 0; if (timeout_us) { From b843c09dc24a674ec1857e6fdead20693bb0da7a Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Tue, 26 Oct 2021 17:45:11 -0700 Subject: [PATCH 039/275] mqtt: allow indicating username and password are not on heap Fix minimal-mqtt-client and minimal-mqtt-client-multi from crashes by allowing indicating username and password are not on heap. --- include/libwebsockets/lws-mqtt.h | 6 ++++++ lib/roles/mqtt/client/client-mqtt.c | 10 ++++++++-- .../minimal-mqtt-client-multi.c | 3 +++ .../minimal-mqtt-client/minimal-mqtt-client.c | 7 ++++++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/libwebsockets/lws-mqtt.h b/include/libwebsockets/lws-mqtt.h index eb9dcbb2a7..22865801ed 100644 --- a/include/libwebsockets/lws-mqtt.h +++ b/include/libwebsockets/lws-mqtt.h @@ -74,6 +74,10 @@ typedef struct lws_mqtt_client_connect_param_s { session */ uint8_t client_id_nofree:1; /**< do not free the client id */ + uint8_t username_nofree:1; + /**< do not free the username */ + uint8_t password_nofree:1; + /**< do not free the password */ struct { const char *topic; const char *message; @@ -152,6 +156,8 @@ typedef enum { /* flags from byte 8 of C_TO_S CONNECT */ typedef enum { + LMQCFT_USERNAME_NOFREE = (1 << 10), + LMQCFT_PASSWORD_NOFREE = (1 << 9), LMQCFT_CLIENT_ID_NOFREE = (1 << 8), /* only the low 8 are standardized and go out in the protocol */ LMQCFT_USERNAME = (1 << 7), diff --git a/lib/roles/mqtt/client/client-mqtt.c b/lib/roles/mqtt/client/client-mqtt.c index 6529fdc997..5324286e20 100644 --- a/lib/roles/mqtt/client/client-mqtt.c +++ b/lib/roles/mqtt/client/client-mqtt.c @@ -122,6 +122,10 @@ lws_create_client_mqtt_object(const struct lws_client_connect_info *i, c->conn_flags = LMQCFT_CLEAN_START; if (cp->client_id_nofree) c->conn_flags |= LMQCFT_CLIENT_ID_NOFREE; + if (cp->username_nofree) + c->conn_flags |= LMQCFT_USERNAME_NOFREE; + if (cp->password_nofree) + c->conn_flags |= LMQCFT_PASSWORD_NOFREE; if (!(c->conn_flags & LMQCFT_CLIENT_ID_NOFREE)) lws_free((void *)cp->client_id); @@ -152,14 +156,16 @@ lws_create_client_mqtt_object(const struct lws_client_connect_info *i, if (!c->username) goto oom3; c->conn_flags |= LMQCFT_USERNAME; - lws_free((void *)cp->username); + if (!(c->conn_flags & LMQCFT_USERNAME_NOFREE)) + lws_free((void *)cp->username); if (cp->password) { c->password = lws_mqtt_str_create_cstr_dup(cp->password, 0); if (!c->password) goto oom4; c->conn_flags |= LMQCFT_PASSWORD; - lws_free((void *)cp->password); + if (!(c->conn_flags & LMQCFT_PASSWORD_NOFREE)) + lws_free((void *)cp->password); } } diff --git a/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c b/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c index 31f2aa2b71..a523e096a0 100644 --- a/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c +++ b/minimal-examples/mqtt-client/minimal-mqtt-client-multi/minimal-mqtt-client-multi.c @@ -53,6 +53,9 @@ static const lws_mqtt_client_connect_param_t client_connect_param = { .client_id = NULL, .keep_alive = 60, .clean_start = 1, + .client_id_nofree = 1, + .username_nofree = 1, + .password_nofree = 1, .will_param = { .topic = "good/bye", .message = "sign-off", diff --git a/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c b/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c index 8eb9542400..5ff00c6371 100644 --- a/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c +++ b/minimal-examples/mqtt-client/minimal-mqtt-client/minimal-mqtt-client.c @@ -42,6 +42,8 @@ static const lws_mqtt_client_connect_param_t client_connect_param = { .keep_alive = 60, .clean_start = 1, .client_id_nofree = 1, + .username_nofree = 1, + .password_nofree = 1, .will_param = { .topic = "good/bye", .message = "sign-off", @@ -184,6 +186,7 @@ callback_mqtt(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_MQTT_SUBSCRIBED: lwsl_user("%s: MQTT_SUBSCRIBED\n", __func__); + lws_callback_on_writable(wsi); break; case LWS_CALLBACK_MQTT_CLIENT_WRITEABLE: @@ -250,8 +253,10 @@ callback_mqtt(struct lws *wsi, enum lws_callback_reasons reason, */ pss->state++; - if (pss->state != STATE_TEST_FINISH) + if (pss->state != STATE_TEST_FINISH) { + lws_callback_on_writable(wsi); break; + } /* Oh we are done then */ From b912958a678437030f609264a70de5d18017f37d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 28 Oct 2021 07:17:52 +0100 Subject: [PATCH 040/275] cmake: bring tls include requirement out as PUBLIC There's no problem for library build, also with LWS_WITH_MINIMAL_EXAMPLES, but after install at least on OSX, there are problems finding the installed lws include dir (concealed on most platforms by the path being in the default search list for the toolchain), and the references in the lws includes to the tls includes meaning that explicit paths for that must be available at consuming cmakes. This patch enhances the cmake config installed by lws to deal with adding the lws include paths to CMAKE_REQUIRED_INCLUDES and include_directories, so it can be found before the target is introduced. The tls include is passed back up the CMakeLists layers and the lws targets marked with target_include_directories(PUBLIC) with them, so they are understood as needed by consumers. More boilerplate is moved out of the example consuming cmakes. After this, on machines with previous installs of older lws, you may have to clean out the cmake install path, that is usually something like /usr/local/lib/cmake/libwebsockets/* before make installing lws and putting the latest content in there. --- CMakeLists.txt | 3 +++ cmake/libwebsockets-config.cmake.in | 19 ++++++++++++++++--- lib/CMakeLists.txt | 6 +++++- lib/tls/CMakeLists.txt | 12 ++++++++---- .../api-test-async-dns/CMakeLists.txt | 4 ---- 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4020645692..62bb22271f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1055,6 +1055,9 @@ file(RELATIVE_PATH if (DEFINED REL_INCLUDE_DIR) set(LWS__INCLUDE_DIRS "\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}") endif() +if (DEFINED OPENSSL_INCLUDE_DIRS) + set(LWS__INCLUDE_DIRS "${LWS__INCLUDE_DIRS};${OPENSSL_INCLUDE_DIRS}") +endif() configure_file(${PROJECT_SOURCE_DIR}/cmake/libwebsockets-config.cmake.in ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/libwebsockets-config.cmake diff --git a/cmake/libwebsockets-config.cmake.in b/cmake/libwebsockets-config.cmake.in index 49482ca1b6..6247b2cbe0 100644 --- a/cmake/libwebsockets-config.cmake.in +++ b/cmake/libwebsockets-config.cmake.in @@ -1,14 +1,14 @@ # - Config file for lws # It defines the following variables -# LIBWEBSOCKETS_INCLUDE_DIRS - include directories for FooBar +# LIBWEBSOCKETS_INCLUDE_DIRS - include directories for lws # LIBWEBSOCKETS_LIBRARIES - libraries to link against # Get the path of the current file. get_filename_component(LWS_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +list(APPEND CMAKE_MODULE_PATH ${libwebsockets_DIR}) -# Set the include directories. -set(LIBWEBSOCKETS_INCLUDE_DIRS "@LWS__INCLUDE_DIRS@") +set(LIBWEBSOCKETS_INCLUDE_DIRS "@LWS__INCLUDE_DIRS@" "@LWS_PUBLIC_INCLUDES@") # Include the project Targets file, this contains definitions for IMPORTED targets. include(${LWS_CMAKE_DIR}/LibwebsocketsTargets.cmake) @@ -17,8 +17,21 @@ include(${LWS_CMAKE_DIR}/LwsCheckRequirements.cmake) # IMPORTED targets from LibwebsocketsTargets.cmake set(LIBWEBSOCKETS_LIBRARIES websockets websockets_shared) +# These are additional include paths you will need +foreach(item "${LIBWEBSOCKETS_INCLUDE_DIRS}") + include_directories(${item}) + set(CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES}" ${item}) +endforeach() + # These are additional libs that lws wants your app to also link to foreach(item "@LIB_LIST_AT_END@") list(APPEND LIBWEBSOCKETS_DEP_LIBS ${item}) endforeach() +# Move boilerplate for consuming cmake files into here + +include(CheckIncludeFile) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) +set(requirements 1) + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 88f14fa195..c55c619851 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -115,7 +115,7 @@ CHECK_C_SOURCE_COMPILES(" # after kernel 2.6.37 CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return TCP_USER_TIMEOUT; }\n" LWS_HAVE_TCP_USER_TIMEOUT) - +set(LWS_PUBLIC_INCLUDES "") if (LWS_WITH_TLS) add_subdir_include_dirs(tls) endif() @@ -170,6 +170,8 @@ if (LWS_WITH_STATIC) ) target_include_directories(websockets PRIVATE ${LWS_LIB_BUILD_INC_PATHS}) target_compile_definitions(websockets PRIVATE LWS_BUILDING_STATIC) + target_include_directories(websockets PUBLIC ${LWS_PUBLIC_INCLUDES}) + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) if (WIN32) # Windows uses the same .lib ending for static libraries and shared @@ -196,6 +198,8 @@ if (LWS_WITH_SHARED) ) target_include_directories(websockets_shared PRIVATE ${LWS_LIB_BUILD_INC_PATHS}) target_compile_definitions(websockets_shared PRIVATE LWS_BUILDING_SHARED) + target_include_directories(websockets_shared PUBLIC ${LWS_PUBLIC_INCLUDES}) + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) # We want the shared lib to be named "libwebsockets" # not "libwebsocket_shared". diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index 91ca8be93f..aaf4f4a260 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -217,12 +217,14 @@ if (LWS_WITH_SSL) if (LWS_WITH_CYASSL) foreach(inc ${WOLFSSL_INCLUDE_DIRS}) set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/cyassl) - include_directories("${inc}" "${inc}/cyassl") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} "${inc}" "${inc}/cyassl") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) endforeach() else() foreach(inc ${WOLFSSL_INCLUDE_DIRS}) set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS} ${inc} ${inc}/wolfssl) - include_directories("${inc}" "${inc}/wolfssl") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} "${inc}" "${inc}/wolfssl") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) endforeach() endif() set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) @@ -240,7 +242,8 @@ if (LWS_WITH_SSL) message("MBEDTLS libraries: ${MBEDTLS_LIBRARIES}") foreach(inc ${MBEDTLS_INCLUDE_DIRS}) - include_directories("${inc}" "${inc}/mbedtls") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} "${inc}" "${inc}/mbedtls") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) endforeach() list(INSERT LIB_LIST 0 "${MBEDTLS_LIBRARIES}") @@ -269,7 +272,8 @@ if (LWS_WITH_SSL) endif() if (OPENSSL_INCLUDE_DIRS) - include_directories("${OPENSSL_INCLUDE_DIRS}") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} "${OPENSSL_INCLUDE_DIRS}") + set(LWS_PUBLIC_INCLUDES ${LWS_PUBLIC_INCLUDES} PARENT_SCOPE) endif() if (NOT LWS_PLAT_FREERTOS) list(INSERT LIB_LIST 0 ${OPENSSL_LIBRARIES}) diff --git a/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt b/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt index 256726ca11..f2954d0fae 100644 --- a/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt +++ b/minimal-examples/api-tests/api-test-async-dns/CMakeLists.txt @@ -1,14 +1,10 @@ project(lws-api-test-async-dns C) cmake_minimum_required(VERSION 2.8.12) find_package(libwebsockets CONFIG REQUIRED) -list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) -include(CheckCSourceCompiles) -include(LwsCheckRequirements) set(SAMP lws-api-test-async-dns) set(SRCS main.c) -set(requirements 1) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) require_lws_config(LWS_WITH_SYS_ASYNC_DNS 1 requirements) From 7451ce5cfb708ef30fd06c7bacfde61a3467d94e Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Sat, 30 Oct 2021 06:14:28 +0100 Subject: [PATCH 041/275] server: SO_REUSEPORT: enable with LWS_MAX_SMP > 1 Either explicit option selection, or multiple SMP service threads, should enable SO_REUSEPORT https://github.com/warmcat/libwebsockets/issues/2470 --- lib/roles/http/server/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index cb56907f2c..150eeec562 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -261,7 +261,7 @@ _lws_vhost_init_server_af(struct vh_sock_args *a) n = lws_check_opt(a->vhost->options, LWS_SERVER_OPTION_ALLOW_LISTEN_SHARE); #endif - if (n && cx->count_threads > 1) + if (n || cx->count_threads > 1) /* ... also implied by threads > 1 */ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const void *)&opt, sizeof(opt)) < 0) { compatible_close(sockfd); From c0f324fce250a47ae77e4433c54d3cc5ed449600 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 29 Oct 2021 15:00:26 +0100 Subject: [PATCH 042/275] esp32-c3dev: remove stray ssd1306 copy --- .../embedded/esp32/esp-c3dev/main/ssd1306.h | 52 ------------------- 1 file changed, 52 deletions(-) delete mode 100644 minimal-examples/embedded/esp32/esp-c3dev/main/ssd1306.h diff --git a/minimal-examples/embedded/esp32/esp-c3dev/main/ssd1306.h b/minimal-examples/embedded/esp32/esp-c3dev/main/ssd1306.h deleted file mode 100644 index 5e89987a74..0000000000 --- a/minimal-examples/embedded/esp32/esp-c3dev/main/ssd1306.h +++ /dev/null @@ -1,52 +0,0 @@ -#if !defined(__LWS_SSD1306_H__) -#define __LWS_SSD1306_H__ - -/* - * D/C# pin on SSD1306 sets the I2C slave ads - * from these two options (7-bit address) - */ - -#define SSD1306_I2C7_ADS1 0x3c -#define SSD1306_I2C7_ADS2 0x3d - -enum { - SSD1306_SETLOWCOLUMN = 0x00, - SSD1306_SETHIGHCOLUMN = 0x10, - - SSD1306_MEMORYMODE = 0x20, - SSD1306_COLUMNADDR = 0x21, - SSD1306_PAGEADDR = 0x22, - SSD1306_DEACTIVATE_SCROLL = 0x2e, - - SSD1306_SETSTARTLINE = 0x40, - - SSD1306_SETCONTRAST = 0x81, - SSD1306_CHARGEPUMP = 0x8d, - - SSD1306_SEGREMAP = 0xa0, - SSD1306_SETSEGMENTREMAP = 0xa1, - SSD1306_DISPLAYALLON_RESUME = 0xa4, - SSD1306_DISPLAYALLON = 0xa5, - SSD1306_NORMALDISPLAY = 0xa6, - SSD1306_INVERTDISPLAY = 0xa7, - SSD1306_SETMULTIPLEX = 0xa8, - SSD1306_DISPLAYOFF = 0xae, - SSD1306_DISPLAYON = 0xaf, - - SSD1306_COMSCANINC = 0xc0, - SSD1306_COMSCANDEC = 0xc8, - - SSD1306_SETDISPLAYOFFSET = 0xd3, - SSD1306_SETDISPLAYCLOCKDIV = 0xd5, - SSD1306_SETPRECHARGE = 0xd9, - SSD1306_SETCOMPINS = 0xda, - SSD1306_SETVCOMDESELECT = 0xdb, - - SSD1306_NOP = 0xe3, - - SSD1306_EXTERNALVCC = 0x01, - SSD1306_SWITCHCAPVCC = 0x02, -}; - -#endif - From 4935fe9e1e4328e79717ea3cc402cae91ad6d8c0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 29 Oct 2021 15:58:08 +0100 Subject: [PATCH 043/275] openssl: remove lws_ssl_get_error_string as cruft It's not exported, it seems nothing wants it any more --- lib/tls/openssl/openssl-tls.c | 39 ----------------------------------- lib/tls/private-lib-tls.h | 2 -- 2 files changed, 41 deletions(-) diff --git a/lib/tls/openssl/openssl-tls.c b/lib/tls/openssl/openssl-tls.c index bdefd12c2a..577acf3578 100644 --- a/lib/tls/openssl/openssl-tls.c +++ b/lib/tls/openssl/openssl-tls.c @@ -31,45 +31,6 @@ extern int openssl_websocket_private_data_index, static char openssl_ex_indexes_acquired; #endif -char* lws_ssl_get_error_string(int status, int ret, char *buf, size_t len) { - switch (status) { - case SSL_ERROR_NONE: - return lws_strncpy(buf, "SSL_ERROR_NONE", len); - case SSL_ERROR_ZERO_RETURN: - return lws_strncpy(buf, "SSL_ERROR_ZERO_RETURN", len); - case SSL_ERROR_WANT_READ: - return lws_strncpy(buf, "SSL_ERROR_WANT_READ", len); - case SSL_ERROR_WANT_WRITE: - return lws_strncpy(buf, "SSL_ERROR_WANT_WRITE", len); - case SSL_ERROR_WANT_CONNECT: - return lws_strncpy(buf, "SSL_ERROR_WANT_CONNECT", len); - case SSL_ERROR_WANT_ACCEPT: - return lws_strncpy(buf, "SSL_ERROR_WANT_ACCEPT", len); - case SSL_ERROR_WANT_X509_LOOKUP: - return lws_strncpy(buf, "SSL_ERROR_WANT_X509_LOOKUP", len); - case SSL_ERROR_SYSCALL: - switch (ret) { - case 0: - lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: EOF"); - return buf; - case -1: -#ifndef LWS_PLAT_OPTEE - lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %s", - strerror(errno)); -#else - lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %d", errno); -#endif - return buf; - default: - return strncpy(buf, "SSL_ERROR_SYSCALL", len); - } - case SSL_ERROR_SSL: - return "SSL_ERROR_SSL"; - default: - return "SSL_ERROR_UNKNOWN"; - } -} - void lws_tls_err_describe_clear(void) { diff --git a/lib/tls/private-lib-tls.h b/lib/tls/private-lib-tls.h index 13ac692667..28203c58a2 100644 --- a/lib/tls/private-lib-tls.h +++ b/lib/tls/private-lib-tls.h @@ -174,8 +174,6 @@ int lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename, const char *inbuf, lws_filepos_t inlen, uint8_t **buf, lws_filepos_t *amount); -char * -lws_ssl_get_error_string(int status, int ret, char *buf, size_t len); int lws_gencrypto_bits_to_bytes(int bits); From 0c8dbadc1f35ddc320d978f1739ca19f5c9d5ace Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 2 Nov 2021 07:10:51 +0000 Subject: [PATCH 044/275] examples-lowlevel: ws-server: pvo for WITH_PLUGINS --- .../ws-server/minimal-ws-server/minimal-ws-server.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c b/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c index 921bcffaf2..6cfce7f93b 100644 --- a/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c +++ b/minimal-examples/ws-server/minimal-ws-server/minimal-ws-server.c @@ -54,6 +54,11 @@ static const struct lws_http_mount mount = { /* .basic_auth_login_file */ NULL, }; +#if defined(LWS_WITH_PLUGINS) +/* if plugins enabled, only protocols explicitly named in pvo bind to vhost */ +static struct lws_protocol_vhost_options pvo = { NULL, NULL, "lws-minimal", "" }; +#endif + void sigint_handler(int sig) { interrupted = 1; @@ -85,6 +90,9 @@ int main(int argc, const char **argv) info.mounts = &mount; info.protocols = protocols; info.vhost_name = "localhost"; +#if defined(LWS_WITH_PLUGINS) + info.pvo = &pvo; +#endif info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; From 972f154a62a376449419df79b4f53fbb13119a7a Mon Sep 17 00:00:00 2001 From: Hannes Achleitner Date: Mon, 1 Nov 2021 10:17:37 +0100 Subject: [PATCH 045/275] examples-lowlevel: ws client: add -n to README table --- minimal-examples/ws-client/minimal-ws-client/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/minimal-examples/ws-client/minimal-ws-client/README.md b/minimal-examples/ws-client/minimal-ws-client/README.md index bf87ab36a6..5cf297b3c1 100644 --- a/minimal-examples/ws-client/minimal-ws-client/README.md +++ b/minimal-examples/ws-client/minimal-ws-client/README.md @@ -20,6 +20,7 @@ Option|Meaning -j|Allow selfsigned tls cert -k|Allow insecure certs -m|Skip server hostname check +-n|Skip tls usage -e|Allow expired certs --protocol|Use a specific ws subprotocol rather than dumb-increment-protocol, eg, `--protocol myprotocol` From 897eb024319a5d233d908e404a00298240cd0edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakov=20Smoli=C4=87?= Date: Thu, 4 Nov 2021 06:58:40 +0000 Subject: [PATCH 046/275] plugins: sshd: eg musl needs sys/types if available https://github.com/warmcat/libwebsockets/issues/2477 --- plugins/ssh-base/include/lws-ssh.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/ssh-base/include/lws-ssh.h b/plugins/ssh-base/include/lws-ssh.h index 6b1dbf8175..8796dd284b 100644 --- a/plugins/ssh-base/include/lws-ssh.h +++ b/plugins/ssh-base/include/lws-ssh.h @@ -25,6 +25,10 @@ #if !defined(__LWS_SSH_H__) #define __LWS_SSH_H__ +#if defined(LWS_HAVE_SYS_TYPES_H) +#include +#endif + #if defined(LWS_WITH_MBEDTLS) #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" From c42c2adba949677c0e5f49b307d1f45aaf849101 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 6 Nov 2021 09:09:32 +0000 Subject: [PATCH 047/275] retry: handle empty retry table --- lib/core-net/network.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/core-net/network.c b/lib/core-net/network.c index 6c155302be..4ba98a1f85 100644 --- a/lib/core-net/network.c +++ b/lib/core-net/network.c @@ -417,11 +417,13 @@ lws_retry_get_delay_ms(struct lws_context *context, *conceal = 0; if (retry) { - if (*ctry < retry->retry_ms_table_count) - ms = retry->retry_ms_table[*ctry]; - else - ms = retry->retry_ms_table[ - retry->retry_ms_table_count - 1]; + if (retry->retry_ms_table_count) { + if (*ctry < retry->retry_ms_table_count) + ms = retry->retry_ms_table[*ctry]; + else + ms = retry->retry_ms_table[ + retry->retry_ms_table_count - 1]; + } /* if no percent given, use the default 30% */ if (retry->jitter_percent) From 433ad32216757547d321e87bdfef64771939f7ec Mon Sep 17 00:00:00 2001 From: PW Hu Date: Sun, 7 Nov 2021 08:16:34 +0000 Subject: [PATCH 048/275] docs: audit api return information https://github.com/warmcat/libwebsockets/issues/2481 --- include/libwebsockets/lws-client.h | 1 + include/libwebsockets/lws-genec.h | 2 +- include/libwebsockets/lws-genhash.h | 6 ++++-- include/libwebsockets/lws-genrsa.h | 2 +- include/libwebsockets/lws-http.h | 2 +- include/libwebsockets/lws-jose.h | 6 ++++-- include/libwebsockets/lws-jwk.h | 4 ++-- include/libwebsockets/lws-jws.h | 12 +++++++----- include/libwebsockets/lws-network-helper.h | 10 ++++++---- include/libwebsockets/lws-secure-streams-client.h | 5 ++--- include/libwebsockets/lws-x509.h | 14 +++++++------- 11 files changed, 36 insertions(+), 28 deletions(-) diff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h index 4b7fa8cd69..bb5f2d0355 100644 --- a/include/libwebsockets/lws-client.h +++ b/include/libwebsockets/lws-client.h @@ -313,6 +313,7 @@ lws_http_client_read(struct lws *wsi, char **buf, int *len); * \param wsi: client connection * * Returns the last server response code, eg, 200 for client http connections. + * If there is no valid response, it will return 0. * * You should capture this during the LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP * callback, because after that the memory reserved for storing the related diff --git a/include/libwebsockets/lws-genec.h b/include/libwebsockets/lws-genec.h index c18cc1e1f4..5ae1d2f79a 100644 --- a/include/libwebsockets/lws-genec.h +++ b/include/libwebsockets/lws-genec.h @@ -184,7 +184,7 @@ lws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in, * \param sig: pointer to buffer to take signature * \param sig_len: length of the buffer (must be >= length of key N) * - * Returns <0 for error, or 0 for success. + * Returns <0 for error, or >=0 for success. * * This creates a JWS ECDSA signature for a hash you already computed and provide. * diff --git a/include/libwebsockets/lws-genhash.h b/include/libwebsockets/lws-genhash.h index 8407d2f03a..f27c3b9146 100644 --- a/include/libwebsockets/lws-genhash.h +++ b/include/libwebsockets/lws-genhash.h @@ -93,7 +93,8 @@ struct lws_genhmac_ctx { * * \param type: one of LWS_GENHASH_TYPE_... * - * Returns number of bytes in this type of hash + * Returns number of bytes in this type of hash, if the hash type is unknown, it + * will return 0. */ LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT lws_genhash_size(enum lws_genhash_types type); @@ -102,7 +103,8 @@ lws_genhash_size(enum lws_genhash_types type); * * \param type: one of LWS_GENHASH_TYPE_... * - * Returns number of bytes in this type of hmac + * Returns number of bytes in this type of hmac, if the hmac type is unknown, it + * will return 0. */ LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT lws_genhmac_size(enum lws_genhmac_types type); diff --git a/include/libwebsockets/lws-genrsa.h b/include/libwebsockets/lws-genrsa.h index c9409463f6..3f230312e6 100644 --- a/include/libwebsockets/lws-genrsa.h +++ b/include/libwebsockets/lws-genrsa.h @@ -216,7 +216,7 @@ lws_genrsa_hash_sig_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in, * \param sig: pointer to buffer to take signature * \param sig_len: length of the buffer (must be >= length of key N) * - * Returns <0 for error, or 0 for success. + * Returns <0 for error, or \p sig_len for success. * * This creates an RSA signature for a hash you already computed and provide. * You should have created the hash before calling this by iterating over the diff --git a/include/libwebsockets/lws-http.h b/include/libwebsockets/lws-http.h index 9d60903221..2c5bd64dce 100644 --- a/include/libwebsockets/lws-http.h +++ b/include/libwebsockets/lws-http.h @@ -866,7 +866,7 @@ lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len, * lws_http_transaction_completed() - wait for new http transaction or close * \param wsi: websocket connection * - * Returns 1 if the HTTP connection must close now + * Returns nonzero if the HTTP connection must close now * Returns 0 and resets connection to wait for new HTTP header / * transaction if possible */ diff --git a/include/libwebsockets/lws-jose.h b/include/libwebsockets/lws-jose.h index 247d02c686..c780c0e2be 100644 --- a/include/libwebsockets/lws-jose.h +++ b/include/libwebsockets/lws-jose.h @@ -189,7 +189,8 @@ lws_gencrypto_jwe_enc_to_definition(const char *enc, * \param temp: parent-owned buffer to "allocate" elements into * \param temp_len: amount of space available in temp * - * returns the amount of temp used, or -1 for error + * returns 0 for success, or -1 for error + * *\p temp_len is updated to reflect the amount of \p temp used if successful. */ LWS_VISIBLE LWS_EXTERN int lws_jws_parse_jose(struct lws_jose *jose, @@ -204,7 +205,8 @@ lws_jws_parse_jose(struct lws_jose *jose, * \param temp: parent-owned buffer to "allocate" elements into * \param temp_len: amount of space available in temp * - * returns the amount of temp used, or -1 for error + * returns 0 for success, or -1 for error + * *\p temp_len is updated to reflect the amount of \p temp used if successful. */ LWS_VISIBLE LWS_EXTERN int lws_jwe_parse_jose(struct lws_jose *jose, diff --git a/include/libwebsockets/lws-jwk.h b/include/libwebsockets/lws-jwk.h index bf33b80418..a2205d2e17 100644 --- a/include/libwebsockets/lws-jwk.h +++ b/include/libwebsockets/lws-jwk.h @@ -193,7 +193,7 @@ lws_jwk_rfc7638_fingerprint(struct lws_jwk *jwk, char *digest32); * \param in: string to copy * \param len: length of string to copy * - * Returns 0 for OK or -1 for failure + * Returns 0 for OK or nonzero for failure */ LWS_VISIBLE LWS_EXTERN int lws_jwk_strdup_meta(struct lws_jwk *jwk, enum enum_jwk_meta_tok idx, @@ -211,7 +211,7 @@ lws_jwk_dump(struct lws_jwk *jwk); * \param bits: for OCT and RSA keys, the number of bits * \param curve: for EC keys, the name of the curve * - * Returns 0 for OK or -1 for failure + * Returns 0 for OK or nonzero for failure */ LWS_VISIBLE int lws_jwk_generate(struct lws_context *context, struct lws_jwk *jwk, diff --git a/include/libwebsockets/lws-jws.h b/include/libwebsockets/lws-jws.h index 0ad4714b7c..f15d503cc1 100644 --- a/include/libwebsockets/lws-jws.h +++ b/include/libwebsockets/lws-jws.h @@ -111,7 +111,7 @@ lws_jws_destroy(struct lws_jws *jws); * in a map... it'll make a temp b64 version needed for comparison. See below * for other variants. * - * Returns 0 on match. + * Returns 0 on match, else nonzero. */ LWS_VISIBLE LWS_EXTERN int lws_jws_sig_confirm_compact(struct lws_jws_map *map, struct lws_jwk *jwk, @@ -139,7 +139,7 @@ lws_jws_sig_confirm_compact_b64_map(struct lws_jws_map *map_b64, * (jose.payload.hdr.sig) as an aggregated string... it'll make a temp plain * version needed for comparison. * - * Returns 0 on match. + * Returns 0 on match, else nonzero. */ LWS_VISIBLE LWS_EXTERN int lws_jws_sig_confirm_compact_b64(const char *in, size_t len, @@ -163,7 +163,7 @@ lws_jws_sig_confirm_compact_b64(const char *in, size_t len, * will end up with both maps, and can use this api version, saving needlessly * regenerating any temp map. * - * Returns 0 on match. + * Returns 0 on match, else nonzero. */ LWS_VISIBLE LWS_EXTERN int lws_jws_sig_confirm(struct lws_jws_map *map_b64, /* b64-encoded */ @@ -187,7 +187,9 @@ lws_jws_sig_confirm(struct lws_jws_map *map_b64, /* b64-encoded */ * case \p b64_hdr may be NULL, and only the payload will be hashed before * signing. * - * Returns the length of the encoded signature written to \p b64_sig, or -1. + * If successful, returns the length of the encoded signature written to + * \p b64_sig. If the jose signing type is unknown, 0 is returned. Otherwise + * -1 indicates failure. */ LWS_VISIBLE LWS_EXTERN int lws_jws_sign_from_b64(struct lws_jose *jose, struct lws_jws *jws, char *b64_sig, @@ -556,7 +558,7 @@ struct lws_jwt_sign_set_cookie { }; /** - * lws_jwt_sign_token_set_cookie() - creates sets a JWT in a wsi cookie + * lws_jwt_sign_token_set_http_cookie() - creates sets a JWT in a wsi cookie * * \param wsi: the wsi to create the cookie header on * \param i: structure describing what should be in the JWT diff --git a/include/libwebsockets/lws-network-helper.h b/include/libwebsockets/lws-network-helper.h index 4ad16bef83..20a3225309 100644 --- a/include/libwebsockets/lws-network-helper.h +++ b/include/libwebsockets/lws-network-helper.h @@ -223,8 +223,9 @@ lws_sa46_parse_numeric_address(const char *ads, lws_sockaddr46 *sa46); * \param len: max size of text buffer * * Converts an array of network-ordered byte address elements to a textual - * representation of the numeric address, like "1.2.3.4" or "::1". Return 0 - * if OK else < 0. ipv6 only supported with LWS_IPV6=1 at cmake. + * representation of the numeric address, like "1.2.3.4" or "::1". Returns the + * number of chars written into buf, else < 0. ipv6 only supported with + * LWS_IPV6=1 at cmake. */ LWS_VISIBLE LWS_EXTERN int lws_write_numeric_address(const uint8_t *ads, int size, char *buf, size_t len); @@ -237,8 +238,9 @@ lws_write_numeric_address(const uint8_t *ads, int size, char *buf, size_t len); * \param len: max size of text buffer * * Converts the ipv4 or ipv6 address in an lws_sockaddr46 to a textual - * representation of the numeric address, like "1.2.3.4" or "::1". Return 0 - * if OK else < 0. ipv6 only supported with LWS_IPV6=1 at cmake. + * representation of the numeric address, like "1.2.3.4" or "::1". Returns the + * number of chars written into buf, else < 0. ipv6 only supported with + * LWS_IPV6=1 at cmake. */ LWS_VISIBLE LWS_EXTERN int lws_sa46_write_numeric_address(lws_sockaddr46 *sa46, char *buf, size_t len); diff --git a/include/libwebsockets/lws-secure-streams-client.h b/include/libwebsockets/lws-secure-streams-client.h index adca1db169..4d24cbaea0 100644 --- a/include/libwebsockets/lws-secure-streams-client.h +++ b/include/libwebsockets/lws-secure-streams-client.h @@ -223,8 +223,7 @@ lws_sspc_request_tx_len(struct lws_sspc_handle *h, unsigned long len); * * \param h: secure streams handle * - * Starts the connection process for the secure stream. Returns 0 if OK or - * nonzero if we have already failed. + * Starts the connection process for the secure stream. Returns 0. */ LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t lws_sspc_client_connect(struct lws_sspc_handle *h); @@ -292,7 +291,7 @@ lws_sspc_rideshare(struct lws_sspc_handle *h); * when the policy is using h1 is interpreted to add h1 headers of the given * name with the value of the metadata on the left. * - * Return 0 if OK. + * Return 0 if OK, or nonzero if failed. */ LWS_VISIBLE LWS_EXTERN int lws_sspc_set_metadata(struct lws_sspc_handle *h, const char *name, diff --git a/include/libwebsockets/lws-x509.h b/include/libwebsockets/lws-x509.h index 17a834c190..e60d6d16e0 100644 --- a/include/libwebsockets/lws-x509.h +++ b/include/libwebsockets/lws-x509.h @@ -106,7 +106,7 @@ lws_x509_create(struct lws_x509_cert **x509); * IMPORTANT for compatibility with mbedtls, the last used byte of \p pem * must be '\0' and the \p len must include it. * - * Returns 0 if all went OK. + * Returns 0 if all went OK, or nonzero for failure. */ LWS_VISIBLE LWS_EXTERN int lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len); @@ -192,8 +192,8 @@ lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type, * lws_tls_peer_cert_info() lets you get hold of information from the peer * certificate. * - * Return 0 if there is a result in \p buf, or -1 indicating there was no cert - * or another problem. + * Return 0 if there is a result in \p buf, or nonzero indicating there was no + * cert, or another problem. * * This function works the same no matter if the TLS backend is OpenSSL or * mbedTLS. @@ -213,8 +213,8 @@ lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type, * lws_tls_vhost_cert_info() lets you get hold of information from the vhost * certificate. * - * Return 0 if there is a result in \p buf, or -1 indicating there was no cert - * or another problem. + * Return 0 if there is a result in \p buf, or nonzero indicating there was no + * cert, or another problem. * * This function works the same no matter if the TLS backend is OpenSSL or * mbedTLS. @@ -232,8 +232,8 @@ lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type, * \param san_b: second SAN written into the certificate * * - * Returns 0 if created and attached to the vhost. Returns -1 if problems and - * frees all allocations before returning. + * Returns 0 if created and attached to the vhost. Returns nonzero if problems, + * and frees all allocations before returning. * * On success, any allocations are destroyed at vhost destruction automatically. */ From 7882a6dc13f0d44cbab9f916e7340ff2b9d9890b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 09:22:46 +0000 Subject: [PATCH 049/275] jit-trust: clean after failed mbedtls_x509_get_name mbedtls_x509_get_name() does not clean up properly after itself in the case of OOM on multi-segment name. We have to add extra handling and cleaning. --- lib/tls/mbedtls/mbedtls-client.c | 1 + lib/tls/mbedtls/mbedtls-extensions.c | 33 +++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/tls/mbedtls/mbedtls-client.c b/lib/tls/mbedtls/mbedtls-client.c index 7f9651feb6..c12bbd5069 100644 --- a/lib/tls/mbedtls/mbedtls-client.c +++ b/lib/tls/mbedtls/mbedtls-client.c @@ -161,6 +161,7 @@ lws_ssl_client_bio_create(struct lws *wsi) #if defined(LWS_WITH_TLS_JIT_TRUST) SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER, lws_mbedtls_client_verify_callback); + (void)fl; #else SSL_set_verify(wsi->tls.ssl, fl, NULL); #endif diff --git a/lib/tls/mbedtls/mbedtls-extensions.c b/lib/tls/mbedtls/mbedtls-extensions.c index 092c36dc79..839563e57e 100644 --- a/lib/tls/mbedtls/mbedtls-extensions.c +++ b/lib/tls/mbedtls/mbedtls-extensions.c @@ -185,6 +185,34 @@ x509_get_skid(uint8_t **p, const uint8_t *end, mbedtls_x509_buf *skid) return *p != end; } +/* + * Names may have multiple allocated segments in a linked-list, when the mbedtls + * api mbedtls_x509_get_name() fails, it doesn't clean up any already-allocated + * segments, wrongly leaving it to the caller to handle. This helper takes care + * of the missing cleaning for allocation error path. + * + * name.next must be set to NULL by user code before calling ...get_name(..., + * &name), since not every error exit sets it and it will contain garbage if + * defined on stack as is usual. + */ + +static void +lws_x509_clean_name(mbedtls_x509_name *name) +{ + mbedtls_x509_name *n1; + + if (!name) + return; + + n1 = name->MBEDTLS_PRIVATE(next); + + while (n1) { + name = n1->MBEDTLS_PRIVATE(next); + free(n1); + n1 = name; + } +} + static int lws_mbedtls_x509_parse_general_name(const mbedtls_x509_buf *name_buf, lws_mbedtls_x509_subject_alternative_name *name) @@ -221,9 +249,12 @@ lws_mbedtls_x509_parse_general_name(const mbedtls_x509_buf *name_buf, * expects the beginning of the SET tag */ *p = *p - 2; + rfc822Name.MBEDTLS_PRIVATE(next) = NULL; ret = mbedtls_x509_get_name( p, end, &rfc822Name ); - if (ret) + if (ret) { + lws_x509_clean_name(&rfc822Name); return ret; + } memset(name, 0, sizeof(*name)); name->type = LWS_MBEDTLS_X509_SAN_OTHER_NAME; From 240cd55ef6c43f603f275e44ea8c7ef0f87b058b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 09:27:59 +0000 Subject: [PATCH 050/275] jit-trust: show coverity we handle NULL attribute source Coverity doesn't understand that since we already handled akid.keyIdentifier.MBEDTLS_PRIVATE(len) being zero, we don't need to check for akid.keyIdentifier.MBEDTLS_PRIVATE(p) being NULL. So explicitly check it, even though it is a NOP. --- lib/tls/mbedtls/mbedtls-x509.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/tls/mbedtls/mbedtls-x509.c b/lib/tls/mbedtls/mbedtls-x509.c index e20e07fc1c..b6d944d356 100644 --- a/lib/tls/mbedtls/mbedtls-x509.c +++ b/lib/tls/mbedtls/mbedtls-x509.c @@ -202,7 +202,8 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, if (akid.keyIdentifier.MBEDTLS_PRIVATE(tag) != MBEDTLS_ASN1_OCTET_STRING) return 1; buf->ns.len = (int)akid.keyIdentifier.MBEDTLS_PRIVATE(len); - if (len < (size_t)buf->ns.len) + if (!akid.keyIdentifier.MBEDTLS_PRIVATE(p) || + len < (size_t)buf->ns.len) return -1; memcpy(buf->ns.name, akid.keyIdentifier.MBEDTLS_PRIVATE(p), (size_t)buf->ns.len); break; @@ -224,6 +225,7 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, while (ip) { if (akid.keyIdentifier.MBEDTLS_PRIVATE(tag) != MBEDTLS_ASN1_OCTET_STRING || + !ip->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(p) || ip->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(len) < 9 || len < (size_t)ip->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(len) - 9u) break; @@ -246,7 +248,8 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, if (akid.authorityCertSerialNumber.MBEDTLS_PRIVATE(tag) != MBEDTLS_ASN1_OCTET_STRING) return 1; buf->ns.len = (int)akid.authorityCertSerialNumber.MBEDTLS_PRIVATE(len); - if (len < (size_t)buf->ns.len) + if (!akid.authorityCertSerialNumber.MBEDTLS_PRIVATE(p) || + len < (size_t)buf->ns.len) return -1; memcpy(buf->ns.name, akid.authorityCertSerialNumber. MBEDTLS_PRIVATE(p), (size_t)buf->ns.len); From 57c5a0da55d871df6a311ce9f847171995fc29e6 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 09:37:44 +0000 Subject: [PATCH 051/275] jit-trust: SAN_RFC822_NAME needs other_name union member ->san is a union, in this case we set the type to indicate we use SAN_OTHER_NAME member, but set the unstructured_name union member, that is smaller. This doesn't cause any problem, since the union has space for it. But Coverity noticed, it is wrong, so fix it. --- lib/tls/mbedtls/mbedtls-extensions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tls/mbedtls/mbedtls-extensions.c b/lib/tls/mbedtls/mbedtls-extensions.c index 839563e57e..dc406e8267 100644 --- a/lib/tls/mbedtls/mbedtls-extensions.c +++ b/lib/tls/mbedtls/mbedtls-extensions.c @@ -258,7 +258,7 @@ lws_mbedtls_x509_parse_general_name(const mbedtls_x509_buf *name_buf, memset(name, 0, sizeof(*name)); name->type = LWS_MBEDTLS_X509_SAN_OTHER_NAME; - memcpy(&name->san.unstructured_name, + memcpy(&name->san.other_name, &rfc822Name, sizeof(rfc822Name)); return 0; From 39380ffbac0df4af91fe79a2eb51ae86769bdc45 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 09:45:39 +0000 Subject: [PATCH 052/275] client: connect: confirm we have a protocol Coverity gets antsy that we were checking wsi->a.protocol for NULL earlier then start using it... explicitly bail if it's NULL before we start using it. --- lib/core-net/client/connect.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/core-net/client/connect.c b/lib/core-net/client/connect.c index 89db49d915..23c4c36764 100644 --- a/lib/core-net/client/connect.c +++ b/lib/core-net/client/connect.c @@ -451,6 +451,10 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) if (i->pwsi) *i->pwsi = wsi; + if (!wsi->a.protocol) + /* we must have one protocol or another bound by this point */ + goto bail; + /* PHASE 8: notify protocol with role-specific connected callback */ /* raw socket per se doesn't want this... raw socket proxy wants it... */ From a00703f50074f53d4af0250c6340245e3470490b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 09:51:19 +0000 Subject: [PATCH 053/275] unix-sockets: NOP for coverity continue here makes no difference than using break, but continue gets us a pointless complaint "statement continue does not have any effect" and break does not. --- lib/plat/unix/unix-sockets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index 3efe08e8cf..24fdb70403 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -371,7 +371,7 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, break; #endif default: - continue; + break; } } From 6e9c25d1f76f40a91a070a237359189feb3f8d7d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 09:53:56 +0000 Subject: [PATCH 054/275] mbedtls-x509: coverity: remove needless check ip can't be NULL, it's set to the address of another object. --- lib/tls/mbedtls/mbedtls-x509.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/tls/mbedtls/mbedtls-x509.c b/lib/tls/mbedtls/mbedtls-x509.c index b6d944d356..2dad865d68 100644 --- a/lib/tls/mbedtls/mbedtls-x509.c +++ b/lib/tls/mbedtls/mbedtls-x509.c @@ -220,9 +220,6 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, buf->ns.len = 0; - if (!ip) - return 1; - while (ip) { if (akid.keyIdentifier.MBEDTLS_PRIVATE(tag) != MBEDTLS_ASN1_OCTET_STRING || !ip->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(p) || From b0cd8f6703645ac2eafd65e841c5f06458a7c319 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 09:56:55 +0000 Subject: [PATCH 055/275] ss-h1: coverity: add needless header NULL check Coverity does not understand that once we checked that the header has a non-zero length, the associated pointer can never be NULL. Add a pointless check to make it happy. --- lib/secure-streams/protocols/ss-h1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 73cc25629e..9bfed470e8 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -326,7 +326,7 @@ lws_extract_metadata(lws_ss_handle_t *h, struct lws *wsi) const char *cp = lws_hdr_simple_ptr(wsi, polmd->value_is_http_token); omd = lws_ss_get_handle_metadata(h, polmd->name); - if (!omd) + if (!omd || !cp) return 1; assert(!strcmp(omd->name, polmd->name)); From 11ba0b713b83621f65ca859d2798d8d603bbb65b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 10:00:17 +0000 Subject: [PATCH 056/275] adopt: coverity: add pointless vh NULL check The wsi is always created on a valid vhost. Add a needless NULL check on it to satisfy coverity. --- lib/core-net/adopt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index 212adc4d95..963fd3d24f 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -133,6 +133,9 @@ __lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, * we initialize it, it may become "live" concurrently unexpectedly... */ + if (!vh) + return NULL; + lws_context_assert_lock_held(vh->context); n = -1; From b415f59bd27975e8e781526a8c5ee846f37fcb66 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 10:41:53 +0000 Subject: [PATCH 057/275] ss-deserialize: add pointless h NULL check h cannot be NULL since it's set by address offset earlier. Help coverity understand that. --- lib/secure-streams/secure-streams-serialize.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/secure-streams/secure-streams-serialize.c b/lib/secure-streams/secure-streams-serialize.c index 09969fea80..2202e02984 100644 --- a/lib/secure-streams/secure-streams-serialize.c +++ b/lib/secure-streams/secure-streams-serialize.c @@ -1074,6 +1074,11 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, lwsl_err("%s: OOM\n", __func__); goto hangup; } + + if (!h) + /* coverity */ + goto hangup; + memset(md, 0, sizeof(lws_sspc_metadata_t)); lws_strncpy(md->name, par->metadata_name, From 1db45d17dfd6282ee7a88676ac01525714305cce Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 10:09:35 +0000 Subject: [PATCH 058/275] h2: coverity: check for OOM on dynamic table alloc It can fail, we should check it. --- lib/roles/http/server/server.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index 150eeec562..57953cac67 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -2437,8 +2437,9 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len) lws_h2_settings(wsi, &wsi->h2.h2n->peer_set, (uint8_t *)tbuf, n); - lws_hpack_dynamic_size(wsi, (int)wsi->h2.h2n->peer_set.s[ - H2SET_HEADER_TABLE_SIZE]); + if (lws_hpack_dynamic_size(wsi, (int)wsi->h2.h2n->peer_set.s[ + H2SET_HEADER_TABLE_SIZE])) + return 1; strcpy(tbuf, "HTTP/1.1 101 Switching Protocols\x0d\x0a" "Connection: Upgrade\x0d\x0a" From f9fc45bd9896e19b00a40da64134845ccf5fcea0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 8 Nov 2021 10:44:55 +0000 Subject: [PATCH 059/275] sspc: proxy: coverity: handle unknown metadata name --- lib/secure-streams/secure-streams-serialize.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/secure-streams/secure-streams-serialize.c b/lib/secure-streams/secure-streams-serialize.c index 2202e02984..53a9ed8151 100644 --- a/lib/secure-streams/secure-streams-serialize.c +++ b/lib/secure-streams/secure-streams-serialize.c @@ -1156,8 +1156,22 @@ lws_ss_deserialize_parse(struct lws_ss_serialization_parser *par, if (client) { *par->rxmetaval++ = *cp++; - } else + } else { + + if (!par->ssmd) { + /* we don't recognize the name */ + + cp++; + + if (--par->rem) + break; + + par->ps = RPAR_TYPE; + break; + } + ((uint8_t *)(par->ssmd->value__may_own_heap))[par->ctr++] = *cp++; + } if (--par->rem) break; From 3e1a1a443dd5c904e8773c425f9bdbeea8a43f08 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 17 Oct 2021 07:48:40 +0100 Subject: [PATCH 060/275] coverity: client_reset: no longer any way to get NULL *pwsi Coverity belatedly noticed that client_reset no longer changes *pwsi --- lib/roles/http/client/client-http.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 221f394dee..7dce850006 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -819,21 +819,9 @@ lws_client_interpret_server_handshake(struct lws *wsi) } if (!lws_client_reset(&wsi, ssl, ads, port, path, ads, 1)) { - /* - * There are two ways to fail out with NULL return... - * simple, early problem where the wsi is intact, or - * we went through with the reconnect attempt and the - * wsi is already closed. In the latter case, the wsi - * has been set to NULL additionally. - */ lwsl_err("Redirect failed\n"); cce = "HS: Redirect failed"; - /* coverity[reverse_inull] */ - if (wsi) - goto bail3; - - /* wsi has closed */ - return 1; + goto bail3; } /* From f8a21fec225a324e9ff8bc5fc05aeffc001d77aa Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 9 Nov 2021 09:27:38 +0000 Subject: [PATCH 061/275] adopt: coverity: move vh deref until after pointless check --- lib/core-net/adopt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index 963fd3d24f..e411945104 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -122,7 +122,7 @@ __lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, const char *vh_prot_name, struct lws *parent, void *opaque, const char *fi_wsi_name) { - struct lws_context *context = vh->context; + struct lws_context *context; struct lws_context_per_thread *pt; struct lws *new_wsi; int n; @@ -136,6 +136,8 @@ __lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, if (!vh) return NULL; + context = vh->context; + lws_context_assert_lock_held(vh->context); n = -1; From cab34801ea7841d320ee264e172d849135030291 Mon Sep 17 00:00:00 2001 From: Yichen Gu Date: Mon, 8 Nov 2021 13:42:52 +0000 Subject: [PATCH 062/275] wsimux: immortal: only process immortality once per stream We can call mark immortal multiple times for a child stream, make sure it is only processed (and increments the nwsi refcount) the once. --- lib/core-net/wsi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index 7a0ffeaede..978d1e80c6 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -1305,10 +1305,14 @@ lws_mux_mark_immortal(struct lws *wsi) && !wsi->client_mux_substream #endif ) { - lwsl_wsi_err(wsi, "not h2 substream"); + lwsl_wsi_err(wsi, "not mux substream"); return; } + if (wsi->mux_stream_immortal) + /* only need to handle it once per child wsi */ + return; + nwsi = lws_get_network_wsi(wsi); if (!nwsi) return; From b45dfcb81e6d3c129969bcc3592f9b7a128b4eb0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 7 Nov 2021 07:19:21 +0000 Subject: [PATCH 063/275] windows: mingw file type is int --- include/libwebsockets.h | 2 +- lib/plat/windows/private-lib-plat-windows.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 759f3d61f6..bc7407c991 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -383,7 +383,7 @@ struct lws; #if defined(_WIN32) #if !defined(LWS_WIN32_HANDLE_TYPES) typedef SOCKET lws_sockfd_type; -typedef HANDLE lws_filefd_type; +typedef int lws_filefd_type; #endif diff --git a/lib/plat/windows/private-lib-plat-windows.h b/lib/plat/windows/private-lib-plat-windows.h index beb5f544de..f2e93f318b 100644 --- a/lib/plat/windows/private-lib-plat-windows.h +++ b/lib/plat/windows/private-lib-plat-windows.h @@ -155,7 +155,7 @@ struct lws_fd_hashtable { #endif typedef SOCKET lws_sockfd_type; -typedef HANDLE lws_filefd_type; +typedef int lws_filefd_type; #define LWS_WIN32_HANDLE_TYPES LWS_EXTERN struct lws * From 3ef446f27ca3a7a3f5af5402521a20246f434fd3 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 9 Nov 2021 08:58:01 +0000 Subject: [PATCH 064/275] freertos-service: remove cruft This can't be reached currently, so remove it and simplify the setting of c to the exact equivalent. --- lib/plat/freertos/freertos-service.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/plat/freertos/freertos-service.c b/lib/plat/freertos/freertos-service.c index 41f55fcbe9..795e382859 100644 --- a/lib/plat/freertos/freertos-service.c +++ b/lib/plat/freertos/freertos-service.c @@ -191,15 +191,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) a = 1; m = lws_service_flag_pending(context, tsi); - if (m) - c = -1; /* unknown limit */ - else - if (n < 0) { - if (LWS_ERRNO != LWS_EINTR) - return -1; - return 0; - } else - c = n; + c = m ? -1 : n; /* any socket with events to service? */ for (n = 0; n < (int)pt->fds_count && c; n++) { From 121dd5e8eefdd3eeae2966e2cedc2d64319d2b79 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 9 Nov 2021 09:53:11 +0000 Subject: [PATCH 065/275] ss: revert make ss timeout handle underlying wsi gone --- lib/secure-streams/secure-streams.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 9d02d5a6f4..489543dba7 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -1745,10 +1745,8 @@ lws_ss_to_cb(lws_sorted_usec_list_t *sul) if (r != LWSSSSRET_DISCONNECT_ME && r != LWSSSSRET_DESTROY_ME) return; - if (!h->wsi) - return; - - lws_set_timeout(h->wsi, 1, LWS_TO_KILL_ASYNC); + if (h->wsi) + lws_set_timeout(h->wsi, 1, LWS_TO_KILL_ASYNC); _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, h->wsi, &h); } From bc83a5720782b310ab683e123d27a1558823c345 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 17 Nov 2021 14:48:59 +0000 Subject: [PATCH 066/275] h2: post: do not try to bind origin for files --- lib/roles/h2/ops-h2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/roles/h2/ops-h2.c b/lib/roles/h2/ops-h2.c index a791081176..989cb5b95e 100644 --- a/lib/roles/h2/ops-h2.c +++ b/lib/roles/h2/ops-h2.c @@ -837,6 +837,9 @@ lws_h2_bind_for_post_before_action(struct lws *wsi) if (hit->protocol) name = hit->protocol; + else + if (hit->origin_protocol == LWSMPRO_FILE) + return 0; pp = lws_vhost_name_to_protocol(wsi->a.vhost, name); if (!pp) { From eba4f8cfb850a8a5edf467a73ea085e194ffcf61 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 11 Nov 2021 08:58:29 +0000 Subject: [PATCH 067/275] http: remove stray debug log --- lib/roles/http/parsers.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/roles/http/parsers.c b/lib/roles/http/parsers.c index 18e5b5aabf..446bc986ae 100644 --- a/lib/roles/http/parsers.c +++ b/lib/roles/http/parsers.c @@ -545,11 +545,6 @@ int lws_hdr_copy(struct lws *wsi, char *dst, int len, return -1; n = wsi->http.ah->frag_index[h]; - if (h == WSI_TOKEN_HTTP_URI_ARGS) - lwsl_err("%s: WSI_TOKEN_HTTP_URI_ARGS start frag %d\n", - __func__, n); - - if (!n) return 0; do { From b0b7fff957cc15b7d059ff62c6ce245b4a76067c Mon Sep 17 00:00:00 2001 From: calvin2021y Date: Wed, 10 Nov 2021 16:45:02 +0000 Subject: [PATCH 068/275] android: fix extra warnings on android-resolv --- lib/plat/unix/android/android-resolv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/plat/unix/android/android-resolv.c b/lib/plat/unix/android/android-resolv.c index d28fb9cc10..3ae38d5ca0 100644 --- a/lib/plat/unix/android/android-resolv.c +++ b/lib/plat/unix/android/android-resolv.c @@ -38,13 +38,13 @@ lws_plat_asyncdns_init(struct lws_context *context, lws_sockaddr46 *sa46) return LADNS_CONF_SERVER_UNKNOWN; for (n = 0; n < 4; n++) { - i[n] = atoi(d); + i[n] = (uint8_t)atoi(d); p = strchr(d, '.'); if (n != 3 && !p) return LADNS_CONF_SERVER_UNKNOWN; } - ip32 = (i[0] << 24) | (i[1] << 16) | (i[2] << 8) | i[3]; + ip32 = (uint32_t) ((i[0] << 24) | (i[1] << 16) | (i[2] << 8) | i[3]); n = ip32 == sa46->sa4.sin_addr.s_addr; sa46->sa4.sin_family = AF_INET; sa46->sa4.sin_addr.s_addr = ip32; From c1828713582d5c9d50c9fbde151c577e9583e413 Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Mon, 15 Nov 2021 07:45:12 -0800 Subject: [PATCH 069/275] mqtt: always init wildcard and shadow --- lib/roles/mqtt/mqtt.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index 7170b2e32e..67d64dbc0d 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -429,10 +429,8 @@ lws_mqtt_create_sub(struct _lws_mqtt_related *mqtt, const char *topic) __func__); return NULL; } - if (flag == LMVTR_VALID_WILDCARD) - mysub->wildcard = 1; - else if (flag == LMVTR_VALID_SHADOW) - mysub->shadow = 1; + mysub->wildcard = (flag == LMVTR_VALID_WILDCARD); + mysub->shadow = (flag == LMVTR_VALID_SHADOW); break; default: From d42a7900d6e1c1ed533ca4206d4f248b96d48a11 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 10 Nov 2021 16:26:18 +0000 Subject: [PATCH 070/275] ws: client: fail server link if masked --- lib/roles/ws/client-parser-ws.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/roles/ws/client-parser-ws.c b/lib/roles/ws/client-parser-ws.c index 09e681f921..f569532ec3 100644 --- a/lib/roles/ws/client-parser-ws.c +++ b/lib/roles/ws/client-parser-ws.c @@ -177,6 +177,8 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) case LWS_RXPS_04_FRAME_HDR_LEN: wsi->ws->this_frame_masked = !!(c & 0x80); + if (wsi->ws->this_frame_masked) + goto server_cannot_mask; switch (c & 0x7f) { case 126: @@ -674,6 +676,16 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) illegal_ctl_length: lwsl_wsi_warn(wsi, "Control frame asking for extended length is illegal"); + /* kill the connection */ + return -1; + +server_cannot_mask: + lws_close_reason(wsi, + LWS_CLOSE_STATUS_PROTOCOL_ERR, + (uint8_t *)"srv mask", 8); + + lwsl_wsi_warn(wsi, "Server must not mask"); + /* kill the connection */ return -1; } From c295f8014ad88a3bdf833abd772375c92eb1d484 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 22 Nov 2021 15:37:18 +0000 Subject: [PATCH 071/275] extpoll: make sure DEL_POLL_FD only coming once https://github.com/warmcat/libwebsockets/issues/2500 --- lib/core-net/pollfd.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/core-net/pollfd.c b/lib/core-net/pollfd.c index e5a8ac9b27..dea85aec02 100644 --- a/lib/core-net/pollfd.c +++ b/lib/core-net/pollfd.c @@ -438,15 +438,17 @@ __remove_wsi_socket_from_fds(struct lws *wsi) /* removed wsi has no position any more */ wsi->position_in_fds_table = LWS_NO_FDS_POS; - } #if defined(LWS_WITH_EXTERNAL_POLL) - /* remove also from external POLL support via protocol 0 */ - if (lws_socket_is_valid(wsi->desc.sockfd) && wsi->a.vhost && - wsi->a.vhost->protocols[0].callback(wsi, LWS_CALLBACK_DEL_POLL_FD, - wsi->user_space, (void *) &pa, 0)) - ret = -1; + /* remove also from external POLL support via protocol 0 */ + if (lws_socket_is_valid(wsi->desc.sockfd) && wsi->a.vhost && + wsi->a.vhost->protocols[0].callback(wsi, + LWS_CALLBACK_DEL_POLL_FD, + wsi->user_space, + (void *) &pa, 0)) + ret = -1; #endif + } #if defined(LWS_WITH_SERVER) if (!context->being_destroyed && From 741cf67b7fc66857332c29bc165bada0a03c8309 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 7 Nov 2021 07:19:21 +0000 Subject: [PATCH 072/275] windows: mingw file type is int (v2) --- include/libwebsockets.h | 8 ++++++++ lib/plat/windows/private-lib-plat-windows.h | 4 ++++ lib/plat/windows/windows-file.c | 19 ++++++++++++------- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/include/libwebsockets.h b/include/libwebsockets.h index bc7407c991..4409ee2784 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -125,7 +125,11 @@ typedef int suseconds_t; #define LWS_EXTERN #endif +#if defined(__MINGW32__) +#define LWS_INVALID_FILE -1 +#else #define LWS_INVALID_FILE INVALID_HANDLE_VALUE +#endif #define LWS_SOCK_INVALID (INVALID_SOCKET) #define LWS_O_RDONLY _O_RDONLY #define LWS_O_WRONLY _O_WRONLY @@ -383,7 +387,11 @@ struct lws; #if defined(_WIN32) #if !defined(LWS_WIN32_HANDLE_TYPES) typedef SOCKET lws_sockfd_type; +#if defined(__MINGW32__) typedef int lws_filefd_type; +#else +typedef HANDLE lws_filefd_type; +#endif #endif diff --git a/lib/plat/windows/private-lib-plat-windows.h b/lib/plat/windows/private-lib-plat-windows.h index f2e93f318b..18d87ac251 100644 --- a/lib/plat/windows/private-lib-plat-windows.h +++ b/lib/plat/windows/private-lib-plat-windows.h @@ -155,7 +155,11 @@ struct lws_fd_hashtable { #endif typedef SOCKET lws_sockfd_type; +#if defined(__MINGW32__) typedef int lws_filefd_type; +#else +typedef HANDLE lws_filefd_type; +#endif #define LWS_WIN32_HANDLE_TYPES LWS_EXTERN struct lws * diff --git a/lib/plat/windows/windows-file.c b/lib/plat/windows/windows-file.c index d768b284d1..27b0a9cc64 100644 --- a/lib/plat/windows/windows-file.c +++ b/lib/plat/windows/windows-file.c @@ -50,7 +50,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } - if (ret == LWS_INVALID_FILE) + if (ret == NULL) goto bail; fop_fd = malloc(sizeof(*fop_fd)); @@ -58,8 +58,13 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, goto bail; fop_fd->fops = fops; +#if defined(__MINGW32__) + /* we use filesystem_priv */ + fop_fd->fd = (int)(intptr_t)ret; +#else fop_fd->fd = ret; - fop_fd->filesystem_priv = NULL; /* we don't use it */ +#endif + fop_fd->filesystem_priv = ret; fop_fd->flags = *flags; fop_fd->len = GetFileSize(ret, NULL); if(GetFileSizeEx(ret, &llFileSize)) @@ -76,7 +81,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, int _lws_plat_file_close(lws_fop_fd_t *fop_fd) { - HANDLE fd = (*fop_fd)->fd; + HANDLE fd = (*fop_fd)->filesystem_priv; free(*fop_fd); *fop_fd = NULL; @@ -92,7 +97,7 @@ _lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset) LARGE_INTEGER l; l.QuadPart = offset; - if (!SetFilePointerEx((HANDLE)fop_fd->fd, l, NULL, FILE_CURRENT)) + if (!SetFilePointerEx((HANDLE)fop_fd->filesystem_priv, l, NULL, FILE_CURRENT)) { lwsl_err("error seeking from cur %ld, offset %ld\n", (long)fop_fd->pos, (long)offset); return -1; @@ -101,7 +106,7 @@ _lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset) LARGE_INTEGER zero; zero.QuadPart = 0; LARGE_INTEGER newPos; - if (!SetFilePointerEx((HANDLE)fop_fd->fd, zero, &newPos, FILE_CURRENT)) + if (!SetFilePointerEx((HANDLE)fop_fd->filesystem_priv, zero, &newPos, FILE_CURRENT)) { lwsl_err("error seeking from cur %ld, offset %ld\n", (long)fop_fd->pos, (long)offset); return -1; @@ -117,7 +122,7 @@ _lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, { DWORD _amount; - if (!ReadFile((HANDLE)fop_fd->fd, buf, (DWORD)len, &_amount, NULL)) { + if (!ReadFile((HANDLE)fop_fd->filesystem_priv, buf, (DWORD)len, &_amount, NULL)) { *amount = 0; return 1; @@ -135,7 +140,7 @@ _lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount, { DWORD _amount; - if (!WriteFile((HANDLE)fop_fd->fd, buf, (DWORD)len, &_amount, NULL)) { + if (!WriteFile((HANDLE)fop_fd->filesystem_priv, buf, (DWORD)len, &_amount, NULL)) { *amount = 0; return 1; From 0dc0f92f29da0d3320a8c1b9f42830ee7531924f Mon Sep 17 00:00:00 2001 From: Vitaliy Orazov Date: Mon, 29 Nov 2021 17:26:48 +0300 Subject: [PATCH 073/275] http proxy: support PUT, PATCH and DELETE methods --- lib/roles/http/server/server.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index 57953cac67..bd38a33f7e 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -1393,6 +1393,36 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, #endif ) i.method = "POST"; + else if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PUT_URI) +#if defined(LWS_WITH_HTTP2) + || ( + lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) && + !strcmp(lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_COLON_METHOD), "put") + ) +#endif + ) + i.method = "PUT"; + else if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PATCH_URI) +#if defined(LWS_WITH_HTTP2) + || ( + lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) && + !strcmp(lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_COLON_METHOD), "patch") + ) +#endif + ) + i.method = "PATCH"; + else if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_DELETE_URI) +#if defined(LWS_WITH_HTTP2) + || ( + lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) && + !strcmp(lws_hdr_simple_ptr(wsi, + WSI_TOKEN_HTTP_COLON_METHOD), "delete") + ) +#endif + ) + i.method = "DELETE"; else i.method = "GET"; } From 122cf591a3b573f5a78299602faabf364e6c99be Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 29 Nov 2021 05:04:56 +0000 Subject: [PATCH 074/275] docs: decruft README.coding --- READMEs/README.coding.md | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/READMEs/README.coding.md b/READMEs/README.coding.md index f0c7008e2a..d1143f5690 100644 --- a/READMEs/README.coding.md +++ b/READMEs/README.coding.md @@ -183,28 +183,17 @@ loop wait (sleeping in `poll()` or `epoll()` or whatever). The rules above mean directly sending data on the connection from another thread is out of the question. -Therefore the two apis mentioned above that may be used from another thread are - - - For LWS using the default poll() event loop, `lws_callback_on_writable()` - - - For LWS using libuv/libev/libevent event loop, `lws_cancel_service()` - -If you are using the default poll() event loop, one "foreign thread" at a time may -call `lws_callback_on_writable()` directly for a wsi. You need to use your own -locking around that to serialize multiple thread access to it. - -If you implement LWS_CALLBACK_GET_THREAD_ID in protocols[0], then LWS will detect -when it has been called from a foreign thread and automatically use -`lws_cancel_service()` to additionally wake the service loop from its wait. - -For libuv/libev/libevent event loop, they cannot handle being called from other -threads. So there is a slightly different scheme, you may call `lws_cancel_service()` -to force the event loop to end immediately. This then broadcasts a callback (in the -service thread context) `LWS_CALLBACK_EVENT_WAIT_CANCELLED`, to all protocols on all -vhosts, where you can perform your own locking and walk a list of wsi that need -`lws_callback_on_writable()` calling on them. - -`lws_cancel_service()` is very cheap to call. +The only lws api that's safe to call from other thread contexts is `lws_cancel_service()`. +This will take a platform-specific action to wake the lws event loop thread wait, +either put a byte into a pipe2() the event loop is waiting on, or send a packet on +a UDP socket pair that the event loop waits on. When the wake is handled by the +lws event loop thread, it will broadcast a `LWS_CALLBACK_EVENT_WAIT_CANCELLED` +message to every vhost-protocol instantiation, so you can handle this callback, +usually lock a shared data region, and if you see you need to write, call +`lws_callback_on_writeable()` for the wsi(s) that need to write. + +There's no restriction on multiple threads calling `lws_cancel_service()`, it's +unconditionally safe due to how it is implemented underneath. 5) The obverse of this truism about the receiver being the boss is the case where we are receiving. If we get into a situation we actually can't usefully From 0bc5b58ee3bf103ba78b6ccacbc58395e3825f8a Mon Sep 17 00:00:00 2001 From: DerKleinePunk Date: Thu, 2 Dec 2021 09:18:23 +0000 Subject: [PATCH 075/275] http: cookie_get The loop check shouldn't care about bl any more, since we snipped bl from n already. --- lib/roles/http/parsers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/http/parsers.c b/lib/roles/http/parsers.c index 446bc986ae..220f9cf821 100644 --- a/lib/roles/http/parsers.c +++ b/lib/roles/http/parsers.c @@ -1592,7 +1592,7 @@ lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, p += bl; n -= (int)bl; - while (n-- > (int)bl) { + while (n-- > 0) { if (*p == '=' && !memcmp(p - bl, name, (unsigned int)bl)) { p++; while (*p != ';' && n-- && max) { From 91da9e30c7527275d232d2d5f161b53e697ecfe1 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 8 Dec 2021 06:28:16 +0000 Subject: [PATCH 076/275] cancel pipe: mark close when wsi is close --- lib/core-net/close.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index 1a4e0f7f72..5e4edafbd9 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -896,6 +896,18 @@ __lws_close_free_wsi_final(struct lws *wsi) sanity_assert_no_sockfd_traces(wsi->a.context, wsi->desc.sockfd); } + /* ... if we're closing the cancel pipe, account for it */ + + { + struct lws_context_per_thread *pt = + &wsi->a.context->pt[(int)wsi->tsi]; + + if (pt->pipe_wsi == wsi) + pt->pipe_wsi = NULL; + if (pt->dummy_pipe_fds[0] == wsi->desc.sockfd) + pt->dummy_pipe_fds[0] = LWS_SOCK_INVALID; + } + wsi->desc.sockfd = LWS_SOCK_INVALID; #if defined(LWS_WITH_CLIENT) From e529720fc1d66f89b87c6865bb7b50ff75c554db Mon Sep 17 00:00:00 2001 From: Vitaliy Orazov Date: Mon, 13 Dec 2021 18:51:22 +0300 Subject: [PATCH 077/275] http: proxying: allow for large headers set the buffer size (rpath) for header processing during proxying equal to the value in max_http_header_data --- lib/roles/http/server/server.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index bd38a33f7e..c7eb94c3b7 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -1248,10 +1248,12 @@ int lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, char *uri_ptr, char ws) { - char ads[96], rpath[256], host[96], *pcolon, *pslash, unix_skt = 0; + char ads[96], host[96], *pcolon, *pslash, unix_skt = 0; struct lws_client_connect_info i; struct lws *cwsi; int n, na; + unsigned int max_http_header_data = wsi->a.context->max_http_header_data > 256 ? wsi->a.context->max_http_header_data : 256; + char rpath[max_http_header_data]; #if defined(LWS_ROLE_WS) if (ws) @@ -1318,7 +1320,7 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, if (pcolon) i.port = atoi(pcolon + 1); - n = lws_snprintf(rpath, sizeof(rpath) - 1, "/%s/%s", + n = lws_snprintf(rpath, max_http_header_data - 1, "/%s/%s", pslash + 1, uri_ptr + hit->mountpoint_len) - 1; lws_clean_url(rpath); n = (int)strlen(rpath); @@ -1335,7 +1337,7 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, p = rpath + n; - if (na >= (int)sizeof(rpath) - n - 2) { + if (na >= (int)max_http_header_data - n - 2) { lwsl_info("%s: query string %d longer " "than we can handle\n", __func__, na); @@ -1345,7 +1347,7 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, *p++ = '?'; budg = lws_hdr_copy(wsi, p, - (int)(&rpath[sizeof(rpath) - 1] - p), + (int)(&rpath[max_http_header_data - 1] - p), WSI_TOKEN_HTTP_URI_ARGS); if (budg > 0) p += budg; From 7aaa87766dbce818a96f97fc780a3886fa23ea13 Mon Sep 17 00:00:00 2001 From: chilL1n Date: Mon, 13 Dec 2021 21:06:48 +0100 Subject: [PATCH 078/275] docs: lws_service_tsi --- include/libwebsockets/lws-service.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libwebsockets/lws-service.h b/include/libwebsockets/lws-service.h index 2f597b317a..73e498a782 100644 --- a/include/libwebsockets/lws-service.h +++ b/include/libwebsockets/lws-service.h @@ -59,7 +59,7 @@ lws_service(struct lws_context *context, int timeout_ms); * \param tsi: Thread service index, starting at 0 * * Same as lws_service(), but for a specific thread service index. Only needed - * if you are spawning multiple service threads. + * if you are spawning multiple service threads that operate on the same lws_context. */ LWS_VISIBLE LWS_EXTERN int lws_service_tsi(struct lws_context *context, int timeout_ms, int tsi); From 141ebf373ca0fed7b41eb960cdbd7ab1f29490dc Mon Sep 17 00:00:00 2001 From: Paul Lee Date: Tue, 14 Dec 2021 06:56:45 +0000 Subject: [PATCH 079/275] service: make sure to sleep if nothing to do https://github.com/warmcat/libwebsockets/issues/2524 --- lib/core-net/service.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/core-net/service.c b/lib/core-net/service.c index c7b15f320f..02e4c05e2a 100644 --- a/lib/core-net/service.c +++ b/lib/core-net/service.c @@ -322,7 +322,11 @@ lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi) u = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, lws_now_usecs()); - if (u < (lws_usec_t)timeout_ms * (lws_usec_t)1000) + /* + * We will come back with 0 if nothing to do at the moment, or + * the number of us until something to do + */ + if (u && u < (lws_usec_t)timeout_ms * (lws_usec_t)1000) timeout_ms = (int)(u / 1000); lws_pt_unlock(pt); From 9cd7438259d1678d5b59df6483eba96130320cfe Mon Sep 17 00:00:00 2001 From: chenzhongaaron Date: Wed, 15 Dec 2021 04:52:33 +0000 Subject: [PATCH 080/275] qnx: toolchain file and adaptations https://github.com/warmcat/libwebsockets/issues/2527 --- CMakeLists-implied-options.txt | 2 +- cmake/LwsCheckRequirements.cmake | 4 +- contrib/cross-aarch64-qnx.cmake | 50 +++++++++++++++++++ lib/misc/getifaddrs.c | 4 ++ lib/plat/unix/unix-sockets.c | 3 +- .../CMakeLists.txt | 5 +- .../raw/minimal-raw-serial/minimal-raw-file.c | 6 ++- 7 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 contrib/cross-aarch64-qnx.cmake diff --git a/CMakeLists-implied-options.txt b/CMakeLists-implied-options.txt index 9579b1a124..c8137af3ea 100644 --- a/CMakeLists-implied-options.txt +++ b/CMakeLists-implied-options.txt @@ -47,7 +47,7 @@ if (LWS_PLAT_OPTEE) set(LWS_WITH_UDP 0) endif() -if (LWS_PLAT_FREERTOS) +if (LWS_PLAT_FREERTOS OR (${CMAKE_SYSTEM_NAME} MATCHES "QNX")) message(STATUS "No LWS_WITH_DIR or LWS_WITH_LEJP_CONF") set(LWS_WITH_DIR OFF) set(LWS_WITH_LEJP_CONF OFF) diff --git a/cmake/LwsCheckRequirements.cmake b/cmake/LwsCheckRequirements.cmake index fa3fb9fdd6..9fc76e69ca 100644 --- a/cmake/LwsCheckRequirements.cmake +++ b/cmake/LwsCheckRequirements.cmake @@ -75,7 +75,9 @@ MACRO(require_pthreads result) if (WIN32) set(PTHREAD_LIB ${LWS_EXT_PTHREAD_LIBRARIES}) else() - set(PTHREAD_LIB pthread) + if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "QNX") + set(PTHREAD_LIB pthread) + endif() endif() endif() ENDMACRO() diff --git a/contrib/cross-aarch64-qnx.cmake b/contrib/cross-aarch64-qnx.cmake new file mode 100644 index 0000000000..404d1d9896 --- /dev/null +++ b/contrib/cross-aarch64-qnx.cmake @@ -0,0 +1,50 @@ +# +# CMake Toolchain file for crosscompiling aarch64 for QNX. +# +# This can be used when running cmake in the following way: +# cd build/ +# cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-aarch64-qnx.cmake +# + +# adapt to your toolchain path +set(CROSS_PATH /var/toolchain/qnx5.4/host/linux/x86_64/usr) + +# Target operating system name. +set(CMAKE_SYSTEM_NAME QNX) +set(BUILD_SHARED_LIBS OFF) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +# Name of C compiler. +set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/ntoaarch64-gcc") +set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/ntoaarch64-g++") + +set(CMAKE_C_FLAGS "-Wno-error") +set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") + +# +# Different build system distros set release optimization level to different +# things according to their local policy, eg, Fedora is -O2 and Ubuntu is -O3 +# here. Actually the build system's local policy is completely unrelated to +# our desire for cross-build release optimization policy for code built to run +# on a completely different target than the build system itself. +# +# Since this goes last on the compiler commandline we have to override it to a +# sane value for cross-build here. Notice some gcc versions enable broken +# optimizations with -O3. +# +if (CMAKE_BUILD_TYPE MATCHES RELEASE OR CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES release) + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") +endif() + +# Where to look for the target environment. (More paths can be added here) +set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}") + +# Adjust the default behavior of the FIND_XXX() commands: +# search programs in the host environment only. +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# Search headers and libraries in the target environment only. +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/lib/misc/getifaddrs.c b/lib/misc/getifaddrs.c index 98e768c780..125088e228 100644 --- a/lib/misc/getifaddrs.c +++ b/lib/misc/getifaddrs.c @@ -90,7 +90,11 @@ getifaddrs2(struct ifaddrs **ifap, int af, int siocgifconf, int siocgifflags, ret = ENOMEM; goto error_out; } +#if defined(__QNX__) + ifconf.ifc_len = (short)(int)buf_size; +#else ifconf.ifc_len = (int)buf_size; +#endif ifconf.ifc_buf = buf; /* diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index 24fdb70403..07df994cce 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -236,7 +236,8 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) !defined(__OpenBSD__) && \ !defined(__sun) && \ !defined(__HAIKU__) && \ - !defined(__CYGWIN__) + !defined(__CYGWIN__) && \ + !defined(__QNX__) /* the BSDs don't have SO_PRIORITY */ diff --git a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt index e7be79a96f..f332dc5b92 100644 --- a/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt +++ b/minimal-examples/http-client/minimal-http-client-captive-portal/CMakeLists.txt @@ -10,6 +10,7 @@ set(SAMP lws-minimal-http-client-captive-portal) set(SRCS minimal-http-client-captive-portal.c) set(requirements 1) +require_pthreads(requirements) require_lws_config(LWS_ROLE_H1 1 requirements) require_lws_config(LWS_WITH_TLS 1 requirements) require_lws_config(LWS_WITH_CLIENT 1 requirements) @@ -19,9 +20,9 @@ if (NOT WIN32 AND requirements) add_executable(${SAMP} ${SRCS}) if (websockets_shared) - target_link_libraries(${SAMP} websockets_shared pthread ${LIBWEBSOCKETS_DEP_LIBS}) + target_link_libraries(${SAMP} websockets_shared ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) add_dependencies(${SAMP} websockets_shared) else() - target_link_libraries(${SAMP} websockets pthread ${LIBWEBSOCKETS_DEP_LIBS}) + target_link_libraries(${SAMP} websockets ${PTHREAD_LIB} ${LIBWEBSOCKETS_DEP_LIBS}) endif() endif() diff --git a/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c b/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c index 45d50af0af..57ba8f0963 100644 --- a/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c +++ b/minimal-examples/raw/minimal-raw-serial/minimal-raw-file.c @@ -109,7 +109,11 @@ callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, #if defined(__linux__) CBAUD | #endif - CSIZE | CSTOPB | PARENB | CRTSCTS); + CSIZE | CSTOPB | PARENB +#if !defined(__QNX__) + | CRTSCTS +#endif + ); tio.c_cflag |= 0x1412 | CS8 | CREAD | CLOCAL; tcsetattr(vhd->filefd, TCSANOW, &tio); From f2e43272a77dba4264828506c98a1d1424576a92 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 18 Dec 2021 06:36:33 +0000 Subject: [PATCH 081/275] esp32: update against Dec 21 idf Freertos in idf has moved around a bit. --- CMakeLists.txt | 12 ++++++++++++ lib/drivers/button/lws-button.c | 4 ++-- lib/drivers/led/led-gpio.c | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 62bb22271f..c4cd2949c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,10 @@ if (ESP_PLATFORM) include_directories( $ENV{IDF_PATH}/components/esp_hw_support/include/soc/ $ENV{IDF_PATH}/components/freertos/include/ + $ENV{IDF_PATH}/components/freertos/esp_additions/include/ + $ENV{IDF_PATH}/components/freertos/esp_additions/include/freertos/ + $ENV{IDF_PATH}/components/freertos/FreeRTOS-Kernel/include/ + $ENV{IDF_PATH}/components/freertos/FreeRTOS-Kernel/portable/linux/include/ $ENV{IDF_PATH}/components/xtensa/${CONFIG_IDF_TARGET}/include/ $ENV{IDF_PATH}/components/freertos/include/esp_additions $ENV{IDF_PATH}/components/hal/include @@ -795,6 +799,14 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR COMPILER_IS_CLANG) set(CMAKE_C_FLAGS "-Wall -Wsign-compare ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" ) endif() + if (PICO_SDK_PATH) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wconversion -Wsign-compare -Wstrict-aliasing -Wundef -nolibc") + endif() + + if (ESP_PLATFORM AND (CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S2 OR CONFIG_IDF_TARGET_ESP32S3)) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlongcalls") + endif() + if ("${DISABLE_WERROR}" STREQUAL "OFF") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") endif() diff --git a/lib/drivers/button/lws-button.c b/lib/drivers/button/lws-button.c index e937db6f61..43456fb541 100644 --- a/lib/drivers/button/lws-button.c +++ b/lib/drivers/button/lws-button.c @@ -471,8 +471,8 @@ lws_button_controller_destroy(struct lws_button_state *bcs) lws_button_enable(bcs, 0, 0); #if defined(LWS_PLAT_TIMER_DELETE) - LWS_PLAT_TIMER_DELETE(&bcs->timer); - LWS_PLAT_TIMER_DELETE(&bcs->timer_mon); + LWS_PLAT_TIMER_DELETE(bcs->timer); + LWS_PLAT_TIMER_DELETE(bcs->timer_mon); #endif lws_free(bcs); diff --git a/lib/drivers/led/led-gpio.c b/lib/drivers/led/led-gpio.c index 664a120c73..382c3e6305 100644 --- a/lib/drivers/led/led-gpio.c +++ b/lib/drivers/led/led-gpio.c @@ -81,7 +81,7 @@ void lws_led_gpio_destroy(struct lws_led_state *lcs) { #if defined(LWS_PLAT_TIMER_DELETE) - LWS_PLAT_TIMER_DELETE(&lcs->timer); + LWS_PLAT_TIMER_DELETE(lcs->timer); #endif lws_free(lcs); } From 0d9acf7a31c54e4995bb649417cdda30eb2d551c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 23 Dec 2021 06:13:27 +0000 Subject: [PATCH 082/275] http: redirect: keep ssl options at redirect --- lib/core-net/close.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index 5e4edafbd9..1d92b39058 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -956,7 +956,7 @@ __lws_close_free_wsi_final(struct lws *wsi) //_lws_header_table_reset(wsi->http.ah); #if defined(LWS_WITH_TLS) - wsi->tls.use_ssl = wsi->flags & LCCSCF_USE_SSL; + wsi->tls.use_ssl = (unsigned int)wsi->flags; #endif #if defined(LWS_WITH_TLS_JIT_TRUST) From d90361b771441b45f4ac0123a96c67babc8456b5 Mon Sep 17 00:00:00 2001 From: Ferenc Gerlits Date: Mon, 10 Jan 2022 16:46:10 +0100 Subject: [PATCH 083/275] cmake: fix compilation with OpenSSL subproject https://github.com/warmcat/libwebsockets/pull/2535 --- lib/tls/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index aaf4f4a260..fd3c27fab2 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -254,6 +254,10 @@ if (LWS_WITH_SSL) endif() if (NOT chose_ssl) + if (OPENSSL_FOUND AND "${OPENSSL_INCLUDE_DIRS}" STREQUAL "") + set(OPENSSL_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}") + endif() + if (NOT OPENSSL_FOUND AND NOT LWS_WITH_BORINGSSL) # TODO: Add support for STATIC also. if (NOT LWS_PLAT_FREERTOS) From 10a34fc43b5137d08df5de71e4461d302f317147 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 10 Jan 2022 15:33:14 +0000 Subject: [PATCH 084/275] coverity fixes --- lib/core-net/client/connect3.c | 6 +++++- lib/core-net/route.c | 2 ++ lib/tls/tls.c | 11 +++++------ minimal-examples/api-tests/api-test-dhcpc/main.c | 4 ++++ .../minimal-ws-client-spam-tx-rx/minimal-ws-client.c | 7 ++++++- plugins/ssh-base/sshd.c | 2 +- 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/lib/core-net/client/connect3.c b/lib/core-net/client/connect3.c index e4d4cd23db..a31021659d 100644 --- a/lib/core-net/client/connect3.c +++ b/lib/core-net/client/connect3.c @@ -183,6 +183,10 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, result = NULL; } +#if defined(LWS_WITH_UNIX_SOCK) + memset(&sau, 0, sizeof(sau)); +#endif + /* * async dns calls back here for everybody who cares when it gets a * result... but if we are piggybacking, we do not want to connect @@ -246,10 +250,10 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, } #if defined(LWS_WITH_UNIX_SOCK) + if (ads && *ads == '+') { ads++; memset(&wsi->sa46_peer, 0, sizeof(wsi->sa46_peer)); - memset(&sau, 0, sizeof(sau)); af = sau.sun_family = AF_UNIX; strncpy(sau.sun_path, ads, sizeof(sau.sun_path)); sau.sun_path[sizeof(sau.sun_path) - 1] = '\0'; diff --git a/lib/core-net/route.c b/lib/core-net/route.c index 9174437205..2a8515216b 100644 --- a/lib/core-net/route.c +++ b/lib/core-net/route.c @@ -39,6 +39,8 @@ _lws_routing_entry_dump(struct lws_context *cx, lws_route_t *rou) { char sa[48], fin[192], *end = &fin[sizeof(fin)]; + fin[0] = '\0'; + if (rou->dest.sa4.sin_family) { lws_sa46_write_numeric_address(&rou->dest, sa, sizeof(sa)); lws_snprintf(fin, lws_ptr_diff_size_t(end, fin), diff --git a/lib/tls/tls.c b/lib/tls/tls.c index b5b43859fb..29a7a5d5d6 100644 --- a/lib/tls/tls.c +++ b/lib/tls/tls.c @@ -377,7 +377,6 @@ lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename, p++; if (*p != '-') { - lwsl_err("b\n"); goto bail; } @@ -385,7 +384,6 @@ lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename, p++; if (p >= end) { - lwsl_err("c\n"); goto bail; } @@ -398,10 +396,8 @@ lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename, while (q > opem && *q != '\n') q--; - if (*q != '\n') { - lwsl_err("d\n"); + if (*q != '\n') goto bail; - } /* we can't write into the input buffer for mem, since it may be in RO * const segment @@ -409,7 +405,10 @@ lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename, if (filename) *q = '\0'; - *amount = (unsigned int)lws_b64_decode_string_len((char *)p, lws_ptr_diff(q, p), + n = lws_ptr_diff(q, p); + if (n == -1) /* coverity */ + goto bail; + *amount = (unsigned int)lws_b64_decode_string_len((char *)p, n, (char *)pem, (int)(long long)len); *buf = (uint8_t *)pem; diff --git a/minimal-examples/api-tests/api-test-dhcpc/main.c b/minimal-examples/api-tests/api-test-dhcpc/main.c index 3914f43974..b0dccbb331 100644 --- a/minimal-examples/api-tests/api-test-dhcpc/main.c +++ b/minimal-examples/api-tests/api-test-dhcpc/main.c @@ -52,7 +52,9 @@ int main(int argc, const char **argv) { struct lws_context_creation_info info; +#if !defined(__COVERITY__) const char *p; +#endif int n = 1; signal(SIGINT, sigint_handler); @@ -64,8 +66,10 @@ main(int argc, const char **argv) info.port = CONTEXT_PORT_NO_LISTEN; info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; +#if !defined(__COVERITY__) if ((p = lws_cmdline_option(argc, argv, "-i"))) nif = p; +#endif context = lws_create_context(&info); if (!context) { diff --git a/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c b/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c index 98b08cd06a..19a22cc250 100644 --- a/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c +++ b/minimal-examples/ws-client/minimal-ws-client-spam-tx-rx/minimal-ws-client.c @@ -179,13 +179,18 @@ int main(int argc, const char **argv) LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; } - if ((p = lws_cmdline_option(argc, argv, "-p"))) + if ((p = lws_cmdline_option(argc, argv, "-p"))) { port = atoi(p); + if (port > 65535 || port < 0) + return 1; + } if ((p = lws_cmdline_option(argc, argv, "-n"))) { n = atoi(p); if (n < 1) n = 1; + if (n > LWS_MAX_SMP) + n = LWS_MAX_SMP; if (n < nclients) nclients = n; lwsl_notice("Start test clients: %d\n", nclients); diff --git a/plugins/ssh-base/sshd.c b/plugins/ssh-base/sshd.c index fb5afffe86..90fa3d7271 100644 --- a/plugins/ssh-base/sshd.c +++ b/plugins/ssh-base/sshd.c @@ -2090,7 +2090,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_RAW_ADOPT: lwsl_info("LWS_CALLBACK_RAW_ADOPT\n"); - if (!vhd) + if (!vhd || !pss) return -1; pss->next = vhd->live_pss_list; vhd->live_pss_list = pss; From a352b9bf2021d168cf0d1e8d64f951fac668d776 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 15 Jan 2022 08:10:01 +0000 Subject: [PATCH 085/275] http: access_log: fix nwsi check h2 logging often lacked the IP as it checked the af on the sa46_peer of the child stream when it meant to check the nwsi one. --- lib/roles/http/server/access-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/http/server/access-log.c b/lib/roles/http/server/access-log.c index 98b13284c0..155201932e 100644 --- a/lib/roles/http/server/access-log.c +++ b/lib/roles/http/server/access-log.c @@ -96,7 +96,7 @@ lws_prepare_access_log_info(struct lws *wsi, char *uri_ptr, int uri_len, int met nwsi = lws_get_network_wsi(wsi); - if (wsi->sa46_peer.sa4.sin_family) + if (nwsi->sa46_peer.sa4.sin_family) lws_sa46_write_numeric_address(&nwsi->sa46_peer, ta, sizeof(ta)); else strncpy(ta, "unknown", sizeof(ta)); From 91f0b3bc0f6530f74e4961b9ae49fba6bee8f7b6 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 16 Jan 2022 06:49:38 +0000 Subject: [PATCH 086/275] sort-dns: fix scope comparison https://github.com/warmcat/libwebsockets/issues/2537 --- lib/core-net/client/sort-dns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core-net/client/sort-dns.c b/lib/core-net/client/sort-dns.c index c8d668685b..db105c5228 100644 --- a/lib/core-net/client/sort-dns.c +++ b/lib/core-net/client/sort-dns.c @@ -406,7 +406,7 @@ lws_sort_dns_dcomp(const lws_dns_sort_t *da, const lws_dns_sort_t *db) */ scopea = lws_ipv6_unicast_scope(to_v6_sa(&da->dest)); - scopeb = lws_ipv6_unicast_scope(to_v6_sa(&db)); + scopeb = lws_ipv6_unicast_scope(to_v6_sa(&db->dest)); scope_srca = lws_ipv6_unicast_scope(to_v6_sa(&da->source)); scope_srcb = lws_ipv6_unicast_scope(to_v6_sa(&db->source)); From 637ed905af71b91ea79c6b519abf4dc4f0c619df Mon Sep 17 00:00:00 2001 From: yogpstop Date: Thu, 27 Jan 2022 21:30:08 +0900 Subject: [PATCH 087/275] http: lws_add_http_header_by_name: add colon if needed --- lib/roles/http/header.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/roles/http/header.c b/lib/roles/http/header.c index b0d54776f2..032bf6bdf4 100644 --- a/lib/roles/http/header.c +++ b/lib/roles/http/header.c @@ -78,10 +78,15 @@ lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name, (void)wsi; #endif if (name) { - while (*p < end && *name) + char has_colon = 0; + while (*p < end && *name) { + has_colon = has_colon || *name == ':'; *((*p)++) = *name++; - if (*p == end) + } + if (*p + (has_colon ? 1 : 2) >= end) return 1; + if (!has_colon) + *((*p)++) = ':'; *((*p)++) = ' '; } if (*p + length + 3 >= end) From f99bf7748c78e6645e9d1b8ffb60c1ecab359ec3 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 21 Jan 2022 06:43:58 +0000 Subject: [PATCH 088/275] logs: openssl session: improve detection of INFO enabled https://github.com/warmcat/libwebsockets/issues/2540 --- lib/tls/openssl/openssl-session.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/tls/openssl/openssl-session.c b/lib/tls/openssl/openssl-session.c index d7dd04c65a..e27a8f38e4 100644 --- a/lib/tls/openssl/openssl-session.c +++ b/lib/tls/openssl/openssl-session.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2021 Andy Green + * Copyright (C) 2010 - 2022 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -33,7 +33,12 @@ typedef struct lws_tls_session_cache_openssl { /* name is overallocated here */ } lws_tls_sco_t; -#define lwsl_tlssess lwsl_info +#define tlssess_loglevel LLL_INFO +#if (_LWS_ENABLED_LOGS & tlssess_loglevel) +#define lwsl_tlssess(...) _lws_log(tlssess_loglevel, __VA_ARGS__) +#else +#define lwsl_tlssess(...) +#endif static void __lws_tls_session_destroy(lws_tls_sco_t *ts) @@ -211,7 +216,7 @@ lws_tls_session_new_cb(SSL *ssl, SSL_SESSION *sess) struct lws_vhost *vh; lws_tls_sco_t *ts; long ttl; -#if !defined(LWS_WITH_NO_LOGS) && defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & tlssess_loglevel) const char *disposition = "reuse"; #endif @@ -247,7 +252,7 @@ lws_tls_session_new_cb(SSL *ssl, SSL_SESSION *sess) lws_tls_session_expiry_cb, ttl * LWS_US_PER_SEC); -#if !defined(LWS_WITH_NO_LOGS) && defined(_DEBUG) +#if (_LWS_ENABLED_LOGS & tlssess_loglevel) disposition = "new"; #endif From 310c8baa81a2ac63c7db187b77f386c2434affbb Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 25 Jan 2022 08:49:00 +0000 Subject: [PATCH 089/275] logs: lock log context refcount changes Enabling the locking requires -DLWS_MAX_SMP=2 or more. --- include/libwebsockets/lws-logs.h | 8 ++++++++ lib/core/logs.c | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/libwebsockets/lws-logs.h b/include/libwebsockets/lws-logs.h index 3f21b81009..795ba55c10 100644 --- a/include/libwebsockets/lws-logs.h +++ b/include/libwebsockets/lws-logs.h @@ -82,6 +82,11 @@ typedef struct lws_log_cx { lws_log_emit_t emit; /* legacy emit function */ lws_log_emit_cx_t emit_cx; /* LLLF_LOG_CONTEXT_AWARE */ } u; + +#if LWS_MAX_SMP > 1 + pthread_mutex_t refcount_lock; +#endif + lws_log_use_cx_t refcount_cb; /**< NULL, or a function called after each change to .refcount below, * this enables implementing side-effects like opening and closing @@ -99,6 +104,9 @@ typedef struct lws_log_cx { /**< mask of log levels we want to emit in this context */ int32_t refcount; /**< refcount of objects bound to this log context */ +#if LWS_MAX_SMP > 1 + char inited; +#endif } lws_log_cx_t; /** diff --git a/lib/core/logs.c b/lib/core/logs.c index a13c84194b..d58de0df0e 100644 --- a/lib/core/logs.c +++ b/lib/core/logs.c @@ -506,9 +506,24 @@ int lwsl_visible_cx(lws_log_cx_t *cx, int level) void lwsl_refcount_cx(lws_log_cx_t *cx, int _new) { +#if LWS_MAX_SMP > 1 + volatile lws_log_cx_t *vcx = (volatile lws_log_cx_t *)cx; +#endif + if (!cx) return; +#if LWS_MAX_SMP > 1 + if (!vcx->inited) { + vcx->inited = 1; + lws_pthread_mutex_init(&cx->refcount_lock); + vcx->inited = 2; + } + while (vcx->inited != 2) + ; + lws_pthread_mutex_lock(&cx->refcount_lock); +#endif + if (_new > 0) cx->refcount++; else { @@ -518,6 +533,10 @@ lwsl_refcount_cx(lws_log_cx_t *cx, int _new) if (cx->refcount_cb) cx->refcount_cb(cx, _new); + +#if LWS_MAX_SMP > 1 + lws_pthread_mutex_unlock(&cx->refcount_lock); +#endif } void From 1b77c2ff4cfa9814cbeee67201a09e3fad10be4d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 28 Jan 2022 08:58:25 +0000 Subject: [PATCH 090/275] coverity: change ss handle priv style Coverity is able to misunderstand &h[1] to be a dereference of h, when it is just (h + 1). Adapt places where we use this style to get a pointer to the SS priv data to use (h + 1) so we don't have to see any more of coverity's confusion. --- lib/secure-streams/protocols/ss-h2.c | 4 ++-- lib/secure-streams/secure-streams-client.c | 8 ++++---- lib/secure-streams/secure-streams.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/secure-streams/protocols/ss-h2.c b/lib/secure-streams/protocols/ss-h2.c index 3d1aa9c233..910067ab7d 100644 --- a/lib/secure-streams/protocols/ss-h2.c +++ b/lib/secure-streams/protocols/ss-h2.c @@ -52,7 +52,7 @@ secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user, */ lwsl_info("%s: reporting initial tx cr from server %d\n", __func__, wsi->txc.tx_cr); - ss_proxy_onward_txcr((void *)&h[1], wsi->txc.tx_cr); + ss_proxy_onward_txcr((void *)(h + 1), wsi->txc.tx_cr); } #endif @@ -106,7 +106,7 @@ secstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user, #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) if (h->being_serialized) /* we are the proxy-side SS for a remote client */ - ss_proxy_onward_txcr((void *)&h[1], (int)len); + ss_proxy_onward_txcr((void *)(h + 1), (int)len); #endif break; diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index 76ea9522eb..075cf9657e 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -84,7 +84,7 @@ lws_sspc_event_helper(lws_sspc_handle_t *h, lws_ss_constate_t cs, return LWSSSSRET_OK; h->h_in_svc = h; - ret = h->ssi.state((void *)((uint8_t *)&h[1]), NULL, cs, flags); + ret = h->ssi.state((void *)((uint8_t *)(h + 1)), NULL, cs, flags); h->h_in_svc = NULL; return ret; @@ -201,7 +201,7 @@ callback_sspc_client(struct lws *wsi, enum lws_callback_reasons reason, { lws_sspc_handle_t *h = (lws_sspc_handle_t *)lws_get_opaque_user_data(wsi); size_t pktsize = wsi->a.context->max_http_header_data; - void *m = (void *)((uint8_t *)&h[1]); + void *m = (void *)((uint8_t *)(h + 1)); uint8_t *pkt = NULL, *p = NULL, *end = NULL; lws_ss_state_return_t r; uint64_t interval; @@ -661,7 +661,7 @@ lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, ssi->streamtype); memcpy(&h->ssi, ssi, sizeof(*ssi)); - ua = (uint8_t *)&h[1]; + ua = (uint8_t *)(h + 1); memset(ua, 0, ssi->user_alloc); p = (char *)ua + ssi->user_alloc; memcpy(p, ssi->streamtype, strlen(ssi->streamtype) + 1); @@ -1070,7 +1070,7 @@ lws_sspc_cancel_timeout(struct lws_sspc_handle *h) void * lws_sspc_to_user_object(struct lws_sspc_handle *h) { - return (void *)&h[1]; + return (void *)(h + 1); } void diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 489543dba7..510b016457 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -614,7 +614,7 @@ lws_smd_ss_cb(void *opaque, lws_smd_class_t _class, lws_ser_wu64be(p + 8, (uint64_t)timestamp); if (h->info.rx) - h->info.rx((void *)&h[1], p, len + LWS_SMD_SS_RX_HEADER_LEN, + h->info.rx((void *)(h + 1), p, len + LWS_SMD_SS_RX_HEADER_LEN, LWSSS_FLAG_SOM | LWSSS_FLAG_EOM); return 0; @@ -634,7 +634,7 @@ lws_ss_smd_tx_cb(lws_sorted_usec_list_t *sul) if (!h->info.tx) return; - n = h->info.tx(&h[1], h->txord++, buf, &len, &flags); + n = h->info.tx((h + 1), h->txord++, buf, &len, &flags); if (n) /* nonzero return means don't want to send anything */ return; @@ -1072,7 +1072,7 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, h->proxy_onward = 1; /* start of overallocated area */ - p = (char *)&h[1]; + p = (char *)(h + 1); /* set the handle pointer in the user data struct */ v = (void **)(p + ssi->handle_offset); @@ -1350,7 +1350,7 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, void * lws_ss_to_user_object(struct lws_ss_handle *h) { - return (void *)&h[1]; + return (void *)(h + 1); } void From b709d50f8f70b8768fe6d73c91abc59a436b4d6b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 28 Jan 2022 10:19:10 +0000 Subject: [PATCH 091/275] coverity: mark false positive Coverity doesn't understand the state relationship means that ssi will only be used to create the proxy-side SS representing the remote client SS, which happens as the first command in the state flow. Mark the call up to disable the false error report. --- lib/secure-streams/secure-streams-process.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/secure-streams/secure-streams-process.c b/lib/secure-streams/secure-streams-process.c index d5822b69be..552e1d12ca 100644 --- a/lib/secure-streams/secure-streams-process.c +++ b/lib/secure-streams/secure-streams-process.c @@ -487,6 +487,7 @@ callback_ss_proxy(struct lws *wsi, enum lws_callback_reasons reason, ssi.state = ss_proxy_onward_state; ssi.flags = 0; + // coverity[uninit_use_in_call] n = lws_ss_deserialize_parse(&conn->parser, lws_get_context(wsi), conn->dsh, in, len, &conn->state, conn, &conn->ss, &ssi, 0); From 1f9925b44379941065690f0dce8ca0c79414b9f1 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 1 Feb 2022 09:13:11 +0000 Subject: [PATCH 092/275] genec: show correct nid when not allowed As noticed by gcc11 warning https://github.com/warmcat/libwebsockets/pull/2551 --- lib/tls/lws-genec-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tls/lws-genec-common.c b/lib/tls/lws-genec-common.c index 0ea3fb0243..8b5d30b765 100644 --- a/lib/tls/lws-genec-common.c +++ b/lib/tls/lws-genec-common.c @@ -94,7 +94,7 @@ lws_genec_confirm_curve_allowed_by_tls_id(const char *allowed, int id, } } while (e > 0); - lwsl_err("%s: unsupported curve group nid %d\n", __func__, n); + lwsl_err("%s: unsupported curve group nid %d\n", __func__, id); return -1; } From 939a51241330f73e3cac1f769c0b3ace3b3fc01f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 1 Feb 2022 07:59:41 +0000 Subject: [PATCH 093/275] mbedtls: improve api detection mbedtls cmake api detection was not able to work on esp-idf well. Improve diagnostics and reaction if we ever see that again. --- lib/CMakeLists.txt | 8 +++- lib/core-net/adopt.c | 4 ++ lib/roles/h2/http2.c | 6 +++ lib/tls/CMakeLists.txt | 45 ++++++++++++++++------- lib/tls/mbedtls/mbedtls-client.c | 6 +-- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 3 ++ 6 files changed, 54 insertions(+), 18 deletions(-) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index c55c619851..f9553fd8c9 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -38,7 +38,8 @@ set(LWS_LIB_INCLUDES "") if (LWS_PLAT_FREERTOS) add_subdir_include_dirs(plat/freertos) if (ESP_PLATFORM) - include_directories($ENV{IDF_PATH}/components/freertos/include + list(APPEND LWS_ESP_IDF_DIRS + $ENV{IDF_PATH}/components/freertos/include $ENV{IDF_PATH}/components/esp_hw_support/include/soc/ $ENV{IDF_PATH}/components/esp_common/include $ENV{IDF_PATH}/components/esp_timer/include @@ -71,7 +72,12 @@ if (LWS_PLAT_FREERTOS) $ENV{IDF_PATH}/components/lwip/lwip/src/include $ENV{IDF_PATH}/components/lwip/lwip/src/include/lwip $ENV{IDF_PATH}/components/newlib/platform_include ) + + include_directories(${LWS_ESP_IDF_DIRS}) + + list(APPEND CMAKE_REQUIRED_INCLUDES ${LWS_ESP_IDF_DIRS}) endif() + else() if (LWS_PLAT_OPTEE) diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index e411945104..579f4bfe16 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -847,12 +847,16 @@ lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port, lws_snprintf(buf, sizeof(buf), "%u", port); n = getaddrinfo(ads, buf, &h, &r); if (n) { + +#if (_LWS_ENABLED_LOGS & LLL_INFO) #if !defined(LWS_PLAT_FREERTOS) lwsl_info("%s: getaddrinfo error: %s\n", __func__, gai_strerror(n)); #else + lwsl_info("%s: getaddrinfo error: %s\n", __func__, strerror(n)); +#endif #endif //freeaddrinfo(r); goto bail1; diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index a09b97fc0f..58e7c107dd 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -431,6 +431,12 @@ lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pps) struct lws *nwsi = lws_get_network_wsi(wsi); struct lws_h2_netconn *h2n = nwsi->h2.h2n; + if (!h2n) { + lwsl_warn("%s: null h2n\n", __func__); + lws_free(pps); + return; + } + pps->next = h2n->pps; h2n->pps = pps; lws_rx_flow_control(wsi, LWS_RXFLOW_REASON_APPLIES_DISABLE | diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index fd3c27fab2..a161879f1e 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -375,22 +375,39 @@ if (LWS_WITH_MBEDTLS) # not supported in esp-idf openssl wrapper yet, but is in our version set(LWS_HAVE_X509_VERIFY_PARAM_set1_host 1 PARENT_SCOPE) endif() - set(CMAKE_REQUIRED_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${MBEDTLS_INCLUDE_DIRS}) - CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct mbedtls_x509_crt c; c.authority_key_id.keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; return c.authority_key_id.keyIdentifier.tag; }\n" LWS_HAVE_MBEDTLS_AUTH_KEY_ID) - CHECK_C_SOURCE_COMPILES("#include \nint main(void) { void *v = (void *)mbedtls_ssl_set_verify; return !!v; }\n" LWS_HAVE_mbedtls_ssl_set_verify) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_alpn_protocols LWS_HAVE_mbedtls_ssl_conf_alpn_protocols PARENT_SCOPE) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_get_alpn_protocol LWS_HAVE_mbedtls_ssl_get_alpn_protocol PARENT_SCOPE) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_sni LWS_HAVE_mbedtls_ssl_conf_sni PARENT_SCOPE) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_ca_chain LWS_HAVE_mbedtls_ssl_set_hs_ca_chain PARENT_SCOPE) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_own_cert LWS_HAVE_mbedtls_ssl_set_hs_own_cert PARENT_SCOPE) - CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_authmode LWS_HAVE_mbedtls_ssl_set_hs_authmode PARENT_SCOPE) - CHECK_FUNCTION_EXISTS(mbedtls_net_init LWS_HAVE_mbedtls_net_init PARENT_SCOPE) - CHECK_FUNCTION_EXISTS(mbedtls_x509_crt_parse_file LWS_HAVE_mbedtls_x509_crt_parse_file PARENT_SCOPE) # some embedded may lack filesystem - CHECK_FUNCTION_EXISTS(mbedtls_md_setup LWS_HAVE_mbedtls_md_setup PARENT_SCOPE) # not on xenial 2.2 - CHECK_FUNCTION_EXISTS(mbedtls_rsa_complete LWS_HAVE_mbedtls_rsa_complete PARENT_SCOPE) # not on xenial 2.2 - CHECK_FUNCTION_EXISTS(mbedtls_internal_aes_encrypt LWS_HAVE_mbedtls_internal_aes_encrypt PARENT_SCOPE) # not on xenial 2.2 + + if (ESP_PLATFORM) + # we know we should have things + set(LWS_HAVE_MBEDTLS_AUTH_KEY_ID 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_get_alpn_protocol 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_conf_sni 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_set_hs_ca_chain 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_set_hs_own_cert 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_ssl_set_hs_authmode 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_net_init 1 CACHE BOOL x) + set(LWS_HAVE_mbedtls_x509_crt_parse_file 1 CACHE BOOL x) # some embedded may lack filesystem + set(LWS_HAVE_mbedtls_md_setup 1 CACHE BOOL x) # not on xenial 2.2 + set(LWS_HAVE_mbedtls_rsa_complete 1 CACHE BOOL x) # not on xenial 2.2 + set(LWS_HAVE_mbedtls_internal_aes_encrypt 1 CACHE BOOL x) # not on xenial 2.2 + else() + CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct mbedtls_x509_crt c; c.authority_key_id.keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; return c.authority_key_id.keyIdentifier.tag; }\n" LWS_HAVE_MBEDTLS_AUTH_KEY_ID) + CHECK_C_SOURCE_COMPILES("#include \nint main(void) { void *v = (void *)mbedtls_ssl_set_verify; return !!v; }\n" LWS_HAVE_mbedtls_ssl_set_verify) + CHECK_SYMBOL_EXISTS(mbedtls_ssl_conf_alpn_protocols LWS_HAVE_mbedtls_ssl_conf_alpn_protocols PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_get_alpn_protocol LWS_HAVE_mbedtls_ssl_get_alpn_protocol PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_sni LWS_HAVE_mbedtls_ssl_conf_sni PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_ca_chain LWS_HAVE_mbedtls_ssl_set_hs_ca_chain PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_own_cert LWS_HAVE_mbedtls_ssl_set_hs_own_cert PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_authmode LWS_HAVE_mbedtls_ssl_set_hs_authmode PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_net_init LWS_HAVE_mbedtls_net_init PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_x509_crt_parse_file LWS_HAVE_mbedtls_x509_crt_parse_file PARENT_SCOPE) # some embedded may lack filesystem + CHECK_FUNCTION_EXISTS(mbedtls_md_setup LWS_HAVE_mbedtls_md_setup PARENT_SCOPE) # not on xenial 2.2 + CHECK_FUNCTION_EXISTS(mbedtls_rsa_complete LWS_HAVE_mbedtls_rsa_complete PARENT_SCOPE) # not on xenial 2.2 + CHECK_FUNCTION_EXISTS(mbedtls_internal_aes_encrypt LWS_HAVE_mbedtls_internal_aes_encrypt PARENT_SCOPE) # not on xenial 2.2 + endif() else() CHECK_FUNCTION_EXISTS(${VARIA}TLS_client_method LWS_HAVE_TLS_CLIENT_METHOD PARENT_SCOPE) CHECK_FUNCTION_EXISTS(${VARIA}TLSv1_2_client_method LWS_HAVE_TLSV1_2_CLIENT_METHOD PARENT_SCOPE) diff --git a/lib/tls/mbedtls/mbedtls-client.c b/lib/tls/mbedtls/mbedtls-client.c index c12bbd5069..bc7644ae83 100644 --- a/lib/tls/mbedtls/mbedtls-client.c +++ b/lib/tls/mbedtls/mbedtls-client.c @@ -137,12 +137,12 @@ lws_ssl_client_bio_create(struct lws *wsi) alpn_comma = hostname; } - lwsl_info("%s: %s: client conn sending ALPN list '%s'\n", - __func__, lws_wsi_tag(wsi), alpn_comma); - protos.len = (uint8_t)lws_alpn_comma_to_openssl(alpn_comma, protos.data, sizeof(protos.data) - 1); + lwsl_info("%s: %s: client conn sending ALPN list '%s' (protos.len %d)\n", + __func__, lws_wsi_tag(wsi), alpn_comma, protos.len); + /* with mbedtls, protos is not pointed to after exit from this call */ SSL_set_alpn_select_cb(wsi->tls.ssl, &protos); diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index 04354f6b47..df38334faa 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -874,6 +874,8 @@ void _ssl_set_alpn_list(const SSL *ssl) return; if (mbedtls_ssl_conf_alpn_protocols(&((struct ssl_pm *)(ssl->ssl_pm))->conf, ssl->ctx->alpn_protos)) fprintf(stderr, "mbedtls_ssl_conf_alpn_protocols failed\n"); +#else + fprintf(stderr, "mbedtls_ssl_conf_alpn_protocols absent\n"); #endif } @@ -889,6 +891,7 @@ void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, else *len = 0; #else + fprintf(stderr, "mbedtls_ssl_conf_alpn_protocols absent\n"); *len = 0; #endif } From bb759fd983c3aa278fbe51a82d9bd4b59818ff88 Mon Sep 17 00:00:00 2001 From: Sylvain Saunier Date: Wed, 2 Feb 2022 14:28:24 +0000 Subject: [PATCH 094/275] route: fix nl groups and local ipv6 ads --- lib/core-net/route.c | 11 ++++++++--- lib/roles/netlink/ops-netlink.c | 16 +++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/core-net/route.c b/lib/core-net/route.c index 2a8515216b..270ed863d6 100644 --- a/lib/core-net/route.c +++ b/lib/core-net/route.c @@ -38,25 +38,30 @@ void _lws_routing_entry_dump(struct lws_context *cx, lws_route_t *rou) { char sa[48], fin[192], *end = &fin[sizeof(fin)]; + char *it = fin; + int n; fin[0] = '\0'; if (rou->dest.sa4.sin_family) { lws_sa46_write_numeric_address(&rou->dest, sa, sizeof(sa)); - lws_snprintf(fin, lws_ptr_diff_size_t(end, fin), + n = lws_snprintf(it, lws_ptr_diff_size_t(end, it), "dst: %s/%d, ", sa, rou->dest_len); + it = it + n; } if (rou->src.sa4.sin_family) { lws_sa46_write_numeric_address(&rou->src, sa, sizeof(sa)); - lws_snprintf(fin, lws_ptr_diff_size_t(end, fin), + n = lws_snprintf(it, lws_ptr_diff_size_t(end, it), "src: %s/%d, ", sa, rou->src_len); + it = it + n; } if (rou->gateway.sa4.sin_family) { lws_sa46_write_numeric_address(&rou->gateway, sa, sizeof(sa)); - lws_snprintf(fin, lws_ptr_diff_size_t(end, fin), + n = lws_snprintf(it, lws_ptr_diff_size_t(end, it), "gw: %s, ", sa); + it = it + n; } lwsl_cx_info(cx, " %s ifidx: %d, pri: %d, proto: %d\n", fin, diff --git a/lib/roles/netlink/ops-netlink.c b/lib/roles/netlink/ops-netlink.c index bb32048394..31fb0133b7 100644 --- a/lib/roles/netlink/ops-netlink.c +++ b/lib/roles/netlink/ops-netlink.c @@ -259,6 +259,15 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, lwsl_cx_netlink(cx, "RTA_SRC: %s", buf); break; case RTA_DST: + /* check if is local addr -> considering it as src addr too */ + if (rm->rtm_type == RTN_LOCAL && + ((rm->rtm_family == AF_INET && rm->rtm_dst_len == 32) || + (rm->rtm_family == AF_INET6 && rm->rtm_dst_len == 128))) { + lws_sa46_copy_address(&robj.src, RTA_DATA(ra), + rm->rtm_family); + lwsl_cx_netlink(cx, "Local addr: RTA_DST -> added to RTA_SRC"); + } + lws_sa46_copy_address(&robj.dest, RTA_DATA(ra), rm->rtm_family); robj.dest_len = rm->rtm_dst_len; @@ -519,12 +528,9 @@ rops_pt_init_destroy_netlink(struct lws_context *context, memset(&sanl, 0, sizeof(sanl)); sanl.nl_family = AF_NETLINK; sanl.nl_pid = (uint32_t)getpid(); - sanl.nl_groups = (1 << (RTNLGRP_LINK - 1)) | - (1 << (RTNLGRP_IPV4_ROUTE - 1)) | - (1 << (RTNLGRP_IPV4_IFADDR - 1)) + sanl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR #if defined(LWS_WITH_IPV6) - | (1 << (RTNLGRP_IPV6_ROUTE - 1)) | - (1 << (RTNLGRP_IPV6_IFADDR - 1)) + | RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR #endif ; From eda299bd71a140c3ed4cadc6d28942ffb1abe058 Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Wed, 2 Feb 2022 16:46:20 -0800 Subject: [PATCH 095/275] ss: mqtt: fix wrong QoS value on Birth message --- lib/secure-streams/protocols/ss-mqtt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index f13eea4a57..9d58cf887f 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2019 - 2021 Andy Green + * Copyright (C) 2019 - 2022 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -187,6 +187,7 @@ secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buflen, mqpp.topic_len = (uint16_t)strlen(mqpp.topic); mqpp.packet_id = (uint16_t)(h->txord - 1); + mqpp.qos = qos; mqpp.payload = buf; if (h->writeable_len) mqpp.payload_len = (uint32_t)h->writeable_len; @@ -196,8 +197,6 @@ secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buflen, lwsl_notice("%s: payload len %d\n", __func__, (int)mqpp.payload_len); - mqpp.qos = h->policy->u.mqtt.qos; - if (lws_mqtt_client_send_publish(wsi, &mqpp, (const char *)buf, (uint32_t)buflen, From 7e3125b818a40ebef7dc3fd6c20bd44691adf1ca Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Wed, 2 Feb 2022 16:48:11 -0800 Subject: [PATCH 096/275] minimal: ss: policy2c: add more MQTT related fields This adds 'aws_iot', 'birth_topic', and 'birth_message' on policy2c. --- .../minimal-secure-streams.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c index f3a0b699b1..6f777656dc 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c @@ -574,6 +574,12 @@ int main(int argc, const char **argv) printf("\t\t\t.will_message = \"%s\",\n", pol->u.mqtt.will_message); + if (pol->u.mqtt.birth_topic) + printf("\t\t\t.birth_topic = \"%s\",\n", + pol->u.mqtt.birth_topic); + if (pol->u.mqtt.birth_message) + printf("\t\t\t.birth_message = \"%s\",\n", + pol->u.mqtt.birth_message); if (pol->u.mqtt.keep_alive) printf("\t\t\t.keep_alive = %u,\n", pol->u.mqtt.keep_alive); @@ -589,6 +595,9 @@ int main(int argc, const char **argv) if (pol->u.mqtt.will_retain) printf("\t\t\t.will_retain = %u,\n", pol->u.mqtt.will_retain); + if (pol->u.mqtt.aws_iot) + printf("\t\t\t.aws_iot = %u,\n", + pol->u.mqtt.aws_iot); printf("\t\t}\n\t},\n"); From a80fbeb820b90f783a032824f64beee6666569e4 Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Sat, 5 Feb 2022 15:10:44 -0800 Subject: [PATCH 097/275] ss: mqtt: add support for retained message --- include/libwebsockets/lws-mqtt.h | 1 + include/libwebsockets/lws-secure-streams-policy.h | 1 + lib/roles/mqtt/mqtt.c | 2 +- lib/secure-streams/README.md | 4 ++++ lib/secure-streams/policy-json.c | 7 +++++++ lib/secure-streams/protocols/ss-mqtt.c | 10 +++++++--- .../minimal-secure-streams.c | 3 +++ 7 files changed, 24 insertions(+), 4 deletions(-) diff --git a/include/libwebsockets/lws-mqtt.h b/include/libwebsockets/lws-mqtt.h index 22865801ed..b228315a1a 100644 --- a/include/libwebsockets/lws-mqtt.h +++ b/include/libwebsockets/lws-mqtt.h @@ -114,6 +114,7 @@ typedef struct lws_mqtt_publish_param_s { 0 */ uint8_t dup:1; /* Retried PUBLISH, for QoS > 0 */ + uint8_t retain:1; /* Retained message */ } lws_mqtt_publish_param_t; typedef struct topic_elem { diff --git a/include/libwebsockets/lws-secure-streams-policy.h b/include/libwebsockets/lws-secure-streams-policy.h index 863140d74b..2c81f9fd8d 100644 --- a/include/libwebsockets/lws-secure-streams-policy.h +++ b/include/libwebsockets/lws-secure-streams-policy.h @@ -323,6 +323,7 @@ typedef struct lws_ss_policy { uint8_t birth_qos; uint8_t birth_retain; uint8_t aws_iot; + uint8_t retain; } mqtt; diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index 67d64dbc0d..4ba49c74f4 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -1982,7 +1982,7 @@ lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, * payload (if any) */ if (lws_mqtt_fill_fixed_header(p++, LMQCP_PUBLISH, - 0, pub->qos, 0)) { + pub->dup, pub->qos, pub->retain)) { lwsl_err("%s: Failed to fill fixed header\n", __func__); return 1; } diff --git a/lib/secure-streams/README.md b/lib/secure-streams/README.md index b7a9c3d505..5d707aed61 100644 --- a/lib/secure-streams/README.md +++ b/lib/secure-streams/README.md @@ -661,6 +661,10 @@ Set the topic this streamtype subscribes to Set the QOS level for this streamtype +### `mqtt_retain` + +Set to true if this streamtype should use MQTT's "retain" feature. + ### `mqtt_keep_alive` 16-bit number representing MQTT keep alive for the stream. diff --git a/lib/secure-streams/policy-json.c b/lib/secure-streams/policy-json.c index 7e5656f675..e230ce5eb0 100644 --- a/lib/secure-streams/policy-json.c +++ b/lib/secure-streams/policy-json.c @@ -111,6 +111,7 @@ static const char * const lejp_tokens_policy[] = { "s[].*.mqtt_topic", "s[].*.mqtt_subscribe", "s[].*.mqtt_qos", + "s[].*.mqtt_retain", "s[].*.mqtt_keep_alive", "s[].*.mqtt_clean_start", "s[].*.mqtt_will_topic", @@ -218,6 +219,7 @@ typedef enum { LSSPPT_MQTT_TOPIC, LSSPPT_MQTT_SUBSCRIBE, LSSPPT_MQTT_QOS, + LSSPPT_MQTT_RETAIN, LSSPPT_MQTT_KEEPALIVE, LSSPPT_MQTT_CLEAN_START, LSSPPT_MQTT_WILL_TOPIC, @@ -1020,6 +1022,11 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason) a->curr[LTY_POLICY].p->u.mqtt.qos = (uint8_t)atoi(ctx->buf); break; + case LSSPPT_MQTT_RETAIN: + a->curr[LTY_POLICY].p->u.mqtt.retain = + reason == LEJPCB_VAL_TRUE; + break; + case LSSPPT_MQTT_KEEPALIVE: a->curr[LTY_POLICY].p->u.mqtt.keep_alive = (uint16_t)atoi(ctx->buf); break; diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 9d58cf887f..11489d2503 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -143,7 +143,7 @@ secstream_mqtt_subscribe(struct lws *wsi) static int secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buflen, const char* topic, - lws_mqtt_qos_levels_t qos, int f) + lws_mqtt_qos_levels_t qos, uint8_t retain, int f) { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); size_t used_in, used_out, topic_limit; @@ -188,6 +188,7 @@ secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buflen, mqpp.topic_len = (uint16_t)strlen(mqpp.topic); mqpp.packet_id = (uint16_t)(h->txord - 1); mqpp.qos = qos; + mqpp.retain = !!retain; mqpp.payload = buf; if (h->writeable_len) mqpp.payload_len = (uint32_t)h->writeable_len; @@ -407,7 +408,9 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, wsi->mqtt->inside_birth = 1; return secstream_mqtt_publish(wsi, buf + LWS_PRE, used_out, h->policy->u.mqtt.birth_topic, - h->policy->u.mqtt.birth_qos, LWSSS_FLAG_EOM); + h->policy->u.mqtt.birth_qos, + h->policy->u.mqtt.birth_retain, + LWSSS_FLAG_EOM); } r = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, &buflen, &f); @@ -435,7 +438,8 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, return secstream_mqtt_publish(wsi, buf + LWS_PRE, buflen, h->policy->u.mqtt.topic, - h->policy->u.mqtt.qos, f); + h->policy->u.mqtt.qos, + h->policy->u.mqtt.retain, f); } case LWS_CALLBACK_MQTT_UNSUBSCRIBED: diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c index 6f777656dc..a89d0c8d6b 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c @@ -598,6 +598,9 @@ int main(int argc, const char **argv) if (pol->u.mqtt.aws_iot) printf("\t\t\t.aws_iot = %u,\n", pol->u.mqtt.aws_iot); + if (pol->u.mqtt.retain) + printf("\t\t\t.retain = %u,\n", + pol->u.mqtt.retain); printf("\t\t}\n\t},\n"); From 1027d3a740a835e9031cc9ba2a48c26c8ba16044 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 9 Feb 2022 12:38:19 +0000 Subject: [PATCH 098/275] ss: http: ensure SS points to wsi when using wsi pointing to SS If we're going to take a wsi's word for it that it is bound to a particular SS, make sure the SS is also bound to the same wsi. --- lib/secure-streams/protocols/ss-h1.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index 9bfed470e8..d2ee2171af 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -283,7 +283,7 @@ lws_apply_instant_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, lwsl_debug("%s add header %s %s %d\n", __func__, imd->name, (char *)imd->value__may_own_heap, - imd->length); + (int)imd->length); if (lws_add_http_header_by_name(wsi, (const unsigned char *)imd->name, (const unsigned char *)imd->value__may_own_heap, @@ -560,6 +560,8 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, return -1; lws_ss_assert_extant(wsi->a.context, wsi->tsi, h); + h->wsi = wsi; /* since we accept the wsi is bound to the SS, + * ensure the SS feels the same way about the wsi */ #if defined(LWS_WITH_CONMON) if (wsi->conmon.pcol == LWSCONMON_PCOL_NONE) { @@ -863,6 +865,8 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, // lwsl_notice("%s: HTTP_READ: client side sent len %d fl 0x%x\n", // __func__, (int)len, (int)f); + h->wsi = wsi; /* since we accept the wsi is bound to the SS, + * ensure the SS feels the same way about the wsi */ r = h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f); if (r != LWSSSSRET_OK) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); From 3eae5f8bcad9f865353330eaf9a21614e696a678 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 9 Feb 2022 11:59:06 +0000 Subject: [PATCH 099/275] ss: reject direct protocol metadata if NULL ss wsi The ss wsi may be NULL after any time around the event loop. Make sure we check that before we start trying to use it. --- lib/secure-streams/policy-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/secure-streams/policy-common.c b/lib/secure-streams/policy-common.c index b782c1e5bb..a98abaeaf8 100644 --- a/lib/secure-streams/policy-common.c +++ b/lib/secure-streams/policy-common.c @@ -177,7 +177,7 @@ lws_ss_get_metadata(struct lws_ss_handle *h, const char *name, return 0; } #if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) - if (!(h->policy->flags & LWSSSPOLF_DIRECT_PROTO_STR)) + if (!(h->policy->flags & LWSSSPOLF_DIRECT_PROTO_STR) || !h->wsi) goto bail; n = lws_http_string_to_known_header(name, strlen(name)); From 3f19d94040fd23614db21594be2dec3638b995ec Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 4 Feb 2022 07:34:54 +0000 Subject: [PATCH 100/275] jit-trust: adapt for esp-idf pre v3 mbedtls Ensure we still work with mbedtls_ssl_conf_verify() as well as mbedtls_ssl_set_verify() if that's what we have got. Make sure mbedtls tls validation is noisy and fast. Disable Xenial + mbedtls in sai, it fails but not when the same tests are run from the commandline. Very few people will be using Xenial (2016 Ubuntu release) with mbedtls. --- .sai.json | 4 ++-- lib/tls/mbedtls/mbedtls-client.c | 3 ++- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 4 ++-- lib/tls/tls-client.c | 6 ++++++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.sai.json b/.sai.json index 7ac992e1e6..3d349e9411 100644 --- a/.sai.json +++ b/.sai.json @@ -243,11 +243,11 @@ "mbedtls": { "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG", # no distro -devel package for mbedtls - "platforms": "not linux-centos-7/x86_64-amd/gcc, not linux-centos-8/x86_64-amd/gcc" + "platforms": "not linux-centos-7/x86_64-amd/gcc, not linux-centos-8/x86_64-amd/gcc, not linux-ubuntu-xenial/x86_64-amd/gcc" }, "mbedtls-metrics": { "cmake": "-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_JOSE=1 -DCMAKE_BUILD_TYPE=DEBUG -DLWS_WITH_SYS_METRICS=1", - "platforms": "not linux-centos-7/x86_64-amd/gcc, not linux-centos-8/x86_64-amd/gcc" + "platforms": "not linux-centos-7/x86_64-amd/gcc, not linux-centos-8/x86_64-amd/gcc, not linux-ubuntu-xenial/x86_64-amd/gcc" }, "noserver": { "cmake": "-DLWS_WITHOUT_SERVER=ON -DLWS_WITH_MINIMAL_EXAMPLES=1 -DLWS_WITH_SECURE_STREAMS=1", diff --git a/lib/tls/mbedtls/mbedtls-client.c b/lib/tls/mbedtls/mbedtls-client.c index bc7644ae83..187e860537 100644 --- a/lib/tls/mbedtls/mbedtls-client.c +++ b/lib/tls/mbedtls/mbedtls-client.c @@ -272,7 +272,8 @@ lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) if (!n) /* we don't know what he wants, but he says to retry */ return LWS_SSL_CAPABLE_MORE_SERVICE; - if (m == SSL_ERROR_SYSCALL && !en) + if (m == SSL_ERROR_SYSCALL && !en && n >= 0) /* otherwise we miss explicit failures and spin + * in hs state 17 until timeout... */ return LWS_SSL_CAPABLE_MORE_SERVICE; lws_snprintf(errbuf, elen, "mbedtls connect %d %d %d", n, m, en); diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index df38334faa..0faf0d713e 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -98,7 +98,6 @@ static void ssl_platform_debug(void *ctx, int level, } //#endif -#if defined(LWS_HAVE_mbedtls_ssl_set_verify) static int lws_mbedtls_f_vrfy(void *opaque, mbedtls_x509_crt *x509, int state, uint32_t *pflags) { @@ -109,7 +108,6 @@ lws_mbedtls_f_vrfy(void *opaque, mbedtls_x509_crt *x509, int state, uint32_t *pf return 0; } -#endif /** * @brief create SSL low-level object @@ -151,6 +149,8 @@ int ssl_pm_new(SSL *ssl) #if defined(LWS_HAVE_mbedtls_ssl_set_verify) mbedtls_ssl_set_verify(&ssl_pm->ssl, lws_mbedtls_f_vrfy, ssl_pm); +#else + mbedtls_ssl_conf_verify(&ssl_pm->conf, lws_mbedtls_f_vrfy, ssl_pm); #endif ret = mbedtls_ctr_drbg_seed(&ssl_pm->ctr_drbg, mbedtls_entropy_func, &ssl_pm->entropy, pers, pers_len); diff --git a/lib/tls/tls-client.c b/lib/tls/tls-client.c index 9d93a3daea..5b29923f53 100644 --- a/lib/tls/tls-client.c +++ b/lib/tls/tls-client.c @@ -66,6 +66,12 @@ lws_ssl_client_connect2(struct lws *wsi, char *errbuf, size_t len) switch (n) { case LWS_SSL_CAPABLE_ERROR: lws_tls_restrict_return_handshake(wsi); + + if (lws_tls_client_confirm_peer_cert(wsi, errbuf, len)) { + lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); + return -1; + } + // lws_snprintf(errbuf, len, "client connect failed"); return -1; case LWS_SSL_CAPABLE_DONE: From c7e82fb29cadaa9d437d2e7c1e65043b9566c03b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 4 Feb 2022 16:55:55 +0000 Subject: [PATCH 101/275] ss: http: unreachable superfluous if we did DISCONNECTED --- lib/secure-streams/protocols/ss-h1.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index d2ee2171af..d9ffe85296 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -467,16 +467,17 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); if (r != LWSSSSRET_OK) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); - } - /* already disconnected, no action for DISCONNECT_ME */ - r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); - if (r) { - if (h->inside_connect) { - h->pending_ret = r; - break; - } + } else { + /* already disconnected, no action for DISCONNECT_ME */ + r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); + if (r) { + if (h->inside_connect) { + h->pending_ret = r; + break; + } - return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + } } h->wsi = NULL; From 8111d47f4050e524124a240a0e59ee6c739b4533 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 7 Feb 2022 14:48:55 +0000 Subject: [PATCH 102/275] cmake: remove duplicate LwsCheckRequirements --- cmake/libwebsockets-config.cmake.in | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/libwebsockets-config.cmake.in b/cmake/libwebsockets-config.cmake.in index 6247b2cbe0..8ba97e6f56 100644 --- a/cmake/libwebsockets-config.cmake.in +++ b/cmake/libwebsockets-config.cmake.in @@ -32,6 +32,5 @@ endforeach() include(CheckIncludeFile) include(CheckCSourceCompiles) -include(LwsCheckRequirements) set(requirements 1) From ab7ce5017455dea9f9d55790e901012d2f5474e8 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 7 Feb 2022 13:35:23 +0000 Subject: [PATCH 103/275] http: proxy server: move C99 VLA to heap --- lib/roles/http/server/server.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index c7eb94c3b7..c98bf0d69a 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -1252,8 +1252,9 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, struct lws_client_connect_info i; struct lws *cwsi; int n, na; - unsigned int max_http_header_data = wsi->a.context->max_http_header_data > 256 ? wsi->a.context->max_http_header_data : 256; - char rpath[max_http_header_data]; + unsigned int max_http_header_data = wsi->a.context->max_http_header_data > 256 ? + wsi->a.context->max_http_header_data : 256; + char *rpath = NULL; #if defined(LWS_ROLE_WS) if (ws) @@ -1320,6 +1321,12 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, if (pcolon) i.port = atoi(pcolon + 1); + rpath = lws_malloc(max_http_header_data, __func__); + if (!rpath) + return -1; + + /* rpath needs cleaning after this... ---> */ + n = lws_snprintf(rpath, max_http_header_data - 1, "/%s/%s", pslash + 1, uri_ptr + hit->mountpoint_len) - 1; lws_clean_url(rpath); @@ -1341,7 +1348,7 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, lwsl_info("%s: query string %d longer " "than we can handle\n", __func__, na); - + lws_free(rpath); return -1; } @@ -1371,9 +1378,8 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, #endif { n = lws_hdr_total_length(wsi, WSI_TOKEN_HOST); - if (n > 0) { + if (n > 0) i.host = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST); - } } #if 0 @@ -1467,9 +1473,10 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit, "The server is temporarily unable to service " "your request due to maintenance downtime or " "capacity problems. Please try again later."); - + lws_free(rpath); return 1; } + lws_free(rpath); lwsl_info("%s: setting proxy clientside on %s (parent %s)\n", __func__, lws_wsi_tag(cwsi), lws_wsi_tag(lws_get_parent(cwsi))); From ca3f639eddc76a37ff68cc039592696385699ea0 Mon Sep 17 00:00:00 2001 From: Poppy Date: Tue, 8 Feb 2022 04:58:13 +0000 Subject: [PATCH 104/275] tls: libressl: refactor set_options to work with macro implementations Libressl uses macros for set_options(), causing compilation failure. Refactor the related code to work well with macro definitions for these apis. https://github.com/warmcat/libwebsockets/issues/2554 --- lib/tls/openssl/openssl-client.c | 52 +++++++++++++++++++++++------- lib/tls/openssl/openssl-server.c | 54 +++++++++++++++++++++++++------- 2 files changed, 83 insertions(+), 23 deletions(-) diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index d8c56c518f..6c8d5c1c9e 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -904,37 +904,67 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_RELEASE_BUFFERS); - if (info->ssl_client_options_set) - SSL_CTX_set_options(vh->tls.ssl_client_ctx, +#if !defined(USE_WOLFSSL) +#if defined(LWS_WITH_BORINGSSL) + uint32_t +#else +#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \ + !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ + unsigned long +#else + long +#endif +#endif +#else + long +#endif + ssl_client_options_set_value = #if !defined(USE_WOLFSSL) #if defined(LWS_WITH_BORINGSSL) (uint32_t) #else #if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \ !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ - (unsigned long) + (unsigned long) #else - (long) + (long) #endif #endif #endif - info->ssl_client_options_set); + info->ssl_client_options_set; + + if (info->ssl_client_options_set) + SSL_CTX_set_options(vh->tls.ssl_client_ctx, ssl_client_options_set_value); - /* SSL_clear_options introduced in 0.9.8m */ #if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL) - if (info->ssl_client_options_clear) - SSL_CTX_clear_options(vh->tls.ssl_client_ctx, + + /* SSL_clear_options introduced in 0.9.8m */ +#if defined(LWS_WITH_BORINGSSL) + uint32_t +#else +#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \ + !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ + unsigned long +#else + long +#endif +#endif + + ssl_client_options_clear_value = #if defined(LWS_WITH_BORINGSSL) (uint32_t) #else #if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \ !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ - (unsigned long) + (unsigned long) #else - (long) + (long) #endif #endif - info->ssl_client_options_clear); + info->ssl_client_options_clear; + + if (info->ssl_client_options_clear) + SSL_CTX_clear_options(vh->tls.ssl_client_ctx, ssl_client_options_clear_value); #endif if (cipher_list) diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c index 94e8846226..34a6ada2c3 100644 --- a/lib/tls/openssl/openssl-server.c +++ b/lib/tls/openssl/openssl-server.c @@ -579,8 +579,20 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, __func__); } - if (info->ssl_options_set) - SSL_CTX_set_options(vhost->tls.ssl_ctx, +#if defined(USE_WOLFSSL) + long +#else +#if defined(LWS_WITH_BORINGSSL) + uint32_t +#else +#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ + unsigned long +#else + long +#endif +#endif +#endif + ssl_options_set_value = #if defined(USE_WOLFSSL) (long) #else @@ -588,32 +600,50 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, (uint32_t) #else #if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && !defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */ - (unsigned long) + (unsigned long) #else - (long) + (long) #endif #endif #endif - info->ssl_options_set); + info->ssl_options_set; + + if (info->ssl_options_set) + SSL_CTX_set_options(vhost->tls.ssl_ctx, ssl_options_set_value); -/* SSL_clear_options introduced in 0.9.8m */ #if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL) - if (info->ssl_options_clear) - SSL_CTX_clear_options(vhost->tls.ssl_ctx, + +/* SSL_clear_options introduced in 0.9.8m */ #if defined(LWS_WITH_BORINGSSL) - (uint32_t) + uint32_t #else #if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && !defined(LIBRESSL_VERSION_NUMBER)/* not documented by openssl */ - (unsigned long) + unsigned long #else - (long) + long #endif #endif - info->ssl_options_clear); + + ssl_options_clear_value = +#if defined(LWS_WITH_BORINGSSL) + (uint32_t) +#else +#if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && !defined(LIBRESSL_VERSION_NUMBER)/* not documented by openssl */ + (unsigned long) +#else + (long) +#endif #endif + info->ssl_options_clear; + + if (info->ssl_options_clear) { + SSL_CTX_clear_options(vhost->tls.ssl_ctx, ssl_options_clear_value); + } lwsl_info(" SSL options 0x%lX\n", (unsigned long)SSL_CTX_get_options(vhost->tls.ssl_ctx)); +#endif + if (!vhost->tls.use_ssl || (!info->ssl_cert_filepath && !info->server_ssl_cert_mem)) return 0; From 890766083dde82d528a30c3f10d94ed036560fd5 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 10 Feb 2022 05:58:48 +0000 Subject: [PATCH 105/275] ss: avoid POLL-POLL transition --- lib/secure-streams/secure-streams.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 510b016457..35e63bb33d 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -1617,9 +1617,12 @@ _lws_ss_request_tx(lws_ss_handle_t *h) return LWSSSSRET_OK; h->seqstate = SSSEQ_TRY_CONNECT; - r = lws_ss_event_helper(h, LWSSSCS_POLL); - if (r) - return r; + if (h->prev_ss_state != LWSSSCS_POLL) { /* possible if we were created + * before we could action it */ + r = lws_ss_event_helper(h, LWSSSCS_POLL); + if (r) + return r; + } /* * Retries operate via lws_ss_request_tx(), explicitly ask for a From 8d560a562f3680bd364fd2c9e632c1742853b2a1 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 10 Feb 2022 08:03:54 +0000 Subject: [PATCH 106/275] ss: POLL to all retries failed is possible It's possible we started POLL, but no connection could happen for some reason, and we end in the window between POLL and trying the connection. --- lib/secure-streams/secure-streams.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 35e63bb33d..c74d229ce8 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -136,6 +136,7 @@ const uint32_t ss_state_txn_validity[] = { [LWSSSCS_POLL] = (1 << LWSSSCS_CONNECTING) | (1 << LWSSSCS_TIMEOUT) | + (1 << LWSSSCS_ALL_RETRIES_FAILED) | (1 << LWSSSCS_DESTROYING), [LWSSSCS_ALL_RETRIES_FAILED] = (1 << LWSSSCS_CONNECTING) | From 0033accb839caab49ef8565049417425b9bad5e5 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 9 Feb 2022 15:04:12 +0000 Subject: [PATCH 107/275] lejp-conf: provide matches for block start paths Also valgrind shows we should zero down the lejp context to avoid problems with the wildcard stack --- lib/misc/lejp.c | 2 +- lib/roles/http/server/lejp-conf.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/misc/lejp.c b/lib/misc/lejp.c index cbce4ee4fe..b898c6f934 100644 --- a/lib/misc/lejp.c +++ b/lib/misc/lejp.c @@ -160,7 +160,7 @@ lejp_check_path_match(struct lejp_ctx *ctx) p = ctx->path; q = *((char **)(((char *)ctx->pst[ctx->pst_sp].paths) + ((unsigned int)n * s))); - +//lwsl_notice("%s: %s %s\n", __func__, p, q); while (*p && *q) { if (*q != '*') { if (*p != *q) diff --git a/lib/roles/http/server/lejp-conf.c b/lib/roles/http/server/lejp-conf.c index 98392d4ad3..0f979cf21a 100644 --- a/lib/roles/http/server/lejp-conf.c +++ b/lib/roles/http/server/lejp-conf.c @@ -71,7 +71,6 @@ enum lejp_global_paths { static const char * const paths_vhosts[] = { "vhosts[]", - "vhosts[].mounts[]", "vhosts[].name", "vhosts[].port", "vhosts[].interface", @@ -89,13 +88,17 @@ static const char * const paths_vhosts[] = { "vhosts[].mounts[].auth-mask", "vhosts[].mounts[].cgi-timeout", "vhosts[].mounts[].cgi-env[].*", + "vhosts[].mounts[].cgi-env[]", "vhosts[].mounts[].cache-max-age", "vhosts[].mounts[].cache-reuse", "vhosts[].mounts[].cache-revalidate", "vhosts[].mounts[].basic-auth", "vhosts[].mounts[].cache-intermediaries", "vhosts[].mounts[].extra-mimetypes.*", + "vhosts[].mounts[].extra-mimetypes", "vhosts[].mounts[].interpret.*", + "vhosts[].mounts[].interpret", + "vhosts[].mounts[]", "vhosts[].ws-protocols[].*.*", "vhosts[].ws-protocols[].*", "vhosts[].ws-protocols[]", @@ -108,6 +111,7 @@ static const char * const paths_vhosts[] = { "vhosts[].ssl-option-set", "vhosts[].ssl-option-clear", "vhosts[].mounts[].pmo[].*", + "vhosts[].mounts[].pmo[]", "vhosts[].headers[].*", "vhosts[].headers[]", "vhosts[].client-ssl-key", @@ -140,7 +144,6 @@ static const char * const paths_vhosts[] = { enum lejp_vhost_paths { LEJPVP, - LEJPVP_MOUNTS, LEJPVP_NAME, LEJPVP_PORT, LEJPVP_INTERFACE, @@ -158,13 +161,19 @@ enum lejp_vhost_paths { LEJPVP_DEFAULT_AUTH_MASK, LEJPVP_CGI_TIMEOUT, LEJPVP_CGI_ENV, + LEJPVP_CGI_ENV_base, LEJPVP_MOUNT_CACHE_MAX_AGE, LEJPVP_MOUNT_CACHE_REUSE, LEJPVP_MOUNT_CACHE_REVALIDATE, LEJPVP_MOUNT_BASIC_AUTH, LEJPVP_MOUNT_CACHE_INTERMEDIARIES, LEJPVP_MOUNT_EXTRA_MIMETYPES, + LEJPVP_MOUNT_EXTRA_MIMETYPES_base, LEJPVP_MOUNT_INTERPRET, + LEJPVP_MOUNT_INTERPRET_base, + + LEJPVP_MOUNTS, + LEJPVP_PROTOCOL_NAME_OPT, LEJPVP_PROTOCOL_NAME, LEJPVP_PROTOCOL, @@ -177,6 +186,7 @@ enum lejp_vhost_paths { LEJPVP_SSL_OPTION_SET, LEJPVP_SSL_OPTION_CLEAR, LEJPVP_PMO, + LEJPVP_PM_baseO, LEJPVP_HEADERS_NAME, LEJPVP_HEADERS, LEJPVP_CLIENT_SSL_KEY, @@ -937,6 +947,8 @@ lwsws_get_config(void *user, const char *f, const char * const *paths, struct lejp_ctx ctx; int n, m = 0, fd; + memset(&ctx, 0, sizeof(ctx)); + fd = lws_open(f, O_RDONLY); if (fd < 0) { lwsl_err("Cannot open %s\n", f); From 28b1e1f46329356b3de0da610ab1d55794b523a6 Mon Sep 17 00:00:00 2001 From: Luciano Iam Date: Mon, 14 Feb 2022 11:53:07 +0100 Subject: [PATCH 108/275] mingw: correct winsock recv() and send() buffer ptr type This allows to build libwebsockets on MinGW. Winsock recv() and send() expect non unsigned char* while lws uses uint_8*. https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recv --- lib/plat/windows/windows-sockets.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/plat/windows/windows-sockets.c b/lib/plat/windows/windows-sockets.c index ce9b7192e9..b0e15dd1ea 100644 --- a/lib/plat/windows/windows-sockets.c +++ b/lib/plat/windows/windows-sockets.c @@ -564,7 +564,7 @@ lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) if (fd < 0) return MBEDTLS_ERR_NET_INVALID_CONTEXT; - ret = send(fd, buf, (unsigned int)len, 0); + ret = send(fd, (const char *)buf, (unsigned int)len, 0); if (ret >= 0) return ret; @@ -589,7 +589,7 @@ lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) if (fd < 0) return MBEDTLS_ERR_NET_INVALID_CONTEXT; - ret = (int)recv(fd, buf, (unsigned int)len, 0); + ret = (int)recv(fd, (char *)buf, (unsigned int)len, 0); if (ret >= 0) return ret; From 027fe42ceca78e04beb65d5c926cf6342e65acc8 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 11 Feb 2022 07:18:22 +0000 Subject: [PATCH 109/275] h1: deal with WAITING_CONNECT in ops-h1 We don't normally see events on the wsi in this state, but it is possible since warmcat.com lwsws asserted on it in WAITING_CONNECT. Explicitly handle it so we don't blow up. --- lib/roles/h1/ops-h1.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c index 4590a49757..b21b69e4b7 100644 --- a/lib/roles/h1/ops-h1.c +++ b/lib/roles/h1/ops-h1.c @@ -292,6 +292,9 @@ lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len) // assert(0); /* fallthru */ + case LRS_WAITING_CONNECT: /* observed on warmcat.com */ + break; + default: lwsl_err("%s: Unhandled state %d\n", __func__, lwsi_state(wsi)); assert(0); From fcde566fc6586bc85c154f6b19d4695016b8b769 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 11 Feb 2022 07:31:05 +0000 Subject: [PATCH 110/275] cgi: gracefully handle missing wsi->http.cgi --- lib/core-net/dummy-callback.c | 26 ++++++++++++++------------ lib/roles/cgi/cgi-server.c | 11 +++++++---- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/core-net/dummy-callback.c b/lib/core-net/dummy-callback.c index 9552af5acd..d36000fa73 100644 --- a/lib/core-net/dummy-callback.c +++ b/lib/core-net/dummy-callback.c @@ -686,21 +686,23 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, break; case LWS_CALLBACK_CGI_TERMINATED: - lwsl_wsi_debug(wsi, "CGI_TERMINATED: %d %" PRIu64, + if (wsi->http.cgi) { + lwsl_wsi_debug(wsi, "CGI_TERMINATED: %d %" PRIu64, wsi->http.cgi->explicitly_chunked, (uint64_t)wsi->http.cgi->content_length); - if (!(wsi->http.cgi->explicitly_chunked && wsi->mux_substream) && - !wsi->http.cgi->content_length) { - /* send terminating chunk */ - lwsl_wsi_debug(wsi, "LWS_CALLBACK_CGI_TERMINATED: ending"); - wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_CHUNK_END; - lws_callback_on_writable(wsi); - lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, 3); - break; - } - if (wsi->mux_substream && !wsi->cgi_stdout_zero_length) - lws_write(wsi, (unsigned char *)buf + LWS_PRE, 0, + if (!(wsi->http.cgi->explicitly_chunked && wsi->mux_substream) && + !wsi->http.cgi->content_length) { + /* send terminating chunk */ + lwsl_wsi_debug(wsi, "LWS_CALLBACK_CGI_TERMINATED: ending"); + wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_CHUNK_END; + lws_callback_on_writable(wsi); + lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, 3); + break; + } + if (wsi->mux_substream && !wsi->cgi_stdout_zero_length) + lws_write(wsi, (unsigned char *)buf + LWS_PRE, 0, LWS_WRITE_HTTP_FINAL); + } #if defined(LWS_WITH_SERVER) if (lws_http_transaction_completed(wsi)) return -1; diff --git a/lib/roles/cgi/cgi-server.c b/lib/roles/cgi/cgi-server.c index cd039e84ea..a6f04fa1b1 100644 --- a/lib/roles/cgi/cgi-server.c +++ b/lib/roles/cgi/cgi-server.c @@ -95,14 +95,16 @@ lws_cgi_reap_cb(void *opaque, lws_usec_t *accounting, siginfo_t *si, * The cgi has come to an end, by itself or with a signal... */ - lwsl_wsi_info(wsi, "post_in_expected %d", + if (wsi->http.cgi) + lwsl_wsi_info(wsi, "post_in_expected %d", (int)wsi->http.cgi->post_in_expected); /* * Grace period to handle the incoming stdout */ - lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->http.cgi->sul_grace, + if (wsi->http.cgi) + lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->http.cgi->sul_grace, lws_cgi_grace, 1 * LWS_US_PER_SEC); } @@ -907,7 +909,7 @@ lws_cgi_kill(struct lws *wsi) { struct lws_cgi_args args; pid_t pid; - int n, m; + int n, m = 0; if (!wsi->http.cgi || !wsi->http.cgi->lsp) return 0; @@ -919,7 +921,8 @@ lws_cgi_kill(struct lws *wsi) /* that has invalidated and NULL'd wsi->http.cgi->lsp */ if (pid != -1) { - m = wsi->http.cgi->being_closed; + if (wsi->http.cgi) + m = wsi->http.cgi->being_closed; n = user_callback_handle_rxflow(wsi->a.protocol->callback, wsi, LWS_CALLBACK_CGI_TERMINATED, wsi->user_space, (void *)&args, From 4fb9a535db39399361616c4fb738b1e1be3fd3c0 Mon Sep 17 00:00:00 2001 From: wayneonway <121931005@qq.com> Date: Mon, 21 Feb 2022 15:16:35 +0800 Subject: [PATCH 111/275] route: extend lws_route_uidx_t from 1 byte to 2 bytes --- include/libwebsockets/lws-network-helper.h | 3 ++- lib/core-net/route.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/libwebsockets/lws-network-helper.h b/include/libwebsockets/lws-network-helper.h index 20a3225309..09308b8b2e 100644 --- a/include/libwebsockets/lws-network-helper.h +++ b/include/libwebsockets/lws-network-helper.h @@ -33,7 +33,8 @@ #include #endif -typedef uint8_t lws_route_uidx_t; +/* cope with large amounts of route information */ +typedef uint16_t lws_route_uidx_t; typedef struct lws_dns_score { uint8_t precedence; diff --git a/lib/core-net/route.c b/lib/core-net/route.c index 270ed863d6..d94ea5a046 100644 --- a/lib/core-net/route.c +++ b/lib/core-net/route.c @@ -103,7 +103,7 @@ _lws_routing_table_dump(struct lws_context *cx) lws_route_uidx_t _lws_route_get_uidx(struct lws_context *cx) { - uint8_t ou; + lws_route_uidx_t ou; if (!cx->route_uidx) cx->route_uidx++; From 1f2912d383c2d76328b5a318bf83ca3635bbaec9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 17 Feb 2022 11:46:07 +0000 Subject: [PATCH 112/275] pkgconfig: use appropriate static lib name --- lib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f9553fd8c9..19dc0cf645 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -340,7 +340,7 @@ Name: libwebsockets_static Description: Websockets server and client static library Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} -Libs: -L\${libdir} -lwebsockets_static +Libs: -L\${libdir} -l:libwebsockets${CMAKE_STATIC_LIBRARY_SUFFIX} Libs.private: Cflags: -I\${includedir} " From 058f97e687a8fef5e925ac8bcccb8810df96d2e4 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 18 Feb 2022 08:29:13 +0000 Subject: [PATCH 113/275] netlink: always delete route if it exists https://github.com/warmcat/libwebsockets/issues/2567 --- lib/core-net/private-lib-core-net.h | 1 - lib/core-net/route.c | 2 -- lib/roles/netlink/ops-netlink.c | 1 - 3 files changed, 4 deletions(-) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 2d3f73abb1..c515c10d5b 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -1375,7 +1375,6 @@ _lws_routing_table_dump(struct lws_context *cx); #define LRR_IGNORE_PRI (1 << 0) #define LRR_MATCH_SRC (1 << 1) -#define LRR_JUST_CHECK (1 << 2) lws_route_t * _lws_route_remove(struct lws_context_per_thread *pt, lws_route_t *robj, int flags); diff --git a/lib/core-net/route.c b/lib/core-net/route.c index d94ea5a046..14f4beb07e 100644 --- a/lib/core-net/route.c +++ b/lib/core-net/route.c @@ -154,8 +154,6 @@ _lws_route_remove(struct lws_context_per_thread *pt, lws_route_t *robj, int flag ((flags & LRR_IGNORE_PRI) || robj->priority == rou->priority) ) { - if (flags & LRR_JUST_CHECK) - return rou; lwsl_cx_info(pt->context, "deleting route"); _lws_route_pt_close_route_users(pt, robj->uidx); lws_dll2_remove(&rou->list); diff --git a/lib/roles/netlink/ops-netlink.c b/lib/roles/netlink/ops-netlink.c index 31fb0133b7..846a974330 100644 --- a/lib/roles/netlink/ops-netlink.c +++ b/lib/roles/netlink/ops-netlink.c @@ -372,7 +372,6 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, /* returns zero on match already in table */ rmat = _lws_route_remove(pt, &robj, LRR_MATCH_SRC | - LRR_JUST_CHECK | LRR_IGNORE_PRI); lws_pt_unlock(pt); From 8b6f2d5dba0b81891d2445685158ed442cc82328 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 18 Feb 2022 08:25:58 +0000 Subject: [PATCH 114/275] gcc4: conceal typedef in public header Modern toolchains are fine with giving a typedef as a forward reference, but gcc 4.3 can't cope with that and then seeing the real definition in the .c later. Just conceal the typedef and use the struct form for the forward reference resolution type in the public header so even senior toolchains are happy. --- include/libwebsockets/lws-map.h | 16 ++++++++-------- .../api-tests/api-test-lws_map/main.c | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/libwebsockets/lws-map.h b/include/libwebsockets/lws-map.h index 4462881be4..cf2368a0be 100644 --- a/include/libwebsockets/lws-map.h +++ b/include/libwebsockets/lws-map.h @@ -43,7 +43,7 @@ //@{ typedef struct lws_map lws_map_t; -typedef struct lws_map_item lws_map_item_t; +struct lws_map_item; typedef void * lws_map_key_t; typedef void * lws_map_value_t; @@ -76,13 +76,13 @@ typedef struct lws_map_info { } lws_map_info_t; LWS_VISIBLE LWS_EXTERN const void * -lws_map_item_key(lws_map_item_t *_item); +lws_map_item_key(struct lws_map_item *_item); LWS_VISIBLE LWS_EXTERN const void * -lws_map_item_value(lws_map_item_t *_item); +lws_map_item_value(struct lws_map_item *_item); LWS_VISIBLE LWS_EXTERN size_t -lws_map_item_key_len(lws_map_item_t *_item); +lws_map_item_key_len(struct lws_map_item *_item); LWS_VISIBLE LWS_EXTERN size_t -lws_map_item_value_len(lws_map_item_t *_item); +lws_map_item_value_len(struct lws_map_item *_item); /* * Helpers for C string keys case @@ -158,7 +158,7 @@ lws_map_destroy(lws_map_t **pmap); * creating and adding the new one. */ -LWS_VISIBLE LWS_EXTERN lws_map_item_t * +LWS_VISIBLE LWS_EXTERN struct lws_map_item * lws_map_item_create(lws_map_t *map, const lws_map_key_t key, size_t keylen, const lws_map_value_t value, size_t valuelen); @@ -169,7 +169,7 @@ lws_map_item_create(lws_map_t *map, * \param item: the item in the map to remove and free */ LWS_VISIBLE LWS_EXTERN void -lws_map_item_destroy(lws_map_item_t *item); +lws_map_item_destroy(struct lws_map_item *item); /** * lws_map_item_lookup() - look for a item with the given key in the map @@ -182,7 +182,7 @@ lws_map_item_destroy(lws_map_item_t *item); * functions. */ -LWS_VISIBLE LWS_EXTERN lws_map_item_t * +LWS_VISIBLE LWS_EXTERN struct lws_map_item * lws_map_item_lookup(lws_map_t *map, const lws_map_key_t key, size_t keylen); //@} diff --git a/minimal-examples/api-tests/api-test-lws_map/main.c b/minimal-examples/api-tests/api-test-lws_map/main.c index 022c98a848..c17be8188a 100644 --- a/minimal-examples/api-tests/api-test-lws_map/main.c +++ b/minimal-examples/api-tests/api-test-lws_map/main.c @@ -11,6 +11,8 @@ #include +typedef struct lws_map_item lws_map_item_t; + /* custom key and comparator for test 3 */ typedef struct mykey { From 89f489f15c29ba79872f4901269ef717256fe07e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 21 Feb 2022 05:29:44 +0000 Subject: [PATCH 115/275] plugins: openmetrics_export: graceful fail if unconfigured --- plugins/protocol_lws_openmetrics_export.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/protocol_lws_openmetrics_export.c b/plugins/protocol_lws_openmetrics_export.c index f7fb601550..f6b1850b1d 100644 --- a/plugins/protocol_lws_openmetrics_export.c +++ b/plugins/protocol_lws_openmetrics_export.c @@ -971,7 +971,7 @@ callback_lws_openmetrics_prox_client(struct lws *wsi, /* the proxy server uri */ - if (lws_pvo_get_str(in, "ws-server-uri", &cp)) { + if (lws_pvo_get_str(in, "ws-server-uri", &cp) || !cp) { lwsl_warn("%s: ws-server-uri pvo required\n", __func__); return 0; From 15db074b701a066a297016bf2d4e12f2e66f1568 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 21 Feb 2022 08:18:47 +0000 Subject: [PATCH 116/275] context_destroy: clean up early fail path --- lib/core/context.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index fb684e5118..af818ebe35 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -2009,15 +2009,18 @@ lws_context_destroy(struct lws_context *context) lws_plat_context_late_destroy(context); #if defined(LWS_WITH_PEER_LIMITS) - for (nu = 0; nu < context->pl_hash_elements; nu++) { - lws_start_foreach_llp(struct lws_peer **, peer, - context->pl_hash_table[nu]) { - struct lws_peer *df = *peer; - *peer = df->next; - lws_free(df); - continue; - } lws_end_foreach_llp(peer, next); - } + if (context->pl_hash_table) + for (nu = 0; nu < context->pl_hash_elements; nu++) { + if (!context->pl_hash_table[nu]) + continue; + lws_start_foreach_llp(struct lws_peer **, peer, + context->pl_hash_table[nu]) { + struct lws_peer *df = *peer; + *peer = df->next; + lws_free(df); + continue; + } lws_end_foreach_llp(peer, next); + } lws_free(context->pl_hash_table); #endif From 49af3742c6c7ccf1bf5746869c460002cc6f85f4 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 22 Feb 2022 17:35:02 +0000 Subject: [PATCH 117/275] mbedtls: v3.1 reverts privacy of mbedtls_net_context fd mbedtls seemed to realize that they went overboard with the privacy stuff on v3.0 and removed some of it. Introduce support for those members that are only private on exactly v3.0 and unprotected before and after. --- include/libwebsockets.h | 7 ++ lib/plat/unix/unix-sockets.c | 4 +- lib/tls/mbedtls/mbedtls-extensions.c | 82 ++++++++++----------- lib/tls/mbedtls/mbedtls-x509.c | 88 +++++++++++------------ lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 5 +- 5 files changed, 96 insertions(+), 90 deletions(-) diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 4409ee2784..8fb98c3443 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -291,11 +291,18 @@ typedef int suseconds_t; #include #include #include +#include #if !defined(MBEDTLS_PRIVATE) #define MBEDTLS_PRIVATE(_q) _q #endif +#if (MBEDTLS_VERSION_MAJOR == 3) && (MBEDTLS_VERSION_MINOR == 0) +#define MBEDTLS_PRIVATE_V30_ONLY(_q) MBEDTLS_PRIVATE(_q) +#else +#define MBEDTLS_PRIVATE_V30_ONLY(_q) _q +#endif + #endif #else #include diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index 07df994cce..0f5bf4b93e 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -589,7 +589,7 @@ lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost) int lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) { - int fd = ((mbedtls_net_context *) ctx)->MBEDTLS_PRIVATE(fd); + int fd = ((mbedtls_net_context *) ctx)->MBEDTLS_PRIVATE_V30_ONLY(fd); int ret; if (fd < 0) @@ -614,7 +614,7 @@ lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) int lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) { - int fd = ((mbedtls_net_context *) ctx)->MBEDTLS_PRIVATE(fd); + int fd = ((mbedtls_net_context *) ctx)->MBEDTLS_PRIVATE_V30_ONLY(fd); int ret; if (fd < 0) diff --git a/lib/tls/mbedtls/mbedtls-extensions.c b/lib/tls/mbedtls/mbedtls-extensions.c index dc406e8267..bf275eefe4 100644 --- a/lib/tls/mbedtls/mbedtls-extensions.c +++ b/lib/tls/mbedtls/mbedtls-extensions.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2021 Andy Green + * Copyright (C) 2010 - 2022 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -104,8 +104,8 @@ static const oid_x509_ext_t oid_x509_ext[] = { (const mbedtls_oid_descriptor_t *) p; \ if( p == NULL || oid == NULL ) return( NULL ); \ while( cur->MBEDTLS_PRIVATE(asn1) != NULL ) { \ - if( cur->MBEDTLS_PRIVATE(asn1_len) == oid->MBEDTLS_PRIVATE(len) && \ - memcmp( cur->MBEDTLS_PRIVATE(asn1), oid->MBEDTLS_PRIVATE(p), oid->MBEDTLS_PRIVATE(len) ) == 0 ) { \ + if( cur->MBEDTLS_PRIVATE(asn1_len) == oid->MBEDTLS_PRIVATE_V30_ONLY(len) && \ + memcmp( cur->MBEDTLS_PRIVATE(asn1), oid->MBEDTLS_PRIVATE_V30_ONLY(p), oid->MBEDTLS_PRIVATE_V30_ONLY(len) ) == 0 ) { \ return( p ); \ } \ p++; \ @@ -177,10 +177,10 @@ x509_get_skid(uint8_t **p, const uint8_t *end, mbedtls_x509_buf *skid) if (ret) return ret; - skid->MBEDTLS_PRIVATE(len) = len; - skid->MBEDTLS_PRIVATE(tag) = MBEDTLS_ASN1_OCTET_STRING; - skid->MBEDTLS_PRIVATE(p) = *p; - *p += len; + skid->MBEDTLS_PRIVATE_V30_ONLY(len) = len; + skid->MBEDTLS_PRIVATE_V30_ONLY(tag) = MBEDTLS_ASN1_OCTET_STRING; + skid->MBEDTLS_PRIVATE_V30_ONLY(p) = *p; + *p += len; return *p != end; } @@ -204,10 +204,10 @@ lws_x509_clean_name(mbedtls_x509_name *name) if (!name) return; - n1 = name->MBEDTLS_PRIVATE(next); + n1 = name->MBEDTLS_PRIVATE_V30_ONLY(next); while (n1) { - name = n1->MBEDTLS_PRIVATE(next); + name = n1->MBEDTLS_PRIVATE_V30_ONLY(next); free(n1); n1 = name; } @@ -222,7 +222,7 @@ lws_mbedtls_x509_parse_general_name(const mbedtls_x509_buf *name_buf, mbedtls_x509_name rfc822Name; int ret; - switch (name_buf->MBEDTLS_PRIVATE(tag) & + switch (name_buf->MBEDTLS_PRIVATE_V30_ONLY(tag) & (LWS_MBEDTLS_ASN1_TAG_CLASS_MASK | LWS_MBEDTLS_ASN1_TAG_VALUE_MASK)) { @@ -239,17 +239,17 @@ lws_mbedtls_x509_parse_general_name(const mbedtls_x509_buf *name_buf, #endif case MBEDTLS_ASN1_SEQUENCE | LWS_MBEDTLS_X509_SAN_RFC822_NAME: - bufferPointer = name_buf->MBEDTLS_PRIVATE(p); + bufferPointer = name_buf->MBEDTLS_PRIVATE_V30_ONLY(p); p = &bufferPointer; - end = name_buf->MBEDTLS_PRIVATE(p) + - name_buf->MBEDTLS_PRIVATE(len); + end = name_buf->MBEDTLS_PRIVATE_V30_ONLY(p) + + name_buf->MBEDTLS_PRIVATE_V30_ONLY(len); /* The leading ASN1 tag and length has been processed. * Stepping back with 2 bytes, because mbedtls_x509_get_name * expects the beginning of the SET tag */ *p = *p - 2; - rfc822Name.MBEDTLS_PRIVATE(next) = NULL; + rfc822Name.MBEDTLS_PRIVATE_V30_ONLY(next) = NULL; ret = mbedtls_x509_get_name( p, end, &rfc822Name ); if (ret) { lws_x509_clean_name(&rfc822Name); @@ -318,51 +318,51 @@ lws_x509_get_general_names(uint8_t **p, const uint8_t *end, * Check that the name is structured correctly. */ r = lws_mbedtls_x509_parse_general_name( - &cur->MBEDTLS_PRIVATE(buf), &dnb); + &cur->MBEDTLS_PRIVATE_V30_ONLY(buf), &dnb); /* * In case the extension is malformed, return an error, * and clear the allocated sequences. */ if (r && r != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { - mbedtls_x509_sequence *seq_cur = name->MBEDTLS_PRIVATE(next); + mbedtls_x509_sequence *seq_cur = name->MBEDTLS_PRIVATE_V30_ONLY(next); mbedtls_x509_sequence *seq_prv; while( seq_cur != NULL ) { seq_prv = seq_cur; - seq_cur = seq_cur->MBEDTLS_PRIVATE(next); + seq_cur = seq_cur->MBEDTLS_PRIVATE_V30_ONLY(next); lws_explicit_bzero(seq_prv, sizeof(*seq_cur)); lws_free(seq_prv); } - name->MBEDTLS_PRIVATE(next) = NULL; + name->MBEDTLS_PRIVATE_V30_ONLY(next) = NULL; return r; } /* Allocate and assign next pointer */ - if (cur->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(p)) { - if (cur->MBEDTLS_PRIVATE(next)) + if (cur->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p)) { + if (cur->MBEDTLS_PRIVATE_V30_ONLY(next)) return 1; - cur->MBEDTLS_PRIVATE(next) = + cur->MBEDTLS_PRIVATE_V30_ONLY(next) = lws_zalloc(sizeof(*cur), __func__); - if (!cur->MBEDTLS_PRIVATE(next)) + if (!cur->MBEDTLS_PRIVATE_V30_ONLY(next)) return 1; - cur = cur->MBEDTLS_PRIVATE(next); + cur = cur->MBEDTLS_PRIVATE_V30_ONLY(next); } - buf = &(cur->MBEDTLS_PRIVATE(buf)); - buf->MBEDTLS_PRIVATE(tag) = tag; - buf->MBEDTLS_PRIVATE(p) = *p; - buf->MBEDTLS_PRIVATE(len) = tag_len; + buf = &(cur->MBEDTLS_PRIVATE_V30_ONLY(buf)); + buf->MBEDTLS_PRIVATE_V30_ONLY(tag) = tag; + buf->MBEDTLS_PRIVATE_V30_ONLY(p) = *p; + buf->MBEDTLS_PRIVATE_V30_ONLY(len) = tag_len; - *p += buf->MBEDTLS_PRIVATE(len); + *p += buf->MBEDTLS_PRIVATE_V30_ONLY(len); } /* Set final sequence entry's next pointer to NULL */ - cur->MBEDTLS_PRIVATE(next) = NULL; + cur->MBEDTLS_PRIVATE_V30_ONLY(next) = NULL; return *p != end; } @@ -380,9 +380,9 @@ x509_get_akid(uint8_t **p, uint8_t *end, lws_mbedtls_x509_authority *akid) r = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC); if (!r) { - akid->keyIdentifier.MBEDTLS_PRIVATE(len) = len; - akid->keyIdentifier.MBEDTLS_PRIVATE(p) = *p; - akid->keyIdentifier.MBEDTLS_PRIVATE(tag) = MBEDTLS_ASN1_OCTET_STRING; + akid->keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(len) = len; + akid->keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p) = *p; + akid->keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(tag) = MBEDTLS_ASN1_OCTET_STRING; *p += len; } @@ -416,9 +416,9 @@ x509_get_akid(uint8_t **p, uint8_t *end, lws_mbedtls_x509_authority *akid) if (r) return r; - akid->authorityCertSerialNumber.MBEDTLS_PRIVATE(len) = len; - akid->authorityCertSerialNumber.MBEDTLS_PRIVATE(p) = *p; - akid->authorityCertSerialNumber.MBEDTLS_PRIVATE(tag) = MBEDTLS_ASN1_OCTET_STRING; + akid->authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(len) = len; + akid->authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(p) = *p; + akid->authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(tag) = MBEDTLS_ASN1_OCTET_STRING; *p += len; } @@ -434,9 +434,9 @@ int lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid, lws_mbedtls_x509_authority *akid) { - uint8_t *p = crt->MBEDTLS_PRIVATE(v3_ext).MBEDTLS_PRIVATE(p), + uint8_t *p = crt->MBEDTLS_PRIVATE_V30_ONLY(v3_ext).MBEDTLS_PRIVATE_V30_ONLY(p), *end_ext_data, *end_ext_octet; - const uint8_t *end = p + crt->MBEDTLS_PRIVATE(v3_ext).MBEDTLS_PRIVATE(len); + const uint8_t *end = p + crt->MBEDTLS_PRIVATE_V30_ONLY(v3_ext).MBEDTLS_PRIVATE_V30_ONLY(len); size_t len; int r = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); @@ -457,14 +457,14 @@ lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid, end_ext_data = p + len; /* Get extension ID */ - r = mbedtls_asn1_get_tag(&p, end_ext_data, &extn_oid.MBEDTLS_PRIVATE(len), + r = mbedtls_asn1_get_tag(&p, end_ext_data, &extn_oid.MBEDTLS_PRIVATE_V30_ONLY(len), MBEDTLS_ASN1_OID); if (r) return r; - extn_oid.MBEDTLS_PRIVATE(tag) = MBEDTLS_ASN1_OID; - extn_oid.MBEDTLS_PRIVATE(p) = p; - p += extn_oid.MBEDTLS_PRIVATE(len); + extn_oid.MBEDTLS_PRIVATE_V30_ONLY(tag) = MBEDTLS_ASN1_OID; + extn_oid.MBEDTLS_PRIVATE_V30_ONLY(p) = p; + p += extn_oid.MBEDTLS_PRIVATE_V30_ONLY(len); /* Get optional critical */ r = mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical); diff --git a/lib/tls/mbedtls/mbedtls-x509.c b/lib/tls/mbedtls/mbedtls-x509.c index 2dad865d68..8b0ccd3f17 100644 --- a/lib/tls/mbedtls/mbedtls-x509.c +++ b/lib/tls/mbedtls/mbedtls-x509.c @@ -49,17 +49,17 @@ lws_tls_mbedtls_time_to_unix(mbedtls_x509_time *xtime) { struct tm t; - if (!xtime || !xtime->MBEDTLS_PRIVATE(year) || xtime->MBEDTLS_PRIVATE(year) < 0) + if (!xtime || !xtime->MBEDTLS_PRIVATE_V30_ONLY(year) || xtime->MBEDTLS_PRIVATE_V30_ONLY(year) < 0) return (time_t)(long long)-1; memset(&t, 0, sizeof(t)); - t.tm_year = xtime->MBEDTLS_PRIVATE(year) - 1900; - t.tm_mon = xtime->MBEDTLS_PRIVATE(mon) - 1; /* mbedtls months are 1+, tm are 0+ */ - t.tm_mday = xtime->MBEDTLS_PRIVATE(day) - 1; /* mbedtls days are 1+, tm are 0+ */ - t.tm_hour = xtime->MBEDTLS_PRIVATE(hour); - t.tm_min = xtime->MBEDTLS_PRIVATE(min); - t.tm_sec = xtime->MBEDTLS_PRIVATE(sec); + t.tm_year = xtime->MBEDTLS_PRIVATE_V30_ONLY(year) - 1900; + t.tm_mon = xtime->MBEDTLS_PRIVATE_V30_ONLY(mon) - 1; /* mbedtls months are 1+, tm are 0+ */ + t.tm_mday = xtime->MBEDTLS_PRIVATE_V30_ONLY(day) - 1; /* mbedtls days are 1+, tm are 0+ */ + t.tm_hour = xtime->MBEDTLS_PRIVATE_V30_ONLY(hour); + t.tm_min = xtime->MBEDTLS_PRIVATE_V30_ONLY(min); + t.tm_sec = xtime->MBEDTLS_PRIVATE_V30_ONLY(sec); t.tm_isdst = -1; return mktime(&t); @@ -81,13 +81,13 @@ lws_tls_mbedtls_get_x509_name(mbedtls_x509_name *name, } */ lws_strnncpy(&buf->ns.name[buf->ns.len], - (const char *)name->MBEDTLS_PRIVATE(val).MBEDTLS_PRIVATE(p), - name->MBEDTLS_PRIVATE(val).MBEDTLS_PRIVATE(len), + (const char *)name->MBEDTLS_PRIVATE_V30_ONLY(val).MBEDTLS_PRIVATE_V30_ONLY(p), + name->MBEDTLS_PRIVATE_V30_ONLY(val).MBEDTLS_PRIVATE_V30_ONLY(len), len - (size_t)buf->ns.len); buf->ns.len = (int)strlen(buf->ns.name); r = 0; - name = name->MBEDTLS_PRIVATE(next); + name = name->MBEDTLS_PRIVATE_V30_ONLY(next); } return r; @@ -109,22 +109,22 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, switch (type) { case LWS_TLS_CERT_INFO_VALIDITY_FROM: - buf->time = lws_tls_mbedtls_time_to_unix(&x509->MBEDTLS_PRIVATE(valid_from)); + buf->time = lws_tls_mbedtls_time_to_unix(&x509->MBEDTLS_PRIVATE_V30_ONLY(valid_from)); if (buf->time == (time_t)(long long)-1) return -1; break; case LWS_TLS_CERT_INFO_VALIDITY_TO: - buf->time = lws_tls_mbedtls_time_to_unix(&x509->MBEDTLS_PRIVATE(valid_to)); + buf->time = lws_tls_mbedtls_time_to_unix(&x509->MBEDTLS_PRIVATE_V30_ONLY(valid_to)); if (buf->time == (time_t)(long long)-1) return -1; break; case LWS_TLS_CERT_INFO_COMMON_NAME: - return lws_tls_mbedtls_get_x509_name(&x509->MBEDTLS_PRIVATE(subject), buf, len); + return lws_tls_mbedtls_get_x509_name(&x509->MBEDTLS_PRIVATE_V30_ONLY(subject), buf, len); case LWS_TLS_CERT_INFO_ISSUER_NAME: - return lws_tls_mbedtls_get_x509_name(&x509->MBEDTLS_PRIVATE(issuer), buf, len); + return lws_tls_mbedtls_get_x509_name(&x509->MBEDTLS_PRIVATE_V30_ONLY(issuer), buf, len); case LWS_TLS_CERT_INFO_USAGE: buf->usage = x509->MBEDTLS_PRIVATE(key_usage); @@ -135,10 +135,10 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, char *p = buf->ns.name; size_t r = len, u; - switch (mbedtls_pk_get_type(&x509->MBEDTLS_PRIVATE(pk))) { + switch (mbedtls_pk_get_type(&x509->MBEDTLS_PRIVATE_V30_ONLY(pk))) { case MBEDTLS_PK_RSA: { - mbedtls_rsa_context *rsa = mbedtls_pk_rsa(x509->MBEDTLS_PRIVATE(pk)); + mbedtls_rsa_context *rsa = mbedtls_pk_rsa(x509->MBEDTLS_PRIVATE_V30_ONLY(pk)); if (mbedtls_mpi_write_string(&rsa->MBEDTLS_PRIVATE(N), 16, p, r, &u)) return -1; @@ -153,7 +153,7 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, } case MBEDTLS_PK_ECKEY: { - mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(x509->MBEDTLS_PRIVATE(pk)); + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(x509->MBEDTLS_PRIVATE_V30_ONLY(pk)); if (mbedtls_mpi_write_string(&ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 16, p, r, &u)) return -1; @@ -172,7 +172,7 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, default: lwsl_notice("%s: x509 has unsupported pubkey type %d\n", __func__, - mbedtls_pk_get_type(&x509->MBEDTLS_PRIVATE(pk))); + mbedtls_pk_get_type(&x509->MBEDTLS_PRIVATE_V30_ONLY(pk))); return -1; } @@ -180,17 +180,17 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, } case LWS_TLS_CERT_INFO_DER_RAW: - buf->ns.len = (int)x509->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len); + buf->ns.len = (int)x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len); - if (len < x509->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) + if (len < x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len)) /* * The buffer is too small and the attempt failed, but * the required object length is in buf->ns.len */ return -1; - memcpy(buf->ns.name, x509->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p), - x509->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)); + memcpy(buf->ns.name, x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(p), + x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len)); break; case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID: @@ -199,13 +199,13 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, memset(&skid, 0, sizeof(skid)); lws_x509_get_crt_ext(x509, &skid, &akid); - if (akid.keyIdentifier.MBEDTLS_PRIVATE(tag) != MBEDTLS_ASN1_OCTET_STRING) + if (akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING) return 1; - buf->ns.len = (int)akid.keyIdentifier.MBEDTLS_PRIVATE(len); - if (!akid.keyIdentifier.MBEDTLS_PRIVATE(p) || + buf->ns.len = (int)akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(len); + if (!akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p) || len < (size_t)buf->ns.len) return -1; - memcpy(buf->ns.name, akid.keyIdentifier.MBEDTLS_PRIVATE(p), (size_t)buf->ns.len); + memcpy(buf->ns.name, akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len); break; case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER: { @@ -221,17 +221,17 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, buf->ns.len = 0; while (ip) { - if (akid.keyIdentifier.MBEDTLS_PRIVATE(tag) != MBEDTLS_ASN1_OCTET_STRING || - !ip->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(p) || - ip->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(len) < 9 || - len < (size_t)ip->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(len) - 9u) + if (akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING || + !ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p) || + ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) < 9 || + len < (size_t)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9u) break; - memcpy(buf->ns.name + buf->ns.len, ip->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(p), - (size_t)ip->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(len) - 9); - buf->ns.len = buf->ns.len + (int)ip->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(len) - 9; + memcpy(buf->ns.name + buf->ns.len, ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p), + (size_t)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9); + buf->ns.len = buf->ns.len + (int)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9; - ip = ip->MBEDTLS_PRIVATE(next); + ip = ip->MBEDTLS_PRIVATE_V30_ONLY(next); } break; } @@ -242,14 +242,14 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, lws_x509_get_crt_ext(x509, &skid, &akid); - if (akid.authorityCertSerialNumber.MBEDTLS_PRIVATE(tag) != MBEDTLS_ASN1_OCTET_STRING) + if (akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING) return 1; - buf->ns.len = (int)akid.authorityCertSerialNumber.MBEDTLS_PRIVATE(len); - if (!akid.authorityCertSerialNumber.MBEDTLS_PRIVATE(p) || + buf->ns.len = (int)akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(len); + if (!akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(p) || len < (size_t)buf->ns.len) return -1; memcpy(buf->ns.name, akid.authorityCertSerialNumber. - MBEDTLS_PRIVATE(p), (size_t)buf->ns.len); + MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len); break; case LWS_TLS_CERT_INFO_SUBJECT_KEY_ID: @@ -259,12 +259,12 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, lws_x509_get_crt_ext(x509, &skid, &akid); - if (skid.MBEDTLS_PRIVATE(tag) != MBEDTLS_ASN1_OCTET_STRING) + if (skid.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING) return 1; - buf->ns.len = (int)skid.MBEDTLS_PRIVATE(len); + buf->ns.len = (int)skid.MBEDTLS_PRIVATE_V30_ONLY(len); if (len < (size_t)buf->ns.len) return -1; - memcpy(buf->ns.name, skid.MBEDTLS_PRIVATE(p), (size_t)buf->ns.len); + memcpy(buf->ns.name, skid.MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len); break; default: return -1; @@ -379,7 +379,7 @@ int lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, const char *curves, int rsa_min_bits) { - int kt = (int)mbedtls_pk_get_type(&x509->cert.MBEDTLS_PRIVATE(pk)), + int kt = (int)mbedtls_pk_get_type(&x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk)), n, count = 0, ret = -1; mbedtls_rsa_context *rsactx; mbedtls_ecp_keypair *ecpctx; @@ -391,7 +391,7 @@ lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, case MBEDTLS_PK_RSA: lwsl_notice("%s: RSA key\n", __func__); jwk->kty = LWS_GENCRYPTO_KTY_RSA; - rsactx = mbedtls_pk_rsa(x509->cert.MBEDTLS_PRIVATE(pk)); + rsactx = mbedtls_pk_rsa(x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk)); mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = &rsactx->MBEDTLS_PRIVATE(E); mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = &rsactx->MBEDTLS_PRIVATE(N); @@ -409,7 +409,7 @@ lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, case MBEDTLS_PK_ECKEY: lwsl_notice("%s: EC key\n", __func__); jwk->kty = LWS_GENCRYPTO_KTY_EC; - ecpctx = mbedtls_pk_ec(x509->cert.MBEDTLS_PRIVATE(pk)); + ecpctx = mbedtls_pk_ec(x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk)); mpi[LWS_GENCRYPTO_EC_KEYEL_X] = &ecpctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X); mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->MBEDTLS_PRIVATE(d); mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = &ecpctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y); diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index 0faf0d713e..db63d09586 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -499,14 +499,13 @@ void ssl_pm_set_fd(SSL *ssl, int fd, int mode) { struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm; - ssl_pm->fd.MBEDTLS_PRIVATE(fd) = fd; + ssl_pm->fd.MBEDTLS_PRIVATE_V30_ONLY(fd) = fd; } int ssl_pm_get_fd(const SSL *ssl, int mode) { struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm; - - return ssl_pm->fd.MBEDTLS_PRIVATE(fd); + return ssl_pm->fd.MBEDTLS_PRIVATE_V30_ONLY(fd); } OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl) From 2cf7e0f4ec7df46209456fff21f5fa6685fca01c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 23 Feb 2022 14:50:49 +0000 Subject: [PATCH 118/275] coverity: 2021-12-1 uplevel fixes --- lib/cose/cose_sign.c | 19 +++++++++++++------ plugins/ssh-base/sshd.c | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/cose/cose_sign.c b/lib/cose/cose_sign.c index d7ae64f3d2..7c624de59d 100644 --- a/lib/cose/cose_sign.c +++ b/lib/cose/cose_sign.c @@ -209,9 +209,12 @@ lws_cose_sign_payload_chunk(struct lws_cose_sign_context *csc, lws_lec_init(&lec, lbuf, sizeof(lbuf)); - /* we know it will fit */ - lws_lec_printf(&lec, "{1:%lld}", + /* we know it will fit... but coverity doesn't */ + ret = lws_lec_printf(&lec, "{1:%lld}", (long long)alg->cose_alg); + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; + lws_lec_scratch(&lec); if (!csc->subsequent) { @@ -293,9 +296,11 @@ lws_cose_sign_payload_chunk(struct lws_cose_sign_context *csc, lws_lec_init(&lec, lbuf, sizeof(lbuf)); - /* we know it will fit */ - lws_lec_printf(&lec, "{1:%lld}", + /* we know it will fit... but coverity doesn't... */ + ret = lws_lec_printf(&lec, "{1:%lld}", (long long)alg->cose_alg); + if (ret != LWS_LECPCTX_RET_FINISHED) + return ret; lws_lec_init(&lec1, lb, sizeof(lb)); lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, @@ -454,8 +459,10 @@ lws_cose_sign_payload_chunk(struct lws_cose_sign_context *csc, lws_lec_init(&lec1, lb, sizeof(lb)); lws_lec_int(&lec1, LWS_CBOR_MAJTYP_BSTR, 0, lec.used); - lws_lec_printf(csc->info.lec, "{1:%lld}", - (long long)csc->alg->cose_alg); + if (lws_lec_printf(csc->info.lec, "{1:%lld}", + (long long)csc->alg->cose_alg) != LWS_LECPCTX_RET_FINISHED) + /* coverity */ + return 0; break; default: lec.used = 0; diff --git a/plugins/ssh-base/sshd.c b/plugins/ssh-base/sshd.c index 90fa3d7271..cab174f6b2 100644 --- a/plugins/ssh-base/sshd.c +++ b/plugins/ssh-base/sshd.c @@ -2014,7 +2014,7 @@ lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason, const struct lws_protocol_vhost_options *pvo; const struct lws_protocols *prot; struct lws_ssh_channel *ch; - char lang[10]; + char lang[10] = ""; int n, m, o; /* From 8782a47a05ab7ba8711e4b9d1d40415823c19fe3 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 23 Feb 2022 20:32:53 +0000 Subject: [PATCH 119/275] gcc12: fix potential test app string overflow --- test-apps/test-client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-apps/test-client.c b/test-apps/test-client.c index 640fa8a0ad..afed493f9e 100644 --- a/test-apps/test-client.c +++ b/test-apps/test-client.c @@ -125,7 +125,7 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, #endif #endif const char *which = "http"; - char which_wsi[10], buf[50 + LWS_PRE]; + char which_wsi[20], buf[50 + LWS_PRE]; int n; switch (reason) { From b92391050d8d62e0c9bc3c76574cdced5669143c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 24 Feb 2022 08:08:48 +0000 Subject: [PATCH 120/275] esp32: heltec: change delay Newer esp-idf has lost ets-delay-us --- .../embedded/esp32/esp-heltec-wb32/main/devices.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c index a4dab2a04b..da7cbe9c6c 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c @@ -31,7 +31,10 @@ lws_netdev_instance_wifi_t *wnd; static void esp32_i2c_delay(void) { - ets_delay_us(1); + volatile int n = 0; + + while (n < 20) + n++; } static const lws_bb_i2c_t li2c = { From db5f574b03fcbb387dbd4fc4bf5fe527fff6e752 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 1 Mar 2022 11:42:58 +0000 Subject: [PATCH 121/275] nsc: fall back to internal headers when no stash --- lib/roles/http/cookie.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/roles/http/cookie.c b/lib/roles/http/cookie.c index 03b88ae0bd..1860e87de3 100644 --- a/lib/roles/http/cookie.c +++ b/lib/roles/http/cookie.c @@ -281,6 +281,7 @@ static int lws_cookie_write_nsc(struct lws *wsi, struct lws_cookie *c) { char cache_name[LWS_COOKIE_MAX_CACHE_NAME_LEN]; + const char *ads, *path; struct lws_cache_ttl_lru *l1; struct client_info_stash *stash; char *cookie_string = NULL, *dl; @@ -297,11 +298,16 @@ lws_cookie_write_nsc(struct lws *wsi, struct lws_cookie *c) return -1; stash = wsi->stash ? wsi->stash : lws_get_network_wsi(wsi)->stash; - if (!stash || !stash->cis[CIS_ADDRESS] || - !stash->cis[CIS_PATH]) + if (stash) { + ads = stash->cis[CIS_ADDRESS]; + path = stash->cis[CIS_PATH]; + } else { + ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS); + path = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI); + } + if (!ads || !path) return -1; - if (!c->f[CE_NAME] || !c->f[CE_VALUE]) { lwsl_err("%s: malformed c\n", __func__); @@ -320,13 +326,13 @@ lws_cookie_write_nsc(struct lws *wsi, struct lws_cookie *c) if (!c->f[CE_DOMAIN]) { c->f[CE_HOSTONLY] = "T"; c->l[CE_HOSTONLY] = 1; - c->f[CE_DOMAIN] = stash->cis[CIS_ADDRESS]; - c->l[CE_DOMAIN] = strlen(c->f[CE_DOMAIN]); + c->f[CE_DOMAIN] = ads; + c->l[CE_DOMAIN] = strlen(ads); } if (!c->f[CE_PATH]) { - c->f[CE_PATH] = stash->cis[CIS_PATH]; - c->l[CE_PATH] = strlen(c->f[CE_PATH]); + c->f[CE_PATH] = path; + c->l[CE_PATH] = strlen(path); dl = memchr(c->f[CE_PATH], '?', c->l[CE_PATH]); if (dl) c->l[CE_PATH] = (size_t)(dl - c->f[CE_PATH]); From 69e1507c8c779cd03406947cdcc2e25f82e4e915 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 6 Mar 2022 15:56:24 +0000 Subject: [PATCH 122/275] logs: freertos adds free heap to all logs --- lib/core/logs.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/core/logs.c b/lib/core/logs.c index d58de0df0e..27b7b9fa1c 100644 --- a/lib/core/logs.c +++ b/lib/core/logs.c @@ -242,6 +242,16 @@ lwsl_timestamp(int level, char *p, size_t len) n = lws_snprintf(p, len, "[%llu:%04d] %c: ", (unsigned long long) now / 10000, (int)(now % 10000), log_level_names[n]); + +#if defined(LWS_PLAT_FREERTOS) + n += lws_snprintf(p + n, len - n, "%6u: ", +#if defined(LWS_AMAZON_RTOS) + (unsigned int)xPortGetFreeHeapSize()); +#else + (unsigned int)esp_get_free_heap_size()); +#endif +#endif + return n; } #else From f8e3d0911343071f227ecd424d3591b13bbec3a8 Mon Sep 17 00:00:00 2001 From: Max Lehn Date: Tue, 8 Mar 2022 15:55:21 +0100 Subject: [PATCH 123/275] cmake: fix FindOpenSSLbins error when no OpenSSL executable found This fixes CMake error "mode MATCH needs at least 5 arguments total to command" while configuring when no OpenSSL executable was found. Tested under Windows using VS2019. --- cmake/FindOpenSSLbins.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindOpenSSLbins.cmake b/cmake/FindOpenSSLbins.cmake index 3f32994a06..3d791f463e 100644 --- a/cmake/FindOpenSSLbins.cmake +++ b/cmake/FindOpenSSLbins.cmake @@ -44,7 +44,7 @@ if(OPENSSL_FOUND) get_filename_component(OPENSSL_EXECUTABLE_PATH ${OPENSSL_EXECUTABLE} DIRECTORY) message(VERBOSE "OPENSSL_EXECUTABLE_PATH=${OPENSSL_EXECUTABLE_PATH}") set(OPENSSL_EXECUTABLE_BIN_PATH "") - string(REGEX MATCH "^(.*)/tools/openssl$" REGEX_MATCH ${OPENSSL_EXECUTABLE_PATH}) + string(REGEX MATCH "^(.*)/tools/openssl$" REGEX_MATCH "${OPENSSL_EXECUTABLE_PATH}") message(DEBUG "REGEX_MATCH=\"${REGEX_MATCH}\"") message(DEBUG "CMAKE_MATCH_1=\"${CMAKE_MATCH_1}\"") if (NOT ${REGEX_MATCH} EQUAL "") From 995a7591846f68dc6155d2362ff83c1590dad07b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 10 Mar 2022 04:57:58 +0000 Subject: [PATCH 124/275] h1: remove assert on unexpected POLLIN state just hangup --- lib/roles/h1/ops-h1.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c index b21b69e4b7..769490fe7e 100644 --- a/lib/roles/h1/ops-h1.c +++ b/lib/roles/h1/ops-h1.c @@ -297,7 +297,6 @@ lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len) default: lwsl_err("%s: Unhandled state %d\n", __func__, lwsi_state(wsi)); - assert(0); goto bail; } From 02f7e06776906ac339b57e0a679ee0d8eebfa15a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 14 Mar 2022 09:48:23 +0000 Subject: [PATCH 125/275] sul: add clear advice for zombie suls --- lib/core-net/sorted-usec-list.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/core-net/sorted-usec-list.c b/lib/core-net/sorted-usec-list.c index e9b9c1f6b0..d9af0f1185 100644 --- a/lib/core-net/sorted-usec-list.c +++ b/lib/core-net/sorted-usec-list.c @@ -146,6 +146,12 @@ __lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow) /* his moment has come... remove him from his owning list */ + if (!hit->cb) { + lwsl_err("%s: sul with NULL callback (did not cancel on destory?)\n", __func__); + + return 0; + } + lws_dll2_remove(&hit->list); hit->us = 0; From 3d98e29518b1e7d28ecca1a0e492be4ceff75cfa Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 25 Jan 2022 19:31:36 +0000 Subject: [PATCH 126/275] raw: tls conns Raw + tls needs a little extra handling during connect. --- lib/roles/raw-skt/ops-raw-skt.c | 74 +++++- .../raw/minimal-raw-client/CMakeLists.txt | 23 ++ .../raw/minimal-raw-client/main.c | 214 ++++++++++++++++++ 3 files changed, 306 insertions(+), 5 deletions(-) create mode 100644 minimal-examples-lowlevel/raw/minimal-raw-client/CMakeLists.txt create mode 100644 minimal-examples-lowlevel/raw/minimal-raw-client/main.c diff --git a/lib/roles/raw-skt/ops-raw-skt.c b/lib/roles/raw-skt/ops-raw-skt.c index fd4fd341a2..453c64e75f 100644 --- a/lib/roles/raw-skt/ops-raw-skt.c +++ b/lib/roles/raw-skt/ops-raw-skt.c @@ -24,6 +24,57 @@ #include +#if defined(LWS_WITH_CLIENT) +static int +lws_raw_skt_connect(struct lws *wsi) +{ + int n; +#if defined(LWS_WITH_TLS) + const char *cce = NULL; + char ccebuf[128]; + +#if !defined(LWS_WITH_SYS_ASYNC_DNS) + switch (lws_client_create_tls(wsi, &cce, 1)) { +#else + switch (lws_client_create_tls(wsi, &cce, 0)) { +#endif + case CCTLS_RETURN_ERROR: + lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); + return -1; + case CCTLS_RETURN_RETRY: + return 0; + case CCTLS_RETURN_DONE: + break; + } + + if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { + n = lws_ssl_client_connect2(wsi, ccebuf, sizeof(ccebuf)); + if (n < 0) { + lws_inform_client_conn_fail(wsi, (void *)ccebuf, + strlen(ccebuf)); + + return -1; + } + if (n != 1) + return 0; /* wait */ + } +#endif + + n = user_callback_handle_rxflow(wsi->a.protocol->callback, + wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)], + wsi->user_space, NULL, 0); + if (n) { + lws_inform_client_conn_fail(wsi, (void *)"user", 4); + return 1; + } + + lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); + lwsi_set_state(wsi, LRS_ESTABLISHED); + + return 1; /* success */ +} +#endif + static int rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, struct lws_pollfd *pollfd) @@ -82,6 +133,14 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, case LRS_WAITING_CONNECT: goto nope; + case LRS_WAITING_SSL: +#if defined(LWS_WITH_CLIENT) + n = lws_raw_skt_connect(wsi); + if (n < 0) + goto fail; +#endif + break; + #if defined(LWS_WITH_SOCKS5) /* SOCKS Greeting Reply */ @@ -177,16 +236,21 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, return LWS_HPI_RET_HANDLED; #if defined(LWS_WITH_CLIENT) - if (lwsi_state(wsi) == LRS_WAITING_CONNECT && - !lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL)) + if (lwsi_state(wsi) == LRS_WAITING_CONNECT) { + if (!lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL)) return LWS_HPI_RET_WSI_ALREADY_DIED; + + if (lws_raw_skt_connect(wsi) < 0) + goto fail; + } #endif + if (lwsi_state(wsi) == LRS_WAITING_SSL) + return LWS_HPI_RET_HANDLED; + /* one shot */ - if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { - lwsl_notice("%s a\n", __func__); + if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) goto fail; - } /* clear back-to-back write detection */ wsi->could_have_pending = 0; diff --git a/minimal-examples-lowlevel/raw/minimal-raw-client/CMakeLists.txt b/minimal-examples-lowlevel/raw/minimal-raw-client/CMakeLists.txt new file mode 100644 index 0000000000..4ff5c55ca7 --- /dev/null +++ b/minimal-examples-lowlevel/raw/minimal-raw-client/CMakeLists.txt @@ -0,0 +1,23 @@ +project(lws-minimal-raw-client C) +cmake_minimum_required(VERSION 2.8.12) +find_package(libwebsockets CONFIG REQUIRED) +list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) +include(CheckCSourceCompiles) +include(LwsCheckRequirements) + +set(SAMP lws-minimal-raw-client) +set(SRCS main.c) + +set(requirements 1) +require_lws_config(LWS_WITH_CLIENT 1 requirements) + +if (requirements) + add_executable(${SAMP} ${SRCS}) + + if (websockets_shared) + target_link_libraries(${SAMP} websockets_shared ${LIBWEBSOCKETS_DEP_LIBS}) + add_dependencies(${SAMP} websockets_shared) + else() + target_link_libraries(${SAMP} websockets ${LIBWEBSOCKETS_DEP_LIBS}) + endif() +endif() diff --git a/minimal-examples-lowlevel/raw/minimal-raw-client/main.c b/minimal-examples-lowlevel/raw/minimal-raw-client/main.c new file mode 100644 index 0000000000..db18a99eb2 --- /dev/null +++ b/minimal-examples-lowlevel/raw/minimal-raw-client/main.c @@ -0,0 +1,214 @@ +/* + * lws-minimal-raw-client + * + * Written in 2010-2022 by Andy Green + * + * This file is made available under the Creative Commons CC0 1.0 + * Universal Public Domain Dedication. + * + * This demonstrates connecting a "raw" client connection + */ + +#include +#include +#include +#if !defined(WIN32) +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#if !defined(WIN32) +#include +#endif +#include + +#include + +static struct lws *raw_wsi, *stdin_wsi; +static uint8_t buf[LWS_PRE + 4096]; +static int waiting, interrupted; +static struct lws_context *context; +static int us_wait_after_input_close = LWS_USEC_PER_SEC / 10; + +static const char *server = "libwebsockets.org", *port = "443"; + +static int +callback_raw_test(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + const char *cp = (const char *)in; + + switch (reason) { + + /* callbacks related to file descriptor */ + + case LWS_CALLBACK_RAW_ADOPT_FILE: + lwsl_user("LWS_CALLBACK_RAW_ADOPT_FILE\n"); + break; + + case LWS_CALLBACK_RAW_CLOSE_FILE: + lwsl_user("LWS_CALLBACK_RAW_CLOSE_FILE\n"); + /* stdin close, wait 1s then close the raw skt */ + stdin_wsi = NULL; /* invalid now we close */ + if (raw_wsi) + lws_set_timer_usecs(raw_wsi, us_wait_after_input_close); + else { + interrupted = 1; + lws_cancel_service(context); + } + break; + + case LWS_CALLBACK_RAW_RX_FILE: + lwsl_user("LWS_CALLBACK_RAW_RX_FILE\n"); + waiting = (int)read(0, buf, sizeof(buf)); + lwsl_notice("raw file read %d\n", waiting); + if (waiting < 0) + return -1; + + if (raw_wsi) + lws_callback_on_writable(raw_wsi); + lws_rx_flow_control(wsi, 0); + break; + + + /* callbacks related to raw socket descriptor */ + + case LWS_CALLBACK_RAW_ADOPT: + lwsl_user("LWS_CALLBACK_RAW_ADOPT\n"); + lws_callback_on_writable(wsi); + break; + + case LWS_CALLBACK_RAW_CONNECTED: + lwsl_user("LWS_CALLBACK_RAW_CONNECTED\n"); + break; + + case LWS_CALLBACK_RAW_CLOSE: + lwsl_user("LWS_CALLBACK_RAW_CLOSE\n"); + /* + * If the socket to the remote server closed, we must close + * and drop any remaining stdin + */ + interrupted = 1; + lws_cancel_service(context); + /* our pointer to this wsi is invalid now we close */ + raw_wsi = NULL; + break; + + case LWS_CALLBACK_RAW_RX: + lwsl_user("LWS_CALLBACK_RAW_RX (%d)\n", (int)len); + while (len--) + putchar(*cp++); + fflush(stdout); + break; + + case LWS_CALLBACK_RAW_WRITEABLE: + lwsl_user("LWS_CALLBACK_RAW_WRITEABLE\n"); + // lwsl_hexdump_info(buf, waiting); + if (!waiting) + break; + if (stdin_wsi) + lws_rx_flow_control(stdin_wsi, 1); + if (lws_write(wsi, buf, (unsigned int)waiting, LWS_WRITE_RAW) != waiting) { + lwsl_notice("%s: raw skt write failed\n", __func__); + + return -1; + } + break; + + case LWS_CALLBACK_TIMER: + lwsl_user("LWS_CALLBACK_TIMER\n"); + interrupted = 1; + lws_cancel_service(context); + return -1; + + default: + break; + } + + return 0; +} + +static struct lws_protocols protocols[] = { + { "raw-test", callback_raw_test, 0, 0, 0, NULL, 0 }, + LWS_PROTOCOL_LIST_TERM +}; + +static int +system_notify_cb(lws_state_manager_t *mgr, lws_state_notify_link_t *link, + int current, int target) +{ + struct lws_client_connect_info i; + + if (current != LWS_SYSTATE_OPERATIONAL || + target != LWS_SYSTATE_OPERATIONAL) + return 0; + + memset(&i, 0, sizeof i); + i.context = context; + i.method = "RAW"; + i.ssl_connection = LCCSCF_USE_SSL; + i.alpn = "http/1.1"; + i.address = server; + i.host = server; + i.port = atoi(port); + i.local_protocol_name = "raw-test"; + + waiting = lws_snprintf((char *)buf, sizeof(buf), "GET / HTTP/1.1\xaHost: libwebsockets.org\xa\xa"); + + if (!lws_client_connect_via_info(&i)) { + lwsl_err("Client creation failed\n"); + interrupted = 1; + } + + return 0; +} + +void sigint_handler(int sig) +{ + interrupted = 1; +} + +int main(int argc, const char **argv) +{ + struct lws_context_creation_info info; + const char *p; + int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; + lws_state_notify_link_t notifier = { { NULL, NULL, NULL }, + system_notify_cb, "app" }; + lws_state_notify_link_t *na[] = { ¬ifier, NULL }; + + signal(SIGINT, sigint_handler); + + if ((p = lws_cmdline_option(argc, argv, "-d"))) + logs = atoi(p); + + lws_set_log_level(logs, NULL); + lwsl_user("LWS minimal raw client\n"); + + memset(&info, 0, sizeof info); + + info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.port = CONTEXT_PORT_NO_LISTEN_SERVER; + info.protocols = protocols; + info.register_notifier_list = na; + + context = lws_create_context(&info); + if (!context) { + lwsl_err("lws init failed\n"); + return 1; + } + + while (n >= 0 && !interrupted) + n = lws_service(context, 0); + + lwsl_user("%s: destroying context\n", __func__); + + lws_context_destroy(context); + + return 0; +} From e5d73be53d028a0cf86414f2d896a798163e3792 Mon Sep 17 00:00:00 2001 From: apcui Date: Sat, 2 Apr 2022 09:26:31 +0100 Subject: [PATCH 127/275] windows: avoid NULL addr on connect check https://github.com/warmcat/libwebsockets/issues/2596 --- lib/core-net/client/connect3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core-net/client/connect3.c b/lib/core-net/client/connect3.c index a31021659d..a1d7fd1174 100644 --- a/lib/core-net/client/connect3.c +++ b/lib/core-net/client/connect3.c @@ -103,7 +103,7 @@ lws_client_connect_check(struct lws *wsi) #else - if (!connect(wsi->desc.sockfd, NULL, 0)) + if (!connect(wsi->desc.sockfd, (const struct sockaddr *)&wsi->sa46_peer.sa4, 0)) return LCCCR_CONNECTED; en = LWS_ERRNO; From 10044198c563e992c5f621b7336056dc56bce6b9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 3 Apr 2022 09:03:10 +0100 Subject: [PATCH 128/275] logs: use finegrained level test on unix-sockets.c --- lib/plat/unix/unix-sockets.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index 0f5bf4b93e..2c1b9569c8 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -216,7 +216,7 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) { int optval = (int)pri, ret = 0, n; socklen_t optlen = sizeof(optval); -#if !defined(LWS_WITH_NO_LOGS) +#if (_LWS_ENABLED_LOGS & LLL_WARN) int en; #endif @@ -244,7 +244,7 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) if (pri) { /* 0 is the default already */ if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (const void *)&optval, optlen) < 0) { -#if !defined(LWS_WITH_NO_LOGS) +#if (_LWS_ENABLED_LOGS & LLL_WARN) en = errno; lwsl_warn("%s: unable to set socket pri %d: errno %d\n", __func__, (int)pri, en); From a7f2e298814d313ad53d33507e68322fe28eb316 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Fri, 15 Oct 2021 09:46:21 -0400 Subject: [PATCH 129/275] client: connect report actual socket error to user callback rather than EINPROGRESS https://github.com/warmcat/libwebsockets/pull/2452 --- lib/core-net/client/connect3.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/core-net/client/connect3.c b/lib/core-net/client/connect3.c index a1d7fd1174..b7523303d7 100644 --- a/lib/core-net/client/connect3.c +++ b/lib/core-net/client/connect3.c @@ -71,7 +71,7 @@ typedef enum { } lcccr_t; static lcccr_t -lws_client_connect_check(struct lws *wsi) +lws_client_connect_check(struct lws *wsi, int *real_errno) { int en = 0; #if !defined(WIN32) @@ -98,6 +98,8 @@ lws_client_connect_check(struct lws *wsi) lwsl_wsi_notice(wsi, "getsockopt fd %d says e %d", wsi->desc.sockfd, e); + *real_errno = e; + return LCCCR_FAILED; } @@ -125,7 +127,8 @@ lws_client_connect_check(struct lws *wsi) } #endif - lwsl_wsi_notice(wsi, "connect check take as FAILED: errno %d", en); + lwsl_wsi_notice(wsi, "connect check FAILED: %d", + *real_errno || en); return LCCCR_FAILED; } @@ -231,7 +234,15 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, /* no dns results and no ongoing timeout for one */ goto connect_to; - switch (lws_client_connect_check(wsi)) { + /* + * If the connection failed, the OS-level errno may be + * something like EINPROGRESS rather than the actual problem + * that prevented a connection. This value will represent the + * “real” problem that we should report to the caller. + */ + int real_errno = 0; + + switch (lws_client_connect_check(wsi, &real_errno)) { case LCCCR_CONNECTED: /* * Oh, it has happened... @@ -240,8 +251,11 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, case LCCCR_CONTINUE: return NULL; default: - lws_snprintf(dcce, sizeof(dcce), "conn fail: errno %d", - LWS_ERRNO); + if (!real_errno) + real_errno = LWS_ERRNO; + lws_snprintf(dcce, sizeof(dcce), "conn fail: %d", + real_errno); + cce = dcce; lwsl_wsi_debug(wsi, "%s", dcce); lws_metrics_caliper_report(wsi->cal_conn, METRES_NOGO); From 3268db0ae87bbec13976fc6ff42c998f0498b8d1 Mon Sep 17 00:00:00 2001 From: Scott Rankin Date: Tue, 5 Apr 2022 05:54:29 +0100 Subject: [PATCH 130/275] cmake: msvc: avoid having to use both preprocessor flags https://github.com/warmcat/libwebsockets/issues/2600 --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4cd2949c3..d56ee920b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -849,7 +849,11 @@ if (MSVC) # Fail the build if any warnings add_compile_options(/W3 /WX) # Unbreak MSVC broken preprocessor __VA_ARGS__ behaviour - add_compile_options(/Zc:preprocessor /experimental:preprocessor /wd5105) + if (MSVC_VERSION GREATER 1925) + add_compile_options(/Zc:preprocessor /wd5105) + else() + add_compile_options(/experimental:preprocessor /wd5105) + endif() endif(MSVC) if (MINGW) From ec81f538be8c851a422109dc19079d482df3d7f3 Mon Sep 17 00:00:00 2001 From: wayneonway <121931005@qq.com> Date: Wed, 6 Apr 2022 14:54:01 +0800 Subject: [PATCH 131/275] netlink: route handling checks for SRC when it means DST https://github.com/warmcat/libwebsockets/issues/2603 --- lib/core-net/private-lib-core-net.h | 1 + lib/core-net/route.c | 2 +- lib/roles/netlink/ops-netlink.c | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index c515c10d5b..4fb99cdf7b 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -1375,6 +1375,7 @@ _lws_routing_table_dump(struct lws_context *cx); #define LRR_IGNORE_PRI (1 << 0) #define LRR_MATCH_SRC (1 << 1) +#define LRR_MATCH_DST (1 << 2) lws_route_t * _lws_route_remove(struct lws_context_per_thread *pt, lws_route_t *robj, int flags); diff --git a/lib/core-net/route.c b/lib/core-net/route.c index 14f4beb07e..c9fdc2ba29 100644 --- a/lib/core-net/route.c +++ b/lib/core-net/route.c @@ -146,7 +146,7 @@ _lws_route_remove(struct lws_context_per_thread *pt, lws_route_t *robj, int flag lws_route_t *rou = lws_container_of(d, lws_route_t, list); if ((!(flags & LRR_MATCH_SRC) || !lws_sa46_compare_ads(&robj->src, &rou->src)) && - ((flags & LRR_MATCH_SRC) || !lws_sa46_compare_ads(&robj->dest, &rou->dest)) && + (!(flags & LRR_MATCH_DST) || !lws_sa46_compare_ads(&robj->dest, &rou->dest)) && (!robj->gateway.sa4.sin_family || !lws_sa46_compare_ads(&robj->gateway, &rou->gateway)) && robj->dest_len <= rou->dest_len && diff --git a/lib/roles/netlink/ops-netlink.c b/lib/roles/netlink/ops-netlink.c index 846a974330..fa3bf29a2f 100644 --- a/lib/roles/netlink/ops-netlink.c +++ b/lib/roles/netlink/ops-netlink.c @@ -371,8 +371,8 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi, lws_pt_lock(pt, __func__); /* returns zero on match already in table */ - rmat = _lws_route_remove(pt, &robj, LRR_MATCH_SRC | - LRR_IGNORE_PRI); + rmat = _lws_route_remove(pt, &robj, h->nlmsg_type == RTM_NEWROUTE ? + LRR_MATCH_DST : LRR_MATCH_SRC | LRR_IGNORE_PRI); lws_pt_unlock(pt); if (rmat) { From 88a400515f6a35d09c5ede99f0901645680cbf63 Mon Sep 17 00:00:00 2001 From: Per Bothner Date: Sun, 10 Apr 2022 09:55:44 +0100 Subject: [PATCH 132/275] docs: fix typo --- include/libwebsockets/lws-http.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/libwebsockets/lws-http.h b/include/libwebsockets/lws-http.h index 2c5bd64dce..8576758950 100644 --- a/include/libwebsockets/lws-http.h +++ b/include/libwebsockets/lws-http.h @@ -534,8 +534,6 @@ lws_hdr_custom_name_foreach(struct lws *wsi, lws_hdr_custom_fe_cb_t cb, void *op * * Use this in place of lws_get_urlarg_by_name() that does not return an * explicit length. - * - * Use lws_get_urlarg_by_name_safe() instead of this, which returns the length. */ LWS_VISIBLE LWS_EXTERN int lws_get_urlarg_by_name_safe(struct lws *wsi, const char *name, char *buf, int len); From cad13a88645d41b45452550f4bad5c8947331ee7 Mon Sep 17 00:00:00 2001 From: orefkov Date: Mon, 11 Apr 2022 06:04:40 +0100 Subject: [PATCH 133/275] acme: update for v2 https://github.com/warmcat/libwebsockets/issues/2609 AG: api logging updates --- lib/tls/tls-server.c | 4 +- .../acme-client/protocol_lws_acme_client.c | 238 ++++++++---------- 2 files changed, 110 insertions(+), 132 deletions(-) diff --git a/lib/tls/tls-server.c b/lib/tls/tls-server.c index dbb517834b..05055f7ec0 100644 --- a/lib/tls/tls-server.c +++ b/lib/tls/tls-server.c @@ -113,12 +113,12 @@ lws_context_init_server_ssl(const struct lws_context_creation_info *info, if (vhost->tls.use_ssl) lws_context_init_alpn(vhost); - /* check certs once a day */ + /* check certs in a few seconds (after protocol init) and then once a day */ context->pt[0].sul_tls.cb = lws_sul_tls_cb; __lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], &context->pt[0].sul_tls, - (lws_usec_t)24 * 3600 * LWS_US_PER_SEC); + (lws_usec_t)5 * LWS_US_PER_SEC); return 0; } diff --git a/plugins/acme-client/protocol_lws_acme_client.c b/plugins/acme-client/protocol_lws_acme_client.c index d202085b95..f6be2b012e 100644 --- a/plugins/acme-client/protocol_lws_acme_client.c +++ b/plugins/acme-client/protocol_lws_acme_client.c @@ -1,7 +1,7 @@ /* * libwebsockets ACME client protocol plugin * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2022 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -21,16 +21,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * - * Acme is in a big messy transition at the moment from a homebrewed api - * to an IETF one. The old repo for the homebrew api (they currently - * implement) is marked up as deprecated and "not accurate[ly] reflect[ing]" - * what they implement, but the IETF standard, currently at v7 is not yet - * implemented at let's encrypt (ETA Jan 2018). - * * This implementation follows draft 7 of the IETF standard, and falls back - * to whatever differences exist for Boulder's tls-sni-01 challenge. The - * tls-sni-02 support is there but nothing to test it against at the time of - * writing (Nov 1 2017). + * to whatever differences exist for Boulder's tls-sni-01 challenge. + * tls-sni-02 is also supported. */ #if !defined (LWS_PLUGIN_STATIC) @@ -148,11 +141,11 @@ callback_chall_http01(struct lws *wsi, enum lws_callback_reasons reason, switch (reason) { case LWS_CALLBACK_HTTP: - lwsl_notice("%s: ca connection received, key_auth %s\n", - __func__, ac->key_auth); + lwsl_wsi_notice(wsi, "CA connection received, key_auth %s", + ac->key_auth); if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) { - lwsl_notice("%s: add status failed\n", __func__); + lwsl_wsi_warn(wsi, "add status failed"); return -1; } @@ -160,14 +153,13 @@ callback_chall_http01(struct lws *wsi, enum lws_callback_reasons reason, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"text/plain", 10, &p, end)) { - lwsl_notice("%s: add content_type failed\n", __func__); + lwsl_wsi_warn(wsi, "add content_type failed"); return -1; } n = (int)strlen(ac->key_auth); if (lws_add_http_header_content_length(wsi, (lws_filepos_t)n, &p, end)) { - lwsl_notice("%s: add content_length failed\n", - __func__); + lwsl_wsi_warn(wsi, "add content_length failed"); return -1; } @@ -175,13 +167,12 @@ callback_chall_http01(struct lws *wsi, enum lws_callback_reasons reason, WSI_TOKEN_HTTP_CONTENT_DISPOSITION, (unsigned char *)"attachment", 10, &p, end)) { - lwsl_notice("%s: add content_dispo failed\n", __func__); + lwsl_wsi_warn(wsi, "add content_dispo failed"); return -1; } if (lws_finalize_write_http_header(wsi, start, &p, end)) { - lwsl_notice("%s: finalize http header failed\n", - __func__); + lwsl_wsi_warn(wsi, "finalize http header failed"); return -1; } @@ -190,10 +181,10 @@ callback_chall_http01(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_HTTP_WRITEABLE: p += lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "%s", ac->key_auth); - lwsl_notice("%s: len %d\n", __func__, lws_ptr_diff(p, start)); + // lwsl_notice("%s: len %d\n", __func__, lws_ptr_diff(p, start)); if (lws_write(wsi, (uint8_t *)start, lws_ptr_diff_size_t(p, start), LWS_WRITE_HTTP_FINAL) != lws_ptr_diff(p, start)) { - lwsl_err("_write content failed\n"); + lwsl_wsi_err(wsi, "_write content failed"); return 1; } @@ -234,7 +225,7 @@ jws_create_packet(struct lws_jwe *jwe, const char *payload, size_t len, n = LWS_PRE + 2048; buf = malloc((unsigned int)n); if (!buf) { - lwsl_notice("%s: malloc %d failed\n", __func__, n); + lwsl_warn("%s: malloc %d failed\n", __func__, n); return -1; } @@ -680,14 +671,14 @@ lws_acme_load_create_auth_keys(struct per_vhost_data__lws_acme_client *vhd, n = lws_genrsa_new_keypair(vhd->context, &vhd->rsactx, LGRSAM_PKCS1_1_5, vhd->jwk.e, bits); if (n) { - lwsl_notice("failed to create keypair\n"); + lwsl_vhost_warn(vhd->vhost, "failed to create keypair"); return 1; } lwsl_notice("...keypair generated\n"); if (lws_jwk_save(&vhd->jwk, vhd->pvop[LWS_TLS_SET_AUTH_PATH])) { - lwsl_notice("unable to save %s\n", + lwsl_vhost_warn(vhd->vhost, "unable to save %s", vhd->pvop[LWS_TLS_SET_AUTH_PATH]); return 1; } @@ -709,8 +700,8 @@ lws_acme_start_acquisition(struct per_vhost_data__lws_acme_client *vhd, /* * ...well... we should try to do something about it then... */ - lwsl_notice("%s: ACME cert needs creating / updating: " - "vhost %s\n", __func__, lws_get_vhost_name(vhd->vhost)); + lwsl_vhost_notice(vhd->vhost, "ACME cert needs creating / updating: " + "vhost %s", lws_get_vhost_name(vhd->vhost)); vhd->ac = malloc(sizeof(*vhd->ac)); memset(vhd->ac, 0, sizeof(*vhd->ac)); @@ -795,11 +786,13 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, switch ((int)reason) { case LWS_CALLBACK_PROTOCOL_INIT: + if (vhd) + return 0; vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), lws_get_protocol(wsi), sizeof(struct per_vhost_data__lws_acme_client)); - if (vhd) - return 0; + if (!vhd) + return -1; vhd->context = lws_get_context(wsi); vhd->protocol = lws_get_protocol(wsi); @@ -867,7 +860,12 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, vhd->pvop[LWS_TLS_SET_CERT_PATH]); vhd->fd_updated_cert = lws_open(buf, LWS_O_WRONLY | LWS_O_CREAT | - LWS_O_TRUNC, 0600); + LWS_O_TRUNC + /*do not replace \n to \r\n on Windows */ + #ifdef WIN32 + | O_BINARY + #endif + , 0600); if (vhd->fd_updated_cert < 0) { lwsl_err("unable to create update cert file %s\n", buf); return -1; @@ -875,9 +873,14 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, lws_snprintf(buf, sizeof(buf) - 1, "%s.upd", vhd->pvop[LWS_TLS_SET_KEY_PATH]); vhd->fd_updated_key = lws_open(buf, LWS_O_WRONLY | LWS_O_CREAT | - LWS_O_TRUNC, 0600); + /*do not replace \n to \r\n on Windows */ + #ifdef WIN32 + O_BINARY | + #endif + LWS_O_TRUNC, 0600); if (vhd->fd_updated_key < 0) { - lwsl_err("unable to create update key file %s\n", buf); + lwsl_vhost_err(vhd->vhost, "unable to create update key file %s", buf); + return -1; } #endif @@ -929,35 +932,18 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, * Client */ - case LWS_CALLBACK_CLIENT_ESTABLISHED: - lwsl_notice("%s: CLIENT_ESTABLISHED\n", __func__); - break; - - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - lwsl_notice("%s: CLIENT_CONNECTION_ERROR: %p\n", __func__, wsi); - break; - - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - lwsl_notice("%s: CLOSED_CLIENT_HTTP: %p\n", __func__, wsi); - break; - - case LWS_CALLBACK_CLOSED: - lwsl_notice("%s: CLOSED: %p\n", __func__, wsi); - break; - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - lwsl_notice("%s: ESTABLISHED_CLIENT_HTTP:" - "%p, state:%d, status:%d\n", __func__, wsi, - ac->state, lws_http_client_http_response(wsi)); if (!ac) break; + ac->resp = (int)lws_http_client_http_response(wsi); + /* we get a new nonce each time */ if (lws_hdr_total_length(wsi, WSI_TOKEN_REPLAY_NONCE) && lws_hdr_copy(wsi, ac->replay_nonce, sizeof(ac->replay_nonce), WSI_TOKEN_REPLAY_NONCE) < 0) { - lwsl_notice("%s: nonce too large\n", __func__); + lwsl_vhost_warn(vhd->vhost, "nonce too large"); goto failed; } @@ -967,11 +953,12 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, lejp_construct(&ac->jctx, cb_dir, vhd, jdir_tok, LWS_ARRAY_SIZE(jdir_tok)); break; + case ACME_STATE_NEW_NONCE: /* - * we try to * register our keys next. - * It's OK if it ends up * they're already registered, - * this eliminates any * gaps where we stored the key + * we try to register our keys next. + * It's OK if it ends up they're already registered, + * this eliminates any gaps where we stored the key * but registration did not complete for some reason... */ ac->state = ACME_STATE_NEW_ACCOUNT; @@ -981,8 +968,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, cwsi = lws_acme_client_connect(vhd->context, vhd->vhost, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) { - lwsl_notice("%s: failed to connect to acme\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "failed to connect to acme"); goto failed; } @@ -991,28 +977,26 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_NEW_ACCOUNT: if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_LOCATION)) { - lwsl_notice("%s: no Location\n", __func__); + lwsl_vhost_warn(vhd->vhost, "no Location"); goto failed; } if (lws_hdr_copy(wsi, ac->acct_id, sizeof(ac->acct_id), WSI_TOKEN_HTTP_LOCATION) < 0) { - lwsl_notice("%s: Location too large\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "Location too large"); goto failed; } ac->kid = ac->acct_id; - lwsl_notice("Location: %s\n", ac->acct_id); + lwsl_vhost_notice(vhd->vhost, "Location: %s", ac->acct_id); break; case ACME_STATE_NEW_ORDER: if (lws_hdr_copy(wsi, ac->order_url, sizeof(ac->order_url), WSI_TOKEN_HTTP_LOCATION) < 0) { - lwsl_notice("%s: missing cert location:\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "missing cert location"); goto failed; } @@ -1061,7 +1045,6 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, ",\"contact\": [\"mailto:%s\"]}", vhd->pvop_active[LWS_TLS_REQ_ELEMENT_EMAIL]); - puts(start); strcpy(ac->active_url, ac->urls[JAD_NEW_ACCOUNT_URL]); pkt_add_hdrs: if (lws_gencrypto_jwe_alg_to_definition("RSA1_5", @@ -1096,7 +1079,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, WSI_TOKEN_HTTP_CONTENT_TYPE, (uint8_t *)content_type, 21, pp, pend)) { - lwsl_notice("could not add content type\n"); + lwsl_vhost_warn(vhd->vhost, "could not add content type"); goto failed; } @@ -1104,7 +1087,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, (uint8_t *)buf, n, pp, pend)) { - lwsl_notice("could not add content length\n"); + lwsl_vhost_warn(vhd->vhost, "could not add content length"); goto failed; } @@ -1122,12 +1105,10 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, "}", vhd->pvop_active[LWS_TLS_REQ_ELEMENT_COMMON_NAME]); - puts(start); strcpy(ac->active_url, ac->urls[JAD_NEW_ORDER_URL]); goto pkt_add_hdrs; case ACME_STATE_AUTHZ: - puts(start); strcpy(ac->active_url, ac->authz_url); goto pkt_add_hdrs; @@ -1136,7 +1117,6 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, end = &buf[sizeof(buf) - 1]; p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{}"); - puts(start); strcpy(ac->active_url, ac->challenge_uri); goto pkt_add_hdrs; @@ -1147,7 +1127,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_POLLING_CSR: if (ac->goes_around) break; - + lwsl_vhost_notice(vhd->vhost, "Generating ACME CSR... may take a little while"); p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{\"csr\":\""); n = lws_tls_acme_sni_csr_create(vhd->context, &vhd->pvop_active[0], @@ -1155,12 +1135,11 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, &ac->alloc_privkey_pem, &ac->len_privkey_pem); if (n < 0) { - lwsl_notice("CSR generation failed\n"); + lwsl_vhost_warn(vhd->vhost, "CSR generation failed"); goto failed; } p += n; p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "\"}"); - puts(start); strcpy(ac->active_url, ac->finalize_url); goto pkt_add_hdrs; @@ -1175,7 +1154,6 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, break; case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: - lwsl_notice("LWS_CALLBACK_CLIENT_HTTP_WRITEABLE\n"); if (!ac) break; @@ -1187,7 +1165,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, if (lws_write(wsi, (uint8_t *)ac->buf + LWS_PRE, (size_t)ac->len, LWS_WRITE_HTTP_FINAL) < 0) return -1; - lwsl_notice("wrote %d\n", ac->len); + ac->pos = ac->len; lws_client_http_body_pending(wsi, 0); break; @@ -1204,28 +1182,29 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_AUTHZ: case ACME_STATE_NEW_ORDER: case ACME_STATE_DIRECTORY: - ((char *)in)[len] = '\0'; - puts(in); + m = lejp_parse(&ac->jctx, (uint8_t *)in, (int)len); if (m < 0 && m != LEJP_CONTINUE) { lwsl_notice("lejp parse failed %d\n", m); goto failed; } break; + case ACME_STATE_NEW_ACCOUNT: - ((char *)in)[len] = '\0'; - puts(in); break; + case ACME_STATE_DOWNLOAD_CERT: - ((char *)in)[len] = '\0'; - puts(in); - /* it should be the DER cert! */ - if ((unsigned int)ac->cpos + len > sizeof(ac->buf)) { - lwsl_notice("Incoming cert is too large!\n"); - goto failed; + /* + * It should be the DER cert... + * ACME 2.0 can send certs chain with 3 certs, store only first bytes + */ + if ((unsigned int)ac->cpos + len > sizeof(ac->buf)) + len = sizeof(ac->buf) - (unsigned int)ac->cpos; + + if (len) { + memcpy(&ac->buf[ac->cpos], in, len); + ac->cpos += (int)len; } - memcpy(&ac->buf[ac->cpos], in, len); - ac->cpos += (int)len; break; default: break; @@ -1234,9 +1213,9 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, /* unchunked content */ case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - lwsl_notice("%s: LWS_CALLBACK_RECEIVE_CLIENT_HTTP\n", __func__); if (!ac) return -1; + switch (ac->state) { default: { @@ -1252,7 +1231,6 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, break; case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - lwsl_notice("%s: COMPLETED_CLIENT_HTTP\n", __func__); if (!ac) return -1; @@ -1281,7 +1259,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_NEW_ACCOUNT: if ((ac->resp >= 200 && ac->resp < 299) || - ac->resp == 409) { + ac->resp == 409) { /* * Our account already existed, or exists now. * @@ -1324,8 +1302,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, vhd->vhost, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) - lwsl_notice("%s: failed to connect\n", - __func__); + lwsl_notice("%s: failed to connect\n", __func__); return -1; /* close the completed client connection */ @@ -1335,13 +1312,12 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, lws_snprintf(buf, sizeof(buf), "Auth failed: %s", ac->detail); failreason = buf; - lwsl_notice("auth failed\n"); + lwsl_vhost_warn(vhd->vhost, "auth failed"); goto failed; } - lwsl_notice("chall: %s (%d)\n", ac->chall_token, - ac->resp); + lwsl_vhost_info(vhd->vhost, "chall: %s (%d)\n", ac->chall_token, ac->resp); if (!ac->chall_token[0]) { - lwsl_notice("no challenge\n"); + lwsl_vhost_warn(vhd->vhost, "no challenge"); goto failed; } @@ -1362,7 +1338,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, if (n < 0) goto failed; - lwsl_notice("key_auth: '%s'\n", ac->key_auth); + lwsl_vhost_notice(vhd->vhost, "key_auth: '%s'", ac->key_auth); lws_snprintf(ac->http01_mountpoint, sizeof(ac->http01_mountpoint), @@ -1378,8 +1354,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, ac->ci.mounts = &ac->mount; - /* listen on the same port as the vhost that triggered - * us */ + /* listen on the same port as the vhost that triggered us */ ac->ci.port = 80; /* make ourselves protocols[0] for the new vhost */ @@ -1396,7 +1371,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, if (!ac->vhost) goto failed; - lwsl_notice("challenge_uri %s\n", ac->challenge_uri); + lwsl_vhost_notice(vhd->vhost, "challenge_uri %s", ac->challenge_uri); /* * The challenge-specific vhost is up... let the ACME @@ -1408,14 +1383,14 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, ac->challenge_uri, "POST"); if (!cwsi) { - lwsl_notice("%s: connect failed\n", __func__); + lwsl_vhost_warn(vhd->vhost, "Connect failed"); goto failed; } return -1; /* close the completed client connection */ case ACME_STATE_START_CHALL: - lwsl_notice("%s: COMPLETED start chall: %s\n", - __func__, ac->challenge_uri); + lwsl_vhost_notice(vhd->vhost, "COMPLETED start chall: %s", + ac->challenge_uri); poll_again: ac->state = ACME_STATE_POLLING; lws_acme_report_status(vhd->vhost, LWS_CUS_CHALLENGE, @@ -1433,8 +1408,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) { - lwsl_notice("%s: failed to connect to acme\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "failed to connect to acme"); goto failed; } @@ -1443,18 +1417,14 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_POLLING: if (ac->resp == 202 && strcmp(ac->status, "invalid") && - strcmp(ac->status, "valid")) { - lwsl_notice("status: %s\n", ac->status); + strcmp(ac->status, "valid")) goto poll_again; - } - if (!strcmp(ac->status, "pending")) { - lwsl_notice("status: %s\n", ac->status); + if (!strcmp(ac->status, "pending")) goto poll_again; - } if (!strcmp(ac->status, "invalid")) { - lwsl_notice("%s: Challenge failed\n", __func__); + lwsl_vhost_warn(vhd->vhost, "Challenge failed"); lws_snprintf(buf, sizeof(buf), "Challenge Invalid: %s", ac->detail); @@ -1462,7 +1432,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, goto failed; } - lwsl_notice("Challenge passed\n"); + lwsl_vhost_notice(vhd->vhost, "ACME challenge passed"); /* * The challenge was validated... so delete the @@ -1487,8 +1457,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) { - lwsl_notice("%s: failed to connect to acme\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "Failed to connect to acme"); goto failed; } @@ -1503,8 +1472,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, if (ac->resp != 200) { if (ac->goes_around++ == 30) { - lwsl_notice("%s: too many retries\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "Too many retries"); goto failed; } @@ -1514,9 +1482,8 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) { - lwsl_notice("%s: " - "failed to connect to acme\n", - __func__); + lwsl_vhost_warn(vhd->vhost, + "Failed to connect to acme"); goto failed; } @@ -1531,8 +1498,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, &ac->cwsi, &ac->i, buf, "POST"); if (!cwsi) { - lwsl_notice("%s: failed to connect to acme\n", - __func__); + lwsl_vhost_warn(vhd->vhost, "Failed to connect to acme"); goto failed; } @@ -1541,11 +1507,11 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, case ACME_STATE_DOWNLOAD_CERT: if (ac->resp != 200) { - lwsl_notice("download cert failed on resp %d\n", + lwsl_vhost_warn(vhd->vhost, "Download cert failed on resp %d", ac->resp); goto failed; } - lwsl_notice("The cert was sent..\n"); + lwsl_vhost_notice(vhd->vhost, "The cert was sent.."); lws_acme_report_status(vhd->vhost, LWS_CUS_ISSUE, NULL); @@ -1554,13 +1520,25 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, * ac->buf, length in ac->cpos; and the key in * ac->alloc_privkey_pem, length in * ac->len_privkey_pem. + * ACME 2.0 can send certs chain with 3 certs, we need save only first */ + { + char *end_cert = strstr(ac->buf, "END CERTIFICATE-----"); + + if (end_cert) { + ac->cpos = (int)(lws_ptr_diff_size_t(end_cert, ac->buf) + sizeof("END CERTIFICATE-----") - 1); + } else { + ac->cpos = 0; + lwsl_vhost_err(vhd->vhost, "Unable to find ACME cert!"); + goto failed; + } + } n = lws_plat_write_cert(vhd->vhost, 0, vhd->fd_updated_cert, ac->buf, (size_t)ac->cpos); if (n) { - lwsl_err("unable to write ACME cert! %d\n", n); + lwsl_vhost_err(vhd->vhost, "unable to write ACME cert! %d", n); goto failed; } @@ -1572,16 +1550,16 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, vhd->fd_updated_key, ac->alloc_privkey_pem, ac->len_privkey_pem)) { - lwsl_err("unable to write ACME key!\n"); + lwsl_vhost_err(vhd->vhost, "unable to write ACME key!"); goto failed; } /* * we have written the persistent copies */ - lwsl_notice("%s: Updated certs written for %s " - "to %s.upd and %s.upd\n", __func__, - vhd->pvop_active[LWS_TLS_REQ_ELEMENT_COMMON_NAME], + lwsl_vhost_notice(vhd->vhost, "Updated certs written for %s " + "to %s.upd and %s.upd", + vhd->pvop_active[LWS_TLS_REQ_ELEMENT_COMMON_NAME], vhd->pvop_active[LWS_TLS_SET_CERT_PATH], vhd->pvop_active[LWS_TLS_SET_KEY_PATH]); @@ -1593,7 +1571,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, ac->buf, (size_t)ac->cpos, ac->alloc_privkey_pem, ac->len_privkey_pem)) { - lwsl_notice("problem setting certs\n"); + lwsl_vhost_warn(vhd->vhost, "problem setting certs"); } lws_acme_finished(vhd); @@ -1615,7 +1593,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, ac->challenge_uri, "GET"); if (!cwsi) { - lwsl_notice("%s: failed to connect\n", __func__); + lwsl_vhost_warn(vhd->vhost, "Failed to connect"); goto failed; } break; @@ -1627,7 +1605,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, return 0; failed: - lwsl_notice("%s: failed out\n", __func__); + lwsl_vhost_warn(vhd->vhost, "Failed out"); lws_acme_report_status(vhd->vhost, LWS_CUS_FAILED, failreason); lws_acme_finished(vhd); From 9e658fa99676e887a45a69a147896c1a604fd6b0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 11 Apr 2022 06:42:53 +0100 Subject: [PATCH 134/275] threadpool: improve relationship with LWS_HAVE_PTHREAD_H Make it clear in more places that threadpool is only built if pthreads available. https://github.com/warmcat/libwebsockets/issues/2607 --- lib/core-net/close.c | 2 +- lib/core-net/private-lib-core-net.h | 2 +- lib/core/private-lib-core.h | 2 +- lib/roles/pipe/ops-pipe.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index 1d92b39058..a8dd72096b 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -560,7 +560,7 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, lwsl_wsi_debug(wsi, "real just_kill_connection A: (sockfd %d)", wsi->desc.sockfd); -#if defined(LWS_WITH_THREADPOOL) +#if defined(LWS_WITH_THREADPOOL) && defined(LWS_HAVE_PTHREAD_H) lws_threadpool_wsi_closing(wsi); #endif diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 4fb99cdf7b..0b3561f742 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -706,7 +706,7 @@ struct lws { lws_log_cx_t *log_cx; -#if defined(LWS_WITH_THREADPOOL) +#if defined(LWS_WITH_THREADPOOL) && defined(LWS_HAVE_PTHREAD_H) lws_dll2_owner_t tp_task_owner; /* struct lws_threadpool_task */ #endif diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 8ba08520d7..6cdc91cff7 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -625,7 +625,7 @@ struct lws_context { mbedtls_ctr_drbg_context mcdc; #endif -#if defined(LWS_WITH_THREADPOOL) +#if defined(LWS_WITH_THREADPOOL) && defined(LWS_HAVE_PTHREAD_H) struct lws_threadpool *tp_list_head; #endif diff --git a/lib/roles/pipe/ops-pipe.c b/lib/roles/pipe/ops-pipe.c index 4d39d311d3..ad54a04fa9 100644 --- a/lib/roles/pipe/ops-pipe.c +++ b/lib/roles/pipe/ops-pipe.c @@ -60,7 +60,7 @@ rops_handle_POLLIN_pipe(struct lws_context_per_thread *pt, struct lws *wsi, return LWS_HPI_RET_PLEASE_CLOSE_ME; #endif -#if defined(LWS_WITH_THREADPOOL) +#if defined(LWS_WITH_THREADPOOL) && defined(LWS_HAVE_PTHREAD_H) /* * threadpools that need to call for on_writable callbacks do it by * marking the task as needing one for its wsi, then cancelling service. From 6108d681ca66932d14c625f79f8c8d7199bd51ef Mon Sep 17 00:00:00 2001 From: Orefkov Date: Mon, 11 Apr 2022 08:20:28 +0100 Subject: [PATCH 135/275] h2: access log: POST: prepare log https://github.com/warmcat/libwebsockets/issues/2608 --- lib/roles/h2/ops-h2.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/roles/h2/ops-h2.c b/lib/roles/h2/ops-h2.c index 989cb5b95e..0f76d171ce 100644 --- a/lib/roles/h2/ops-h2.c +++ b/lib/roles/h2/ops-h2.c @@ -797,9 +797,9 @@ static int lws_h2_bind_for_post_before_action(struct lws *wsi) { const struct lws_http_mount *hit; + int uri_len = 0, methidx; char *uri_ptr = NULL; uint8_t *buffered; - int uri_len = 0; const char *p; size_t blen; @@ -850,7 +850,10 @@ lws_h2_bind_for_post_before_action(struct lws *wsi) if (lws_bind_protocol(wsi, pp, __func__)) return 1; } - if (lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len) >= 0) + + methidx = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len); + + if (methidx >= 0) if (wsi->a.protocol->callback(wsi, LWS_CALLBACK_HTTP, wsi->user_space, hit ? uri_ptr + @@ -860,6 +863,10 @@ lws_h2_bind_for_post_before_action(struct lws *wsi) uri_len))) return 1; +#if defined(LWS_WITH_ACCESS_LOG) + lws_prepare_access_log_info(wsi, uri_ptr, uri_len, methidx); +#endif + lwsl_info("%s: setting LRS_BODY from 0x%x (%s)\n", __func__, (int)wsi->wsistate, wsi->a.protocol->name); From fe0a5b8bb9208a54b84a6f0d9ac814f7afc8ca53 Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Fri, 8 Apr 2022 14:11:19 -0700 Subject: [PATCH 136/275] mqtt: fix wrong awsiot field set on SUBSCRIBE --- lib/roles/mqtt/mqtt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index 4ba49c74f4..08cff44275 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -2215,6 +2215,8 @@ lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub) (int)sub->packet_id); lws_ser_wu16be(p, wsi->mqtt->ack_pkt_id); + nwsi->mqtt->client.aws_iot = wsi->mqtt->client.aws_iot; + if (lws_mqtt_str_advance(&mqtt_vh_payload, 2)) return 1; @@ -2383,6 +2385,8 @@ lws_mqtt_client_send_unsubcribe(struct lws *wsi, (int)wsi->mqtt->ack_pkt_id); lws_ser_wu16be(p, wsi->mqtt->ack_pkt_id); + nwsi->mqtt->client.aws_iot = wsi->mqtt->client.aws_iot; + if (lws_mqtt_str_advance(&mqtt_vh_payload, 2)) return 1; From a51d3564a2bb0cbd6fc9bfe9a12f43d80fa293be Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Sat, 9 Apr 2022 09:42:54 -0700 Subject: [PATCH 137/275] ss: mqtt: set the CONNECTED state after Birth This sets the CONNECTED state after Birth topic is processed if the stream has defined a Birth topic to avoid any confict when the connection is not stable and the Birth is delayed. --- lib/secure-streams/protocols/ss-mqtt.c | 119 ++++++++++++++++++------- 1 file changed, 87 insertions(+), 32 deletions(-) diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 11489d2503..911f5789f6 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -141,8 +141,8 @@ secstream_mqtt_subscribe(struct lws *wsi) } static int -secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buflen, - const char* topic, +secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buf_len, + uint32_t payload_len, const char* topic, lws_mqtt_qos_levels_t qos, uint8_t retain, int f) { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); @@ -190,17 +190,17 @@ secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buflen, mqpp.qos = qos; mqpp.retain = !!retain; mqpp.payload = buf; - if (h->writeable_len) - mqpp.payload_len = (uint32_t)h->writeable_len; + if (payload_len) + mqpp.payload_len = payload_len; else - mqpp.payload_len = (uint32_t)buflen; + mqpp.payload_len = (uint32_t)buf_len; lwsl_notice("%s: payload len %d\n", __func__, (int)mqpp.payload_len); if (lws_mqtt_client_send_publish(wsi, &mqpp, (const char *)buf, - (uint32_t)buflen, + (uint32_t)buf_len, f & LWSSS_FLAG_EOM)) { lwsl_notice("%s: failed to publish\n", __func__); lws_free(expbuf); @@ -210,6 +210,29 @@ secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buflen, return 0; } +static int +secstream_mqtt_birth(struct lws *wsi, uint8_t *buf, size_t buflen) { + lws_strexp_t exp; + size_t used_in, used_out = 0; + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + + if (h->policy->u.mqtt.birth_message) { + lws_strexp_init(&exp, h, lws_ss_exp_cb_metadata, + (char *)buf, buflen); + if (lws_strexp_expand(&exp, h->policy->u.mqtt.birth_message, + strlen(h->policy->u.mqtt.birth_message), + &used_in, &used_out) != LSTRX_DONE) { + return 1; + } + } + wsi->mqtt->inside_birth = 1; + return secstream_mqtt_publish(wsi, buf, + used_out, 0, h->policy->u.mqtt.birth_topic, + h->policy->u.mqtt.birth_qos, + h->policy->u.mqtt.birth_retain, + LWSSS_FLAG_EOM); +} + static int secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -285,6 +308,23 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->retry = 0; h->seqstate = SSSEQ_CONNECTED; + if (h->policy->u.mqtt.birth_topic && + !wsi->mqtt->done_birth) { + struct lws *nwsi = lws_get_network_wsi(wsi); + lws_start_foreach_ll(struct lws *, w, nwsi->mux.child_list) { + if (w != wsi && + (w->mqtt->done_birth || w->mqtt->inside_birth)) { + /* + * If any Birth was sent out or + * is pending on other stream, + * skip sending Birth. + */ + wsi->mqtt->done_birth = 1; + break; + } + } lws_end_foreach_ll(w, mux.sibling_list); + } + if (!h->policy->u.mqtt.subscribe || !h->policy->u.mqtt.subscribe[0]) { /* @@ -313,6 +353,17 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_callback_on_writable(wsi); break; } + + if (h->policy->u.mqtt.birth_topic && + !wsi->mqtt->done_birth) { + /* + * If a Birth is pending on the stream, then make + * sure the Birth is done before signaling the + * user application. + */ + lws_callback_on_writable(wsi); + break; + } lws_sul_cancel(&h->sul); #if defined(LWS_WITH_SYS_METRICS) /* @@ -351,10 +402,10 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_MQTT_SUBSCRIBED: /* - * Stream demanded a subscribe while connecting, once + * Stream demanded a subscribe without a Birth while connecting, once * done notify CONNECTED event to the application. */ - if (wsi->mqtt->done_subscribe == 0) { + if (!wsi->mqtt->done_subscribe && !h->policy->u.mqtt.birth_topic) { lws_sul_cancel(&h->sul); r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); if (r != LWSSSSRET_OK) @@ -368,10 +419,15 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_sul_cancel(&h->sul_timeout); if (wsi->mqtt->inside_birth) { /* - * Skip LWSSSCS_QOS_ACK_REMOTE for birth topic. + * Skip LWSSSCS_QOS_ACK_REMOTE for a Birth, notify + * CONNECTED event to the application. */ wsi->mqtt->inside_birth = 0; wsi->mqtt->done_birth = 1; + r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + lws_callback_on_writable(wsi); break; } r = lws_ss_event_helper(h, LWSSSCS_QOS_ACK_REMOTE); @@ -379,6 +435,14 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); break; + case LWS_CALLBACK_MQTT_RESEND: + if (wsi->mqtt->inside_birth) { + lwsl_err("%s: %s: Failed to send Birth\n", __func__, + lws_ss_tag(h)); + return -1; + } + break; + case LWS_CALLBACK_MQTT_CLIENT_WRITEABLE: { if (!h || !h->info.tx) @@ -393,27 +457,12 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (!wsi->mqtt->done_subscribe && h->policy->u.mqtt.subscribe) return secstream_mqtt_subscribe(wsi); - if (!wsi->mqtt->done_birth && h->policy->u.mqtt.birth_topic) { - lws_strexp_t exp; - size_t used_in, used_out = 0; - if (h->policy->u.mqtt.birth_message) { - lws_strexp_init(&exp, h, lws_ss_exp_cb_metadata, - (char *)(buf + LWS_PRE), buflen); - if (lws_strexp_expand(&exp, h->policy->u.mqtt.birth_message, - strlen(h->policy->u.mqtt.birth_message), - &used_in, &used_out) != LSTRX_DONE) { - return 1; - } - } - wsi->mqtt->inside_birth = 1; - return secstream_mqtt_publish(wsi, buf + LWS_PRE, - used_out, h->policy->u.mqtt.birth_topic, - h->policy->u.mqtt.birth_qos, - h->policy->u.mqtt.birth_retain, - LWSSS_FLAG_EOM); - } + if (!wsi->mqtt->done_birth && h->policy->u.mqtt.birth_topic) + return secstream_mqtt_birth(wsi, buf + LWS_PRE, buflen); + r = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, &buflen, &f); + if (r == LWSSSSRET_TX_DONT_SEND) return 0; @@ -436,10 +485,16 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (r < 0) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); - return secstream_mqtt_publish(wsi, buf + LWS_PRE, buflen, - h->policy->u.mqtt.topic, - h->policy->u.mqtt.qos, - h->policy->u.mqtt.retain, f); + if (secstream_mqtt_publish(wsi, buf + LWS_PRE, buflen, + (uint32_t)h->writeable_len, + h->policy->u.mqtt.topic, + h->policy->u.mqtt.qos, + h->policy->u.mqtt.retain, f) != 0) { + r = lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + } + return 0; } case LWS_CALLBACK_MQTT_UNSUBSCRIBED: From 21baf47aed1fbf0b39231eb7fe880b60177edd98 Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Sat, 9 Apr 2022 10:26:33 -0700 Subject: [PATCH 138/275] ss: mqtt: add QOS_NACK_REMOTE state on PUBLISH failure This adds setting QOS_NACK_REMOTE state when QoS 1/2 PUBLISH transmissions and all retries are unacked and failed. Also this allows state transitions between QOS_ACK_REMOTE and QOS_NACK_REMOTE. --- lib/roles/mqtt/mqtt.c | 4 +- lib/roles/mqtt/private-lib-roles-mqtt.h | 3 +- .../private-lib-secure-streams.h | 4 + lib/secure-streams/protocols/ss-mqtt.c | 103 +++++++++++++++++- lib/secure-streams/secure-streams.c | 5 + 5 files changed, 113 insertions(+), 6 deletions(-) diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index 08cff44275..b41d44d120 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -2027,7 +2027,9 @@ lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, /* Packet ID */ if (pub->qos != QOS0) { p = lws_mqtt_str_next(&mqtt_vh_payload, NULL); - wsi->mqtt->ack_pkt_id = pub->packet_id = ++nwsi->mqtt->pkt_id; + if (!pub->dup) + nwsi->mqtt->pkt_id++; + wsi->mqtt->ack_pkt_id = pub->packet_id = nwsi->mqtt->pkt_id; lwsl_debug("%s: pkt_id = %d\n", __func__, (int)wsi->mqtt->ack_pkt_id); lws_ser_wu16be(p, pub->packet_id); diff --git a/lib/roles/mqtt/private-lib-roles-mqtt.h b/lib/roles/mqtt/private-lib-roles-mqtt.h index d89f371879..575d2be581 100644 --- a/lib/roles/mqtt/private-lib-roles-mqtt.h +++ b/lib/roles/mqtt/private-lib-roles-mqtt.h @@ -45,6 +45,7 @@ extern struct lws_role_ops role_ops_mqtt; #define LWS_MQTT_RESPONSE_TIMEOUT (3 * LWS_US_PER_SEC) #define LWS_MQTT_RETRY_CEILING (60 * LWS_US_PER_SEC) +#define LWS_MQTT_MAX_PUBLISH_RETRY (3) typedef enum { LMSPR_COMPLETED = 0, @@ -354,7 +355,7 @@ struct _lws_mqtt_related { lws_mqttc_t client; lws_sorted_usec_list_t sul_qos_puback_pubrec_wait; /* QoS1 puback or QoS2 pubrec wait TO */ lws_sorted_usec_list_t sul_qos1_puback_wait; /* QoS1 puback wait TO */ - lws_sorted_usec_list_t sul_unsuback_wait; /* QoS1 unsuback wait TO */ + lws_sorted_usec_list_t sul_unsuback_wait; /* unsuback wait TO */ lws_sorted_usec_list_t sul_qos2_pubrec_wait; /* QoS2 pubrec wait TO */ struct lws *wsi; /**< so sul can use lws_container_of */ lws_mqtt_subs_t *subs_head; /**< Linked-list of heap-allocated subscription objects */ diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 6af59e4707..b14a828764 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -151,6 +151,10 @@ typedef struct lws_ss_handle { void *heap_baggage; const char *subscribe_to; size_t subscribe_to_len; + struct lws_buflist *buflist_unacked; + uint32_t unacked_size; + uint8_t retry_count; + uint8_t send_unacked:1; } mqtt; #endif #if defined(LWS_WITH_SYS_SMD) diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 911f5789f6..11ab7b27b1 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -44,6 +44,7 @@ secstream_mqtt_cleanup(lws_ss_handle_t *h) lws_free(h->u.mqtt.sub_info.topic); h->u.mqtt.sub_info.topic = NULL; } + lws_buflist_destroy_all_segments(&h->u.mqtt.buflist_unacked); } static int @@ -143,7 +144,8 @@ secstream_mqtt_subscribe(struct lws *wsi) static int secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buf_len, uint32_t payload_len, const char* topic, - lws_mqtt_qos_levels_t qos, uint8_t retain, int f) + lws_mqtt_qos_levels_t qos, uint8_t retain, uint8_t dup, + int f) { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); size_t used_in, used_out, topic_limit; @@ -190,6 +192,7 @@ secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buf_len, mqpp.qos = qos; mqpp.retain = !!retain; mqpp.payload = buf; + mqpp.dup = !!dup; if (payload_len) mqpp.payload_len = payload_len; else @@ -207,6 +210,15 @@ secstream_mqtt_publish(struct lws *wsi, uint8_t *buf, size_t buf_len, return -1; } lws_free(expbuf); + + if ((mqpp.qos == QOS1 || mqpp.qos == QOS2) && buf_len > 0) { + if (lws_buflist_append_segment(&h->u.mqtt.buflist_unacked, + buf, buf_len) < 0) { + lwsl_notice("%s: failed to store unacked\n", __func__); + return -1; + } + } + return 0; } @@ -229,10 +241,63 @@ secstream_mqtt_birth(struct lws *wsi, uint8_t *buf, size_t buflen) { return secstream_mqtt_publish(wsi, buf, used_out, 0, h->policy->u.mqtt.birth_topic, h->policy->u.mqtt.birth_qos, - h->policy->u.mqtt.birth_retain, + h->policy->u.mqtt.birth_retain, 0, LWSSS_FLAG_EOM); } +static int +secstream_mqtt_resend(struct lws *wsi, uint8_t *buf) { + uint8_t *buffered; + size_t len; + int f = 0, r; + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + + len = lws_buflist_next_segment_len(&h->u.mqtt.buflist_unacked, + &buffered); + + if (h->u.mqtt.unacked_size <= len) + f |= LWSSS_FLAG_EOM; + + if (!len) { + /* when the message does not have payload */ + buffered = buf; + } else { + h->u.mqtt.unacked_size -= (uint32_t)len; + } + + if (wsi->mqtt->inside_birth) { + r = secstream_mqtt_publish(wsi, buffered, len, 0, + h->policy->u.mqtt.birth_topic, + h->policy->u.mqtt.birth_qos, + h->policy->u.mqtt.birth_retain, + 1, f); + } else { + r = secstream_mqtt_publish(wsi, buffered, len, + (uint32_t)h->writeable_len, + h->policy->u.mqtt.topic, + h->policy->u.mqtt.qos, + h->policy->u.mqtt.retain, 1, f); + } + if (len) + lws_buflist_use_segment(&h->u.mqtt.buflist_unacked, len); + + if (r) { + lws_buflist_destroy_all_segments(&h->u.mqtt.buflist_unacked); + h->u.mqtt.retry_count = h->u.mqtt.send_unacked = 0; + + if (wsi->mqtt->inside_birth) { + lwsl_err("%s: %s: failed to send Birth\n", __func__, + lws_ss_tag(h)); + return -1; + } else { + r = lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + } + } + return 0; +} + static int secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) @@ -417,6 +482,11 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_MQTT_ACK: lws_sul_cancel(&h->sul_timeout); + if (h->u.mqtt.send_unacked) { + lws_buflist_destroy_all_segments(&h->u.mqtt.buflist_unacked); + h->u.mqtt.retry_count = h->u.mqtt.send_unacked = 0; + } + if (wsi->mqtt->inside_birth) { /* * Skip LWSSSCS_QOS_ACK_REMOTE for a Birth, notify @@ -436,11 +506,33 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, break; case LWS_CALLBACK_MQTT_RESEND: + lws_sul_cancel(&h->sul_timeout); + if (h->u.mqtt.retry_count++ < LWS_MQTT_MAX_PUBLISH_RETRY) { + h->u.mqtt.unacked_size = + (uint32_t)lws_buflist_total_len(&h->u.mqtt.buflist_unacked); + if (h->u.mqtt.unacked_size) { + lwsl_notice("%s: %s: resend unacked message (%d/%d) \n", + __func__, lws_ss_tag(h), + h->u.mqtt.retry_count, + LWS_MQTT_MAX_PUBLISH_RETRY); + h->u.mqtt.send_unacked = 1; + lws_callback_on_writable(wsi); + break; + } + } + + lws_buflist_destroy_all_segments(&h->u.mqtt.buflist_unacked); + h->u.mqtt.retry_count = h->u.mqtt.send_unacked = 0; + if (wsi->mqtt->inside_birth) { - lwsl_err("%s: %s: Failed to send Birth\n", __func__, + lwsl_err("%s: %s: failed to send Birth\n", __func__, lws_ss_tag(h)); return -1; } + + r = lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE); + if (r != LWSSSSRET_OK) + return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); break; case LWS_CALLBACK_MQTT_CLIENT_WRITEABLE: @@ -457,6 +549,9 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (!wsi->mqtt->done_subscribe && h->policy->u.mqtt.subscribe) return secstream_mqtt_subscribe(wsi); + if (h->u.mqtt.send_unacked) + return secstream_mqtt_resend(wsi, buf + LWS_PRE); + if (!wsi->mqtt->done_birth && h->policy->u.mqtt.birth_topic) return secstream_mqtt_birth(wsi, buf + LWS_PRE, buflen); @@ -489,7 +584,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, (uint32_t)h->writeable_len, h->policy->u.mqtt.topic, h->policy->u.mqtt.qos, - h->policy->u.mqtt.retain, f) != 0) { + h->policy->u.mqtt.retain, 0, f) != 0) { r = lws_ss_event_helper(h, LWSSSCS_QOS_NACK_REMOTE); if (r != LWSSSSRET_OK) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index c74d229ce8..911f713213 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -147,11 +147,16 @@ const uint32_t ss_state_txn_validity[] = { (1 << LWSSSCS_TIMEOUT) | #if defined(LWS_ROLE_MQTT) (1 << LWSSSCS_QOS_ACK_REMOTE) | + (1 << LWSSSCS_QOS_NACK_REMOTE) | #endif (1 << LWSSSCS_DESTROYING), [LWSSSCS_QOS_NACK_REMOTE] = (1 << LWSSSCS_DISCONNECTED) | (1 << LWSSSCS_TIMEOUT) | +#if defined(LWS_ROLE_MQTT) + (1 << LWSSSCS_QOS_ACK_REMOTE) | + (1 << LWSSSCS_QOS_NACK_REMOTE) | +#endif (1 << LWSSSCS_DESTROYING), [LWSSSCS_QOS_ACK_LOCAL] = (1 << LWSSSCS_DISCONNECTED) | From 8eb6cbf5ac1db1458e727eba8c86b142b936f8fa Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Sat, 9 Apr 2022 10:51:13 -0700 Subject: [PATCH 139/275] minimal: ss: policy2c: update MQTT fields --- .../minimal-secure-streams.c | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c index a89d0c8d6b..bb86d3d3d5 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c @@ -573,13 +573,24 @@ int main(int argc, const char **argv) if (pol->u.mqtt.will_message) printf("\t\t\t.will_message = \"%s\",\n", pol->u.mqtt.will_message); - + if (pol->u.mqtt.will_qos) + printf("\t\t\t.will_qos = %u,\n", + pol->u.mqtt.will_qos); + if (pol->u.mqtt.will_retain) + printf("\t\t\t.will_retain = %u,\n", + pol->u.mqtt.will_retain); if (pol->u.mqtt.birth_topic) printf("\t\t\t.birth_topic = \"%s\",\n", pol->u.mqtt.birth_topic); if (pol->u.mqtt.birth_message) printf("\t\t\t.birth_message = \"%s\",\n", pol->u.mqtt.birth_message); + if (pol->u.mqtt.birth_qos) + printf("\t\t\t.birth_qos = %u,\n", + pol->u.mqtt.birth_qos); + if (pol->u.mqtt.birth_retain) + printf("\t\t\t.birth_retain = %u,\n", + pol->u.mqtt.birth_retain); if (pol->u.mqtt.keep_alive) printf("\t\t\t.keep_alive = %u,\n", pol->u.mqtt.keep_alive); @@ -589,19 +600,12 @@ int main(int argc, const char **argv) if (pol->u.mqtt.clean_start) printf("\t\t\t.clean_start = %u,\n", pol->u.mqtt.clean_start); - if (pol->u.mqtt.will_qos) - printf("\t\t\t.will_qos = %u,\n", - pol->u.mqtt.will_qos); - if (pol->u.mqtt.will_retain) - printf("\t\t\t.will_retain = %u,\n", - pol->u.mqtt.will_retain); if (pol->u.mqtt.aws_iot) printf("\t\t\t.aws_iot = %u,\n", pol->u.mqtt.aws_iot); if (pol->u.mqtt.retain) printf("\t\t\t.retain = %u,\n", pol->u.mqtt.retain); - printf("\t\t}\n\t},\n"); break; From fe762e586d1e30c31b2093b444d109684a8e0b39 Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Wed, 13 Apr 2022 21:03:26 +0200 Subject: [PATCH 140/275] CMakeLists.txt: fix build without C++ Fix the following build failure without C++ raised since version 4.2.0 and https://github.com/warmcat/libwebsockets/commit/962e9ee345bc28749577c1fca2542a273404627d: CMake Error at /nvmedata/autobuild/instance-11/output-1/per-package/libwebsockets/host/share/cmake-3.18/Modules/CMakeTestCXXCompiler.cmake:59 (message): The C++ compiler "/usr/bin/clang++" is not able to compile a simple test program. Fixes: - http://autobuild.buildroot.org/results/550e7f7d54adf74f8cc078be5b91b3567d622ede Signed-off-by: Fabrice Fontaine --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d56ee920b6..dd02e4847a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,7 +63,10 @@ if (ESP_PLATFORM) endif() # it's at this point any toolchain file is brought in -project(libwebsockets C CXX) +project(libwebsockets C) +if (LWS_WITH_SECURE_STREAMS_CPP) + enable_language(CXX) +endif() include(CTest) if (ESP_PLATFORM) From 6e997a9e709279e42343aa6f6611bfaaa5081321 Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Thu, 14 Apr 2022 18:13:16 +0200 Subject: [PATCH 141/275] tls: cmake: add wolfssl pkg-config support Use pkg-config to search for wolfssl.pc which is available since version 3.3.3 and https://github.com/wolfSSL/wolfssl/commit/a50af85e953e6096eaa779b72d9dee5b4a66737c This will avoid setting manually LWS_WOLFSSL_{INCLUDE_DIRS,LIBRARIES} Signed-off-by: Fabrice Fontaine --- CMakeLists.txt | 2 +- lib/tls/CMakeLists.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd02e4847a..a6a62e4db8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -182,7 +182,7 @@ option(LWS_WITH_SSL "Include SSL support (defaults to OpenSSL or similar, mbedTL option(LWS_WITH_MBEDTLS "Use mbedTLS (>=2.0) replacement for OpenSSL. When setting this, you also may need to specify LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS" OFF) option(LWS_WITH_BORINGSSL "Use BoringSSL replacement for OpenSSL" OFF) option(LWS_WITH_CYASSL "Use CyaSSL replacement for OpenSSL. When setting this, you also need to specify LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS" OFF) -option(LWS_WITH_WOLFSSL "Use wolfSSL replacement for OpenSSL. When setting this, you also need to specify LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS" OFF) +option(LWS_WITH_WOLFSSL "Use wolfSSL replacement for OpenSSL. When setting this, you also may need to specify LWS_WOLFSSL_LIBRARIES and LWS_WOLFSSL_INCLUDE_DIRS" OFF) option(LWS_SSL_CLIENT_USE_OS_CA_CERTS "SSL support should make use of the OS-installed CA root certs" ON) option(LWS_TLS_LOG_PLAINTEXT_RX "For debugging log the received plaintext as soon as decrypted" OFF) option(LWS_TLS_LOG_PLAINTEXT_TX "For debugging log the transmitted plaintext just before encryption" OFF) diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index a161879f1e..fb9a75fe55 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -69,6 +69,9 @@ endif() if (LWS_WITH_SSL AND LWS_WITH_WOLFSSL) if ("${LWS_WOLFSSL_LIBRARIES}" STREQUAL "" OR "${LWS_WOLFSSL_INCLUDE_DIRS}" STREQUAL "") + include (FindPkgConfig) + PKG_SEARCH_MODULE(LWS_WOLFSSL wolfssl) + if (NOT WOLFSSL_FOUND) if (LWS_WITH_CYASSL) message(FATAL_ERROR "You must set LWS_CYASSL_LIBRARIES and LWS_CYASSL_INCLUDE_DIRS when LWS_WITH_CYASSL is turned on.") From e02aaff34c6361a09fc037818419a00ae6c638d8 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 17 Apr 2022 07:46:38 +0100 Subject: [PATCH 142/275] gcc12: extend test-client buffer for dumb increment --- test-apps/test-client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-apps/test-client.c b/test-apps/test-client.c index afed493f9e..05d08ed728 100644 --- a/test-apps/test-client.c +++ b/test-apps/test-client.c @@ -125,7 +125,7 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, #endif #endif const char *which = "http"; - char which_wsi[20], buf[50 + LWS_PRE]; + char which_wsi[50], buf[80 + LWS_PRE]; int n; switch (reason) { From 65870ebce3d9abd1b8c92149a26892dd39a4bf34 Mon Sep 17 00:00:00 2001 From: dcpng Date: Tue, 19 Apr 2022 06:00:05 +0100 Subject: [PATCH 143/275] windows: plugins uv fixes https://github.com/warmcat/libwebsockets/issues/2617 --- lib/plat/windows/windows-plugins.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/plat/windows/windows-plugins.c b/lib/plat/windows/windows-plugins.c index b2153d677e..313d58ffac 100644 --- a/lib/plat/windows/windows-plugins.c +++ b/lib/plat/windows/windows-plugins.c @@ -66,7 +66,7 @@ lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath, if (uv_dlsym(&lib, sym, &v)) { uv_dlerror(&lib); lwsl_err("%s: Failed to get '%s' on %s: %s\n", - __func__, path, dent.name, lib.errmsg); + __func__, path, libpath, lib.errmsg); goto bail; } @@ -123,7 +123,9 @@ lws_plat_dlopen(struct lws_plugin **pplugin, const char *libpath, int lws_plat_destroy_dl(struct lws_plugin *p) { - return uv_dlclose(&p->u.lib); + uv_dlclose(&p->u.lib); + + return 0; } #endif From cf7862dd3c68ad54c6e314f4ff34f5f7dc37a8a7 Mon Sep 17 00:00:00 2001 From: Harshit Malpani Date: Thu, 21 Apr 2022 14:28:10 +0530 Subject: [PATCH 144/275] plat: esp32: Remove esp_attr.h file --- lib/plat/freertos/esp32/esp_attr.h | 58 ------------------- lib/plat/freertos/private-lib-plat-freertos.h | 4 ++ 2 files changed, 4 insertions(+), 58 deletions(-) delete mode 100644 lib/plat/freertos/esp32/esp_attr.h diff --git a/lib/plat/freertos/esp32/esp_attr.h b/lib/plat/freertos/esp32/esp_attr.h deleted file mode 100644 index 5bf9a22926..0000000000 --- a/lib/plat/freertos/esp32/esp_attr.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef __ESP_ATTR_H__ -#define __ESP_ATTR_H__ - -#define ROMFN_ATTR - -//Normally, the linker script will put all code and rodata in flash, -//and all variables in shared RAM. These macros can be used to redirect -//particular functions/variables to other memory regions. - -// Forces code into IRAM instead of flash. -#define IRAM_ATTR __attribute__((section(".iram1"))) - -// Forces data into DRAM instead of flash -#define DRAM_ATTR __attribute__((section(".dram1"))) - -// Forces data to be 4 bytes aligned -#define WORD_ALIGNED_ATTR __attribute__((aligned(4))) - -// Forces data to be placed to DMA-capable places -#define DMA_ATTR WORD_ALIGNED_ATTR DRAM_ATTR - -// Forces a string into DRAM instead of flash -// Use as ets_printf(DRAM_STR("Hello world!\n")); -#define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;})) - -// Forces code into RTC fast memory. See "docs/deep-sleep-stub.rst" -#define RTC_IRAM_ATTR __attribute__((section(".rtc.text"))) - -// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst" -// Any variable marked with this attribute will keep its value -// during a deep sleep / wake cycle. -#define RTC_DATA_ATTR __attribute__((section(".rtc.data"))) - -// Forces read-only data into RTC slow memory. See "docs/deep-sleep-stub.rst" -#define RTC_RODATA_ATTR __attribute__((section(".rtc.rodata"))) - -// Forces data into noinit section to avoid initialization after restart. -#define __NOINIT_ATTR __attribute__((section(".noinit"))) - -// Forces data into RTC slow memory of .noinit section. -// Any variable marked with this attribute will keep its value -// after restart or during a deep sleep / wake cycle. -#define RTC_NOINIT_ATTR __attribute__((section(".rtc_noinit"))) - -#endif /* __ESP_ATTR_H__ */ diff --git a/lib/plat/freertos/private-lib-plat-freertos.h b/lib/plat/freertos/private-lib-plat-freertos.h index d544e2b112..67b83997ad 100644 --- a/lib/plat/freertos/private-lib-plat-freertos.h +++ b/lib/plat/freertos/private-lib-plat-freertos.h @@ -59,11 +59,15 @@ gai_strerror(int); #include "FreeRTOS_IP.h" #endif #include "timers.h" +#if defined(LWS_ESP_PLATFORM) #include +#endif #include #else #include "freertos/timers.h" +#if defined(LWS_ESP_PLATFORM) #include +#endif #include #include #endif From 2d48f559f0a3f9a73c15216f54c8c8b9bbc94ceb Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 21 Apr 2022 12:19:48 +0100 Subject: [PATCH 145/275] mbedtls: some versions need x509 overallocation --- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index db63d09586..e8a0cb2d40 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -659,7 +659,7 @@ int x509_pm_load(X509 *x, const unsigned char *buffer, int len) struct x509_pm *x509_pm = (struct x509_pm *)x->x509_pm; if (!x509_pm->x509_crt) { - x509_pm->x509_crt = ssl_mem_malloc(sizeof(mbedtls_x509_crt)); + x509_pm->x509_crt = ssl_mem_malloc(sizeof(mbedtls_x509_crt) + 80); if (!x509_pm->x509_crt) { SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "no enough memory > (x509_pm->x509_crt)"); goto no_mem; From c398dd546bde7711303f579e23b966c84198fad7 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 29 Apr 2022 10:45:55 +0100 Subject: [PATCH 146/275] coverity: reorder NULL check --- lib/system/metrics/metrics.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/system/metrics/metrics.c b/lib/system/metrics/metrics.c index 92d5e0d0f8..1a978cca7e 100644 --- a/lib/system/metrics/metrics.c +++ b/lib/system/metrics/metrics.c @@ -437,11 +437,13 @@ int lws_metric_destroy(lws_metric_t **pmt, int keep) { lws_metric_t *mt = *pmt; - lws_metric_pub_t *pub = lws_metrics_priv_to_pub(mt); + lws_metric_pub_t *pub; if (!mt) return 0; + pub = lws_metrics_priv_to_pub(mt); + lws_dll2_remove(&mt->list); if (keep) { From 8b1693a05e77e57bb65ecf2c16c9583b29e0761f Mon Sep 17 00:00:00 2001 From: Chunho Lee Date: Thu, 28 Apr 2022 23:22:20 -0700 Subject: [PATCH 147/275] ss: mqtt: add support for AWS IoT Shadow topic This introduces AWS IoT Shadow topic support. This subscribes and unsubscribes shadow response topics before and after shadow topic is transmitted. --- include/libwebsockets/lws-callbacks.h | 5 + include/libwebsockets/lws-mqtt.h | 23 ++ lib/roles/mqtt/mqtt.c | 234 +++++++------- lib/roles/mqtt/private-lib-roles-mqtt.h | 7 + .../private-lib-secure-streams.h | 1 + lib/secure-streams/protocols/ss-mqtt.c | 299 +++++++++++++++++- 6 files changed, 457 insertions(+), 112 deletions(-) diff --git a/include/libwebsockets/lws-callbacks.h b/include/libwebsockets/lws-callbacks.h index 62848fa5ae..fd36f7c7de 100644 --- a/include/libwebsockets/lws-callbacks.h +++ b/include/libwebsockets/lws-callbacks.h @@ -887,6 +887,11 @@ enum lws_callback_reasons { * the _UNSUBSCRIBED one if we timed out waiting for a UNSUBACK. * Return nonzero to close the wsi. */ + LWS_CALLBACK_MQTT_SHADOW_TIMEOUT = 212, + /**< When a Device Shadow is sent, this callback is generated if we + * timed out waiting for a response from AWS IoT. + * Return nonzero to close the wsi. + */ /****** add new things just above ---^ ******/ diff --git a/include/libwebsockets/lws-mqtt.h b/include/libwebsockets/lws-mqtt.h index b228315a1a..cbf8b36373 100644 --- a/include/libwebsockets/lws-mqtt.h +++ b/include/libwebsockets/lws-mqtt.h @@ -42,6 +42,29 @@ typedef struct lws_mqtt_str_st lws_mqtt_str_t; #define LWS_MQTT_RANDOM_CIDLEN 23 /* 3.1.3.1-5: Server MUST... between 1 and 23 chars... */ +#define LWS_MQTT_SHADOW_MAX_THING_LEN 128 +#define LWS_MQTT_SHADOW_MAX_SHADOW_LEN 64 +#define LWS_MQTT_SHADOW_UPDATE_STR "/update" +#define LWS_MQTT_SHADOW_DELETE_STR "/delete" +#define LWS_MQTT_SHADOW_GET_STR "/get" +#define LWS_MQTT_SHADOW_RESP_ACCEPTED_STR "/accepted" +#define LWS_MQTT_SHADOW_RESP_REJECTED_STR "/rejected" +#define LWS_MQTT_SHADOW_RESP_DELTA_STR "/delta" +#define LWS_MQTT_SHADOW_RESP_DOCUMENT_STR "/documents" +#define LWS_MQTT_SHADOW_UPDATE_ACCEPTED_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_ACCEPTED_STR +#define LWS_MQTT_SHADOW_UPDATE_REJECTED_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_REJECTED_STR +#define LWS_MQTT_SHADOW_UPDATE_DELTA_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_DELTA_STR +#define LWS_MQTT_SHADOW_UPDATE_DOCUMENT_STR LWS_MQTT_SHADOW_UPDATE_STR LWS_MQTT_SHADOW_RESP_DOCUMENT_STR +#define LWS_MQTT_SHADOW_DELETE_ACCEPTED_STR LWS_MQTT_SHADOW_DELETE_STR LWS_MQTT_SHADOW_RESP_ACCEPTED_STR +#define LWS_MQTT_SHADOW_DELETE_REJECTED_STR LWS_MQTT_SHADOW_DELETE_STR LWS_MQTT_SHADOW_RESP_REJECTED_STR +#define LWS_MQTT_SHADOW_GET_ACCEPTED_STR LWS_MQTT_SHADOW_GET_STR LWS_MQTT_SHADOW_RESP_ACCEPTED_STR +#define LWS_MQTT_SHADOW_GET_REJECTED_STR LWS_MQTT_SHADOW_GET_STR LWS_MQTT_SHADOW_RESP_REJECTED_STR +#define LWS_MQTT_SHADOW_PREFIX_FORMAT "$aws/things/%s" +#define LWS_MQTT_SHADOW_NAMED_SHADOW_TOPIC_FORMAT LWS_MQTT_SHADOW_PREFIX_FORMAT "/shadow/name/%s%s" +#define LWS_MQTT_SHADOW_UNNAMED_SHADOW_TOPIC_FORMAT LWS_MQTT_SHADOW_PREFIX_FORMAT "/shadow%s" +#define LWS_MQTT_SHADOW_UNNAMED_TOPIC_MATCH "$aws/things/+/shadow/+" +#define LWS_MQTT_SHADOW_NAMED_TOPIC_MATCH "$aws/things/+/shadow/name/+/+" + typedef enum { QOS0, QOS1, diff --git a/lib/roles/mqtt/mqtt.c b/lib/roles/mqtt/mqtt.c index b41d44d120..aaac84b8be 100644 --- a/lib/roles/mqtt/mqtt.c +++ b/lib/roles/mqtt/mqtt.c @@ -214,13 +214,6 @@ static const uint8_t map_flags[] = { LMQCP_LUT_FLAG_PACKET_ID_NONE | 0x00, }; -void -lws_mqttc_state_transition(lws_mqttc_t *c, lwsgs_mqtt_states_t s) -{ - lwsl_debug("%s: ep %p: state %d -> %d\n", __func__, c, c->estate, s); - c->estate = s; -} - static int lws_mqtt_pconsume(lws_mqtt_parser_t *par, int consumed) { @@ -277,74 +270,6 @@ lws_mqtt_set_client_established(struct lws *wsi) return 0; } - -static lws_mqtt_match_topic_return_t -lws_mqtt_is_topic_matched(const char* sub, const char* pub) -{ - const char *ppos = pub, *spos = sub; - - if (!ppos || !spos) { - return LMMTR_TOPIC_MATCH_ERROR; - } - - while (*spos) { - if (*ppos == '#' || *ppos == '+') { - lwsl_err("%s: PUBLISH to wildcard " - "topic \"%s\" not supported\n", - __func__, pub); - return LMMTR_TOPIC_MATCH_ERROR; - } - /* foo/+/bar == foo/xyz/bar ? */ - if (*spos == '+') { - /* Skip ahead */ - while (*ppos != '\0' && *ppos != '/') { - ppos++; - } - } else if (*spos == '#') { - return LMMTR_TOPIC_MATCH; - } else { - if (*ppos == '\0') { - /* foo/bar == foo/bar/# ? */ - if (!strncmp(spos, "/#", 2)) - return LMMTR_TOPIC_MATCH; - return LMMTR_TOPIC_NOMATCH; - /* Non-matching character */ - } else if (*ppos != *spos) { - return LMMTR_TOPIC_NOMATCH; - } - ppos++; - } - spos++; - } - - if (*spos == '\0' && *ppos == '\0') - return LMMTR_TOPIC_MATCH; - - return LMMTR_TOPIC_NOMATCH; -} - -lws_mqtt_subs_t* lws_mqtt_find_sub(struct _lws_mqtt_related* mqtt, - const char* ptopic) { - lws_mqtt_subs_t *s = mqtt->subs_head; - - while (s) { - /* SUB topic == PUB topic ? */ - /* foo/bar/xyz == foo/bar/xyz ? */ - if (!s->wildcard) { - if (!strcmp((const char*)s->topic, ptopic)) - return s; - } else { - if (lws_mqtt_is_topic_matched( - s->topic, ptopic) == LMMTR_TOPIC_MATCH) - return s; - } - - s = s->next; - } - - return NULL; -} - static lws_mqtt_validate_topic_return_t lws_mqtt_validate_topic(const char *topic, size_t topiclen, uint8_t awsiot) { @@ -477,6 +402,126 @@ lws_mqtt_client_remove_subs(struct _lws_mqtt_related *mqtt) return 1; } +/* + * This fires if the wsi did a PUBLISH under QoS1 or QoS2, but no PUBACK or + * PUBREC came before the timeout period + */ + +static void +lws_mqtt_publish_resend(struct lws_sorted_usec_list *sul) +{ + struct _lws_mqtt_related *mqtt = lws_container_of(sul, + struct _lws_mqtt_related, sul_qos_puback_pubrec_wait); + + lwsl_notice("%s: %s\n", __func__, lws_wsi_tag(mqtt->wsi)); + + if (mqtt->wsi->a.protocol->callback(mqtt->wsi, LWS_CALLBACK_MQTT_RESEND, + mqtt->wsi->user_space, NULL, 0)) + lws_set_timeout(mqtt->wsi, 1, LWS_TO_KILL_ASYNC); +} + +static void +lws_mqtt_unsuback_timeout(struct lws_sorted_usec_list *sul) +{ + struct _lws_mqtt_related *mqtt = lws_container_of(sul, + struct _lws_mqtt_related, sul_unsuback_wait); + + lwsl_debug("%s: %s\n", __func__, lws_wsi_tag(mqtt->wsi)); + + if (mqtt->wsi->a.protocol->callback(mqtt->wsi, + LWS_CALLBACK_MQTT_UNSUBSCRIBE_TIMEOUT, + mqtt->wsi->user_space, NULL, 0)) + lws_set_timeout(mqtt->wsi, 1, LWS_TO_KILL_ASYNC); +} + +static void +lws_mqtt_shadow_timeout(struct lws_sorted_usec_list *sul) +{ + struct _lws_mqtt_related *mqtt = lws_container_of(sul, + struct _lws_mqtt_related, sul_shadow_wait); + + lwsl_debug("%s: %s\n", __func__, lws_wsi_tag(mqtt->wsi)); + + if (mqtt->wsi->a.protocol->callback(mqtt->wsi, + LWS_CALLBACK_MQTT_SHADOW_TIMEOUT, + mqtt->wsi->user_space, NULL, 0)) + lws_set_timeout(mqtt->wsi, 1, LWS_TO_KILL_ASYNC); +} + +void +lws_mqttc_state_transition(lws_mqttc_t *c, lwsgs_mqtt_states_t s) +{ + lwsl_debug("%s: ep %p: state %d -> %d\n", __func__, c, c->estate, s); + c->estate = s; +} + +lws_mqtt_match_topic_return_t +lws_mqtt_is_topic_matched(const char* sub, const char* pub) +{ + const char *ppos = pub, *spos = sub; + + if (!ppos || !spos) { + return LMMTR_TOPIC_MATCH_ERROR; + } + + while (*spos) { + if (*ppos == '#' || *ppos == '+') { + lwsl_err("%s: PUBLISH to wildcard " + "topic \"%s\" not supported\n", + __func__, pub); + return LMMTR_TOPIC_MATCH_ERROR; + } + /* foo/+/bar == foo/xyz/bar ? */ + if (*spos == '+') { + /* Skip ahead */ + while (*ppos != '\0' && *ppos != '/') { + ppos++; + } + } else if (*spos == '#') { + return LMMTR_TOPIC_MATCH; + } else { + if (*ppos == '\0') { + /* foo/bar == foo/bar/# ? */ + if (!strncmp(spos, "/#", 2)) + return LMMTR_TOPIC_MATCH; + return LMMTR_TOPIC_NOMATCH; + /* Non-matching character */ + } else if (*ppos != *spos) { + return LMMTR_TOPIC_NOMATCH; + } + ppos++; + } + spos++; + } + + if (*spos == '\0' && *ppos == '\0') + return LMMTR_TOPIC_MATCH; + + return LMMTR_TOPIC_NOMATCH; +} + +lws_mqtt_subs_t* lws_mqtt_find_sub(struct _lws_mqtt_related* mqtt, + const char* ptopic) { + lws_mqtt_subs_t *s = mqtt->subs_head; + + while (s) { + /* SUB topic == PUB topic ? */ + /* foo/bar/xyz == foo/bar/xyz ? */ + if (!s->wildcard) { + if (!strcmp((const char*)s->topic, ptopic)) + return s; + } else { + if (lws_mqtt_is_topic_matched( + s->topic, ptopic) == LMMTR_TOPIC_MATCH) + return s; + } + + s = s->next; + } + + return NULL; +} + int _lws_mqtt_rx_parser(struct lws *wsi, lws_mqtt_parser_t *par, const uint8_t *buf, size_t len) @@ -1908,38 +1953,6 @@ lws_mqtt_fill_fixed_header(uint8_t *p, lws_mqtt_control_packet_t ctrl_pkt_type, return 0; } -/* - * This fires if the wsi did a PUBLISH under QoS1 or QoS2, but no PUBACK or - * PUBREC came before the timeout period - */ - -static void -lws_mqtt_publish_resend(struct lws_sorted_usec_list *sul) -{ - struct _lws_mqtt_related *mqtt = lws_container_of(sul, - struct _lws_mqtt_related, sul_qos_puback_pubrec_wait); - - lwsl_notice("%s: %s\n", __func__, lws_wsi_tag(mqtt->wsi)); - - if (mqtt->wsi->a.protocol->callback(mqtt->wsi, LWS_CALLBACK_MQTT_RESEND, - mqtt->wsi->user_space, NULL, 0)) - lws_set_timeout(mqtt->wsi, 1, LWS_TO_KILL_ASYNC); -} - -static void -lws_mqtt_unsuback_timeout(struct lws_sorted_usec_list *sul) -{ - struct _lws_mqtt_related *mqtt = lws_container_of(sul, - struct _lws_mqtt_related, sul_unsuback_wait); - - lwsl_debug("%s: %s\n", __func__, lws_wsi_tag(mqtt->wsi)); - - if (mqtt->wsi->a.protocol->callback(mqtt->wsi, - LWS_CALLBACK_MQTT_UNSUBSCRIBE_TIMEOUT, - mqtt->wsi->user_space, NULL, 0)) - lws_set_timeout(mqtt->wsi, 1, LWS_TO_KILL_ASYNC); -} - int lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, const void *buf, uint32_t len, int is_complete) @@ -2093,6 +2106,13 @@ lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, 3 * LWS_USEC_PER_SEC); } + if (wsi->mqtt->inside_shadow) { + wsi->mqtt->sul_shadow_wait.cb = lws_mqtt_shadow_timeout; + __lws_sul_insert_us(&pt->pt_sul_owner[wsi->conn_validity_wakesuspend], + &wsi->mqtt->sul_shadow_wait, + 60 * LWS_USEC_PER_SEC); + } + return 0; } diff --git a/lib/roles/mqtt/private-lib-roles-mqtt.h b/lib/roles/mqtt/private-lib-roles-mqtt.h index 575d2be581..dc46a93629 100644 --- a/lib/roles/mqtt/private-lib-roles-mqtt.h +++ b/lib/roles/mqtt/private-lib-roles-mqtt.h @@ -357,6 +357,7 @@ struct _lws_mqtt_related { lws_sorted_usec_list_t sul_qos1_puback_wait; /* QoS1 puback wait TO */ lws_sorted_usec_list_t sul_unsuback_wait; /* unsuback wait TO */ lws_sorted_usec_list_t sul_qos2_pubrec_wait; /* QoS2 pubrec wait TO */ + lws_sorted_usec_list_t sul_shadow_wait; /* Device Shadow wait TO */ struct lws *wsi; /**< so sul can use lws_container_of */ lws_mqtt_subs_t *subs_head; /**< Linked-list of heap-allocated subscription objects */ void *rx_cpkt_param; @@ -383,6 +384,9 @@ struct _lws_mqtt_related { uint8_t done_subscribe:1; uint8_t done_birth:1; + uint8_t inside_shadow:1; + uint8_t done_shadow_subscribe:1; + uint8_t send_shadow_unsubscribe:1; }; /* @@ -438,5 +442,8 @@ lws_wsi_mqtt_adopt(struct lws *parent_wsi, struct lws *wsi); lws_mqtt_subs_t * lws_mqtt_find_sub(struct _lws_mqtt_related *mqtt, const char *topic); +lws_mqtt_match_topic_return_t +lws_mqtt_is_topic_matched(const char* sub, const char* pub); + #endif /* _PRIVATE_LIB_ROLES_MQTT */ diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index b14a828764..cc2fc4cfb5 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -147,6 +147,7 @@ typedef struct lws_ss_handle { lws_mqtt_topic_elem_t topic_qos; lws_mqtt_topic_elem_t sub_top; lws_mqtt_subscribe_param_t sub_info; + lws_mqtt_subscribe_param_t shadow_sub; /* allocation that must be destroyed with conn */ void *heap_baggage; const char *subscribe_to; diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 11ab7b27b1..551ac0435c 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -298,16 +298,189 @@ secstream_mqtt_resend(struct lws *wsi, uint8_t *buf) { return 0; } +static char * +expand_metadata(lws_ss_handle_t *h, const char* str, const char* post, size_t max_len) +{ + lws_strexp_t exp = {0}; + char* expbuf = NULL; + size_t used_in = 0, used_out = 0, post_len = 0; + + if (post) + post_len = strlen(post); + + if (post_len > max_len) + return NULL; + + lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, NULL, + max_len - post_len); + + if (lws_strexp_expand(&exp, str, strlen(str), &used_in, + &used_out) != LSTRX_DONE) { + lwsl_err("%s, failed to expand %s", __func__, str); + return NULL; + } + + expbuf = lws_malloc(used_out + 1 + post_len, __func__); + if (!expbuf) { + lwsl_err("%s, failed to allocate str_exp for %s", __func__, str); + return NULL; + } + lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, expbuf, + used_out + 1 + post_len); + + if (lws_strexp_expand(&exp, str, strlen(str), &used_in, + &used_out) != LSTRX_DONE) { + lwsl_err("%s, failed to expand str_exp %s\n", __func__, str); + lws_free(expbuf); + return NULL; + } + if (post) { + strcat(expbuf, post); + } + + return expbuf; +} + +static lws_mqtt_match_topic_return_t +secstream_mqtt_is_shadow_matched(struct lws *wsi, const char *topic) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + const char *match[] = { LWS_MQTT_SHADOW_UNNAMED_TOPIC_MATCH, + LWS_MQTT_SHADOW_NAMED_TOPIC_MATCH }; + char *expbuf = NULL; + unsigned int i = 0; + lws_mqtt_match_topic_return_t ret = LMMTR_TOPIC_NOMATCH; + + if (!topic) + return LMMTR_TOPIC_MATCH_ERROR; + + expbuf = expand_metadata(h, topic, NULL, LWS_MQTT_MAX_AWSIOT_TOPICLEN); + if (!expbuf) { + lwsl_warn("%s, failed to expand Shadow topic", __func__); + return LMMTR_TOPIC_MATCH_ERROR; + } + for (i = 0; i < (sizeof(match) / sizeof(match[0])); i++) { + if (lws_mqtt_is_topic_matched( + match[i], expbuf) == LMMTR_TOPIC_MATCH) { + ret = LMMTR_TOPIC_MATCH; + break; + } + } + lws_free(expbuf); + + return ret; +} + +static void +secstream_mqtt_shadow_cleanup(struct lws *wsi) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + uint32_t i = 0; + + for (i = 0; i < h->u.mqtt.shadow_sub.num_topics; i++) { + lws_free((void *)h->u.mqtt.shadow_sub.topic[i].name); + } + + h->u.mqtt.shadow_sub.num_topics = 0; + + if (h->u.mqtt.shadow_sub.topic) { + lws_free(h->u.mqtt.shadow_sub.topic); + h->u.mqtt.shadow_sub.topic = NULL; + } +} + +static lws_ss_state_return_t +secstream_mqtt_shadow_unsubscribe(struct lws *wsi) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + + if (h->u.mqtt.shadow_sub.num_topics == 0) { + wsi->mqtt->send_shadow_unsubscribe = 0; + wsi->mqtt->inside_shadow = 0; + wsi->mqtt->done_shadow_subscribe = 0; + return LWSSSSRET_OK; + } + + if (lws_mqtt_client_send_unsubcribe(wsi, &h->u.mqtt.shadow_sub)) { + lwsl_err("%s, failed to send MQTT unsubsribe", __func__); + return LWSSSSRET_DISCONNECT_ME; + } + /* Expect a UNSUBACK */ + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { + lwsl_err("%s: Unable to set LWS_POLLIN\n", __func__); + return LWSSSSRET_DISCONNECT_ME; + } + wsi->mqtt->send_shadow_unsubscribe = 0; + + return LWSSSSRET_OK; +} + +static int +secstream_mqtt_shadow_subscribe(struct lws *wsi) +{ + lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + char* expbuf = NULL; + const char *suffixes[] = { LWS_MQTT_SHADOW_RESP_ACCEPTED_STR, + LWS_MQTT_SHADOW_RESP_REJECTED_STR }; + unsigned int suffixes_len = sizeof(suffixes) / sizeof(suffixes[0]); + + if (!h->policy->u.mqtt.topic || wsi->mqtt->inside_shadow) + return 0; + + if (h->u.mqtt.shadow_sub.num_topics > 0) + secstream_mqtt_shadow_cleanup(wsi); + + memset(&h->u.mqtt.shadow_sub, 0, sizeof(lws_mqtt_subscribe_param_t)); + h->u.mqtt.shadow_sub.topic = lws_malloc( + sizeof(lws_mqtt_topic_elem_t) * suffixes_len, __func__); + if (!h->u.mqtt.shadow_sub.topic) { + lwsl_err("%s, failed to allocate Shadow topics", __func__); + return -1; + } + h->u.mqtt.shadow_sub.num_topics = suffixes_len; + for (unsigned int i = 0; i < suffixes_len; i++) { + expbuf = expand_metadata(h, h->policy->u.mqtt.topic, suffixes[i], + LWS_MQTT_MAX_AWSIOT_TOPICLEN); + if (!expbuf) { + lwsl_err("%s, failed to allocate Shadow topic", + __func__); + secstream_mqtt_shadow_cleanup(wsi); + return -1; + } + h->u.mqtt.shadow_sub.topic[i].name = expbuf; + h->u.mqtt.shadow_sub.topic[i].qos = h->policy->u.mqtt.qos; + } + h->u.mqtt.shadow_sub.packet_id = (uint16_t)(h->txord - 1); + + if (lws_mqtt_client_send_subcribe(wsi, &h->u.mqtt.shadow_sub)) { + lwsl_notice("%s: unable to subscribe Shadow topics", __func__); + return 0; + } + + /* Expect a SUBACK */ + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { + lwsl_err("%s: Unable to set LWS_POLLIN\n", __func__); + return -1; + } + wsi->mqtt->inside_shadow = 1; + + return 0; +} + static int secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); - lws_mqtt_publish_param_t *pmqpp; - uint8_t buf[LWS_PRE + 1400]; - lws_ss_state_return_t r; + lws_mqtt_publish_param_t *pmqpp = NULL; + lws_ss_metadata_t *omd = NULL; + uint8_t buf[LWS_PRE + 1400] = {0}; + lws_ss_state_return_t r = LWSSSSRET_OK; size_t buflen = sizeof(buf) - LWS_PRE; int f = 0; + lws_strexp_t exp = {0}; + size_t used_in = 0, used_out = 0, topic_len = 0; + char* sub_topic = NULL; switch (reason) { @@ -458,14 +631,85 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->subseq = 1; + if (wsi->mqtt->inside_shadow) { + /* + * When Shadow is used, the stream receives multiple + * topics including Shadow response, set received + * topic on the metadata + */ + lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, + NULL, (size_t)-1); + + if (lws_strexp_expand(&exp, h->policy->u.mqtt.subscribe, + strlen(h->policy->u.mqtt.subscribe), + &used_in, &used_out) != LSTRX_DONE) { + lwsl_err("%s, failed to expand subscribe topic", + __func__); + return -1; + } + omd = lws_ss_get_handle_metadata(h, exp.name); + + if (!omd) { + lwsl_err("%s, failed to find metadata for subscribe", + __func__); + return -1; + } + sub_topic = omd->value__may_own_heap; + topic_len = omd->length; + + _lws_ss_set_metadata(omd, exp.name, + (const void *)pmqpp->topic, + pmqpp->topic_len); + } + r = h->info.rx(ss_to_userobj(h), (const uint8_t *)pmqpp->payload, len, f); + + if (wsi->mqtt->inside_shadow) { + _lws_ss_set_metadata(omd, exp.name, &sub_topic, + topic_len); + } + if (r != LWSSSSRET_OK) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); + if (wsi->mqtt->inside_shadow) { + uint32_t acc_n = strlen(LWS_MQTT_SHADOW_RESP_ACCEPTED_STR); + uint32_t rej_n = strlen(LWS_MQTT_SHADOW_RESP_REJECTED_STR); + + for (uint32_t i = 0; i < h->u.mqtt.shadow_sub.num_topics; i++) { + /* + * received response ('/accepted' or 'rejected') + * and clean up Shadow operation + */ + if (strncmp(h->u.mqtt.shadow_sub.topic[i].name, + pmqpp->topic, pmqpp->topic_len) || + (strlen(pmqpp->topic) < acc_n || + strlen(pmqpp->topic) < rej_n)) + continue; + + if (!strcmp(pmqpp->topic + + (strlen(pmqpp->topic) - acc_n), + LWS_MQTT_SHADOW_RESP_ACCEPTED_STR) || + !strcmp(pmqpp->topic + + (strlen(pmqpp->topic) - rej_n), + LWS_MQTT_SHADOW_RESP_REJECTED_STR)) { + lws_sul_cancel( + &wsi->mqtt->sul_shadow_wait); + wsi->mqtt->send_shadow_unsubscribe = 1; + lws_callback_on_writable(wsi); + return 0; + } + } + } return 0; /* don't passthru */ case LWS_CALLBACK_MQTT_SUBSCRIBED: + if (wsi->mqtt->inside_shadow) { + wsi->mqtt->done_shadow_subscribe = 1; + lws_callback_on_writable(wsi); + return 0; + } /* * Stream demanded a subscribe without a Birth while connecting, once * done notify CONNECTED event to the application. @@ -555,11 +799,25 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (!wsi->mqtt->done_birth && h->policy->u.mqtt.birth_topic) return secstream_mqtt_birth(wsi, buf + LWS_PRE, buflen); + if (h->policy->u.mqtt.aws_iot) { + if (secstream_mqtt_is_shadow_matched(wsi, + h->policy->u.mqtt.topic) == LMMTR_TOPIC_MATCH) { + if (!wsi->mqtt->done_shadow_subscribe) + return secstream_mqtt_shadow_subscribe(wsi); + if (wsi->mqtt->send_shadow_unsubscribe) + return secstream_mqtt_shadow_unsubscribe(wsi); + } + } + r = h->info.tx(ss_to_userobj(h), h->txord++, buf + LWS_PRE, &buflen, &f); - if (r == LWSSSSRET_TX_DONT_SEND) + if (r == LWSSSSRET_TX_DONT_SEND) { + if (wsi->mqtt->done_shadow_subscribe) { + return secstream_mqtt_shadow_unsubscribe(wsi); + } return 0; + } if (r == LWSSSSRET_DISCONNECT_ME) { lws_mqtt_subscribe_param_t lmsp; @@ -595,19 +853,50 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_MQTT_UNSUBSCRIBED: { struct lws *nwsi = lws_get_network_wsi(wsi); + + if (wsi->mqtt->inside_shadow) { + secstream_mqtt_shadow_cleanup(wsi); + wsi->mqtt->inside_shadow = 0; + wsi->mqtt->done_shadow_subscribe = 0; + break; + } if (nwsi && (nwsi->mux.child_count == 1)) lws_mqtt_client_send_disconnect(nwsi); return -1; } case LWS_CALLBACK_MQTT_UNSUBSCRIBE_TIMEOUT: + if (!wsi || !wsi->mqtt) + return -1; + + if (wsi->mqtt->inside_shadow) { + secstream_mqtt_shadow_cleanup(wsi); + wsi->mqtt->inside_shadow = 0; + wsi->mqtt->done_shadow_subscribe = 0; + lwsl_warn("%s: %s: Unsubscribe (Shadow) timeout.\n", + __func__, lws_ss_tag(h)); + break; + } + if (wsi->mqtt->inside_unsubscribe) { - lwsl_warn("%s: %s: Unsubscribe timout.\n", __func__, + lwsl_warn("%s: %s: Unsubscribe timeout.\n", __func__, lws_ss_tag(h)); return -1; } break; + case LWS_CALLBACK_MQTT_SHADOW_TIMEOUT: + if (!wsi || !wsi->mqtt) + return -1; + + if (wsi->mqtt->inside_shadow) { + lwsl_warn("%s: %s: Shadow timeout.\n", __func__, + lws_ss_tag(h)); + wsi->mqtt->send_shadow_unsubscribe = 1; + lws_callback_on_writable(wsi); + } + break; + default: break; } From 71db363fe4d1ca8f27d5eec0db39350b2df6ab64 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 3 May 2022 17:29:12 +0100 Subject: [PATCH 148/275] ss: mqtt: remove c99isms and fix types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Blows on Centos 7 / 8 in Sai with /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c: In function âexpand_metadataâ: /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:304:2: error: missing braces around initializer [-Werror=missing-braces] lws_strexp_t exp = {0}; ^ /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:304:2: error: (near initialization for âexp.nameâ) [-Werror=missing-braces] /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:304:2: error: missing initializer for field âcbâ of âlws_strexp_tâ [-Werror=missing-field-initializers] In file included from /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/include/libwebsockets.h:737:0, from /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/core/./private-lib-core.h:146, from /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:25: /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/include/libwebsockets/lws-tokenize.h:196:23: note: âcbâ declared here lws_strexp_expand_cb cb; ^ /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c: In function âsecstream_mqtt_shadow_subscribeâ: /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:441:2: error: âforâ loop initial declarations are only allowed in C99 mode for (unsigned int i = 0; i < suffixes_len; i++) { ^ /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:441:2: note: use option -std=c99 or -std=gnu99 to compile your code /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c: In function âsecstream_mqttâ: /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:481:2: error: missing braces around initializer [-Werror=missing-braces] lws_strexp_t exp = {0}; ^ /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:481:2: error: (near initialization for âexp.nameâ) [-Werror=missing-braces] /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:481:2: error: missing initializer for field âcbâ of âlws_strexp_tâ [-Werror=missing-field-initializers] In file included from /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/include/libwebsockets.h:737:0, from /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/core/./private-lib-core.h:146, from /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:25: /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/include/libwebsockets/lws-tokenize.h:196:23: note: âcbâ declared here lws_strexp_expand_cb cb; ^ /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:677:27: error: conversion to âuint32_tâ from âsize_tâ may alter its value [-Werror=conversion] uint32_t acc_n = strlen(LWS_MQTT_SHADOW_RESP_ACCEPTED_STR); ^ /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:678:27: error: conversion to âuint32_tâ from âsize_tâ may alter its value [-Werror=conversion] uint32_t rej_n = strlen(LWS_MQTT_SHADOW_RESP_REJECTED_STR); ^ /home/sai/big-long-dir-to-make-rpm-happy-o/jobs/0-0.0/libwebsockets/lib/secure-streams/protocols/ss-mqtt.c:680:4: error: âforâ loop initial declarations are only allowed in C99 mode for (uint32_t i = 0; i < h->u.mqtt.shadow_sub.num_topics; i++) { little additional cleaning and conversion to modern lwsl_xxx_yyy(xxx, ...) --- lib/secure-streams/protocols/ss-mqtt.c | 77 +++++++++++++++----------- 1 file changed, 45 insertions(+), 32 deletions(-) diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index 551ac0435c..f79b94729a 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -301,30 +301,35 @@ secstream_mqtt_resend(struct lws *wsi, uint8_t *buf) { static char * expand_metadata(lws_ss_handle_t *h, const char* str, const char* post, size_t max_len) { - lws_strexp_t exp = {0}; - char* expbuf = NULL; + lws_strexp_t exp; + char *expbuf = NULL; size_t used_in = 0, used_out = 0, post_len = 0; + memset(&exp, 0, sizeof(exp)); + if (post) post_len = strlen(post); if (post_len > max_len) return NULL; - lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, NULL, + lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, NULL, max_len - post_len); if (lws_strexp_expand(&exp, str, strlen(str), &used_in, &used_out) != LSTRX_DONE) { lwsl_err("%s, failed to expand %s", __func__, str); + return NULL; } expbuf = lws_malloc(used_out + 1 + post_len, __func__); if (!expbuf) { lwsl_err("%s, failed to allocate str_exp for %s", __func__, str); + return NULL; } + lws_strexp_init(&exp, (void*)h, lws_ss_exp_cb_metadata, expbuf, used_out + 1 + post_len); @@ -332,11 +337,11 @@ expand_metadata(lws_ss_handle_t *h, const char* str, const char* post, size_t ma &used_out) != LSTRX_DONE) { lwsl_err("%s, failed to expand str_exp %s\n", __func__, str); lws_free(expbuf); + return NULL; } - if (post) { + if (post) strcat(expbuf, post); - } return expbuf; } @@ -356,7 +361,8 @@ secstream_mqtt_is_shadow_matched(struct lws *wsi, const char *topic) expbuf = expand_metadata(h, topic, NULL, LWS_MQTT_MAX_AWSIOT_TOPICLEN); if (!expbuf) { - lwsl_warn("%s, failed to expand Shadow topic", __func__); + lwsl_wsi_warn(wsi, "Failed to expand Shadow topic"); + return LMMTR_TOPIC_MATCH_ERROR; } for (i = 0; i < (sizeof(match) / sizeof(match[0])); i++) { @@ -377,9 +383,8 @@ secstream_mqtt_shadow_cleanup(struct lws *wsi) lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint32_t i = 0; - for (i = 0; i < h->u.mqtt.shadow_sub.num_topics; i++) { + for (i = 0; i < h->u.mqtt.shadow_sub.num_topics; i++) lws_free((void *)h->u.mqtt.shadow_sub.topic[i].name); - } h->u.mqtt.shadow_sub.num_topics = 0; @@ -398,16 +403,19 @@ secstream_mqtt_shadow_unsubscribe(struct lws *wsi) wsi->mqtt->send_shadow_unsubscribe = 0; wsi->mqtt->inside_shadow = 0; wsi->mqtt->done_shadow_subscribe = 0; + return LWSSSSRET_OK; } if (lws_mqtt_client_send_unsubcribe(wsi, &h->u.mqtt.shadow_sub)) { - lwsl_err("%s, failed to send MQTT unsubsribe", __func__); + lwsl_wsi_err(wsi, "Failed to send MQTT unsubsribe"); + return LWSSSSRET_DISCONNECT_ME; } /* Expect a UNSUBACK */ if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { - lwsl_err("%s: Unable to set LWS_POLLIN\n", __func__); + lwsl_wsi_err(wsi, "Unable to set LWS_POLLIN"); + return LWSSSSRET_DISCONNECT_ME; } wsi->mqtt->send_shadow_unsubscribe = 0; @@ -422,7 +430,7 @@ secstream_mqtt_shadow_subscribe(struct lws *wsi) char* expbuf = NULL; const char *suffixes[] = { LWS_MQTT_SHADOW_RESP_ACCEPTED_STR, LWS_MQTT_SHADOW_RESP_REJECTED_STR }; - unsigned int suffixes_len = sizeof(suffixes) / sizeof(suffixes[0]); + unsigned int i, suffixes_len = sizeof(suffixes) / sizeof(suffixes[0]); if (!h->policy->u.mqtt.topic || wsi->mqtt->inside_shadow) return 0; @@ -434,17 +442,17 @@ secstream_mqtt_shadow_subscribe(struct lws *wsi) h->u.mqtt.shadow_sub.topic = lws_malloc( sizeof(lws_mqtt_topic_elem_t) * suffixes_len, __func__); if (!h->u.mqtt.shadow_sub.topic) { - lwsl_err("%s, failed to allocate Shadow topics", __func__); + lwsl_ss_err(h, "Failed to allocate Shadow topics"); return -1; } h->u.mqtt.shadow_sub.num_topics = suffixes_len; - for (unsigned int i = 0; i < suffixes_len; i++) { + for (i = 0; i < suffixes_len; i++) { expbuf = expand_metadata(h, h->policy->u.mqtt.topic, suffixes[i], LWS_MQTT_MAX_AWSIOT_TOPICLEN); if (!expbuf) { - lwsl_err("%s, failed to allocate Shadow topic", - __func__); + lwsl_ss_err(h, "Failed to allocate Shadow topic"); secstream_mqtt_shadow_cleanup(wsi); + return -1; } h->u.mqtt.shadow_sub.topic[i].name = expbuf; @@ -453,7 +461,8 @@ secstream_mqtt_shadow_subscribe(struct lws *wsi) h->u.mqtt.shadow_sub.packet_id = (uint16_t)(h->txord - 1); if (lws_mqtt_client_send_subcribe(wsi, &h->u.mqtt.shadow_sub)) { - lwsl_notice("%s: unable to subscribe Shadow topics", __func__); + lwsl_wsi_notice(wsi, "Unable to subscribe Shadow topics"); + return 0; } @@ -472,15 +481,18 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); + size_t used_in = 0, used_out = 0, topic_len = 0; lws_mqtt_publish_param_t *pmqpp = NULL; - lws_ss_metadata_t *omd = NULL; - uint8_t buf[LWS_PRE + 1400] = {0}; lws_ss_state_return_t r = LWSSSSRET_OK; + uint8_t buf[LWS_PRE + 1400]; size_t buflen = sizeof(buf) - LWS_PRE; + lws_ss_metadata_t *omd = NULL; + char *sub_topic = NULL; + lws_strexp_t exp; int f = 0; - lws_strexp_t exp = {0}; - size_t used_in = 0, used_out = 0, topic_len = 0; - char* sub_topic = NULL; + + memset(buf, 0, sizeof(buf)); + memset(&exp, 0, sizeof(exp)); switch (reason) { @@ -665,19 +677,19 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, r = h->info.rx(ss_to_userobj(h), (const uint8_t *)pmqpp->payload, len, f); - if (wsi->mqtt->inside_shadow) { + if (wsi->mqtt->inside_shadow) _lws_ss_set_metadata(omd, exp.name, &sub_topic, topic_len); - } if (r != LWSSSSRET_OK) return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); if (wsi->mqtt->inside_shadow) { - uint32_t acc_n = strlen(LWS_MQTT_SHADOW_RESP_ACCEPTED_STR); - uint32_t rej_n = strlen(LWS_MQTT_SHADOW_RESP_REJECTED_STR); + size_t acc_n = strlen(LWS_MQTT_SHADOW_RESP_ACCEPTED_STR); + size_t rej_n = strlen(LWS_MQTT_SHADOW_RESP_REJECTED_STR); + uint32_t i; - for (uint32_t i = 0; i < h->u.mqtt.shadow_sub.num_topics; i++) { + for (i = 0; i < h->u.mqtt.shadow_sub.num_topics; i++) { /* * received response ('/accepted' or 'rejected') * and clean up Shadow operation @@ -689,15 +701,15 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, continue; if (!strcmp(pmqpp->topic + - (strlen(pmqpp->topic) - acc_n), - LWS_MQTT_SHADOW_RESP_ACCEPTED_STR) || + (strlen(pmqpp->topic) - acc_n), + LWS_MQTT_SHADOW_RESP_ACCEPTED_STR) || !strcmp(pmqpp->topic + - (strlen(pmqpp->topic) - rej_n), - LWS_MQTT_SHADOW_RESP_REJECTED_STR)) { - lws_sul_cancel( - &wsi->mqtt->sul_shadow_wait); + (strlen(pmqpp->topic) - rej_n), + LWS_MQTT_SHADOW_RESP_REJECTED_STR)) { + lws_sul_cancel(&wsi->mqtt->sul_shadow_wait); wsi->mqtt->send_shadow_unsubscribe = 1; lws_callback_on_writable(wsi); + return 0; } } @@ -708,6 +720,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (wsi->mqtt->inside_shadow) { wsi->mqtt->done_shadow_subscribe = 1; lws_callback_on_writable(wsi); + return 0; } /* From 310abddf5e692b04cec88fa354b53ea4fd9eb293 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 4 May 2022 07:38:49 +0100 Subject: [PATCH 149/275] coverity: ss: mqtt: remove needless wsi check 881 case LWS_CALLBACK_MQTT_UNSUBSCRIBE_TIMEOUT: >>> CID 392688: (REVERSE_INULL) >>> Null-checking "wsi" suggests that it may be null, but it has already been dereferenced on all paths leading to the check. 882 if (!wsi || !wsi->mqtt) 883 return -1; wsi can't be NULL for a callback specific to a wsi. --- lib/secure-streams/protocols/ss-mqtt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/secure-streams/protocols/ss-mqtt.c b/lib/secure-streams/protocols/ss-mqtt.c index f79b94729a..8698bee441 100644 --- a/lib/secure-streams/protocols/ss-mqtt.c +++ b/lib/secure-streams/protocols/ss-mqtt.c @@ -879,7 +879,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, } case LWS_CALLBACK_MQTT_UNSUBSCRIBE_TIMEOUT: - if (!wsi || !wsi->mqtt) + if (!wsi->mqtt) return -1; if (wsi->mqtt->inside_shadow) { @@ -899,7 +899,7 @@ secstream_mqtt(struct lws *wsi, enum lws_callback_reasons reason, void *user, break; case LWS_CALLBACK_MQTT_SHADOW_TIMEOUT: - if (!wsi || !wsi->mqtt) + if (!wsi->mqtt) return -1; if (wsi->mqtt->inside_shadow) { From bfd921df9c79c1b0cf8cf5040ceffdf5fd7d221a Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 3 May 2022 13:25:04 +0100 Subject: [PATCH 150/275] clean: remove needless LWS_PRE Several examples trim their buffer with an extra LWS_PRE from the end... actually end should point to end the end of buf without a second LWS_PRE reservation. https://github.com/warmcat/libwebsockets/issues/2629 --- .../minimal-http-client-multi/minimal-http-client-multi.c | 2 +- .../minimal-http-client-post/minimal-http-client-post.c | 2 +- .../minimal-http-server-custom-headers.c | 2 +- .../minimal-http-server-dynamic/minimal-http-server-dynamic.c | 2 +- .../minimal-http-server-h2-long-poll/minimal-http-server.c | 2 +- plugins/acme-client/protocol_lws_acme_client.c | 2 +- plugins/deaddrop/protocol_lws_deaddrop.c | 2 +- plugins/protocol_fulltext_demo.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c b/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c index d0d11f3fe2..f30ee589b4 100644 --- a/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c +++ b/minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c @@ -167,7 +167,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { char buf[LWS_PRE + 1024], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; int n, idx = (int)(intptr_t)lws_get_opaque_user_data(wsi); struct pss *pss = (struct pss *)user; diff --git a/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c b/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c index 3bff115a68..063f8f1cd1 100644 --- a/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c +++ b/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c @@ -30,7 +30,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, { struct pss *pss = (struct pss *)user; char buf[LWS_PRE + 1024], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; int n; switch (reason) { diff --git a/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c b/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c index d9a1f31ab5..4ffe32c1f8 100644 --- a/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c +++ b/minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c @@ -37,7 +37,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { uint8_t buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; struct pss *pss = (struct pss *)user; char value[32], *pr = &pss->result[LWS_PRE]; size_t e = sizeof(pss->result) - LWS_PRE; diff --git a/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c b/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c index f919146b34..daade23b7a 100644 --- a/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c +++ b/minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c @@ -42,7 +42,7 @@ callback_dynamic_http(struct lws *wsi, enum lws_callback_reasons reason, { struct pss *pss = (struct pss *)user; uint8_t buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; time_t t; int n; #if defined(LWS_HAVE_CTIME_R) diff --git a/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c b/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c index c5614e5590..a47be0b2a4 100644 --- a/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c +++ b/minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c @@ -57,7 +57,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, struct pss * pss = (struct pss *)user; uint8_t buf[LWS_PRE + LWS_RECOMMENDED_MIN_HEADER_SPACE], *start = &buf[LWS_PRE], *p = start, - *end = p + sizeof(buf) - LWS_PRE; + *end = buf + sizeof(buf) - 1; int m, n; switch (reason) { diff --git a/plugins/acme-client/protocol_lws_acme_client.c b/plugins/acme-client/protocol_lws_acme_client.c index f6be2b012e..729c4482e1 100644 --- a/plugins/acme-client/protocol_lws_acme_client.c +++ b/plugins/acme-client/protocol_lws_acme_client.c @@ -136,7 +136,7 @@ callback_chall_http01(struct lws *wsi, enum lws_callback_reasons reason, struct lws_vhost *vhost = lws_get_vhost(wsi); struct acme_connection *ac = lws_vhost_user(vhost); uint8_t buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; int n; switch (reason) { diff --git a/plugins/deaddrop/protocol_lws_deaddrop.c b/plugins/deaddrop/protocol_lws_deaddrop.c index 79f736c0a1..0e51507b65 100644 --- a/plugins/deaddrop/protocol_lws_deaddrop.c +++ b/plugins/deaddrop/protocol_lws_deaddrop.c @@ -383,7 +383,7 @@ callback_deaddrop(struct lws *wsi, enum lws_callback_reasons reason, struct pss_deaddrop *pss = (struct pss_deaddrop *)user; uint8_t buf[LWS_PRE + LWS_RECOMMENDED_MIN_HEADER_SPACE], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; char fname[256], *wp; const char *cp; int n, m, was; diff --git a/plugins/protocol_fulltext_demo.c b/plugins/protocol_fulltext_demo.c index 0d780993ba..35d91e196b 100644 --- a/plugins/protocol_fulltext_demo.c +++ b/plugins/protocol_fulltext_demo.c @@ -65,7 +65,7 @@ callback_fts(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_get_protocol(wsi)); struct pss_fts_demo *pss = (struct pss_fts_demo *)user; uint8_t buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *p = start, - *end = &buf[sizeof(buf) - LWS_PRE - 1]; + *end = &buf[sizeof(buf) - 1]; struct lws_fts_search_params params; const char *ccp = (const char *)in; struct lws_fts_result *result; From 6d8a798742756e191e11947f3b7fc24ed5e301c4 Mon Sep 17 00:00:00 2001 From: Andrii Sevastianov Date: Tue, 3 May 2022 16:47:14 +0200 Subject: [PATCH 151/275] validity: fix bad pointer access We cannot access wsi after __lws_close_free_wsi. --- lib/core-net/wsi-timeout.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/core-net/wsi-timeout.c b/lib/core-net/wsi-timeout.c index bbaed54c82..b72f134f55 100644 --- a/lib/core-net/wsi-timeout.c +++ b/lib/core-net/wsi-timeout.c @@ -206,14 +206,15 @@ lws_validity_cb(lws_sorted_usec_list_t *sul) if (wsi->validity_hup) { lwsl_wsi_info(wsi, "validity too old"); - struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; + struct lws_context *cx = wsi->a.context; + struct lws_context_per_thread *pt = &cx->pt[(int)wsi->tsi]; - lws_context_lock(wsi->a.context, __func__); + lws_context_lock(cx, __func__); lws_pt_lock(pt, __func__); __lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "validity timeout"); lws_pt_unlock(pt); - lws_context_unlock(wsi->a.context); + lws_context_unlock(cx); return; } From 5a008cf282b9ab2b45adc44f55a733e23f6b0cb6 Mon Sep 17 00:00:00 2001 From: Richard Shi Date: Wed, 4 May 2022 05:10:37 +0100 Subject: [PATCH 152/275] http: compression: fix selection https://github.com/warmcat/libwebsockets/issues/2633 --- lib/roles/http/compression/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/http/compression/stream.c b/lib/roles/http/compression/stream.c index 9898b76f9a..d4c72aa439 100644 --- a/lib/roles/http/compression/stream.c +++ b/lib/roles/http/compression/stream.c @@ -65,7 +65,7 @@ lws_http_compression_apply(struct lws *wsi, const char *name, for (n = 0; n < LWS_ARRAY_SIZE(lcs_available); n++) { /* if name is non-NULL, choose only that compression method */ - if (name && !strcmp(lcs_available[n]->encoding_name, name)) + if (name && strcmp(lcs_available[n]->encoding_name, name)) continue; /* * If we're the server, confirm that the client told us he could From b0a749c8e7a8294b68581ce4feac0e55045eb00b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 17 May 2022 17:53:21 +0100 Subject: [PATCH 153/275] v4.3.2 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6a62e4db8..166d48a456 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -410,7 +410,7 @@ set(CPACK_RPM_PACKAGE_LICENSE "MIT") set(CPACK_PACKAGE_NAME "${PACKAGE}") set(CPACK_PACKAGE_VERSION_MAJOR "4") set(CPACK_PACKAGE_VERSION_MINOR "3") -set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "0") +set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "2") set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH_NUMBER}-${LWS_BUILD_HASH}") set(CPACK_PACKAGE_RELEASE 1) From ebabf49bcefe4182323eb2dee26978ff21fa8747 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 13 Feb 2022 09:17:27 +0000 Subject: [PATCH 154/275] http: server: mounts: dont assume Basic Auth if no FILE_OPS --- lib/roles/http/server/server.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index c98bf0d69a..04e6ce71a0 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -1232,6 +1232,8 @@ lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file, return LCBA_CONTINUE; #else + if (!basic_auth_login_file && auth_mode == LWSAUTHM_DEFAULT) + return LCBA_CONTINUE; return LCBA_FAILED_AUTH; #endif } From fe107059fc21694ca41b05cbbf6246d80371a8d7 Mon Sep 17 00:00:00 2001 From: Paul Shark Date: Tue, 14 Jun 2022 05:33:41 +0100 Subject: [PATCH 155/275] http: server: correct plugin name in error --- lib/roles/http/server/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index 04e6ce71a0..dca9a5e60b 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -1856,7 +1856,7 @@ lws_http_action(struct lws *wsi) pp = lws_vhost_name_to_protocol(wsi->a.vhost, name); if (!pp) { lwsl_err("Unable to find plugin '%s'\n", - hit->origin); + name); return 1; } From 754d2b4578ffb5bc49b82f9988fdf8e339876743 Mon Sep 17 00:00:00 2001 From: Mykola Stryebkov Date: Tue, 14 Jun 2022 05:37:52 +0100 Subject: [PATCH 156/275] eventloop: windows: ssl: remove spin --- lib/plat/windows/windows-service.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c index a64501d36c..b56ef43de1 100644 --- a/lib/plat/windows/windows-service.c +++ b/lib/plat/windows/windows-service.c @@ -41,11 +41,12 @@ _lws_plat_service_forced_tsi(struct lws_context *context, int tsi) if (!pt->fds[n].revents) continue; + unsigned int fds_count = pt->fds_count; m = lws_service_fd_tsi(context, &pt->fds[n], tsi); if (m < 0) return -1; - /* if something closed, retry this slot */ - if (m) + /* if something closed, fds_count will change, retry this slot */ + if (pt->fds_count != fds_count) n--; } From 065035ecd568798f3ea3571fd7fbcd41706ab543 Mon Sep 17 00:00:00 2001 From: Jaume Date: Tue, 14 Jun 2022 05:41:05 +0100 Subject: [PATCH 157/275] windows: client connect: use sockaddr size --- lib/core-net/client/connect3.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/core-net/client/connect3.c b/lib/core-net/client/connect3.c index b7523303d7..a9d2e9e0e2 100644 --- a/lib/core-net/client/connect3.c +++ b/lib/core-net/client/connect3.c @@ -105,7 +105,13 @@ lws_client_connect_check(struct lws *wsi, int *real_errno) #else - if (!connect(wsi->desc.sockfd, (const struct sockaddr *)&wsi->sa46_peer.sa4, 0)) + if (!connect(wsi->desc.sockfd, (const struct sockaddr *)&wsi->sa46_peer.sa4, +#if defined(WIN32) + sizeof(struct sockaddr))) +#else + 0)) +#endif + return LCCCR_CONNECTED; en = LWS_ERRNO; From a5f81f833685b4dbdb7b269b654f8494ed2954fb Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Sat, 28 May 2022 23:15:40 +0200 Subject: [PATCH 158/275] lib/tls/CMakeLists.txt: fix build without threads openssl can be built without threads resulting in the following build failure: -- Looking for HMAC_CTX_new -- Looking for HMAC_CTX_new - not found [...] In file included from /home/buildroot/autobuild/instance-0/output-1/build/libwebsockets-4.3.1/include/libwebsockets.h:661, from /home/buildroot/autobuild/instance-0/output-1/build/libwebsockets-4.3.1/lib/core/./private-lib-core.h:140, from /home/buildroot/autobuild/instance-0/output-1/build/libwebsockets-4.3.1/lib/plat/unix/unix-misc.c:28: /home/buildroot/autobuild/instance-0/output-1/build/libwebsockets-4.3.1/include/libwebsockets/lws-genhash.h:85:18: error: field 'ctx' has incomplete type 85 | HMAC_CTX ctx; | ^~~ To fix this build failure, don't unconditionally add pthread if openssl has been found through pkg-config as openssl.pc will contain the appropriate dependencies (i.e. -lpthread but also -lz or -latomic) Fixes: - http://autobuild.buildroot.org/results/2ae9e3249b6fcc9e6c30e7783e264fc6599e61df Signed-off-by: Fabrice Fontaine --- lib/tls/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index fb9a75fe55..f55337cb7a 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -310,7 +310,7 @@ endif() if (UNIX AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "QNX")) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${CMAKE_DL_LIBS}) endif() -if ((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "QNX")) +if ((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT ((${CMAKE_SYSTEM_NAME} MATCHES "QNX") OR PC_OPENSSL_FOUND)) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} pthread) endif() From a723789b0e24a04ac78a04dba4a9974d7b15df1b Mon Sep 17 00:00:00 2001 From: Mike Tettinger Date: Fri, 17 Jun 2022 04:49:19 +0100 Subject: [PATCH 159/275] test-apps: use correct EXTERNAL_POLL flag --- test-apps/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-apps/CMakeLists.txt b/test-apps/CMakeLists.txt index 9ffed9f833..e0c097f1db 100644 --- a/test-apps/CMakeLists.txt +++ b/test-apps/CMakeLists.txt @@ -163,7 +163,7 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2)) set_property( TARGET test-server-extpoll PROPERTY COMPILE_DEFINITIONS - EXTERNAL_POLL + LWS_WITH_EXTERNAL_POLL INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" ) From 5a8f790870ec40f4dc148989a4d97c5d31c28377 Mon Sep 17 00:00:00 2001 From: Poljak181 Date: Wed, 29 Jun 2022 17:19:07 +0100 Subject: [PATCH 160/275] logs: setup earlier so we can use on fail path https://github.com/warmcat/libwebsockets/issues/2679 --- lib/core/context.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index af818ebe35..c12b216118 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -609,6 +609,12 @@ lws_create_context(const struct lws_context_creation_info *info) goto early_bail; } +#if defined(LWS_WITH_SYS_STATE) + // NOTE: we need to init this fields because they may be used in logger when context destroying + context->mgr_system.state_names = system_state_names; + context->mgr_system.context = context; +#endif + #if defined(LWS_WITH_NETWORK) context->event_loop_ops = plev->ops; context->us_wait_resolution = us_wait_resolution; @@ -1340,11 +1346,9 @@ lws_create_context(const struct lws_context_creation_info *info) * init the lws_state mgr for the system state */ - context->mgr_system.state_names = system_state_names; context->mgr_system.name = "system"; context->mgr_system.state = LWS_SYSTATE_CONTEXT_CREATED; context->mgr_system.parent = context; - context->mgr_system.context = context; #if defined(LWS_WITH_SYS_SMD) context->mgr_system.smd_class = LWSSMDCL_SYSTEM_STATE; #endif From ee2e4074e4aee3c00e556d988e7a89074970fe22 Mon Sep 17 00:00:00 2001 From: Marco Gratzke Date: Mon, 4 Jul 2022 14:20:44 +0100 Subject: [PATCH 161/275] spa: file upload fix --- lib/roles/http/server/lws-spa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/roles/http/server/lws-spa.c b/lib/roles/http/server/lws-spa.c index a39c661382..ea5d4abd7b 100644 --- a/lib/roles/http/server/lws-spa.c +++ b/lib/roles/http/server/lws-spa.c @@ -438,12 +438,12 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in, case MT_IGNORE3: if (*in == '\x0d') - s->state = MT_IGNORE1; - else if (*in == '-') { + s->state = MT_IGNORE2; + if (*in == '-') { s->state = MT_COMPLETED; s->wsi->http.rx_content_remain = 0; } - else in++; + in++; break; case MT_COMPLETED: break; From ea3a0ab9e00c38ebcfc5b790e71134335a63d640 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 6 Jul 2022 07:47:01 +0100 Subject: [PATCH 162/275] windows: zlib: internal lib doesnt need find_package --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 166d48a456..af1b1e6e1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -882,7 +882,7 @@ endif() # # ZLIB (needed for deflate extension and if LWS_WITH_HTTP_STREAM_COMPRESSION) # -if (LWS_WITH_ZLIB) +if (LWS_WITH_ZLIB AND NOT LWS_WITH_BUNDLED_ZLIB) if (NOT ZLIB_FOUND) if (LWS_WITH_MINIZ) find_package(Miniz REQUIRED) From 0a5526b9589548d9b0197fbac67d7a78a341448a Mon Sep 17 00:00:00 2001 From: qdztxc Date: Tue, 12 Jul 2022 09:47:00 +0100 Subject: [PATCH 163/275] ws: tell caller we closed wsi on handshake failure https://github.com/warmcat/libwebsockets/issues/2681 --- lib/roles/http/client/client-http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 7dce850006..16fd8b245d 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -270,7 +270,7 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) lwsl_err("Failed to generate handshake for client\n"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "chs"); - return 0; + return -1; } /* send our request to the server */ From 50ed5217b0d9154a9a20429c46c7880d1b73ae06 Mon Sep 17 00:00:00 2001 From: Ammar Faizi Date: Wed, 22 Jun 2022 09:02:02 +0700 Subject: [PATCH 164/275] From aa990b1451e87f2ad221b0a1a7ebfc0b1f369292 Mon Sep 17 00:00:00 2001 Subject: [PATCH] lib/secure-streams: Fix clang build error `-Wunused-but-set-variable` When building with clang-15, I got the following error: ``` error: variable 'm' set but not used [-Werror,-Wunused-but-set-variable] int n, m = 0; ^ ``` Let's just remove the `m` variable here, it's not used. Signed-off-by: Ammar Faizi --- lib/secure-streams/protocols/ss-h1.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index d9ffe85296..ddc61b0de6 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -313,7 +313,7 @@ static int lws_extract_metadata(lws_ss_handle_t *h, struct lws *wsi) { lws_ss_metadata_t *polmd = h->policy->metadata, *omd; - int n, m = 0; + int n; while (polmd) { @@ -410,7 +410,6 @@ lws_extract_metadata(lws_ss_handle_t *h, struct lws *wsi) } #endif - m++; polmd = polmd->next; } From 9bfca5b7c3e1358ba5caa94aca30a8e3c511780e Mon Sep 17 00:00:00 2001 From: Arenoros Date: Thu, 30 Jun 2022 12:37:37 +0300 Subject: [PATCH 165/275] From a966322704e47a4f7af4f750a712ea26c9901174 Mon Sep 17 00:00:00 2001 Subject: [PATCH] fix build on QNX 6.5.0 --- lib/misc/dir.c | 4 ++-- lib/plat/unix/unix-sockets.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/misc/dir.c b/lib/misc/dir.c index 94a07ca920..b343b922f5 100644 --- a/lib/misc/dir.c +++ b/lib/misc/dir.c @@ -131,7 +131,7 @@ lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) } for (i = 0; i < n; i++) { -#if !defined(__sun) +#if !defined(__sun) && !defined(__QNX__) unsigned int type = namelist[i]->d_type; #endif if (strchr(namelist[i]->d_name, '~')) @@ -143,7 +143,7 @@ lws_dir(const char *dirpath, void *user, lws_dir_callback_function cb) * files are LDOT_UNKNOWN */ -#if defined(__sun) +#if defined(__sun) || defined(__QNX__) lws_dir_via_stat(combo, l, namelist[i]->d_name, &lde); #else /* diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index 2c1b9569c8..cb2f1bbae4 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -198,7 +198,7 @@ static const int ip_opt_lws_flags[] = { #endif }, ip_opt_val[] = { IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY -#if !defined(__OpenBSD__) && !defined(__sun) +#if !defined(__OpenBSD__) && !defined(__sun) && !defined(__QNX__) , IPTOS_MINCOST #endif }; From ba84a1d3b5ef58609b54168351f796288750a10a Mon Sep 17 00:00:00 2001 From: Vladimir Shakhov Date: Fri, 5 Aug 2022 20:09:57 +0200 Subject: [PATCH 166/275] Subject: [PATCH] platorm windows-sockets: treat WSAEWOULDBLOCK as MBEDTLS_ERR_SSL_WANT_READ|WRITE --- lib/plat/windows/windows-sockets.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/plat/windows/windows-sockets.c b/lib/plat/windows/windows-sockets.c index b0e15dd1ea..ba0de92cba 100644 --- a/lib/plat/windows/windows-sockets.c +++ b/lib/plat/windows/windows-sockets.c @@ -569,7 +569,7 @@ lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) return ret; en = LWS_ERRNO; - if (en == EAGAIN || en == EWOULDBLOCK) + if (en == EAGAIN || en == EWOULDBLOCK || en == WSAEWOULDBLOCK) return MBEDTLS_ERR_SSL_WANT_WRITE; ret = WSAGetLastError(); @@ -594,7 +594,7 @@ lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) return ret; en = LWS_ERRNO; - if (en == EAGAIN || en == EWOULDBLOCK) + if (en == EAGAIN || en == EWOULDBLOCK || en == WSAEWOULDBLOCK) return MBEDTLS_ERR_SSL_WANT_READ; ret = WSAGetLastError(); From 39f6379c0cf1e193f093c9e2032d640a2ec272a3 Mon Sep 17 00:00:00 2001 From: Dmitry Potapov Date: Wed, 16 Mar 2022 15:24:22 +0300 Subject: [PATCH 167/275] vhost: remove from defer binding on destroy If a vhost is removed, it should remove references to it from the defer binding list to avoid dangling pointers, which can crash the application. --- lib/core-net/vhost.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index 298bf01e8e..74d61417e3 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -1437,6 +1437,20 @@ __lws_vhost_destroy2(struct lws_vhost *vh) // lwsl_info("%s: %s\n", __func__, vh->name); + /* + * remove ourselves from the defer binding list + */ + lws_start_foreach_llp(struct lws_vhost **, pv, + vh->context->no_listener_vhost_list) { + if (*pv == vh) { + lwsl_debug("deferred iface: removing vh %s\n", + (*pv)->name); + *pv = vh->no_listener_vhost_list; + vh->no_listener_vhost_list = NULL; + break; + } + } lws_end_foreach_llp(pv, no_listener_vhost_list); + /* * let the protocols destroy the per-vhost protocol objects */ From 8796dc00f54dc904996f171bb1caa9696151ac5c Mon Sep 17 00:00:00 2001 From: Martlaak Date: Tue, 23 Aug 2022 12:54:58 +0100 Subject: [PATCH 168/275] windows: allow serving files open for write https://github.com/warmcat/libwebsockets/issues/2713 --- lib/plat/windows/windows-file.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/plat/windows/windows-file.c b/lib/plat/windows/windows-file.c index 27b0a9cc64..370204a3f6 100644 --- a/lib/plat/windows/windows-file.c +++ b/lib/plat/windows/windows-file.c @@ -42,13 +42,12 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, LARGE_INTEGER llFileSize = {0}; MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, LWS_ARRAY_SIZE(buf)); - if (((*flags) & 7) == _O_RDONLY) { - ret = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - } else { + if (((*flags) & 7) == _O_RDONLY) + ret = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + else ret = CreateFileW(buf, GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - } + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (ret == NULL) goto bail; From 58af7b4409c60da4cef8ee36b13fdb980574968c Mon Sep 17 00:00:00 2001 From: Damian Hobson-Garcia Date: Wed, 17 Aug 2022 00:16:27 +0900 Subject: [PATCH 169/275] From df9761a261b5c3286ba5ff079ee77e88de8b9ed8 Mon Sep 17 00:00:00 2001 Subject: [PATCH] remove LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY callback When a certificate for a TLS connection is provided, but a private key is not, the SSL_CTX initialization exits early, before the CONTEXT_REQUIRES_PRIVATE_KEY callback can be issued. Remove the now obsolete callback and update the vhost field description to state that the LOAD_EXTRA_SERVER_VERIFY_CERTS callback should be used instead. --- include/libwebsockets/lws-callbacks.h | 9 -------- include/libwebsockets/lws-context-vhost.h | 13 ++++++++---- lib/tls/openssl/openssl-server.c | 26 +++++++---------------- 3 files changed, 17 insertions(+), 31 deletions(-) diff --git a/include/libwebsockets/lws-callbacks.h b/include/libwebsockets/lws-callbacks.h index fd36f7c7de..455bfb0e44 100644 --- a/include/libwebsockets/lws-callbacks.h +++ b/include/libwebsockets/lws-callbacks.h @@ -160,15 +160,6 @@ enum lws_callback_reasons { * the default callback action of returning 0 allows the client * certificates. */ - LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY = 37, - /**< if configured for including OpenSSL support but no private key - * file has been specified (ssl_private_key_filepath is NULL), this is - * called to allow the user to set the private key directly via - * libopenssl and perform further operations if required; this might be - * useful in situations where the private key is not directly accessible - * by the OS, for example if it is stored on a smartcard. - * user is the server's OpenSSL SSL_CTX* */ - LWS_CALLBACK_SSL_INFO = 67, /**< SSL connections only. An event you registered an * interest in at the vhost has occurred on a connection diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index b3de140b58..c14068407c 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -390,10 +390,15 @@ struct lws_context_creation_info { */ const char *ssl_private_key_filepath; /**< VHOST: filepath to private key if wanting SSL mode; - * if this is set to NULL but ssl_cert_filepath is set, the - * OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY callback is called - * to allow setting of the private key directly via openSSL - * library calls. (For backwards compatibility, this can also be used + * this should not be set to NULL when ssl_cert_filepath is set. + * + * Alteratively, the certificate and private key can both be set in + * the OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS callback directly via + * openSSL library calls. This requires that + * LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX is set in the vhost info options + * to force initializtion of the SSL_CTX context. + * + * (For backwards compatibility, this can also be used * to pass the client cert private key filepath when setting up a * vhost client SSL context, but it is preferred to use * .client_ssl_private_key_filepath for that.) diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c index 34a6ada2c3..f2e77324f9 100644 --- a/lib/tls/openssl/openssl-server.c +++ b/lib/tls/openssl/openssl-server.c @@ -228,7 +228,10 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, return 1; } - if (private_key) { + if (!private_key) { + lwsl_err("ssl private key not set\n"); + return 1; + } else { /* set the private key from KeyFile */ if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key, SSL_FILETYPE_PEM) != 1) { @@ -244,14 +247,6 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, private_key, error, s); return 1; } - } else { - if (vhost->protocols[0].callback(wsi, - LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY, - vhost->tls.ssl_ctx, NULL, 0)) { - lwsl_err("ssl private key not set\n"); - - return 1; - } } return 0; @@ -389,7 +384,10 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, return 1; } - if (n != LWS_TLS_EXTANT_ALTERNATIVE && private_key) { + if (n == LWS_TLS_EXTANT_ALTERNATIVE || !private_key) { + lwsl_err("ssl private key not set\n"); + return 1; + } else { /* set the private key from KeyFile */ if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key, SSL_FILETYPE_PEM) != 1) { @@ -400,14 +398,6 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, (char *)vhost->context->pt[0].serv_buf)); return 1; } - } else { - if (vhost->protocols[0].callback(wsi, - LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY, - vhost->tls.ssl_ctx, NULL, 0)) { - lwsl_err("ssl private key not set\n"); - - return 1; - } } check_key: From 937a8db996d29d48793c642e6264e56a1615e1dd Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 18 Sep 2022 06:20:59 +0100 Subject: [PATCH 170/275] tests: disable tests with jig rot A couple of tests can't work because the peer setup they rely on has rotted on the peer side. --- .../secure-streams/minimal-secure-streams-post/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt b/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt index 62404153f2..ea23d84957 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt +++ b/minimal-examples/secure-streams/minimal-secure-streams-post/CMakeLists.txt @@ -19,7 +19,7 @@ if (requirements) find_program(VALGRIND "valgrind") - if (LWS_CTEST_INTERNET_AVAILABLE) + if (LWS_CTEST_INTERNET_AVAILABLE AND DISABLE_IT_DUE_TO_JIG_ROT) if (VALGRIND) add_test(NAME sspost-warmcat COMMAND ${CMAKE_SOURCE_DIR}/scripts/ctest-background.sh From 12250cf3ef563afa10f0ac2462147f4159e08816 Mon Sep 17 00:00:00 2001 From: Dmitry Potapov Date: Thu, 15 Sep 2022 13:26:38 +0300 Subject: [PATCH 171/275] openssl3: change deprecated warnings suppression --- include/libwebsockets.h | 4 ---- lib/core/private-lib-core.h | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 8fb98c3443..7454828a4b 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -41,10 +41,6 @@ extern "C" { #include "lws_config.h" -#if defined(LWS_SUPPRESS_DEPRECATED_API_WARNINGS) -#define OPENSSL_USE_DEPRECATED -#endif - /* place for one-shot opaque forward references */ typedef struct lws_context * lws_ctx_t; diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 6cdc91cff7..8767ec1655 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -34,6 +34,10 @@ #define _GNU_SOURCE #endif +#if defined(LWS_SUPPRESS_DEPRECATED_API_WARNINGS) +#define OPENSSL_SUPPRESS_DEPRECATED +#endif + /* #if !defined(_POSIX_C_SOURCE) #define _POSIX_C_SOURCE 200112L From 41ff4ef8ae487fa0ab58200ef5bf8abd76491f8f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 14 Jun 2023 07:14:23 +0100 Subject: [PATCH 172/275] openssl-server: enum vs int disagreement https://github.com/warmcat/libwebsockets/issues/2907 --- lib/tls/openssl/openssl-server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c index f2e77324f9..1fc8192933 100644 --- a/lib/tls/openssl/openssl-server.c +++ b/lib/tls/openssl/openssl-server.c @@ -699,14 +699,14 @@ lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) return 0; } -int +enum lws_ssl_capable_status lws_tls_server_abort_connection(struct lws *wsi) { if (wsi->tls.use_ssl) SSL_shutdown(wsi->tls.ssl); SSL_free(wsi->tls.ssl); - return 0; + return LWS_SSL_CAPABLE_DONE; } enum lws_ssl_capable_status From c012b12589a04eba73159a0a2f948bd693d2cc10 Mon Sep 17 00:00:00 2001 From: Audric Schiltknecht Date: Fri, 20 Oct 2023 17:42:35 -0400 Subject: [PATCH 173/275] openssl: Properly report OpenSSL error in lws_tls_client_connect In case of an SSL_ERROR_SSL in lws_tls_client_connect, the lws_ssl_get_error call was calling lws_tls_err_describe_clear which cleared the OpenSSL error from the stack. Thus, the tls.err_helper attribute was set to the default value from ERR_error_string_n, masking the actual OpenSSL error message from client code. --- lib/tls/openssl/openssl-client.c | 4 +++- lib/tls/openssl/openssl-ssl.c | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 6c8d5c1c9e..5926184abc 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -515,6 +515,7 @@ lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) unsigned int len; #endif int m, n, en; + unsigned long l; #if defined(LWS_WITH_TLS_SESSIONS) && defined(LWS_HAVE_SSL_SESSION_set_time) SSL_SESSION *sess; #endif @@ -539,9 +540,10 @@ lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) } if (m == SSL_ERROR_SSL) { + l = ERR_get_error(); n = lws_snprintf(errbuf, elen, "tls: %s", wsi->tls.err_helper); if (!wsi->tls.err_helper[0]) - ERR_error_string_n((unsigned int)m, errbuf + n, (elen - (unsigned int)n)); + ERR_error_string_n((unsigned int)l, errbuf + n, (elen - (unsigned int)n)); return LWS_SSL_CAPABLE_ERROR; } diff --git a/lib/tls/openssl/openssl-ssl.c b/lib/tls/openssl/openssl-ssl.c index cf4d2b8c6e..11e9b49faa 100644 --- a/lib/tls/openssl/openssl-ssl.c +++ b/lib/tls/openssl/openssl-ssl.c @@ -57,8 +57,6 @@ int lws_ssl_get_error(struct lws *wsi, int n) m = SSL_get_error(wsi->tls.ssl, n); lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m, LWS_ERRNO); - if (m == SSL_ERROR_SSL) - lws_tls_err_describe_clear(); // assert (LWS_ERRNO != 9); @@ -250,6 +248,9 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) if (m == SSL_ERROR_ZERO_RETURN) /* cleanly shut down */ goto do_err; + if (m == SSL_ERROR_SSL) + lws_tls_err_describe_clear(); + /* hm not retryable.. could be 0 size pkt or error */ if (m == SSL_ERROR_SSL || m == SSL_ERROR_SYSCALL || From 051dfbdb7da39015db887fcd87a923cea047c2ea Mon Sep 17 00:00:00 2001 From: Nate Karstens Date: Fri, 20 Oct 2023 13:25:09 -0500 Subject: [PATCH 174/275] openssl: Add lws ctx ref to client vhost's SSL_CTX Adds a reference to the libwebsockets context to the OpenSSL context used by the client vhost. This allows SSL info callbacks to work correctly for clients, like it currently does for servers. Co-authored-by: Marty Flickinger Signed-off-by: Marty Flickinger Signed-off-by: Nate Karstens --- lib/tls/openssl/openssl-client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 5926184abc..884ca02136 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -868,6 +868,10 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, return 1; } + SSL_CTX_set_ex_data(vh->tls.ssl_client_ctx, + openssl_SSL_CTX_private_data_index, + (char *)vh->context); + lws_plat_vhost_tls_client_ctx_init(vh); tcr = lws_zalloc(sizeof(*tcr), "client ctx tcr"); From 6dfc2702325994ff3e726a97036c405f0aedf0af Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 27 Oct 2023 05:50:26 +0100 Subject: [PATCH 175/275] ss: http: support PATCH https://github.com/warmcat/libwebsockets/issues/2989 --- lib/secure-streams/protocols/ss-h1.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index ddc61b0de6..059138aa1b 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -248,12 +248,13 @@ lws_apply_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, } /* - * Content-length on POST / PUT if we have the length information + * Content-length on POST / PUT / PATCH if we have the length information */ if (h->policy->u.http.method && ( (!strcmp(h->policy->u.http.method, "POST") || - !strcmp(h->policy->u.http.method, "PUT"))) && + !strcmp(h->policy->u.http.method, "PATCH") || + !strcmp(h->policy->u.http.method, "PUT"))) && wsi->http.writeable_len) { if (!(h->policy->flags & LWSSSPOLF_HTTP_NO_CONTENT_LENGTH)) { @@ -830,6 +831,7 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->policy->protocol == LWSSSP_H2) && h->being_serialized && ( !strcmp(h->policy->u.http.method, "PUT") || + !strcmp(h->policy->u.http.method, "PATCH") || !strcmp(h->policy->u.http.method, "POST"))) { wsi->client_suppress_CONNECTION_ERROR = 1; @@ -1095,6 +1097,16 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, return -1; if (lws_ss_alloc_set_metadata(h, "method", "POST", 4)) return -1; + } else { + m = lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI); + if (m) { + if (lws_ss_alloc_set_metadata(h, "path", + lws_hdr_simple_ptr(wsi, + WSI_TOKEN_PATCH_URI), (unsigned int)m)) + return -1; + if (lws_ss_alloc_set_metadata(h, "method", "PATCH", 5)) + return -1; + } } } } From 75b41f4a9dea3d48a5555ffa74df054df8c124a8 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 5 Nov 2023 08:25:33 +0000 Subject: [PATCH 176/275] tls: mbedtls-3.5.0: correct privkey size --- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index e8a0cb2d40..6820b8204d 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -761,8 +761,13 @@ int pkey_pm_load(EVP_PKEY *pk, const unsigned char *buffer, int len) mbedtls_pk_init(pkey_pm->pkey); #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 +#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03050000 + ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, (unsigned int)len, NULL, 0, + mbedtls_ctr_drbg_random, pkey_pm->rngctx); +#else ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, (unsigned int)len + 1, NULL, 0, mbedtls_ctr_drbg_random, pkey_pm->rngctx); +#endif #else ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, (unsigned int)len + 1, NULL, 0); #endif From 5a5c31312e95b55939cc096c4955d270bcab4ab3 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 2 Nov 2023 08:06:50 +0000 Subject: [PATCH 177/275] mbedtls: print library version --- lib/core/context.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index c12b216118..218d924419 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -327,10 +327,6 @@ static const char * const opts_str = #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) "SSPROX " #endif - -#if defined(LWS_WITH_MBEDTLS) - "MbedTLS " -#endif #if defined(LWS_WITH_CONMON) "ConMon " #endif @@ -390,6 +386,9 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) struct lws_cache_creation_info ci; #endif +#if defined(LWS_WITH_MBEDTLS) + char mbedtls_version[32]; +#endif #if defined(__ANDROID__) struct rlimit rt; @@ -788,7 +787,17 @@ lws_create_context(const struct lws_context_creation_info *info) #endif /* network */ - lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s); +#if defined(LWS_WITH_MBEDTLS) + mbedtls_version_get_string(mbedtls_version); +#endif + + lwsl_cx_notice(context, +#if defined(LWS_WITH_MBEDTLS) + "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s); +#else + "LWS: %s, %s%s", library_version, opts_str, s); +#endif + #if defined(LWS_WITH_NETWORK) lwsl_cx_info(context, "Event loop: %s", plev->ops->name); #endif From cf07fef5900e25e581c94666b7ab89b412ea1a50 Mon Sep 17 00:00:00 2001 From: Ogre Transporter Date: Tue, 7 Nov 2023 06:30:25 +0000 Subject: [PATCH 178/275] msvc: avoid error about mixed ellipsis and cond https://github.com/warmcat/libwebsockets/issues/3001 --- lib/core/context.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index 218d924419..c1132d9752 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -791,11 +791,10 @@ lws_create_context(const struct lws_context_creation_info *info) mbedtls_version_get_string(mbedtls_version); #endif - lwsl_cx_notice(context, #if defined(LWS_WITH_MBEDTLS) - "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s); + lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s); #else - "LWS: %s, %s%s", library_version, opts_str, s); + lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s); #endif #if defined(LWS_WITH_NETWORK) From 5e060e29683229b18c3b21af63693cddc3442ed6 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 31 Oct 2023 10:50:40 +0000 Subject: [PATCH 179/275] mbedtls: auto adapt to changed session constant --- cmake/lws_config.h.in | 1 + lib/CMakeLists.txt | 1 + lib/tls/CMakeLists.txt | 1 + lib/tls/mbedtls/CMakeLists.txt | 2 ++ lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 4 ++++ 5 files changed, 9 insertions(+) diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index f3f4a9d79f..e69d0845a4 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -78,6 +78,7 @@ #cmakedefine LWS_HAVE_mbedtls_ssl_set_verify #cmakedefine LWS_HAVE_mbedtls_x509_crt_parse_file #cmakedefine LWS_HAVE_MBEDTLS_NET_SOCKETS +#cmakedefine LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET #cmakedefine LWS_HAVE_MBEDTLS_AUTH_KEY_ID #cmakedefine LWS_HAVE_NEW_UV_VERSION_H #cmakedefine LWS_HAVE_OPENSSL_ECDH_H diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 19dc0cf645..fab59a60bd 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -368,6 +368,7 @@ if (DEFINED LWS_PLAT_UNIX) endif() endif() set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) +set(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET ${LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET} PARENT_SCOPE) set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index f55337cb7a..e7ab5e0027 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -568,6 +568,7 @@ endif() exports_to_parent_scope() set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) +set(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET ${LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET} PARENT_SCOPE) set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) diff --git a/lib/tls/mbedtls/CMakeLists.txt b/lib/tls/mbedtls/CMakeLists.txt index e34151724b..6208f182af 100644 --- a/lib/tls/mbedtls/CMakeLists.txt +++ b/lib/tls/mbedtls/CMakeLists.txt @@ -124,6 +124,7 @@ include_directories(wrapper/include wrapper/include/internal) # old mbedtls has everything in mbedtls/net.h CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return 0;}\n" LWS_HAVE_MBEDTLS_NET_SOCKETS) +CHECK_C_SOURCE_COMPILES("#include \nint main(void) { return MBEDTLS_SSL_NEW_SESSION_TICKET;}\n" LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET) # # Keep explicit parent scope exports at end @@ -131,3 +132,4 @@ CHECK_C_SOURCE_COMPILES("#include \nint main(void) { retu exports_to_parent_scope() set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) +set(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET ${LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET} PARENT_SCOPE) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index 6820b8204d..e1b7ce2b23 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -549,7 +549,11 @@ OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl) case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: state = TLS_ST_SR_KEY_EXCH; break; +#if defined(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET) + case MBEDTLS_SSL_NEW_SESSION_TICKET: +#else case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: +#endif state = TLS_ST_SW_SESSION_TICKET; break; case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: From 115571f0f37560aa91cdb1b4f374b008910e8e1b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 2 Nov 2023 09:54:49 +0000 Subject: [PATCH 180/275] cmake: mbedtls: mbedtls_ssl_conf_alpn_protocols check --- lib/CMakeLists.txt | 1 + lib/tls/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index fab59a60bd..786fa3d90b 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -369,6 +369,7 @@ if (DEFINED LWS_PLAT_UNIX) endif() set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) set(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET ${LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET} PARENT_SCOPE) +set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols ${LWS_HAVE_mbedtls_ssl_conf_alpn_protocols} PARENT_SCOPE) set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index e7ab5e0027..c0014509ae 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -399,7 +399,8 @@ if (LWS_WITH_MBEDTLS) else() CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct mbedtls_x509_crt c; c.authority_key_id.keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; return c.authority_key_id.keyIdentifier.tag; }\n" LWS_HAVE_MBEDTLS_AUTH_KEY_ID) CHECK_C_SOURCE_COMPILES("#include \nint main(void) { void *v = (void *)mbedtls_ssl_set_verify; return !!v; }\n" LWS_HAVE_mbedtls_ssl_set_verify) - CHECK_SYMBOL_EXISTS(mbedtls_ssl_conf_alpn_protocols LWS_HAVE_mbedtls_ssl_conf_alpn_protocols PARENT_SCOPE) + CHECK_C_SOURCE_COMPILES("#include \nint main(void) { void *v = (void *)mbedtls_ssl_conf_alpn_protocols; return !!v; }\n" LWS_HAVE_mbedtls_ssl_conf_alpn_protocols) + CHECK_FUNCTION_EXISTS(mbedtls_ssl_get_alpn_protocol LWS_HAVE_mbedtls_ssl_get_alpn_protocol PARENT_SCOPE) CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_sni LWS_HAVE_mbedtls_ssl_conf_sni PARENT_SCOPE) CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_ca_chain LWS_HAVE_mbedtls_ssl_set_hs_ca_chain PARENT_SCOPE) @@ -569,6 +570,7 @@ endif() exports_to_parent_scope() set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE) set(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET ${LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET} PARENT_SCOPE) +set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols ${LWS_HAVE_mbedtls_ssl_conf_alpn_protocols} PARENT_SCOPE) set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE) set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE) set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE) From e7db2efabf6d4bce492a81f797b974ca7a2dd1d3 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 2 Nov 2023 09:56:20 +0000 Subject: [PATCH 181/275] mbedtls: if we have tls1.2 only accept exactly that --- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index e1b7ce2b23..3879e977b3 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -183,7 +183,12 @@ int ssl_pm_new(SSL *ssl) mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, version); } else { mbedtls_ssl_conf_max_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); +#else mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, 1); +#endif } mbedtls_ssl_conf_rng(&ssl_pm->conf, mbedtls_ctr_drbg_random, &ssl_pm->ctr_drbg); From 08ee6f14de445ed2a10cedbfe71ce0bea02e4e0f Mon Sep 17 00:00:00 2001 From: Carsten Schuette Date: Fri, 10 Nov 2023 11:13:24 +0000 Subject: [PATCH 182/275] clean: gcc13 false positive uninitialized https://github.com/warmcat/libwebsockets/issues/3004 --- lib/roles/h2/http2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 58e7c107dd..9cccdbcdc9 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -2811,7 +2811,6 @@ int lws_read_h2(struct lws *wsi, unsigned char *buf, lws_filepos_t len) { unsigned char *oldbuf = buf; - lws_filepos_t body_chunk_len; // lwsl_notice("%s: h2 path: wsistate 0x%x len %d\n", __func__, // wsi->wsistate, (int)len); @@ -2827,6 +2826,7 @@ lws_read_h2(struct lws *wsi, unsigned char *buf, lws_filepos_t len) * case. */ while (len) { + lws_filepos_t body_chunk_len = 0; int m; /* From ac9e3ba677232fc37db7251fe9de33ed96dbcd6d Mon Sep 17 00:00:00 2001 From: Daren Hayward <54070183+darhaywa@users.noreply.github.com> Date: Thu, 23 Mar 2023 15:36:02 +0000 Subject: [PATCH 183/275] b64: lws_b64_decode_stateful truncates response Addresses issue #2855 by allowing the parsing of the final byte when there are at least 3 bytes remaining in the buffer. For every 4 bytes of input, a maximum of 3 bytes of output are generated when decoding the base64 string. The buffer space, therefore, only requires an additional 3 bytes of space. The code checks for space in the buffer before adding null termination. --- lib/misc/base64-decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/misc/base64-decode.c b/lib/misc/base64-decode.c index 9d18b33fcf..332e91dfb5 100644 --- a/lib/misc/base64-decode.c +++ b/lib/misc/base64-decode.c @@ -113,7 +113,7 @@ lws_b64_decode_stateful(struct lws_b64state *s, const char *in, size_t *in_len, const char *orig_in = in, *end_in = in + *in_len; uint8_t *orig_out = out, *end_out = out + *out_size; - while (in < end_in && *in && out + 4 < end_out) { + while (in < end_in && *in && out + 3 <= end_out) { for (; s->i < 4 && in < end_in && *in; s->i++) { uint8_t v; From c097a444059e82d1e061db7c39325e92f8b7c21a Mon Sep 17 00:00:00 2001 From: Edward Zhang Date: Mon, 24 Apr 2023 14:23:49 +0800 Subject: [PATCH 184/275] pmd: fix ws parser for non pmd packet with pmd ext enabled --- lib/roles/ws/client-parser-ws.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/roles/ws/client-parser-ws.c b/lib/roles/ws/client-parser-ws.c index f569532ec3..f67927b2af 100644 --- a/lib/roles/ws/client-parser-ws.c +++ b/lib/roles/ws/client-parser-ws.c @@ -637,6 +637,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) if (n == PMDR_DID_NOTHING #if !defined(LWS_WITHOUT_EXTENSIONS) + || n == PMDR_NOTHING_WE_SHOULD_DO || n == PMDR_UNKNOWN #endif ) From 7b5a070efc883536eccface318ecdcd83580a354 Mon Sep 17 00:00:00 2001 From: Earl Robsham Date: Wed, 19 Oct 2022 17:11:59 -0400 Subject: [PATCH 185/275] pt_destroy: possible leaking pipe side Updates the `lws_pt_destroy()` logic to ensure the pipe fds are closed if either `pt->dummy_pipe_fds[0]` or `pt->dummy_pipe_fds[1]` are still valid (previously was only checking `pt->dummy_pipe_fds[0]` which was resulting in the write fd to leak whenever a context was destroyed). --- lib/core/context.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index c1132d9752..b9b724edf1 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -1688,9 +1688,9 @@ lws_pt_destroy(struct lws_context_per_thread *pt) pt->pipe_wsi = NULL; } - if (pt->dummy_pipe_fds[0] + if ((pt->dummy_pipe_fds[0] || pt->dummy_pipe_fds[1]) #if !defined(WIN32) - && (int)pt->dummy_pipe_fds[0] != -1 + && ((int)pt->dummy_pipe_fds[0] != -1 || (int)pt->dummy_pipe_fds[1] != -1) #endif ) { struct lws wsi; From 3179273eaea2f09d87dc37474eb2e9ce79fa25c1 Mon Sep 17 00:00:00 2001 From: tjwalton <15825356+tjwalton@users.noreply.github.com> Date: Fri, 30 Sep 2022 00:32:11 +0100 Subject: [PATCH 186/275] server: Always return result of _lws_vhost_init_server_af Fixes https://github.com/warmcat/libwebsockets/issues/2702 --- lib/roles/http/server/server.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index dca9a5e60b..6b132a424e 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -407,6 +407,7 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, struct lws_vhost *vhost) { struct vh_sock_args a; + int n; a.info = info; a.vhost = vhost; @@ -479,8 +480,9 @@ _lws_vhost_init_server(const struct lws_context_creation_info *info, (vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE))) { #endif a.af = AF_INET; - if (_lws_vhost_init_server_af(&a)) - return 1; + n = _lws_vhost_init_server_af(&a); + if (n) + return n; #if defined(LWS_WITH_IPV6) } From 8a190f2758c9b5d24b3722d9fc67e9d2378f2e96 Mon Sep 17 00:00:00 2001 From: Lonny Wong Date: Fri, 17 Nov 2023 00:58:08 +0800 Subject: [PATCH 187/275] libuv: fix idle being stopped when there is still pending stuff https://github.com/warmcat/libwebsockets/pull/3008 --- lib/event-libs/libuv/libuv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/event-libs/libuv/libuv.c b/lib/event-libs/libuv/libuv.c index dad371aac3..e213b8dd93 100644 --- a/lib/event-libs/libuv/libuv.c +++ b/lib/event-libs/libuv/libuv.c @@ -82,8 +82,9 @@ lws_uv_idle(uv_idle_t *handle uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb, LWS_US_TO_MS((uint64_t)us), 0); - /* there is nobody who needs service forcing, shut down idle */ - uv_idle_stop(handle); + /* if there is nobody who needs service forcing, shut down idle */ + if (lws_service_adjust_timeout(pt->context, 1, pt->tid)) + uv_idle_stop(handle); lws_pt_unlock(pt); lws_context_unlock(pt->context); From 59d42bcc742bc376e8ff01e5540bd833ab199893 Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Thu, 26 Jan 2023 17:17:49 -0800 Subject: [PATCH 188/275] gcc: fix mbedtls missing enum https://github.com/openwrt/packages/pull/21206/commits/bcd970fb4ff6029fbf612dccf6d8c2902a65e20e --- lib/tls/mbedtls/mbedtls-server.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/tls/mbedtls/mbedtls-server.c b/lib/tls/mbedtls/mbedtls-server.c index ca703c5a2a..efd7fc8ba5 100644 --- a/lib/tls/mbedtls/mbedtls-server.c +++ b/lib/tls/mbedtls/mbedtls-server.c @@ -264,11 +264,7 @@ lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) return 0; } -#if defined(LWS_AMAZON_RTOS) enum lws_ssl_capable_status -#else -int -#endif lws_tls_server_abort_connection(struct lws *wsi) { if (wsi->tls.use_ssl) From cd8fb61f3b43262cbc3a1f2263966bffbbb04c0d Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sat, 18 Nov 2023 05:31:30 +0000 Subject: [PATCH 189/275] windows: evade unused var warnings when logs disabled https://github.com/warmcat/libwebsockets/pull/2792 --- lib/plat/windows/windows-sockets.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/plat/windows/windows-sockets.c b/lib/plat/windows/windows-sockets.c index ba0de92cba..b82d033621 100644 --- a/lib/plat/windows/windows-sockets.c +++ b/lib/plat/windows/windows-sockets.c @@ -79,11 +79,13 @@ lws_plat_set_nonblocking(lws_sockfd_type fd) { u_long optl = 1; int result = !!ioctlsocket(fd, FIONBIO, &optl); +#if (_LWS_ENABLED_LOGS & LLL_ERR) if (result) { int error = LWS_ERRNO; lwsl_err("ioctlsocket FIONBIO 1 failed with error %d\n", error); } +#endif return result; } @@ -105,8 +107,10 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd, optval = 1; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char *)&optval, optlen) < 0) { +#if (_LWS_ENABLED_LOGS & LLL_ERR) int error = LWS_ERRNO; lwsl_err("setsockopt SO_KEEPALIVE 1 failed with error %d\n", error); +#endif return 1; } @@ -116,8 +120,10 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd, if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), NULL, 0, &dwBytesRet, NULL, NULL)) { +#if (_LWS_ENABLED_LOGS & LLL_ERR) int error = LWS_ERRNO; lwsl_err("WSAIoctl SIO_KEEPALIVE_VALS 1 %lu %lu failed with error %d\n", alive.keepalivetime, alive.keepaliveinterval, error); +#endif return 1; } } @@ -127,8 +133,10 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd, #ifndef _WIN32_WCE tcp_proto = getprotobyname("TCP"); if (!tcp_proto) { +#if (_LWS_ENABLED_LOGS & LLL_WARN) int error = LWS_ERRNO; lwsl_warn("getprotobyname(\"TCP\") failed with error, falling back to 6 %d\n", error); +#endif protonbr = 6; /* IPPROTO_TCP */ } else protonbr = tcp_proto->p_proto; @@ -137,8 +145,10 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd, #endif if (setsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen) ) { +#if (_LWS_ENABLED_LOGS & LLL_WARN) int error = LWS_ERRNO; lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", error); +#endif } return lws_plat_set_nonblocking(fd); From 96dffe862d71d334255038283d6449aeaa0add6b Mon Sep 17 00:00:00 2001 From: zzblydia <13098426+zzblydia@users.noreply.github.com> Date: Sat, 18 Nov 2023 18:00:10 +0800 Subject: [PATCH 190/275] cmake: ssl lib paths replace PC_OPENSSL_LIBRARIES with PC_OPENSSL_LINK_LIBRARIES to link library with absolute path. --- lib/tls/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index c0014509ae..9b15d9c6ce 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -267,7 +267,7 @@ if (LWS_WITH_SSL) find_package(PkgConfig QUIET) pkg_check_modules(PC_OPENSSL openssl QUIET) find_package(OpenSSL REQUIRED) - list(APPEND OPENSSL_LIBRARIES ${PC_OPENSSL_LIBRARIES}) + list(APPEND OPENSSL_LIBRARIES ${PC_OPENSSL_LINK_LIBRARIES}) set(OPENSSL_LIBRARIES ${OPENSSL_LIBRARIES} PARENT_SCOPE) endif() set(OPENSSL_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}") From 4415e84c095857629863804e941b9e1c2e9347ef Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 20 Nov 2023 06:25:02 +0000 Subject: [PATCH 191/275] v4.3.3 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af1b1e6e1d..bd1f9a35ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -410,7 +410,7 @@ set(CPACK_RPM_PACKAGE_LICENSE "MIT") set(CPACK_PACKAGE_NAME "${PACKAGE}") set(CPACK_PACKAGE_VERSION_MAJOR "4") set(CPACK_PACKAGE_VERSION_MINOR "3") -set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "2") +set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "3") set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH_NUMBER}-${LWS_BUILD_HASH}") set(CPACK_PACKAGE_RELEASE 1) From eba1e4aa7f4bb45e5c25297d6915ffe1835e655b Mon Sep 17 00:00:00 2001 From: Lonny Wong Date: Wed, 22 Nov 2023 00:20:18 +0800 Subject: [PATCH 192/275] pmd: fix buffer being reused while draining extensions --- lib/roles/ws/ops-ws.c | 2 +- lib/roles/ws/private-lib-roles-ws.h | 1 + lib/roles/ws/server-ws.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/roles/ws/ops-ws.c b/lib/roles/ws/ops-ws.c index 37fbd34dcd..3898457a04 100644 --- a/lib/roles/ws/ops-ws.c +++ b/lib/roles/ws/ops-ws.c @@ -723,7 +723,7 @@ lws_ws_rx_sm(struct lws *wsi, char already_processed, unsigned char c) } #if !defined(LWS_WITHOUT_EXTENSIONS) - if (!lin) + if (!lin && !(already_processed & ALREADY_PROCESSED_FULL_DRAINING)) break; #endif diff --git a/lib/roles/ws/private-lib-roles-ws.h b/lib/roles/ws/private-lib-roles-ws.h index d0b087073f..69033d6cef 100644 --- a/lib/roles/ws/private-lib-roles-ws.h +++ b/lib/roles/ws/private-lib-roles-ws.h @@ -75,6 +75,7 @@ enum lws_websocket_opcodes_07 { #define ALREADY_PROCESSED_IGNORE_CHAR 1 #define ALREADY_PROCESSED_NO_CB 2 +#define ALREADY_PROCESSED_FULL_DRAINING 4 #if !defined(LWS_WITHOUT_EXTENSIONS) struct lws_vhost_role_ws { diff --git a/lib/roles/ws/server-ws.c b/lib/roles/ws/server-ws.c index b8469a4c5e..f746ab31d8 100644 --- a/lib/roles/ws/server-ws.c +++ b/lib/roles/ws/server-ws.c @@ -1080,7 +1080,7 @@ lws_parse_ws(struct lws *wsi, unsigned char **buf, size_t len) wsi->ws->rx_draining_ext); #endif m = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR | - ALREADY_PROCESSED_NO_CB, 0); + ALREADY_PROCESSED_NO_CB | ALREADY_PROCESSED_FULL_DRAINING, 0); } if (m < 0) { From f8eac4e83b84950a0b2e9ecbc86f56cac7c4e961 Mon Sep 17 00:00:00 2001 From: Luka Kudra Date: Tue, 21 Nov 2023 17:07:29 +0000 Subject: [PATCH 193/275] mbedtls: dont rely on potentially missing version api https://github.com/warmcat/libwebsockets/issues/3013 --- lib/core/context.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/core/context.c b/lib/core/context.c index b9b724edf1..94ffb76007 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -386,9 +386,6 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT) struct lws_cache_creation_info ci; #endif -#if defined(LWS_WITH_MBEDTLS) - char mbedtls_version[32]; -#endif #if defined(__ANDROID__) struct rlimit rt; @@ -788,11 +785,7 @@ lws_create_context(const struct lws_context_creation_info *info) #endif /* network */ #if defined(LWS_WITH_MBEDTLS) - mbedtls_version_get_string(mbedtls_version); -#endif - -#if defined(LWS_WITH_MBEDTLS) - lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s); + lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, MBEDTLS_VERSION_STRING, opts_str, s); #else lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s); #endif From 0c1a090273d73b7f1a252c1b396f36ae74e1984e Mon Sep 17 00:00:00 2001 From: Yurii Nakonechnyi Date: Thu, 23 Nov 2023 18:05:26 +0200 Subject: [PATCH 194/275] Subject: sul: Update README.lws_sul.md Described `lws_container_of(...)` usage, added note about `lws_sorted_usec_list_t` zeroing. --- READMEs/README.lws_sul.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/READMEs/README.lws_sul.md b/READMEs/README.lws_sul.md index f1cae4e2be..234bc8e342 100644 --- a/READMEs/README.lws_sul.md +++ b/READMEs/README.lws_sul.md @@ -30,33 +30,44 @@ scheduler from your own code; it uses it to spread out connection attempts so they are staggered in time. You must create an `lws_sorted_usec_list_t` object somewhere, eg, in you own existing object. -``` +```c static lws_sorted_usec_list_t sul_stagger; ``` Create your own callback for the event... the argument points to the sul object used when the callback was scheduled. You can use pointer arithmetic to translate -that to your own struct when the `lws_sorted_usec_list_t` was a member of the -same struct. +that to your own struct (when the `lws_sorted_usec_list_t` was a member of the +some struct) by using `lws_container_of(sul, container_struct_type, field_name)`. + +```c +typedef struct my_connection_data { + ... + lws_sorted_usec_list_t sul_stagger; + ... +} my_connection_data_t; -``` static void stagger_cb(lws_sorted_usec_list_t *sul) { -... + my_connection_data_t* my_data = lws_container_of(sul, my_connection_data_t, sul_stagger); + ... } ``` +**Important note**: make sure, that `lws_sorted_usec_list_t` data initiallized by +zeros (`memset(&sul_stagger, 0, sizeof(lws_sorted_usec_list_t)`). This struct +contains pointers, so them must initially pointing to `NULL`! + When you want to schedule the callback, use `lws_sul_schedule()`... this will call it 10ms in the future -``` +```c lws_sul_schedule(context, 0, &sul_stagger, stagger_cb, 10 * LWS_US_PER_MS); ``` In the case you destroy your object and need to cancel the scheduled callback, use -``` +```c lws_sul_schedule(context, 0, &sul_stagger, NULL, LWS_SET_TIMER_USEC_CANCEL); ``` From bfa67ecf0ca370d237a0e763598818e357a0468c Mon Sep 17 00:00:00 2001 From: Lonny Wong Date: Wed, 22 Nov 2023 23:08:07 +0800 Subject: [PATCH 195/275] pmd: revert #3014 and drain extensions before next ssl read --- lib/roles/ws/ops-ws.c | 14 ++++++++++++-- lib/roles/ws/private-lib-roles-ws.h | 1 - lib/roles/ws/server-ws.c | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/roles/ws/ops-ws.c b/lib/roles/ws/ops-ws.c index 3898457a04..3282d3dfe5 100644 --- a/lib/roles/ws/ops-ws.c +++ b/lib/roles/ws/ops-ws.c @@ -723,7 +723,7 @@ lws_ws_rx_sm(struct lws *wsi, char already_processed, unsigned char c) } #if !defined(LWS_WITHOUT_EXTENSIONS) - if (!lin && !(already_processed & ALREADY_PROCESSED_FULL_DRAINING)) + if (!lin) break; #endif @@ -1223,8 +1223,18 @@ rops_handle_POLLIN_ws(struct lws_context_per_thread *pt, struct lws *wsi, else pending = pending > wsi->a.context->pt_serv_buf_size ? wsi->a.context->pt_serv_buf_size : pending; - if (--sanity) + if (--sanity) { +#if !defined(LWS_WITHOUT_EXTENSIONS) + while (wsi->ws->rx_draining_ext) { + // RX Extension needs to be drained before next read + n = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR, 0); + if (n < 0) { + return LWS_HPI_RET_PLEASE_CLOSE_ME; + } + } +#endif goto read; + } else /* * Something has gone wrong, we are spinning... diff --git a/lib/roles/ws/private-lib-roles-ws.h b/lib/roles/ws/private-lib-roles-ws.h index 69033d6cef..d0b087073f 100644 --- a/lib/roles/ws/private-lib-roles-ws.h +++ b/lib/roles/ws/private-lib-roles-ws.h @@ -75,7 +75,6 @@ enum lws_websocket_opcodes_07 { #define ALREADY_PROCESSED_IGNORE_CHAR 1 #define ALREADY_PROCESSED_NO_CB 2 -#define ALREADY_PROCESSED_FULL_DRAINING 4 #if !defined(LWS_WITHOUT_EXTENSIONS) struct lws_vhost_role_ws { diff --git a/lib/roles/ws/server-ws.c b/lib/roles/ws/server-ws.c index f746ab31d8..b8469a4c5e 100644 --- a/lib/roles/ws/server-ws.c +++ b/lib/roles/ws/server-ws.c @@ -1080,7 +1080,7 @@ lws_parse_ws(struct lws *wsi, unsigned char **buf, size_t len) wsi->ws->rx_draining_ext); #endif m = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR | - ALREADY_PROCESSED_NO_CB | ALREADY_PROCESSED_FULL_DRAINING, 0); + ALREADY_PROCESSED_NO_CB, 0); } if (m < 0) { From be473054bd06c3aae7c7258d2a2d282fa657e1c0 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 27 Nov 2023 09:57:26 +0100 Subject: [PATCH 196/275] License: Fix typo in MIT text in fsmount.c Somehow, a string replacement of ns by fsm had damaged the license text and introduced garbage. Signed-off-by: Philippe Ombredanne --- lib/misc/fsmount.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/misc/fsmount.c b/lib/misc/fsmount.c index bc9669a4b2..2e97d553af 100644 --- a/lib/misc/fsmount.c +++ b/lib/misc/fsmount.c @@ -6,12 +6,12 @@ * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicefsme, and/or - * sell copies of the Software, and to permit persofsm to whom the Software is - * furnished to do so, subject to the following conditiofsm: + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in - * all copies or substantial portiofsm of the Software. + * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, From 881a0ac34a7d7d48ab00dc21ac39db10f6036942 Mon Sep 17 00:00:00 2001 From: DomB Date: Mon, 8 Jan 2024 08:26:58 +0100 Subject: [PATCH 197/275] lecp: fix format_scan function for numeric longer than 2 digits and negative numbers --- lib/misc/lecp.c | 3 +- .../api-tests/api-test-lecp/main.c | 52 ++++++++++++++++++- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/lib/misc/lecp.c b/lib/misc/lecp.c index 4783241a49..eedc481302 100644 --- a/lib/misc/lecp.c +++ b/lib/misc/lecp.c @@ -985,7 +985,7 @@ format_scan(const char *fmt) } if (numeric) { - if (*fmt >= '0' && *fmt <= '9') + while (*fmt >= '0' && *fmt <= '9') fmt++; numeric = 0; if (*fmt != '(') @@ -1119,6 +1119,7 @@ format_scan(const char *fmt) return count[0]; + case '-': case '0': case '1': case '2': diff --git a/minimal-examples/api-tests/api-test-lecp/main.c b/minimal-examples/api-tests/api-test-lecp/main.c index 89133d70f7..6599ed30d5 100644 --- a/minimal-examples/api-tests/api-test-lecp/main.c +++ b/minimal-examples/api-tests/api-test-lecp/main.c @@ -4477,7 +4477,11 @@ static const uint8_t w26[] = { 0xF9, 0x3E, 0x00 }, w27[] = { 0xFB, 0x3F, 0xF1, 0xF7, 0xCE, 0xD9, 0x16, 0x87, 0x2B }, w28[] = { 0xA2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03 }, - w29[] = { 0x7F, 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0xFF + w29[] = { 0x7F, 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0xFF }, + w30[] = { 0xA2, 0x63, 0x67, 0x68, 0x69, 0x18, 0x7B, 0x63, 0x6A, 0x6B, 0x6C, 0x02 }, + w31[] = { 0x82, 0x18, 0x81, 0x19, 0x04, 0x00 }, + w32[] = { 0xA2, 0x63, 0x67, 0x68, 0x69, 0x38, 0x7A, 0x63, 0x6A, 0x6B, 0x6C, 0x02 }, + w33[] = { 0x82, 0x38, 0x80, 0x39, 0x03, 0xFF } ; @@ -4604,7 +4608,7 @@ int main(int argc, const char **argv) { int n, m, e = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE, expected = (int)LWS_ARRAY_SIZE(cbor_tests) + - 29 /* <-- how many write tests */; + 33 /* <-- how many write tests */; struct lecp_ctx ctx; const char *p; @@ -5000,6 +5004,50 @@ int main(int argc, const char **argv) e++; } else pass++; + + lwsl_user("%s: test30\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "{'ghi':123,'jkl':2}") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w30) || memcmp(w30, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test31\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "[129,1024]") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w31) || memcmp(w31, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test32\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "{'ghi':-123,'jkl':2}") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w32) || memcmp(w32, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; + + lwsl_user("%s: test33\n", __func__); + lws_lec_setbuf(&ctx, buf, sizeof(buf)); + + if (lws_lec_printf(&ctx, "[-129,-1024]") != + LWS_LECPCTX_RET_FINISHED || + ctx.used != sizeof(w33) || memcmp(w33, buf, ctx.used)) { + lwsl_hexdump_notice(ctx.start, ctx.used); + e++; + } else + pass++; } if (e) From ab683ca6a6858d1494efa4f25c11d2b17d0dbe91 Mon Sep 17 00:00:00 2001 From: Dustin Lundquist Date: Mon, 15 Jan 2024 06:12:58 +0000 Subject: [PATCH 198/275] ev: remove any watchers on close --- lib/event-libs/libev/libev.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/event-libs/libev/libev.c b/lib/event-libs/libev/libev.c index 4bdede78da..3f3f2a7f00 100644 --- a/lib/event-libs/libev/libev.c +++ b/lib/event-libs/libev/libev.c @@ -94,6 +94,7 @@ lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) struct lws_context_per_thread *pt; struct lws_pollfd eventfd; struct lws *wsi; + int tsi = 0; if (revents & EV_ERROR) return; @@ -112,10 +113,12 @@ lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) } wsi = wsi_from_fd(context, watcher->fd); - pt = &context->pt[(int)wsi->tsi]; + if (wsi) + tsi = (int)wsi->tsi; + pt = &context->pt[tsi]; ptpr = pt_to_priv_ev(pt); - lws_service_fd_tsi(context, &eventfd, (int)wsi->tsi); + lws_service_fd_tsi(context, &eventfd, tsi); ev_idle_start(ptpr->io_loop, &ptpr->idle); } @@ -413,6 +416,14 @@ elops_destroy_wsi_ev(struct lws *wsi) ev_io_stop(ptpr->io_loop, &w->w_write.watcher); } +static int +elops_wsi_logical_close_ev(struct lws *wsi) +{ + elops_destroy_wsi_ev(wsi); + + return 0; +} + static const struct lws_event_loop_ops event_loop_ops_ev = { /* name */ "libev", /* init_context */ elops_init_context_ev, @@ -420,7 +431,7 @@ static const struct lws_event_loop_ops event_loop_ops_ev = { /* destroy_context2 */ elops_destroy_context2_ev, /* init_vhost_listen_wsi */ elops_init_vhost_listen_wsi_ev, /* init_pt */ elops_init_pt_ev, - /* wsi_logical_close */ NULL, + /* wsi_logical_close */ elops_wsi_logical_close_ev, /* check_client_connect_ok */ NULL, /* close_handle_manually */ NULL, /* accept */ elops_accept_ev, From cd3869e8b9107a06fdcec5e3c4fc5120b5abe1f6 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 1 Mar 2024 08:24:10 +0000 Subject: [PATCH 199/275] certinfo: fix unused var with NO_LOGS --- .../minimal-http-client-certinfo/minimal-http-client-certinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c b/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c index 9f3bf04a62..428a1fb52a 100644 --- a/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c +++ b/minimal-examples/http-client/minimal-http-client-certinfo/minimal-http-client-certinfo.c @@ -26,7 +26,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, uint8_t buf[1280]; union lws_tls_cert_info_results *ci = (union lws_tls_cert_info_results *)buf; -#if defined(LWS_HAVE_CTIME_R) +#if defined(LWS_HAVE_CTIME_R) && !defined(LWS_WITH_NO_LOGS) char date[32]; #endif From 50375030a37a1a2482679b737ad852d22f1d9680 Mon Sep 17 00:00:00 2001 From: Patrick Johnston Date: Wed, 6 Mar 2024 08:54:23 +0000 Subject: [PATCH 200/275] genaes: fix lws_genaes_create comment --- include/libwebsockets/lws-genaes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/libwebsockets/lws-genaes.h b/include/libwebsockets/lws-genaes.h index 6095f6837c..b5c2f22e42 100644 --- a/include/libwebsockets/lws-genaes.h +++ b/include/libwebsockets/lws-genaes.h @@ -89,7 +89,7 @@ struct lws_genaes_ctx { char underway; }; -/** lws_genaes_create() - Create RSA public decrypt context +/** lws_genaes_create() - Create genaes AES context * * \param ctx: your struct lws_genaes_ctx * \param op: LWS_GAESO_ENC or LWS_GAESO_DEC @@ -98,7 +98,7 @@ struct lws_genaes_ctx { * \param padding: 0 = no padding, 1 = padding * \param engine: if openssl engine used, pass the pointer here * - * Creates an RSA context with a public key associated with it, formed from + * Creates an AES context with a key associated with it, formed from * the key elements in \p el. * * Returns 0 for OK or nonzero for error. From 0fd97f652a870f89b33f47e8b746a2b651df2db6 Mon Sep 17 00:00:00 2001 From: Lio DongMiao Date: Thu, 7 Mar 2024 08:28:44 +0000 Subject: [PATCH 201/275] context: fall back if no build-time mbedtls version --- lib/core/context.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/core/context.c b/lib/core/context.c index 94ffb76007..cdbcec8831 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -785,7 +785,16 @@ lws_create_context(const struct lws_context_creation_info *info) #endif /* network */ #if defined(LWS_WITH_MBEDTLS) - lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, MBEDTLS_VERSION_STRING, opts_str, s); + { + char mbedtls_version[32]; + +#if defined(MBEDTLS_VERSION_C) + mbedtls_version_get_string(mbedtls_version); +#else + lws_snprintf(mbedtls_version, sizeof(mbedtls_version), "%s", MBEDTLS_VERSION_STRING); +#endif + lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s); + } #else lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s); #endif From 893ff81a8d1c184d849858c1d2097551ba68da1b Mon Sep 17 00:00:00 2001 From: Liu DongMiao Date: Thu, 7 Mar 2024 09:42:19 +0000 Subject: [PATCH 202/275] raw: connect callback can be triggered twice --- lib/roles/raw-skt/ops-raw-skt.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/roles/raw-skt/ops-raw-skt.c b/lib/roles/raw-skt/ops-raw-skt.c index 453c64e75f..5f0a89886a 100644 --- a/lib/roles/raw-skt/ops-raw-skt.c +++ b/lib/roles/raw-skt/ops-raw-skt.c @@ -60,12 +60,14 @@ lws_raw_skt_connect(struct lws *wsi) } #endif - n = user_callback_handle_rxflow(wsi->a.protocol->callback, - wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)], - wsi->user_space, NULL, 0); - if (n) { - lws_inform_client_conn_fail(wsi, (void *)"user", 4); - return 1; + if (!wsi->hdr_parsing_completed) { + n = user_callback_handle_rxflow(wsi->a.protocol->callback, + wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)], + wsi->user_space, NULL, 0); + if (n) { + lws_inform_client_conn_fail(wsi, (void *)"user", 4); + return 1; + } } lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); From 130a446b9071de34d2f7e9bdd0a48aa038cb015c Mon Sep 17 00:00:00 2001 From: Liu Dongmiao Date: Sun, 3 Mar 2024 10:27:55 +0800 Subject: [PATCH 203/275] wolfssl: fix build --- lib/tls/openssl/openssl-server.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c index 1fc8192933..a3c8d12026 100644 --- a/lib/tls/openssl/openssl-server.c +++ b/lib/tls/openssl/openssl-server.c @@ -308,7 +308,7 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, flen); } #else - ret = wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, flen, + ret = wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, (long) flen, WOLFSSL_FILETYPE_ASN1); #endif lws_free_set_NULL(p); @@ -439,7 +439,7 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, lwsl_notice(" Using ECDH certificate support\n"); /* Get X509 certificate from ssl context */ -#if !defined(LWS_WITH_BORINGSSL) +#if !defined(LWS_WITH_BORINGSSL) && !defined(USE_WOLFSSL) #if !defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS) x = sk_X509_value(vhost->tls.ssl_ctx->extra_certs, 0); #else @@ -482,7 +482,7 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, EC_KEY_free(EC_key); -#if !defined(OPENSSL_NO_EC) && !defined(LWS_WITH_BORINGSSL) +#if !defined(OPENSSL_NO_EC) && !defined(LWS_WITH_BORINGSSL) && !defined(USE_WOLFSSL) post_ecdh: #endif vhost->tls.skipped_certs = 0; From 6901c32a9d8491a6422f1de8edd731645ba40f5b Mon Sep 17 00:00:00 2001 From: Liu DongMiao Date: Tue, 5 Mar 2024 17:43:36 +0800 Subject: [PATCH 204/275] raw-skt: don't read more than rx_buffer_size When other roles like ws reading data, they follow `rx_buffer_size`, then fallback to context's `pt_serv_buf_size`. However, `raw-skt` don't follow `rx_buffer_size`, always use 0, then fallback to `pt_serv_buf_size`. This PR make `raw-skt` don't read more than `rx_buffer_size` data. --- lib/roles/raw-skt/ops-raw-skt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/raw-skt/ops-raw-skt.c b/lib/roles/raw-skt/ops-raw-skt.c index 5f0a89886a..c2a70f0ce0 100644 --- a/lib/roles/raw-skt/ops-raw-skt.c +++ b/lib/roles/raw-skt/ops-raw-skt.c @@ -174,7 +174,7 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, #endif default: ebuf.token = NULL; - ebuf.len = 0; + ebuf.len = (int) wsi->a.protocol->rx_buffer_size; buffered = lws_buflist_aware_read(pt, wsi, &ebuf, 1, __func__); switch (ebuf.len) { From 0a132164c2a2f8801612ad1f11fa122b63088324 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 8 Mar 2024 06:44:20 +0000 Subject: [PATCH 205/275] h2: cleanly return if fd is -1 on custom close --- .../minimal-http-server-eventlib-custom/minimal-http-server.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-custom/minimal-http-server.c b/minimal-examples/http-server/minimal-http-server-eventlib-custom/minimal-http-server.c index e969fea2b9..693ec1140f 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-custom/minimal-http-server.c +++ b/minimal-examples/http-server/minimal-http-server-eventlib-custom/minimal-http-server.c @@ -244,6 +244,10 @@ wsi_logical_close_custom(struct lws *wsi) { struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *) lws_evlib_wsi_to_evlib_pt(wsi); + + if (lws_get_socket_fd(wsi) == LWS_SOCK_INVALID) + return 0; + return custom_poll_del_fd(priv->io_loop, lws_get_socket_fd(wsi)); } From eac448923781abb083cedf0fa114e96ffc89a16e Mon Sep 17 00:00:00 2001 From: p-luke <105498880+p-luke@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:09:41 +0100 Subject: [PATCH 206/275] netlink: when binding the per-context socket, let the kernel choose the unicast address. When using multiple client contextes in a single application, rops_pt_init_destroy_netlink() fails binding the second socket and on - only the first one succeeds. The failure is made obvious by this log: W: rops_pt_init_destroy_netlink: netlink bind failed So, let's fix this by doing what netlink(7) man page suggests: If the application sets nl_pid before calling bind(2), then it is up to the application to make sure that nl_pid is unique. If the application sets it to 0, the kernel takes care of assigning it. The kernel assigns the process ID to the first netlink socket the process opens and assigns a unique nl_pid to every netlink socket that the process subsequently creates. --- lib/roles/netlink/ops-netlink.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/roles/netlink/ops-netlink.c b/lib/roles/netlink/ops-netlink.c index fa3bf29a2f..3782e5d6b0 100644 --- a/lib/roles/netlink/ops-netlink.c +++ b/lib/roles/netlink/ops-netlink.c @@ -526,7 +526,6 @@ rops_pt_init_destroy_netlink(struct lws_context *context, memset(&sanl, 0, sizeof(sanl)); sanl.nl_family = AF_NETLINK; - sanl.nl_pid = (uint32_t)getpid(); sanl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR #if defined(LWS_WITH_IPV6) | RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR From bd8f69e43835f3d57656f25efa84816991e21c10 Mon Sep 17 00:00:00 2001 From: "payne.ye" Date: Fri, 12 Apr 2024 09:49:37 +0800 Subject: [PATCH 207/275] smp: extend client to work with tsi and take care of zombie sul previously left on connect failure path --- lib/core-net/client/connect3.c | 5 +++-- lib/core-net/client/connect4.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/core-net/client/connect3.c b/lib/core-net/client/connect3.c index a9d2e9e0e2..1ab5b1786b 100644 --- a/lib/core-net/client/connect3.c +++ b/lib/core-net/client/connect3.c @@ -217,7 +217,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, */ lwsi_set_state(wsi, LRS_UNCONNECTED); - lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout, + lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->sul_connect_timeout, lws_client_dns_retry_timeout, LWS_USEC_PER_SEC); return wsi; @@ -601,7 +601,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, * uses wsi->sul_connect_timeout just for this purpose */ - lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout, + lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->sul_connect_timeout, lws_client_conn_wait_timeout, wsi->a.context->timeout_secs * LWS_USEC_PER_SEC); @@ -728,6 +728,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads, lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); failed1: + lws_sul_cancel(&wsi->sul_connect_timeout); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect3"); return NULL; diff --git a/lib/core-net/client/connect4.c b/lib/core-net/client/connect4.c index c34d2253be..d96ba7c5c6 100644 --- a/lib/core-net/client/connect4.c +++ b/lib/core-net/client/connect4.c @@ -279,7 +279,7 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, pfd.revents = LWS_POLLOUT; lwsl_wsi_info(wsi, "going to service fd"); - n = lws_service_fd(wsi->a.context, &pfd); + n = lws_service_fd_tsi(wsi->a.context, &pfd, wsi->tsi); if (n < 0) { cce = "first service failed"; goto failed; @@ -318,7 +318,7 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, pfd.events = LWS_POLLIN; pfd.revents = LWS_POLLIN; - n = lws_service_fd(wsi->a.context, &pfd); + n = lws_service_fd_tsi(wsi->a.context, &pfd, wsi->tsi); if (n < 0) { cce = "first service failed"; goto failed; From c90a77f1241e48d8e3ef40b6a46827424adf9489 Mon Sep 17 00:00:00 2001 From: Seo Suchan Date: Tue, 7 May 2024 13:19:13 +0100 Subject: [PATCH 208/275] mbedtls: fix compile on mbedtls ge 3.6 --- lib/tls/mbedtls/private-lib-tls-mbedtls.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/tls/mbedtls/private-lib-tls-mbedtls.h b/lib/tls/mbedtls/private-lib-tls-mbedtls.h index 162d972680..cd368f1974 100644 --- a/lib/tls/mbedtls/private-lib-tls-mbedtls.h +++ b/lib/tls/mbedtls/private-lib-tls-mbedtls.h @@ -57,3 +57,9 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, int lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid, lws_mbedtls_x509_authority *akid); + +#if (MBEDTLS_VERSION_MAJOR == 3) && (MBEDTLS_VERSION_MINOR >= 6) + int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur); +#endif + From c571d22dbacba1fcd0820dab699b44deee8743c6 Mon Sep 17 00:00:00 2001 From: streltsovdd Date: Tue, 4 Jun 2024 07:06:32 +0300 Subject: [PATCH 209/275] windows: fix check of result of CreateFileW --- lib/plat/windows/windows-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plat/windows/windows-file.c b/lib/plat/windows/windows-file.c index 370204a3f6..a648c08e7d 100644 --- a/lib/plat/windows/windows-file.c +++ b/lib/plat/windows/windows-file.c @@ -49,7 +49,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, ret = CreateFileW(buf, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (ret == NULL) + if (ret == LWS_INVALID_FILE) goto bail; fop_fd = malloc(sizeof(*fop_fd)); From ca375a4cab9448a8675c7a73293a60b89553f1bc Mon Sep 17 00:00:00 2001 From: zzblydia <13098426+zzblydia@users.noreply.github.com> Date: Mon, 24 Jun 2024 15:11:17 +0800 Subject: [PATCH 210/275] client hs: fix segmentation fault https://github.com/warmcat/libwebsockets/pull/3171 --- lib/roles/http/client/client-http.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 16fd8b245d..11938b7d81 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -1255,6 +1255,8 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt) // if (!wsi->client_pipeline) // conn1 = "close, "; p = lws_generate_client_ws_handshake(wsi, p, conn1); + if (!p) + return NULL; } else #endif { From b462ccd7dd3db4f7f116db896e5be75540afb8cf Mon Sep 17 00:00:00 2001 From: James Darpinian Date: Mon, 24 Jun 2024 01:44:57 -0700 Subject: [PATCH 211/275] ACME: fixes Increase polling time and poll the "order" endpoint instead of the "finalize" endpoint. These changes are required for ACME to work with Let's Encrypt as of 2024. --- plugins/acme-client/protocol_lws_acme_client.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/plugins/acme-client/protocol_lws_acme_client.c b/plugins/acme-client/protocol_lws_acme_client.c index 729c4482e1..9bcae46c0c 100644 --- a/plugins/acme-client/protocol_lws_acme_client.c +++ b/plugins/acme-client/protocol_lws_acme_client.c @@ -1125,8 +1125,10 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, goto pkt_add_hdrs; case ACME_STATE_POLLING_CSR: - if (ac->goes_around) - break; + if (ac->goes_around) { + strcpy(ac->active_url, ac->order_url); + goto pkt_add_hdrs; + } lwsl_vhost_notice(vhd->vhost, "Generating ACME CSR... may take a little while"); p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{\"csr\":\""); n = lws_tls_acme_sni_csr_create(vhd->context, @@ -1396,7 +1398,7 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, lws_acme_report_status(vhd->vhost, LWS_CUS_CHALLENGE, NULL); - if (ac->goes_around++ == 20) { + if (ac->goes_around++ == 200) { lwsl_notice("%s: too many chall retries\n", __func__); @@ -1470,13 +1472,13 @@ callback_acme_client(struct lws *wsi, enum lws_callback_reasons reason, goto failed; } - if (ac->resp != 200) { - if (ac->goes_around++ == 30) { + if (ac->resp != 200 || ac->cert_url[0] == '\0') { + if (ac->goes_around++ == 200) { lwsl_vhost_warn(vhd->vhost, "Too many retries"); goto failed; } - strcpy(buf, ac->finalize_url); + strcpy(buf, ac->order_url); cwsi = lws_acme_client_connect(vhd->context, vhd->vhost, &ac->cwsi, &ac->i, buf, From 7467274d4d493a6d97e40b3c4014dd167c6bb910 Mon Sep 17 00:00:00 2001 From: ribes96 Date: Mon, 23 Sep 2024 10:35:23 +0100 Subject: [PATCH 212/275] cgi: setenv: remove equals from arg https://github.com/warmcat/libwebsockets/issues/3222 --- lib/plat/unix/unix-spawn.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/plat/unix/unix-spawn.c b/lib/plat/unix/unix-spawn.c index 1c68d45bf6..5a85580aae 100644 --- a/lib/plat/unix/unix-spawn.c +++ b/lib/plat/unix/unix-spawn.c @@ -549,8 +549,10 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) int naml = lws_ptr_diff(p, i->env_array[m]); char enam[32]; - lws_strnncpy(enam, i->env_array[m], naml, sizeof(enam)); - setenv(enam, p, 1); + if (p) { + lws_strnncpy(enam, i->env_array[m], naml, sizeof(enam)); + setenv(enam, p + 1, 1); + } m++; } #endif From 8c8a2a5be3f7583a2678725ed6067976512ceca5 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 23 Sep 2024 11:06:16 +0100 Subject: [PATCH 213/275] lws_map: remove typedef for some toolchains This backports a change that has been in main for a while --- lib/core/lws_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/lws_map.c b/lib/core/lws_map.c index d149d86752..b319d79f49 100644 --- a/lib/core/lws_map.c +++ b/lib/core/lws_map.c @@ -29,11 +29,11 @@ typedef struct lws_map_hashtable { lws_dll2_owner_t ho; } lws_map_hashtable_t; -typedef struct lws_map { +struct lws_map { lws_map_info_t info; /* array of info.modulo x lws_map_hashtable_t overallocated */ -} lws_map_t; +}; typedef struct lws_map_item { lws_dll2_t list; /* owned by hashtable */ From 154bf554416012078cdfe078d35eb27aeb1b3c65 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 23 Sep 2024 13:10:28 +0100 Subject: [PATCH 214/275] openssl: allow custom SSL_CTX with GLOBAL_INIT unset --- lib/tls/openssl/openssl-tls.c | 5 +++-- lib/tls/tls-client.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/tls/openssl/openssl-tls.c b/lib/tls/openssl/openssl-tls.c index 577acf3578..3080d772d2 100644 --- a/lib/tls/openssl/openssl-tls.c +++ b/lib/tls/openssl/openssl-tls.c @@ -97,8 +97,9 @@ lws_context_init_ssl_library(struct lws_context *cx, #endif #endif if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) { - lwsl_cx_info(cx, " SSL disabled: no " - "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT"); + if (!info->provided_client_ssl_ctx) + lwsl_cx_info(cx, " SSL disabled: no " + "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT"); return 0; } diff --git a/lib/tls/tls-client.c b/lib/tls/tls-client.c index 5b29923f53..41dd1c7406 100644 --- a/lib/tls/tls-client.c +++ b/lib/tls/tls-client.c @@ -138,9 +138,6 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info, if (info->client_ssl_ca_filepath) ca_filepath = info->client_ssl_ca_filepath; - if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) - return 0; - if (vhost->tls.ssl_client_ctx) return 0; @@ -155,6 +152,9 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info, } #endif + if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) + return 0; + if (lws_tls_client_create_vhost_context(vhost, info, cipher_list, ca_filepath, info->client_ssl_ca_mem, From 57a0c16aebd286a8e71edad28777f5e0a1a84a6c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 06:22:45 +0100 Subject: [PATCH 215/275] openbsd: disable HIGH_RELIABLITY socket option https://github.com/warmcat/libwebsockets/issues/3204 --- lib/plat/unix/unix-sockets.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index cb2f1bbae4..aff0a2af65 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -191,21 +191,23 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt) } static const int ip_opt_lws_flags[] = { - LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT, - LCCSCF_IP_HIGH_RELIABILITY -#if !defined(__OpenBSD__) + LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT +#if !defined(__OpenBSD__) && !defined(__sun) && !defined(__QNX__) + , LCCSCF_IP_HIGH_RELIABILITY , LCCSCF_IP_LOW_COST #endif }, ip_opt_val[] = { - IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY + IPTOS_LOWDELAY, IPTOS_THROUGHPUT #if !defined(__OpenBSD__) && !defined(__sun) && !defined(__QNX__) + , IPTOS_RELIABILITY , IPTOS_MINCOST #endif }; #if !defined(LWS_WITH_NO_LOGS) static const char *ip_opt_names[] = { - "LOWDELAY", "THROUGHPUT", "RELIABILITY" -#if !defined(__OpenBSD__) && !defined(__sun) + "LOWDELAY", "THROUGHPUT" +#if !defined(__OpenBSD__) && !defined(__sun) && !defined(__QNX__) + , "RELIABILITY" , "MINCOST" #endif }; @@ -255,7 +257,10 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) } #endif - for (n = 0; n < 4; n++) { + +#if !defined(__NuttX__) + /* array size differs by platform */ + for (n = 0; n < (int)LWS_ARRAY_SIZE(ip_opt_lws_flags); n++) { if (!(lws_flags & ip_opt_lws_flags[n])) continue; @@ -272,6 +277,7 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) lwsl_notice("%s: set ip flag %s\n", __func__, ip_opt_names[n]); } +#endif return ret; } From 3976131e351ceea687da346cb212a579046f4a0f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 06:37:41 +0100 Subject: [PATCH 216/275] unix-sockets: extra care around short for some toolchains https://github.com/warmcat/libwebsockets/issues/3163 --- lib/plat/unix/unix-sockets.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index aff0a2af65..1a40c9cf9f 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -441,7 +441,7 @@ lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len, p[3] = (uint8_t)(n); while (p16 < (uint16_t *)(p + 20)) - ucs += ntohs(*p16++); + ucs = ucs + (uint32_t)(ntohs((uint16_t)(*p16++))); ucs += ucs >> 16; ucs ^= 0xffff; @@ -453,7 +453,7 @@ lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len, memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; - sll.sll_protocol = htons(0x800); + sll.sll_protocol = (uint32_t)(htons((uint16_t)0x800)); sll.sll_halen = 6; sll.sll_ifindex = (int)if_nametoindex(iface); memset(sll.sll_addr, 0xff, 6); From 51c47daea3e52266f12612e6ca01236be8bda3a9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 07:01:45 +0100 Subject: [PATCH 217/275] without-server: adapt loops to not touch listen_list https://github.com/warmcat/libwebsockets/issues/3203 --- CMakeLists-implied-options.txt | 6 ++++++ lib/event-libs/libev/libev.c | 5 ++++- lib/event-libs/libevent/libevent.c | 4 ++++ lib/event-libs/libuv/libuv.c | 2 ++ lib/event-libs/sdevent/sdevent.c | 4 ++++ lib/event-libs/uloop/uloop.c | 4 ++++ 6 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CMakeLists-implied-options.txt b/CMakeLists-implied-options.txt index c8137af3ea..37038c3499 100644 --- a/CMakeLists-implied-options.txt +++ b/CMakeLists-implied-options.txt @@ -368,6 +368,12 @@ if (LWS_WITHOUT_SERVER) set(LWS_WITH_SERVER) endif() +if (LWS_WITH_SERVER) +else() + set(LWS_WITH_CGI 0) + set(LWS_ROLE_CGI 0) +endif() + # using any abstract protocol enables LWS_WITH_ABSTRACT #if (LWS_WITH_SMTP) diff --git a/lib/event-libs/libev/libev.c b/lib/event-libs/libev/libev.c index 3f3f2a7f00..6b460d6c40 100644 --- a/lib/event-libs/libev/libev.c +++ b/lib/event-libs/libev/libev.c @@ -139,6 +139,7 @@ lws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents) static int elops_listen_init_ev(struct lws_dll2 *d, void *user) { +#if defined(LWS_WITH_SERVER) struct lws *wsi = lws_container_of(d, struct lws, listen_list); struct lws_context *context = (struct lws_context *)user; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; @@ -153,6 +154,7 @@ elops_listen_init_ev(struct lws_dll2 *d, void *user) ev_io_init(&vh_to_priv_ev(vh)->w_accept.watcher, lws_accept_cb, wsi->desc.sockfd, EV_READ); ev_io_start(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher); +#endif return 0; } @@ -243,6 +245,7 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi) static int elops_listen_destroy_ev(struct lws_dll2 *d, void *user) { +#if defined(LWS_WITH_SERVER) struct lws *wsi = lws_container_of(d, struct lws, listen_list); struct lws_context *context = (struct lws_context *)user; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; @@ -250,7 +253,7 @@ elops_listen_destroy_ev(struct lws_dll2 *d, void *user) struct lws_vhost *vh = wsi->a.vhost; ev_io_stop(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher); - +#endif return 0; } diff --git a/lib/event-libs/libevent/libevent.c b/lib/event-libs/libevent/libevent.c index b7b310ca7c..aaee588092 100644 --- a/lib/event-libs/libevent/libevent.c +++ b/lib/event-libs/libevent/libevent.c @@ -176,6 +176,7 @@ lws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx) static int elops_listen_init_event(struct lws_dll2 *d, void *user) { +#if defined(LWS_WITH_SERVER) struct lws *wsi = lws_container_of(d, struct lws, listen_list); struct lws_context *context = (struct lws_context *)user; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; @@ -188,6 +189,7 @@ elops_listen_init_event(struct lws_dll2 *d, void *user) (EV_READ | EV_PERSIST), lws_event_cb, w_read); event_add(w_read->watcher, NULL); w_read->set = 1; +#endif return 0; } @@ -334,6 +336,7 @@ elops_run_pt_event(struct lws_context *context, int tsi) static int elops_listen_destroy_event(struct lws_dll2 *d, void *user) { +#if defined(LWS_WITH_SERVER) struct lws *wsi = lws_container_of(d, struct lws, listen_list); struct lws_wsi_eventlibs_libevent *w = wsi_to_priv_event(wsi); @@ -341,6 +344,7 @@ elops_listen_destroy_event(struct lws_dll2 *d, void *user) w->w_read.watcher = NULL; event_free(w->w_write.watcher); w->w_write.watcher = NULL; +#endif return 0; } diff --git a/lib/event-libs/libuv/libuv.c b/lib/event-libs/libuv/libuv.c index e213b8dd93..699aaf386a 100644 --- a/lib/event-libs/libuv/libuv.c +++ b/lib/event-libs/libuv/libuv.c @@ -698,10 +698,12 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi) static int elops_listen_init_uv(struct lws_dll2 *d, void *user) { +#if defined(LWS_WITH_SERVER) struct lws *wsi = lws_container_of(d, struct lws, listen_list); if (elops_init_vhost_listen_wsi_uv(wsi) == -1) return -1; +#endif return 0; } diff --git a/lib/event-libs/sdevent/sdevent.c b/lib/event-libs/sdevent/sdevent.c index 0c7ddaec89..9779d3bab3 100644 --- a/lib/event-libs/sdevent/sdevent.c +++ b/lib/event-libs/sdevent/sdevent.c @@ -234,10 +234,12 @@ init_vhost_listen_wsi_sd(struct lws *wsi) static int elops_listen_init_sdevent(struct lws_dll2 *d, void *user) { +#if defined(LWS_WITH_SERVER) struct lws *wsi = lws_container_of(d, struct lws, listen_list); if (init_vhost_listen_wsi_sd(wsi) == -1) return -1; +#endif return 0; } @@ -368,9 +370,11 @@ run_pt_sd(struct lws_context *context, int tsi) static int elops_listen_destroy_sdevent(struct lws_dll2 *d, void *user) { +#if defined(LWS_WITH_SERVER) struct lws *wsi = lws_container_of(d, struct lws, listen_list); wsi_logical_close_sd(wsi); +#endif return 0; } diff --git a/lib/event-libs/uloop/uloop.c b/lib/event-libs/uloop/uloop.c index be9046c757..a6a14bb9e1 100644 --- a/lib/event-libs/uloop/uloop.c +++ b/lib/event-libs/uloop/uloop.c @@ -135,6 +135,7 @@ lws_uloop_cb(struct uloop_fd *ufd, unsigned int revents) static int elops_listen_init_uloop(struct lws_dll2 *d, void *user) { +#if defined(LWS_WITH_SERVER) struct lws *wsi = lws_container_of(d, struct lws, listen_list); struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi); @@ -143,6 +144,7 @@ elops_listen_init_uloop(struct lws_dll2 *d, void *user) wu->fd.cb = lws_uloop_cb; uloop_fd_add(&wu->fd, ULOOP_READ); wu->actual_events = ULOOP_READ; +#endif return 0; } @@ -217,10 +219,12 @@ elops_run_pt_uloop(struct lws_context *context, int tsi) static int elops_listen_destroy_uloop(struct lws_dll2 *d, void *user) { +#if defined(LWS_WITH_SERVER) struct lws *wsi = lws_container_of(d, struct lws, listen_list); struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi); uloop_fd_delete(&wu->fd); +#endif return 0; } From 86819f05af9fa70b23ec8107f6885b756ccfc0a2 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 07:10:54 +0100 Subject: [PATCH 218/275] win32: upscale timeout_ms to 64-bit int This may help with this: https://github.com/warmcat/libwebsockets/issues/3201 --- lib/plat/windows/windows-service.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c index b56ef43de1..e9399c957c 100644 --- a/lib/plat/windows/windows-service.c +++ b/lib/plat/windows/windows-service.c @@ -63,6 +63,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) struct lws_context_per_thread *pt; struct lws_pollfd *pfd; lws_usec_t timeout_us; + int64_t timeout_ms64 = (int64_t)timeout_ms; struct lws *wsi; unsigned int i; int n; @@ -85,12 +86,12 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) pt->service_tid_detected = 1; } - if (timeout_ms < 0) - timeout_ms = 0; + if (timeout_ms64 < 0) + timeout_ms64 = 0; else /* force a default timeout of 23 days */ - timeout_ms = 2000000000; - timeout_us = ((lws_usec_t)timeout_ms) * LWS_US_PER_MS; + timeout_ms64 = 2000000000; + timeout_us = ((lws_usec_t)timeout_ms64) * LWS_US_PER_MS; if (context->event_loop_ops->run_pt) context->event_loop_ops->run_pt(context, tsi); From 82c97d4022a684684c9137c5a245707929548ae1 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 07:45:03 +0100 Subject: [PATCH 219/275] lws_extension_callback_pm_deflate: make visible https://github.com/warmcat/libwebsockets/issues/3178 --- include/libwebsockets/lws-ws-ext.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libwebsockets/lws-ws-ext.h b/include/libwebsockets/lws-ws-ext.h index 10c7a644d9..2d7f22b8b3 100644 --- a/include/libwebsockets/lws-ws-ext.h +++ b/include/libwebsockets/lws-ws-ext.h @@ -184,7 +184,7 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi, * * Built-in callback implementing RFC7692 permessage-deflate */ -LWS_EXTERN int +LWS_VISIBLE LWS_EXTERN int lws_extension_callback_pm_deflate(struct lws_context *context, const struct lws_extension *ext, struct lws *wsi, From b05e95ec87175c83e3a8c8d199f2cc2b2f353925 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 08:38:15 +0100 Subject: [PATCH 220/275] pipe: only pt destroy pipe close should close pipe fds https://github.com/warmcat/libwebsockets/issues/2873 --- lib/core-net/close.c | 16 +++++++++++++--- lib/core-net/private-lib-core-net.h | 2 ++ lib/plat/freertos/freertos-pipe.c | 8 ++++++++ lib/plat/optee/network.c | 6 ++++++ lib/plat/unix/unix-pipe.c | 16 +++++++++++++--- lib/plat/windows/windows-pipe.c | 8 ++++++++ 6 files changed, 50 insertions(+), 6 deletions(-) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index a8dd72096b..71b85a72dc 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -881,9 +881,19 @@ __lws_close_free_wsi_final(struct lws *wsi) if (!wsi->shadow && lws_socket_is_valid(wsi->desc.sockfd) && !lws_ssl_close(wsi)) { lwsl_wsi_debug(wsi, "fd %d", wsi->desc.sockfd); - n = compatible_close(wsi->desc.sockfd); - if (n) - lwsl_wsi_debug(wsi, "closing: close ret %d", LWS_ERRNO); + + /* + * if this is the pt pipe, skip the actual close, + * go through the motions though so we will reach 0 open wsi + * on the pt, and trigger the pt destroy to close the pipe fds + */ + if (!lws_plat_pipe_is_fd_assocated(wsi->a.context, wsi->tsi, + wsi->desc.sockfd)) { + n = compatible_close(wsi->desc.sockfd); + if (n) + lwsl_wsi_debug(wsi, "closing: close ret %d", + LWS_ERRNO); + } __remove_wsi_socket_from_fds(wsi); if (lws_socket_is_valid(wsi->desc.sockfd)) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 0b3561f742..579bc53258 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -1326,6 +1326,8 @@ int lws_plat_pipe_signal(struct lws_context *ctx, int tsi); void lws_plat_pipe_close(struct lws *wsi); +int +lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd); void lws_addrinfo_clean(struct lws *wsi); diff --git a/lib/plat/freertos/freertos-pipe.c b/lib/plat/freertos/freertos-pipe.c index e459bf0ae0..476a7d7beb 100644 --- a/lib/plat/freertos/freertos-pipe.c +++ b/lib/plat/freertos/freertos-pipe.c @@ -124,3 +124,11 @@ lws_plat_pipe_close(struct lws *wsi) fd[0] = fd[1] = -1; } + +int +lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd) +{ + struct lws_context_per_thread *pt = &cx->pt[tsi]; + + return fd == pt->dummy_pipe_fds[0] || fd == pt->dummy_pipe_fds[1]; +} diff --git a/lib/plat/optee/network.c b/lib/plat/optee/network.c index 34f152f021..871abd9c81 100644 --- a/lib/plat/optee/network.c +++ b/lib/plat/optee/network.c @@ -49,6 +49,12 @@ lws_plat_pipe_close(struct lws *wsi) { } +int +lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd) +{ + return 0; +} + int lws_send_pipe_choked(struct lws *wsi) { diff --git a/lib/plat/unix/unix-pipe.c b/lib/plat/unix/unix-pipe.c index ad04acbbc6..cab4bb189b 100644 --- a/lib/plat/unix/unix-pipe.c +++ b/lib/plat/unix/unix-pipe.c @@ -84,10 +84,20 @@ lws_plat_pipe_close(struct lws *wsi) { struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; - if (pt->dummy_pipe_fds[0] && pt->dummy_pipe_fds[0] != -1) + if (pt->dummy_pipe_fds[0] && pt->dummy_pipe_fds[0] != -1) { close(pt->dummy_pipe_fds[0]); - if (pt->dummy_pipe_fds[1] && pt->dummy_pipe_fds[1] != -1) + pt->dummy_pipe_fds[0] = -1; + } + if (pt->dummy_pipe_fds[1] && pt->dummy_pipe_fds[1] != -1) { close(pt->dummy_pipe_fds[1]); + pt->dummy_pipe_fds[1] = -1; + } +} + +int +lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd) +{ + struct lws_context_per_thread *pt = &cx->pt[tsi]; - pt->dummy_pipe_fds[0] = pt->dummy_pipe_fds[1] = -1; + return fd == pt->dummy_pipe_fds[0] || fd == pt->dummy_pipe_fds[1]; } diff --git a/lib/plat/windows/windows-pipe.c b/lib/plat/windows/windows-pipe.c index bbfa31972a..702411a531 100644 --- a/lib/plat/windows/windows-pipe.c +++ b/lib/plat/windows/windows-pipe.c @@ -125,3 +125,11 @@ lws_plat_pipe_close(struct lws *wsi) pt->dummy_pipe_fds[0] = pt->dummy_pipe_fds[1] = LWS_SOCK_INVALID; } + +int +lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd) +{ + struct lws_context_per_thread *pt = &cx->pt[tsi]; + + return fd == pt->dummy_pipe_fds[0] || fd == pt->dummy_pipe_fds[1]; +} From 2ca5d8605b093ea26e1e39e1eb582910f0aee78b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 08:52:28 +0100 Subject: [PATCH 221/275] ws: increase sanity check for spins needed to consume buffer to 100 https://github.com/warmcat/libwebsockets/issues/3184 --- lib/roles/ws/ops-ws.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/ws/ops-ws.c b/lib/roles/ws/ops-ws.c index 3282d3dfe5..881d3f12cd 100644 --- a/lib/roles/ws/ops-ws.c +++ b/lib/roles/ws/ops-ws.c @@ -943,7 +943,7 @@ rops_handle_POLLIN_ws(struct lws_context_per_thread *pt, struct lws *wsi, unsigned int pending = 0; struct lws_tokens ebuf; char buffered = 0; - int n = 0, m, sanity = 10; + int n = 0, m, sanity = 100; #if defined(LWS_WITH_HTTP2) struct lws *wsi1; #endif From 8fc7596fec9913b50357be4e688ea686fc0d191a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 09:03:17 +0100 Subject: [PATCH 222/275] event: blow error if runtime context options want eventlib we dont have https://github.com/warmcat/libwebsockets/issues/3186 --- lib/core/context.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/core/context.c b/lib/core/context.c index cdbcec8831..a733ee38c3 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -542,6 +542,11 @@ lws_create_context(const struct lws_context_creation_info *info) fatal_exit_defer = !!info->foreign_loops; us_wait_resolution = 0; } +#else + if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV)) { + lwsl_cx_err(context, "Application wants libuv, but lws not built with it"); + goto bail; + } #endif #if defined(LWS_WITH_LIBEVENT) @@ -550,6 +555,11 @@ lws_create_context(const struct lws_context_creation_info *info) plev = &evlib_event; us_wait_resolution = 0; } +#else + if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEVENT)) { + lwsl_cx_err(context, "Application wants libevent, but lws not built with it"); + goto bail; + } #endif #if defined(LWS_WITH_GLIB) @@ -558,6 +568,11 @@ lws_create_context(const struct lws_context_creation_info *info) plev = &evlib_glib; us_wait_resolution = 0; } +#else + if (lws_check_opt(info->options, LWS_SERVER_OPTION_GLIB)) { + lwsl_cx_err(context, "Application wants glib, but lws not built with it"); + goto bail; + } #endif #if defined(LWS_WITH_LIBEV) @@ -566,6 +581,11 @@ lws_create_context(const struct lws_context_creation_info *info) plev = &evlib_ev; us_wait_resolution = 0; } +#else + if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEV)) { + lwsl_cx_err(context, "Application wants libev, but lws not built with it"); + goto bail; + } #endif #if defined(LWS_WITH_SDEVENT) @@ -574,6 +594,11 @@ lws_create_context(const struct lws_context_creation_info *info) plev = &evlib_sd; us_wait_resolution = 0; } +#else + if (lws_check_opt(info->options, LWS_SERVER_OPTION_SDEVENT)) { + lwsl_cx_err(context, "Application wants sdevent, but lws not built with it"); + goto bail; + } #endif #if defined(LWS_WITH_ULOOP) @@ -582,6 +607,11 @@ lws_create_context(const struct lws_context_creation_info *info) plev = &evlib_uloop; us_wait_resolution = 0; } +#else + if (lws_check_opt(info->options, LWS_SERVER_OPTION_ULOOP)) { + lwsl_cx_err(context, "Application wants uloop, but lws not built with it"); + goto bail; + } #endif #endif /* with event libs */ From f7aeadeb0e75bce4916368462f2066de22d1a1f7 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 09:35:39 +0100 Subject: [PATCH 223/275] win: trigger context destroy if pt destroying itself https://github.com/warmcat/libwebsockets/issues/3182 This follows the flow for *nix --- lib/plat/windows/windows-service.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c index e9399c957c..5f7c7ddb7c 100644 --- a/lib/plat/windows/windows-service.c +++ b/lib/plat/windows/windows-service.c @@ -177,6 +177,11 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) // lwsl_notice("%s: idx %d, revents 0x%x\n", __func__, n, pt->fds[n].revents); lws_service_fd_tsi(context, &pt->fds[n], tsi); } + + if (pt->destroy_self) { + lws_context_destroy(pt->context); + return -1; + } return 0; } From d1722af79bbee6f8e7a1fa2376a6ed409cdd87b1 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 09:42:22 +0100 Subject: [PATCH 224/275] check func munging https://github.com/warmcat/libwebsockets/issues/3181 --- include/libwebsockets.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 7454828a4b..1f352d1d44 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -132,7 +132,7 @@ typedef int suseconds_t; #define LWS_O_CREAT _O_CREAT #define LWS_O_TRUNC _O_TRUNC -#ifndef __func__ +#if (__STDC_VERSION__ < 199901L) && !defined(__func__) #define __func__ __FUNCTION__ #endif From bad1866c8a5aac303db5060828ffa656f5bebd63 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 10:33:52 +0100 Subject: [PATCH 225/275] wolfssl: have docs follow switch change https://github.com/warmcat/libwebsockets/issues/3116 --- READMEs/README.build.md | 2 +- contrib/cross-openwrt-makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/READMEs/README.build.md b/READMEs/README.build.md index 0b3db34b7a..d417537150 100644 --- a/READMEs/README.build.md +++ b/READMEs/README.build.md @@ -353,7 +353,7 @@ https://www.wolfssl.com/wolfSSL/Products-wolfssl.html It contains a OpenSSL compatibility layer which makes it possible to pretty much link to it instead of OpenSSL, giving a much smaller footprint. -**NOTE**: wolfssl needs to be compiled using the `--enable-opensslextra` flag for +**NOTE**: wolfssl needs to be compiled using the `--enable-libwebsockets` flag for this to work. @section wolf1 Compiling libwebsockets with wolfSSL diff --git a/contrib/cross-openwrt-makefile b/contrib/cross-openwrt-makefile index 8acab6b4fc..5305174e49 100644 --- a/contrib/cross-openwrt-makefile +++ b/contrib/cross-openwrt-makefile @@ -24,13 +24,13 @@ CMAKE_OPTIONS += -DLWS_WITH_SSL=ON CMAKE_OPTIONS += -DLWS_WITHOUT_TESTAPPS=$(if $(CONFIG_PACKAGE_libwebsockets-examples),"OFF","ON") # for wolfssl, define these in addition to LWS_OPENSSL_SUPPORT and -# edit package/libs/wolfssl/Makefile to include --enable-opensslextra +# edit package/libs/wolfssl/Makefile to include --enable-libwebsockets # CMAKE_OPTIONS += -DLWS_WITH_WOLFSSL=ON # CMAKE_OPTIONS += -DLWS_WOLFSSL_LIBRARIES=$(STAGING_DIR)/usr/lib/libwolfssl.so # CMAKE_OPTIONS += -DLWS_WOLFSSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include # for cyassl, define these in addition to LWS_OPENSSL_SUPPORT and -# edit package/libs/wolfssl/Makefile to include --enable-opensslextra +# edit package/libs/wolfssl/Makefile to include --enable-libwebsockets # CMAKE_OPTIONS += -DLWS_WITH_CYASSL=ON # CMAKE_OPTIONS += -DLWS_CYASSL_LIBRARIES=$(STAGING_DIR)/usr/lib/libcyassl.so # CMAKE_OPTIONS += -DLWS_CYASSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include From 0981808868657ff83650188940fcb807a64ab435 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 12:15:46 +0100 Subject: [PATCH 226/275] doc: session tickets https://github.com/warmcat/libwebsockets/issues/3226 --- READMEs/README.tls-sessions.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/READMEs/README.tls-sessions.md b/READMEs/README.tls-sessions.md index 5247555ce2..c0eb6a1c36 100644 --- a/READMEs/README.tls-sessions.md +++ b/READMEs/README.tls-sessions.md @@ -43,8 +43,10 @@ valid session object. ### Difference from Session Tickets TLS also supports sessions as bearer tokens, but these are generally considered -as degrading security. Lws doesn't support Session Tickets, just reuse by -Session IDs. +as degrading security. Lws doesn't do anything special for Session Tickets, but +it's possible your TLS library will support them by default, as is reportedly the +case with mbedtls 2.28.1. Either way, it's expected Session IDs should work with +lws if enabled and your tls library supports them. ## Support in lws From e24114fed9ce6c2b84e2622ad0a698aca43e462c Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 25 Sep 2024 12:23:15 +0100 Subject: [PATCH 227/275] win: file: use INVALID_HANDLE_VALUE directly https://github.com/warmcat/libwebsockets/commit/c571d22dbacba1fcd0820dab699b44deee8743c6#commitcomment-142753910 --- lib/plat/windows/windows-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plat/windows/windows-file.c b/lib/plat/windows/windows-file.c index a648c08e7d..5614b10600 100644 --- a/lib/plat/windows/windows-file.c +++ b/lib/plat/windows/windows-file.c @@ -49,7 +49,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, ret = CreateFileW(buf, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (ret == LWS_INVALID_FILE) + if (ret == INVALID_HANDLE_VALUE) goto bail; fop_fd = malloc(sizeof(*fop_fd)); From a1ee5a2c50d9d1661abe4986360ce126c13dfb03 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 29 Sep 2024 11:49:27 +0100 Subject: [PATCH 228/275] mbedtls: provide declaration if ge 3.5 https://github.com/warmcat/libwebsockets/issues/3169 --- lib/tls/mbedtls/private-lib-tls-mbedtls.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tls/mbedtls/private-lib-tls-mbedtls.h b/lib/tls/mbedtls/private-lib-tls-mbedtls.h index cd368f1974..12cbd4ce72 100644 --- a/lib/tls/mbedtls/private-lib-tls-mbedtls.h +++ b/lib/tls/mbedtls/private-lib-tls-mbedtls.h @@ -58,7 +58,7 @@ int lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid, lws_mbedtls_x509_authority *akid); -#if (MBEDTLS_VERSION_MAJOR == 3) && (MBEDTLS_VERSION_MINOR >= 6) +#if (MBEDTLS_VERSION_MAJOR == 3) && (MBEDTLS_VERSION_MINOR >= 5) int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, mbedtls_x509_name *cur); #endif From a544db3020b3f46b4050b4cf153ed3e4edd8a30a Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Wed, 2 Oct 2024 10:13:14 +0300 Subject: [PATCH 229/275] win32: zlib: Fix buffer overflow on inflate (CVE-2022-37434) --- win32port/zlib/inflate.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/win32port/zlib/inflate.c b/win32port/zlib/inflate.c index 664c4b9cc0..21631c75e8 100644 --- a/win32port/zlib/inflate.c +++ b/win32port/zlib/inflate.c @@ -720,8 +720,9 @@ int flush; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; + state->head->extra != Z_NULL && + (len = state->head->extra_len - state->length) < + state->head->extra_max) { zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); From dcf9dcaf2ab637a530d46d3df1781dfbb190321f Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Wed, 2 Oct 2024 10:12:19 +0300 Subject: [PATCH 230/275] unix-file: Fix signed/unsigned implicit conversion --- lib/plat/unix/unix-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plat/unix/unix-file.c b/lib/plat/unix/unix-file.c index 81cbb222e7..4bdb3c79ab 100644 --- a/lib/plat/unix/unix-file.c +++ b/lib/plat/unix/unix-file.c @@ -83,7 +83,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, const char *vpath, lws_fop_flags_t *flags) { struct stat stat_buf; - int ret = lws_open(filename, (*flags) & LWS_FOP_FLAGS_MASK, 0664); + int ret = lws_open(filename, (int)((*flags) & LWS_FOP_FLAGS_MASK), 0664); lws_fop_fd_t fop_fd; if (ret < 0) From 0ee1984c5cba15f3aae7ecad20d28f7838c9263e Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Wed, 2 Oct 2024 10:11:03 +0300 Subject: [PATCH 231/275] win: change uid_t and gid_t from int to unsigned int Like they are on Linux. --- include/libwebsockets.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 1f352d1d44..ddd710cc5d 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -88,8 +88,8 @@ typedef unsigned long long lws_intptr_t; #define O_RDONLY _O_RDONLY #endif -typedef int uid_t; -typedef int gid_t; +typedef unsigned int uid_t; +typedef unsigned int gid_t; typedef unsigned short sa_family_t; #if !defined(LWS_HAVE_SUSECONDS_T) typedef unsigned int useconds_t; From 8ad16af9a3019b42c26ab176bc724a3387e5dedb Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Tue, 1 Oct 2024 12:15:15 +0300 Subject: [PATCH 232/275] win: simplify error logging in windows-sockets.c --- lib/plat/windows/windows-sockets.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/plat/windows/windows-sockets.c b/lib/plat/windows/windows-sockets.c index b82d033621..f4736b45a9 100644 --- a/lib/plat/windows/windows-sockets.c +++ b/lib/plat/windows/windows-sockets.c @@ -81,10 +81,7 @@ lws_plat_set_nonblocking(lws_sockfd_type fd) int result = !!ioctlsocket(fd, FIONBIO, &optl); #if (_LWS_ENABLED_LOGS & LLL_ERR) if (result) - { - int error = LWS_ERRNO; - lwsl_err("ioctlsocket FIONBIO 1 failed with error %d\n", error); - } + lwsl_err("ioctlsocket FIONBIO 1 failed with error %d\n", LWS_ERRNO); #endif return result; } @@ -108,8 +105,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd, if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char *)&optval, optlen) < 0) { #if (_LWS_ENABLED_LOGS & LLL_ERR) - int error = LWS_ERRNO; - lwsl_err("setsockopt SO_KEEPALIVE 1 failed with error %d\n", error); + lwsl_err("setsockopt SO_KEEPALIVE 1 failed with error %d\n", LWS_ERRNO); #endif return 1; } @@ -121,8 +117,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd, if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), NULL, 0, &dwBytesRet, NULL, NULL)) { #if (_LWS_ENABLED_LOGS & LLL_ERR) - int error = LWS_ERRNO; - lwsl_err("WSAIoctl SIO_KEEPALIVE_VALS 1 %lu %lu failed with error %d\n", alive.keepalivetime, alive.keepaliveinterval, error); + lwsl_err("WSAIoctl SIO_KEEPALIVE_VALS 1 %lu %lu failed with error %d\n", alive.keepalivetime, alive.keepaliveinterval, LWS_ERRNO); #endif return 1; } @@ -134,8 +129,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd, tcp_proto = getprotobyname("TCP"); if (!tcp_proto) { #if (_LWS_ENABLED_LOGS & LLL_WARN) - int error = LWS_ERRNO; - lwsl_warn("getprotobyname(\"TCP\") failed with error, falling back to 6 %d\n", error); + lwsl_warn("getprotobyname(\"TCP\") failed with error, falling back to 6 %d\n", LWS_ERRNO); #endif protonbr = 6; /* IPPROTO_TCP */ } else @@ -146,8 +140,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd, if (setsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen) ) { #if (_LWS_ENABLED_LOGS & LLL_WARN) - int error = LWS_ERRNO; - lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", error); + lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", LWS_ERRNO); #endif } From 5102a5c8d6110b25a01492fcf96fb668b13dd6e7 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Wed, 2 Oct 2024 10:12:41 +0300 Subject: [PATCH 233/275] tls-sessions: Pass correct type for printf %u --- lib/tls/tls-sessions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tls/tls-sessions.c b/lib/tls/tls-sessions.c index b1e90aa54b..da3dc57271 100644 --- a/lib/tls/tls-sessions.c +++ b/lib/tls/tls-sessions.c @@ -34,7 +34,7 @@ lws_tls_session_tag_discrete(const char *vhname, const char *host, * different client certs. */ - lws_snprintf(buf, len, "%s_%s_%u", vhname, host, port); + lws_snprintf(buf, len, "%s_%s_%u", vhname, host, (unsigned int)port); } int From a71a62f51bec63b4eb1cd4a24fbb58ad3db23ad9 Mon Sep 17 00:00:00 2001 From: Lucas Date: Tue, 5 Nov 2024 02:59:58 +0000 Subject: [PATCH 234/275] mbedtls: fix issue about memory leak https://github.com/warmcat/libwebsockets/issues/3177 --- lib/plat/unix/unix-init.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/plat/unix/unix-init.c b/lib/plat/unix/unix-init.c index 46f072f9b9..b36879b882 100644 --- a/lib/plat/unix/unix-init.c +++ b/lib/plat/unix/unix-init.c @@ -240,4 +240,9 @@ lws_plat_context_late_destroy(struct lws_context *context) lwsl_err("ZERO RANDOM FD\n"); if (context->fd_random != LWS_INVALID_FILE) close(context->fd_random); + +#if defined(LWS_WITH_MBEDTLS) + mbedtls_entropy_free(&context->mec); + mbedtls_ctr_drbg_free(&context->mcdc); +#endif } From c4b1e34a5051390438a13c50f0e57434445ce135 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 27 Oct 2024 11:39:51 +0200 Subject: [PATCH 235/275] clean: var unused when no logs --- lib/roles/http/server/server.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index 6b132a424e..d793960585 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -345,9 +345,11 @@ _lws_vhost_init_server_af(struct vh_sock_args *a) if (setsockopt(wsi->desc.sockfd, IPPROTO_TCP, TCP_FASTOPEN, (const char*)&optval, sizeof(optval)) < 0) { +#if (_LWS_ENABLED_LOGS & LLL_WARN) int error = LWS_ERRNO; lwsl_warn("%s: TCP_NODELAY failed with error %d\n", __func__, error); +#endif } } #else From 12e52ae2939d05be88d44fec58a87e4165e73445 Mon Sep 17 00:00:00 2001 From: level 6 <28563107+aphage@users.noreply.github.com> Date: Tue, 2 Jan 2024 10:46:57 +0800 Subject: [PATCH 236/275] test-server-extpoll: remove LWS_WITH_EXTERNAL_POLL redefine --- test-apps/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/test-apps/CMakeLists.txt b/test-apps/CMakeLists.txt index e0c097f1db..d1c58ab048 100644 --- a/test-apps/CMakeLists.txt +++ b/test-apps/CMakeLists.txt @@ -163,7 +163,6 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2)) set_property( TARGET test-server-extpoll PROPERTY COMPILE_DEFINITIONS - LWS_WITH_EXTERNAL_POLL INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share" ) From dc65edd519c2cedee43d6e5114783b5edfbd61c4 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 13 Dec 2024 09:18:16 +0000 Subject: [PATCH 237/275] spa: use sized local info rather than incoming We allow a default 0 length in the incoming const info to mean a default size (of 512). We implement it by copying the incoming const info to a copy in the spa that we can adapt, which is all good. But in two cases after we dumbly use the incoming const info directly instead of the adapted copy. https://github.com/warmcat/libwebsockets/issues/3294 --- lib/roles/http/server/lws-spa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/roles/http/server/lws-spa.c b/lib/roles/http/server/lws-spa.c index ea5d4abd7b..a762be59e9 100644 --- a/lib/roles/http/server/lws-spa.c +++ b/lib/roles/http/server/lws-spa.c @@ -570,7 +570,7 @@ lws_spa_create_via_info(struct lws *wsi, const lws_spa_create_info_t *i) if (!spa->storage) goto bail2; - spa->end = spa->storage + i->max_storage - 1; + spa->end = spa->storage + spa->i.max_storage - 1; if (i->count_params) { if (i->ac) @@ -583,7 +583,7 @@ lws_spa_create_via_info(struct lws *wsi, const lws_spa_create_info_t *i) goto bail3; } - spa->s = lws_urldecode_s_create(spa, wsi, spa->storage, i->max_storage, + spa->s = lws_urldecode_s_create(spa, wsi, spa->storage, spa->i.max_storage, lws_urldecode_spa_cb); if (!spa->s) goto bail4; From c6e9792188c6511117c9ad4c7fb154096867c330 Mon Sep 17 00:00:00 2001 From: Albert Ribes Date: Fri, 10 Jan 2025 13:39:14 +0000 Subject: [PATCH 238/275] lejp: E implies float Since eg, 1e-3 is a float without needing a decimal point, let's just generally take it that anything with the exponent token is a float, ie, 1e3 is also a float despite it can be expressed as an integer. This seems right also because E is itself not valid in an integer. https://github.com/warmcat/libwebsockets/issues/3308 --- lib/misc/lejp.c | 3 ++- minimal-examples/api-tests/api-test-lejp/main.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/misc/lejp.c b/lib/misc/lejp.c index b898c6f934..c0c2bf2c6c 100644 --- a/lib/misc/lejp.c +++ b/lib/misc/lejp.c @@ -580,7 +580,8 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len) } ctx->buf[ctx->npos] = '\0'; - if (ctx->f & LEJP_SEEN_POINT) { + if (ctx->f & (LEJP_SEEN_POINT | LEJP_SEEN_EXP)) { + /* 0.001 or 1E-3 are both floats, take 1E3 as float too */ if (ctx->pst[ctx->pst_sp].callback(ctx, LEJPCB_VAL_NUM_FLOAT)) goto reject_callback; diff --git a/minimal-examples/api-tests/api-test-lejp/main.c b/minimal-examples/api-tests/api-test-lejp/main.c index 352181bbdc..8c5600915d 100644 --- a/minimal-examples/api-tests/api-test-lejp/main.c +++ b/minimal-examples/api-tests/api-test-lejp/main.c @@ -127,6 +127,10 @@ static const char * const json_tests[] = { "{" /* SHOULD_FAIL: test 10, missing open */ "\"a\":123,\"b\":}" + "}", + + "{" /* test 13: float vs int */ + "\"a\": 1, \"b\": 1.0, \"c\": 1e-3, \"d\": 1e3" "}" }; From e5506ade693b5c36384aa790cd023f906025426d Mon Sep 17 00:00:00 2001 From: Davidovory03 Date: Sun, 19 Jan 2025 16:48:31 +0000 Subject: [PATCH 239/275] mbedtls: translate error codes for caller https://github.com/warmcat/libwebsockets/issues/3315 --- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 38 ++++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index 3879e977b3..b74ffe7d2b 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -421,24 +421,38 @@ int ssl_pm_clear(SSL *ssl) int ssl_pm_read(SSL *ssl, void *buffer, int len) { - int ret; - struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm; + int ret; + struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm; - ret = mbedtls_ssl_read(&ssl_pm->ssl, buffer, (size_t)len); - if (ret < 0) { - // lwsl_notice("%s: mbedtls_ssl_read says -0x%x\n", __func__, -ret); - SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_read() return -0x%x", -ret); - if (ret == MBEDTLS_ERR_NET_CONN_RESET || + ret = mbedtls_ssl_read(&ssl_pm->ssl, buffer, (size_t)len); + if (ret < 0) { +// lwsl_notice("%s: mbedtls_ssl_read says -0x%x\n", __func__, -ret); + SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_read() return -0x%x", -ret); + if (ret == MBEDTLS_ERR_NET_CONN_RESET || #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 - ret <= MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE) /* fatal errors */ + ret <= MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE) /* fatal errors */ #else - ret <= MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) /* fatal errors */ + ret <= MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) /* fatal errors */ #endif ssl->err = SSL_ERROR_SYSCALL; - ret = -1; - } - return ret; + switch (ret) { + case MBEDTLS_ERR_NET_CONN_RESET: + ssl->err = SSL_ERROR_SYSCALL; + break; + case MBEDTLS_ERR_SSL_WANT_WRITE: + ssl->err = SSL_ERROR_WANT_WRITE; + break; + case MBEDTLS_ERR_SSL_WANT_READ: + ssl->err = SSL_ERROR_WANT_READ; + break; + default: + break; + } + ret = -1; + } + + return ret; } /* From fce734f27984d6aeead00a7709c4277367bbbc01 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Jan 2025 10:32:03 +0000 Subject: [PATCH 240/275] coverity 472862: cookiejar overflow --- lib/misc/cache-ttl/file.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/misc/cache-ttl/file.c b/lib/misc/cache-ttl/file.c index 3307faf8ea..dad23d8813 100644 --- a/lib/misc/cache-ttl/file.c +++ b/lib/misc/cache-ttl/file.c @@ -163,7 +163,11 @@ nscookiejar_iterate(lws_cache_nscookiejar_t *cache, int fd, lwsl_debug("%s: n %d, m %d\n", __func__, n, m); read: - n1 = (int)read(fd, temp + n, sizeof(temp) - (size_t)n); + if ((size_t)n >= sizeof(temp) - 1) + /* there's no space left in temp */ + n1 = 0; + else + n1 = (int)read(fd, temp + n, sizeof(temp) - (size_t)n); lwsl_debug("%s: n1 %d\n", __func__, n1); @@ -171,12 +175,18 @@ nscookiejar_iterate(lws_cache_nscookiejar_t *cache, int fd, eof = 1; if (m == n) continue; - } else + } else { n += n1; + if ((size_t)n > sizeof(temp)) { /* coverity */ + ret = -1; + goto bail; + } + } + while (m < n) { - m++; + m++; /* m can == n nw then */ if (temp[m - 1] != '\n') continue; @@ -197,6 +207,13 @@ nscookiejar_iterate(lws_cache_nscookiejar_t *cache, int fd, * cb can classify it even if it can't get all the * value part in one go */ + + /* coverity: we will blow up if m > n */ + if (m > n) { + ret = -1; + goto bail; + } + memmove(temp, temp + m, (size_t)(n - m)); n -= m; m = 0; From 5a34404b1ada805b884813ce3ed1c345d4d56c1e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Jan 2025 10:34:53 +0000 Subject: [PATCH 241/275] coverity 872858: hash gen overflow false positive Help it ignore that we use the MS 7 bits in the next part of the operation and discard it in the first part. --- lib/core/lws_map.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/core/lws_map.c b/lib/core/lws_map.c index b319d79f49..3578aa801c 100644 --- a/lib/core/lws_map.c +++ b/lib/core/lws_map.c @@ -88,7 +88,10 @@ lws_map_hash_from_key_default(const lws_map_key_t key, size_t kl) const uint8_t *u = (const uint8_t *)key; while (kl--) - h = ((((h << 7) | (h >> 25)) + 0xa1b2c3d4) ^ (*u++)) ^ h; + h = (( + (((h & 0x1fffffff /* coverity */ ) << 7) | + (h >> 25)) + + 0xa1b2c3d4) ^ (*u++)) ^ h; return h; } From b81b24d10e08410232e35742f3d4406b602f7366 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Jan 2025 10:49:10 +0000 Subject: [PATCH 242/275] coverity 472863: cookies: length check order wrong --- lib/roles/http/cookie.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/roles/http/cookie.c b/lib/roles/http/cookie.c index 1860e87de3..44ad6eb9b7 100644 --- a/lib/roles/http/cookie.c +++ b/lib/roles/http/cookie.c @@ -160,11 +160,13 @@ lws_cookie_rm_sws(const char **buf_p, size_t *len_p) buf = *buf_p; len = *len_p; + while (buf[0] == ' ' && len > 0) { buf++; len--; } - while (buf[len - 1] == ' ' && len > 0) + + while (len && buf[len - 1] == ' ') len--; *buf_p = buf; From ff0e0f3c352eaa2c6729626d5991ac0fa830990d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Jan 2025 10:59:48 +0000 Subject: [PATCH 243/275] coverity 472860: ops-h2: let coverity see all err enums covered x --- lib/roles/h2/ops-h2.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/roles/h2/ops-h2.c b/lib/roles/h2/ops-h2.c index 0f76d171ce..4835598fc5 100644 --- a/lib/roles/h2/ops-h2.c +++ b/lib/roles/h2/ops-h2.c @@ -227,11 +227,13 @@ rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi, // lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2 && lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS))) { + int scr_ret; + ebuf.token = pt->serv_buf; - ebuf.len = lws_ssl_capable_read(wsi, + scr_ret = lws_ssl_capable_read(wsi, ebuf.token, wsi->a.context->pt_serv_buf_size); - switch (ebuf.len) { + switch (scr_ret) { case 0: lwsl_info("%s: zero length read\n", __func__); return LWS_HPI_RET_PLEASE_CLOSE_ME; @@ -243,6 +245,19 @@ rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi, return LWS_HPI_RET_PLEASE_CLOSE_ME; } + /* + * coverity is confused: it knows lws_ssl_capable_read may + * return < 0 and assigning that to ebuf.len is bad, but it + * doesn't understand this check below on scr_ret < 0 + * removes that possibility + */ + + ebuf.len = scr_ret; + if (ebuf.len < 0) /* ie, not usable data */ { + lwsl_info("%s: other error\n", __func__); + return LWS_HPI_RET_PLEASE_CLOSE_ME; + } + // lwsl_notice("%s: Actual RX %d\n", __func__, ebuf.len); // if (ebuf.len > 0) // lwsl_hexdump_notice(ebuf.token, ebuf.len); @@ -313,7 +328,8 @@ rops_handle_POLLIN_h2(struct lws_context_per_thread *pt, struct lws *wsi, lws_dll2_remove(&wsi->dll_buflist); } } else - if (n && n < ebuf.len && ebuf.len > 0) { + /* cov: both n and ebuf.len are int */ + if (n > 0 && n < ebuf.len && ebuf.len > 0) { // lwsl_notice("%s: h2 append seg %d\n", __func__, ebuf.len - n); m = lws_buflist_append_segment(&wsi->buflist, ebuf.token + n, From 7333fcc9cd767ddb4be46fd2aa6bf1a614d0e80a Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 16 Jan 2025 11:40:26 +0000 Subject: [PATCH 244/275] coverity 472861: http2: deal with zero length data without overflow --- lib/roles/h2/http2.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 9cccdbcdc9..0376b10764 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -2322,12 +2322,14 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen, (unsigned int)h2n->count, (unsigned int)h2n->length); - in += (unsigned int)n - 1; - h2n->inside += (unsigned int)n; - h2n->count += (unsigned int)n - 1; + if (n) { + in += (unsigned int)n - 1; + h2n->inside += (unsigned int)n; + h2n->count += (unsigned int)n - 1; - h2n->swsi->txc.peer_tx_cr_est -= n; - wsi->txc.peer_tx_cr_est -= n; + h2n->swsi->txc.peer_tx_cr_est -= n; + wsi->txc.peer_tx_cr_est -= n; + } do_windows: From 5d1947474e5b32c0d73a4790cc8866e85b726cf6 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 24 Feb 2025 11:16:20 +0000 Subject: [PATCH 245/275] lws_tls_openssl_asn1time_to_unix: fix 13 char asn1 epoch Also align to struct tm's year epoch of 1900 https://github.com/warmcat/libwebsockets/issues/3341 --- lib/tls/openssl/openssl-x509.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/tls/openssl/openssl-x509.c b/lib/tls/openssl/openssl-x509.c index dac4aa3915..d8e8dcc829 100644 --- a/lib/tls/openssl/openssl-x509.c +++ b/lib/tls/openssl/openssl-x509.c @@ -47,11 +47,13 @@ lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as) memset(&t, 0, sizeof(t)); if (strlen(p) == 13) { - t.tm_year = (dec(p[0]) * 10) + dec(p[1]) + 100; + t.tm_year = (dec(p[0]) * 10) + dec(p[1]); + if (t.tm_year < 50) /* RFC5280: 13 char dates will break after 2049 */ + t.tm_year += 100; /* struct tm year is -1900, this gives 2000..2049 */ p += 2; } else { - t.tm_year = (dec(p[0]) * 1000) + (dec(p[1]) * 100) + - (dec(p[2]) * 10) + dec(p[3]); + t.tm_year = ((dec(p[0]) * 1000) + (dec(p[1]) * 100) + + (dec(p[2]) * 10) + dec(p[3])) - 1900; /* struct tm year is -1900 */ p += 4; } t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1; From df9f518e9726e5a2e589d8b29d6a570d46601735 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 24 Feb 2025 11:32:01 +0000 Subject: [PATCH 246/275] dos2unix: win32port/zlib/inftrees.c --- win32port/zlib/inftrees.c | 660 +++++++++++++++++++------------------- 1 file changed, 330 insertions(+), 330 deletions(-) diff --git a/win32port/zlib/inftrees.c b/win32port/zlib/inftrees.c index 9dbaec3368..11e9c52acc 100644 --- a/win32port/zlib/inftrees.c +++ b/win32port/zlib/inftrees.c @@ -1,330 +1,330 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" - -#define MAXBITS 15 - -const char inflate_copyright[] = - " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code here; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - static const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; - static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0}; - static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) { /* no symbols to code at all */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)1; - here.val = (unsigned short)0; - *(*table)++ = here; /* make a table to force an error */ - *(*table)++ = here; - *bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - end = 19; - break; - case LENS: - base = lbase; - base -= 257; - extra = lext; - extra -= 257; - end = 256; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { - here.op = (unsigned char)0; - here.val = work[sym]; - } - else if ((int)(work[sym]) > end) { - here.op = (unsigned char)(extra[work[sym]]); - here.val = base[work[sym]]; - } - else { - here.op = (unsigned char)(32 + 64); /* end of block */ - here.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - next[(huff >> drop) + fill] = here; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)(len - drop); - here.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - here.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = here; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + here.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = here; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} From bd57dbc241bda9e08516c966126f0b782aeb131e Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Wed, 21 Sep 2016 23:35:50 -0700 Subject: [PATCH 247/275] win32port: zlib: upstream bugfix patch on inftrees.c From 6a043145ca6e9c55184013841a67b2fef87e44c0 Mon Sep 17 00:00:00 2001 Subject: [PATCH] Remove offset pointer optimization in inftrees.c. inftrees.c was subtracting an offset from a pointer to an array, in order to provide a pointer that allowed indexing starting at the offset. This is not compliant with the C standard, for which the behavior of a pointer decremented before its allocated memory is undefined. Per the recommendation of a security audit of the zlib code by Trail of Bits and TrustInSoft, in support of the Mozilla Foundation, this tiny optimization was removed, in order to avoid the possibility of undefined behavior. --- win32port/zlib/inftrees.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/win32port/zlib/inftrees.c b/win32port/zlib/inftrees.c index 11e9c52acc..71eff202be 100644 --- a/win32port/zlib/inftrees.c +++ b/win32port/zlib/inftrees.c @@ -54,7 +54,7 @@ unsigned short FAR *work; code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ + unsigned match; /* use base and extra for symbol >= match */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ @@ -181,19 +181,17 @@ unsigned short FAR *work; switch (type) { case CODES: base = extra = work; /* dummy value--not used */ - end = 19; + match = 20; break; case LENS: base = lbase; - base -= 257; extra = lext; - extra -= 257; - end = 256; + match = 257; break; default: /* DISTS */ base = dbase; extra = dext; - end = -1; + match = 0; } /* initialize state for loop */ @@ -216,13 +214,13 @@ unsigned short FAR *work; for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { + if (work[sym] + 1 < match) { here.op = (unsigned char)0; here.val = work[sym]; } - else if ((int)(work[sym]) > end) { - here.op = (unsigned char)(extra[work[sym]]); - here.val = base[work[sym]]; + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ From e7fbdac39154c7bdfd42dd73c5cf25e4fd2e190d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 25 Feb 2025 19:34:27 +0000 Subject: [PATCH 248/275] lws_mux_mark_immortal: remove noisy log --- lib/core-net/wsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index 978d1e80c6..a985edb8cd 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -1305,7 +1305,7 @@ lws_mux_mark_immortal(struct lws *wsi) && !wsi->client_mux_substream #endif ) { - lwsl_wsi_err(wsi, "not mux substream"); + // lwsl_wsi_err(wsi, "not mux substream"); return; } From 6414a1b63c71302d8317cea39d2a30042122ce34 Mon Sep 17 00:00:00 2001 From: Glen Mabey Date: Tue, 25 Feb 2025 20:34:53 -0700 Subject: [PATCH 249/275] Subject: docs: fix typo --- READMEs/README.coding.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/READMEs/README.coding.md b/READMEs/README.coding.md index d1143f5690..9fa1a2c8a4 100644 --- a/READMEs/README.coding.md +++ b/READMEs/README.coding.md @@ -190,7 +190,7 @@ a UDP socket pair that the event loop waits on. When the wake is handled by the lws event loop thread, it will broadcast a `LWS_CALLBACK_EVENT_WAIT_CANCELLED` message to every vhost-protocol instantiation, so you can handle this callback, usually lock a shared data region, and if you see you need to write, call -`lws_callback_on_writeable()` for the wsi(s) that need to write. +`lws_callback_on_writable()` for the wsi(s) that need to write. There's no restriction on multiple threads calling `lws_cancel_service()`, it's unconditionally safe due to how it is implemented underneath. From 2ce0be3284d119d3413ba9ccd67054a6506eafce Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 27 Feb 2025 07:39:34 +0000 Subject: [PATCH 250/275] async dns: allow up to 8 x 128-char CNAMEs from 4 https://github.com/warmcat/libwebsockets/issues/3329 Extra ~600 bytes stack needed might be a struggle for RTOS, trimmed from 10 recommended in issue. --- lib/system/async-dns/async-dns-parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system/async-dns/async-dns-parse.c b/lib/system/async-dns/async-dns-parse.c index bdfe205037..577cc45876 100644 --- a/lib/system/async-dns/async-dns-parse.c +++ b/lib/system/async-dns/async-dns-parse.c @@ -154,7 +154,7 @@ lws_adns_iterate(lws_adns_q_t *q, const uint8_t *pkt, int len, const char *expname, lws_async_dns_find_t cb, void *opaque) { const uint8_t *e = pkt + len, *p, *pay; - struct label_stack stack[4]; + struct label_stack stack[8]; int n = 0, stp = 0, ansc, m; uint16_t rrtype, rrpaylen; char *sp, inq; From ab9df9cfc39de7a49967f18387b6b76310947442 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Fri, 28 Feb 2025 06:41:42 +0000 Subject: [PATCH 251/275] tag 4.3.5 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd1f9a35ae..57c35232a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -410,7 +410,7 @@ set(CPACK_RPM_PACKAGE_LICENSE "MIT") set(CPACK_PACKAGE_NAME "${PACKAGE}") set(CPACK_PACKAGE_VERSION_MAJOR "4") set(CPACK_PACKAGE_VERSION_MINOR "3") -set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "3") +set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "5") set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH_NUMBER}-${LWS_BUILD_HASH}") set(CPACK_PACKAGE_RELEASE 1) From 81633bef2ab1f651e6ea372a9fe17304d6f257cb Mon Sep 17 00:00:00 2001 From: Martin Quinson Date: Fri, 7 Feb 2025 11:56:06 +0100 Subject: [PATCH 252/275] PkgConfig: include libsystemd if needed by lib --- lib/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 786fa3d90b..8963030f31 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -304,6 +304,13 @@ if (LWS_HAVE_LIBCAP) set(lws_requires "libcap") endif() endif() +if (LWS_HAVE_SYSTEMD_H) + if (NOT lws_requires STREQUAL "") + set(lws_requires "${lws_requires},libsystemd") + else() + set(lws_requires "libsystemd") + endif() +endif() # Generate and install pkgconfig. From 2b0c5f1653859d94b1850c1b6a8e8e6d324939ea Mon Sep 17 00:00:00 2001 From: makejian Date: Wed, 12 Feb 2025 11:27:51 +0800 Subject: [PATCH 253/275] mbedtls/ssl: free cert chain when mbedtls_client_preload_filepath enabled Signed-off-by: makejian --- lib/tls/mbedtls/wrapper/library/ssl_lib.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/tls/mbedtls/wrapper/library/ssl_lib.c b/lib/tls/mbedtls/wrapper/library/ssl_lib.c index d751d78c20..6bc5ff4227 100644 --- a/lib/tls/mbedtls/wrapper/library/ssl_lib.c +++ b/lib/tls/mbedtls/wrapper/library/ssl_lib.c @@ -231,9 +231,11 @@ SSL_CTX* SSL_CTX_new(const SSL_METHOD *method, void *rngctx) *px = malloc(sizeof(**px)); mbedtls_x509_crt_init(*px); n = mbedtls_x509_crt_parse_file(*px, mbedtls_client_preload_filepath); - if (n < 0) + if (n < 0) { lwsl_err("%s: unable to load cert bundle 0x%x\n", __func__, -n); - else + mbedtls_x509_crt_free(*px); + free(*px); + } else lwsl_info("%s: loaded cert bundle %d\n", __func__, n); } #endif @@ -257,6 +259,17 @@ void SSL_CTX_free(SSL_CTX* ctx) ssl_cert_free(ctx->cert); +#if defined(LWS_HAVE_mbedtls_x509_crt_parse_file) + if (mbedtls_client_preload_filepath) { + mbedtls_x509_crt **px = (mbedtls_x509_crt **)ctx->client_CA->x509_pm; + + if (*px) { + mbedtls_x509_crt_free(*px); + free(*px); + } + } +#endif + X509_free(ctx->client_CA); if (ctx->alpn_protos) { From 45eca45e0955583899f31f318bf330b2edbea962 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 22 Jan 2025 10:08:55 +0000 Subject: [PATCH 254/275] sll_protocol may be be16 Google's fuzzer platform blows a warning /src/libwebsockets/lib/plat/unix/unix-sockets.c:497:21: warning: implicit conversion loses integer precision: 'uint32_t' (aka 'unsigned int') to '__be16' (aka 'unsigned short') [-Wimplicit-int-conversion] 497 | sll.sll_protocol = (uint32_t)(htons((uint16_t)0x800)); --- lib/plat/unix/unix-sockets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plat/unix/unix-sockets.c b/lib/plat/unix/unix-sockets.c index 1a40c9cf9f..61292ff89d 100644 --- a/lib/plat/unix/unix-sockets.c +++ b/lib/plat/unix/unix-sockets.c @@ -453,7 +453,7 @@ lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len, memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; - sll.sll_protocol = (uint32_t)(htons((uint16_t)0x800)); + sll.sll_protocol = (uint16_t)(htons((uint16_t)0x800)); sll.sll_halen = 6; sll.sll_ifindex = (int)if_nametoindex(iface); memset(sll.sll_addr, 0xff, 6); From 9075f01e1670e64435f4ea501667982fc911ad6b Mon Sep 17 00:00:00 2001 From: Albert Ribes Date: Thu, 13 Mar 2025 16:07:24 +0000 Subject: [PATCH 255/275] wolfssl: update membuf to use lws alloc https://github.com/warmcat/libwebsockets/issues/3349 --- lib/tls/openssl/openssl-server.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c index a3c8d12026..f149d1de03 100644 --- a/lib/tls/openssl/openssl-server.c +++ b/lib/tls/openssl/openssl-server.c @@ -329,19 +329,19 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, * The passed memory-buffer cert image is in DER, and the * memory-buffer private key image is PEM. */ -#ifndef USE_WOLFSSL if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert, mem_cert_len, &p, &flen)) { lwsl_err("%s: couldn't convert pem to der\n", __func__); return 1; } +#ifndef USE_WOLFSSL if (SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, (int)flen, (uint8_t *)p) != 1) { #else if (wolfSSL_CTX_use_certificate_buffer(vhost->tls.ssl_ctx, - (uint8_t *)mem_cert, - (int)mem_cert_len, + (uint8_t *)p, + (int)flen, WOLFSSL_FILETYPE_ASN1) != 1) { #endif From d79fa764ba0d6cfd1ce055d51d6b363a8dab4e03 Mon Sep 17 00:00:00 2001 From: stropee Date: Sun, 23 Mar 2025 13:49:01 +0000 Subject: [PATCH 256/275] freertos: fix pipe free https://github.com/warmcat/libwebsockets/issues/3352 --- lib/core-net/close.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index 71b85a72dc..c4fbf60fd4 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -915,7 +915,11 @@ __lws_close_free_wsi_final(struct lws *wsi) if (pt->pipe_wsi == wsi) pt->pipe_wsi = NULL; if (pt->dummy_pipe_fds[0] == wsi->desc.sockfd) + { +#if !defined(LWS_PLAT_FREERTOS) pt->dummy_pipe_fds[0] = LWS_SOCK_INVALID; +#endif + } } wsi->desc.sockfd = LWS_SOCK_INVALID; From 0fb2e4fd1952fac9779665c239d6ae67b0de411d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 24 Mar 2025 12:32:34 +0000 Subject: [PATCH 257/275] clean: remove google fuzzer warning when no MQTT /src/libwebsockets//lib/secure-streams/private-lib-secure-streams.h:214:1: warning: empty union has size 0 in C, size 1 in C++ [-Wextern-c-compat] 214 | union lws_ss_contemp { --- lib/secure-streams/private-lib-secure-streams.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index cc2fc4cfb5..eef22f3196 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -124,19 +124,13 @@ typedef struct lws_ss_handle { union { struct { /* LWSSSP_H1 */ -#if defined(WIN32) uint8_t dummy; -#endif } h1; struct { /* LWSSSP_H2 */ -#if defined(WIN32) uint8_t dummy; -#endif } h2; struct { /* LWSSSP_WS */ -#if defined(WIN32) uint8_t dummy; -#endif } ws; } u; } http; @@ -207,10 +201,8 @@ union lws_ss_contemp { #if defined(LWS_ROLE_MQTT) lws_mqtt_client_connect_param_t ccp; #else -#if defined(WIN32) uint8_t dummy; #endif -#endif }; /* From a5076930168658baf664a1daf27e73029f77eeae Mon Sep 17 00:00:00 2001 From: Albert Ribes Date: Mon, 7 Apr 2025 12:28:09 +0200 Subject: [PATCH 258/275] Subject: [PATCH] Fix cgi QUERY_STRING key only field truncated A request like 'http://host?abc' set the QUERY_STRING variable for CGIs to "ab" instead of "abc". This was because the code didn't account for key-only fields, only for key-value ones. --- lib/roles/cgi/cgi-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/cgi/cgi-server.c b/lib/roles/cgi/cgi-server.c index a6f04fa1b1..5f82b2e475 100644 --- a/lib/roles/cgi/cgi-server.c +++ b/lib/roles/cgi/cgi-server.c @@ -250,7 +250,7 @@ lws_cgi(struct lws *wsi, const char * const *exec_array, if (*t == '=') *p++ = *t++; i = urlencode(t, i - lws_ptr_diff(t, tok), p, lws_ptr_diff(end, p)); - if (i > 0) { + if (i >= 0) { p += i; *p++ = '&'; } From 155726adfb7571e8da812bc921e85310355f6395 Mon Sep 17 00:00:00 2001 From: Dmitry Potapov Date: Tue, 8 Apr 2025 05:34:06 +0100 Subject: [PATCH 259/275] client-http: correct return for write error The error path for the write failing closes the wsi, but returns 0, which indicates to the caller that the wsi is OK. --- lib/roles/http/client/client-http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 11938b7d81..4491859505 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -286,7 +286,7 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) lwsl_debug("ERROR writing to client socket\n"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cws"); - return 0; + return -1; case LWS_SSL_CAPABLE_MORE_SERVICE: lws_callback_on_writable(wsi); break; From ec1cd5c4f750278774df355c543a38821c5607cf Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 8 Apr 2025 05:33:05 +0100 Subject: [PATCH 260/275] client-http: improve exit paths The handling of return codes in client-http generally can do with some improvement. Basically it should be OK (0) or the wsi should be closed synchronously in the function and return nonzero. Re-use LWS_HPI_RET_WSI_ALREADY_DIED as the closed return to make the meaning unambiguous. Add some extra use of bail3 exit path to cleanly return the closed value with cce for some extra cases. --- lib/roles/http/client/client-http.c | 37 +++++++++++++++++++---------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/lib/roles/http/client/client-http.c b/lib/roles/http/client/client-http.c index 4491859505..013cfb1899 100644 --- a/lib/roles/http/client/client-http.c +++ b/lib/roles/http/client/client-http.c @@ -30,6 +30,11 @@ lws_client_http_body_pending(struct lws *wsi, int something_left_to_send) wsi->client_http_body_pending = !!something_left_to_send; } +/* + * Returns 0 for wsi survived OK, or LWS_HPI_RET_WSI_ALREADY_DIED + * meaning the wsi was destroyed by us before return. + */ + int lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) { @@ -54,7 +59,7 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) if (!lws_client_connect_2_dnsreq(wsi)) { /* closed */ lwsl_client("closed\n"); - return -1; + return LWS_HPI_RET_WSI_ALREADY_DIED; } /* either still pending connection, or changed mode */ @@ -69,7 +74,7 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) if (pollfd->revents & LWS_POLLOUT) if (lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL) == NULL) { lwsl_client("closed\n"); - return -1; + return LWS_HPI_RET_WSI_ALREADY_DIED; } break; @@ -137,7 +142,7 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) goto bail3; } - lwsl_info("%s: proxy connection extablished\n", __func__); + lwsl_info("%s: proxy connection established\n", __func__); /* clear his proxy connection timeout */ @@ -163,8 +168,11 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) #if defined(LWS_WITH_SOCKS5) start_ws_handshake: #endif - if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) - return -1; + if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { + cce = "unable to clear POLLOUT"; + /* turn whatever went wrong into a clean close */ + goto bail3; + } #if defined(LWS_ROLE_H2) || defined(LWS_WITH_TLS) if ( @@ -286,7 +294,7 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) lwsl_debug("ERROR writing to client socket\n"); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cws"); - return -1; + return LWS_HPI_RET_WSI_ALREADY_DIED; case LWS_SSL_CAPABLE_MORE_SERVICE: lws_callback_on_writable(wsi); break; @@ -376,8 +384,10 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) } if (pollfd->revents & LWS_POLLOUT) - if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) - return -1; + if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) { + cce = "Unable to clear POLLOUT"; + goto bail3; + } if (!(pollfd->revents & LWS_POLLIN)) break; @@ -443,7 +453,7 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) if (lws_buflist_aware_finished_consuming(wsi, &eb, m, buffered, __func__)) - return -1; + goto bail3; /* * coverity: uncomment if extended @@ -486,7 +496,7 @@ lws_http_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd) lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce)); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cbail3"); - return -1; + return LWS_HPI_RET_WSI_ALREADY_DIED; default: break; @@ -627,7 +637,8 @@ lws_client_interpret_server_handshake(struct lws *wsi) LRS_ESTABLISHED, &role_ops_h1); } #else - return -1; + cce = "h1 not built"; + goto bail3; #endif } @@ -836,7 +847,7 @@ lws_client_interpret_server_handshake(struct lws *wsi) lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "redir"); wsi->a.opaque_user_data = opaque; - return -1; + return LWS_HPI_RET_WSI_ALREADY_DIED; } /* if h1 KA is allowed, enable the queued pipeline guys */ @@ -1051,7 +1062,7 @@ lws_client_interpret_server_handshake(struct lws *wsi) /* closing will free up his parsing allocations */ lws_close_free_wsi(wsi, (enum lws_close_status)close_reason, "c hs interp"); - return 1; + return LWS_HPI_RET_WSI_ALREADY_DIED; } #endif From db62fbc27138f7be6f56d7760f114d30a5bdec40 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 6 May 2025 11:33:43 +0100 Subject: [PATCH 261/275] close: trim length of reason In the case of "closed before connection", we need to use sizeof(_reason) - 1 https://github.com/warmcat/libwebsockets/issues/3380 --- lib/core-net/close.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index c4fbf60fd4..bb621a497e 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -629,7 +629,7 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, wsi->socket_is_permanently_unusable = 1; lws_inform_client_conn_fail(wsi, - (void *)_reason, sizeof(_reason)); + (void *)_reason, sizeof(_reason) - 1); } #endif From 92b475220dc60e07436b2eec0ada1e42c39e28b0 Mon Sep 17 00:00:00 2001 From: Dmitry Potapov Date: Fri, 9 May 2025 09:57:39 +0100 Subject: [PATCH 262/275] libev: run the loop in a way it can be cancelled --- lib/event-libs/libev/libev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/event-libs/libev/libev.c b/lib/event-libs/libev/libev.c index 6b460d6c40..cafdebe6ae 100644 --- a/lib/event-libs/libev/libev.c +++ b/lib/event-libs/libev/libev.c @@ -345,7 +345,7 @@ static void elops_run_pt_ev(struct lws_context *context, int tsi) { if (pt_to_priv_ev(&context->pt[tsi])->io_loop) - ev_run(pt_to_priv_ev(&context->pt[tsi])->io_loop, 0); + ev_run(pt_to_priv_ev(&context->pt[tsi])->io_loop, EVRUN_ONCE); } static int @@ -371,7 +371,7 @@ elops_destroy_context2_ev(struct lws_context *context) continue; } while (budget-- && - (m = ev_run(ptpr->io_loop, 0))) + (m = ev_run(ptpr->io_loop, EVRUN_NOWAIT))) ; ev_loop_destroy(ptpr->io_loop); From bb1261254e5709e610d63c59ce9744ce470760ce Mon Sep 17 00:00:00 2001 From: Matt Fischer Date: Wed, 14 May 2025 15:03:48 -0500 Subject: [PATCH 263/275] adns: Report error code if callback destroyed wsi https://github.com/warmcat/libwebsockets/issues/3389 --- lib/system/async-dns/async-dns.c | 25 +++++++++----------- lib/system/async-dns/private-lib-async-dns.h | 2 +- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/lib/system/async-dns/async-dns.c b/lib/system/async-dns/async-dns.c index e722214f1f..07cda4d3a3 100644 --- a/lib/system/async-dns/async-dns.c +++ b/lib/system/async-dns/async-dns.c @@ -82,9 +82,10 @@ lws_async_dns_drop_server(struct lws_context *context) context->async_dns.dns_server_connected = 0; } -int +lws_async_dns_retcode_t lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c) { + lws_async_dns_retcode_t ret = LADNS_RET_FOUND; lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, lws_dll2_get_head(&q->wsi_adns)) { @@ -101,11 +102,10 @@ lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c) * This may decide to close / delete w */ if (w->adns_cb(w, (const char *)&q[1], c ? c->results : NULL, 0, - q->opaque) == NULL) + q->opaque) == NULL) { lwsl_info("%s: failed\n", __func__); - // lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS, - // "adopt udp2 fail"); - + ret = LADNS_RET_FAILED_WSI_CLOSED; + } } lws_end_foreach_dll_safe(d, d1); @@ -116,13 +116,14 @@ lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c) c->refcount++; } - q->standalone_cb(NULL, (const char *)&q[1], - c ? c->results : NULL, 0, q->opaque); + if (q->standalone_cb(NULL, (const char *)&q[1], + c ? c->results : NULL, 0, q->opaque) == NULL) + ret = LADNS_RET_FAILED_WSI_CLOSED; } lws_adns_dump(q->dns); - return 0; + return ret; } static void @@ -775,9 +776,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, ai->ai_addr = (struct sockaddr *)&sa46->sa4; memcpy(&sa46->sa4.sin_addr, ads, (unsigned int)m); - lws_async_dns_complete(&tmq.tq, c); - - return LADNS_RET_FOUND; + return lws_async_dns_complete(&tmq.tq, c); } #if defined(LWS_WITH_IPV6) @@ -787,9 +786,7 @@ lws_async_dns_query(struct lws_context *context, int tsi, const char *name, ai->ai_addr = (struct sockaddr *)&sa46->sa6; memcpy(&sa46->sa6.sin6_addr, ads, (unsigned int)m); - lws_async_dns_complete(&tmq.tq, c); - - return LADNS_RET_FOUND; + return lws_async_dns_complete(&tmq.tq, c); } #endif diff --git a/lib/system/async-dns/private-lib-async-dns.h b/lib/system/async-dns/private-lib-async-dns.h index f213448ab2..5992fd069a 100644 --- a/lib/system/async-dns/private-lib-async-dns.h +++ b/lib/system/async-dns/private-lib-async-dns.h @@ -115,7 +115,7 @@ sul_cb_expire(struct lws_sorted_usec_list *sul); void lws_adns_cache_destroy(lws_adns_cache_t *c); -int +lws_async_dns_retcode_t lws_async_dns_complete(lws_adns_q_t *q, lws_adns_cache_t *c); lws_adns_cache_t * From e2cbcf72736be35a76f4c2154810a1cea8c118a0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 10 Jun 2025 17:21:46 +0100 Subject: [PATCH 264/275] cgi: allow some space for sundries in stdout buf We need to hold back a few bytes of our max usage of the cgi stdout in buffer to allow for chunking header size, otherwise we run the risk of buffer overrun trashing other stack vars. https://github.com/warmcat/libwebsockets/issues/3402 --- lib/roles/cgi/cgi-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/roles/cgi/cgi-server.c b/lib/roles/cgi/cgi-server.c index 5f82b2e475..74800f32c9 100644 --- a/lib/roles/cgi/cgi-server.c +++ b/lib/roles/cgi/cgi-server.c @@ -828,7 +828,7 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) n = lws_get_socket_fd(wsi->http.cgi->lsp->stdwsi[LWS_STDOUT]); if (n < 0) return -1; - n = (int)read(n, start, sizeof(buf) - LWS_PRE); + n = (int)read(n, start, sizeof(buf) - LWS_PRE - 16); if (n < 0 && errno != EAGAIN) { lwsl_wsi_debug(wsi, "stdout read says %d", n); From d444bc5c7735b780de09d72c0b8c9cfdf588bfde Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 1 Jul 2025 15:54:35 +0100 Subject: [PATCH 265/275] client: use return enum to clarify closure plan --- lib/roles/h1/ops-h1.c | 4 ++-- lib/roles/ws/client-parser-ws.c | 37 +++++++++++++++++++-------------- lib/roles/ws/client-ws.c | 27 ++++++++++++++++-------- lib/roles/ws/ops-ws.c | 2 +- 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c index 769490fe7e..b5669a2035 100644 --- a/lib/roles/h1/ops-h1.c +++ b/lib/roles/h1/ops-h1.c @@ -71,7 +71,7 @@ lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len) } lwsl_parser("issuing %d bytes to parser\n", (int)len); #if defined(LWS_ROLE_WS) && defined(LWS_WITH_CLIENT) - if (lws_ws_handshake_client(wsi, &buf, (size_t)len)) + if (lws_ws_handshake_client(wsi, &buf, (size_t)len) == LWS_HPI_RET_PLEASE_CLOSE_ME) goto bail; #endif last_char = buf; @@ -259,7 +259,7 @@ lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len) ws_mode: #if defined(LWS_WITH_CLIENT) && defined(LWS_ROLE_WS) // lwsl_notice("%s: ws_mode\n", __func__); - if (lws_ws_handshake_client(wsi, &buf, (size_t)len)) + if (lws_ws_handshake_client(wsi, &buf, (size_t)len) == LWS_HPI_RET_PLEASE_CLOSE_ME) goto bail; #endif #if defined(LWS_ROLE_WS) diff --git a/lib/roles/ws/client-parser-ws.c b/lib/roles/ws/client-parser-ws.c index f67927b2af..05d6677f5a 100644 --- a/lib/roles/ws/client-parser-ws.c +++ b/lib/roles/ws/client-parser-ws.c @@ -27,6 +27,11 @@ /* * parsers.c: lws_ws_rx_sm() needs to be roughly kept in * sync with changes here, esp related to ext draining + * + * + * We return eithe LWS_HPI_RET_PLEASE_CLOSE_ME if we identified + * a situation that requires the stream to close now, or + * LWS_HPI_RET_HANDLED if we can continue okay. */ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) @@ -101,7 +106,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) case LWSWSOPC_CONTINUATION: if (!wsi->ws->continuation_possible) { lwsl_wsi_info(wsi, "disordered continuation"); - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } wsi->ws->first_fragment = 0; break; @@ -120,7 +125,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) case 0xe: case 0xf: lwsl_wsi_info(wsi, "illegal opcode"); - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; default: wsi->ws->defeat_check_utf8 = 1; break; @@ -133,7 +138,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) #endif wsi->ws->rsv) { lwsl_wsi_info(wsi, "illegal rsv bits set"); - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } wsi->ws->final = !!((c >> 7) & 1); lwsl_wsi_ext(wsi, " This RX frame Final %d", @@ -143,7 +148,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME || wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)) { lwsl_wsi_info(wsi, "hey you owed us a FIN"); - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } if ((!(wsi->ws->opcode & 8)) && wsi->ws->final) { wsi->ws->continuation_possible = 0; @@ -152,7 +157,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) if ((wsi->ws->opcode & 8) && !wsi->ws->final) { lwsl_wsi_info(wsi, "control msg can't be fragmented"); - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } if (!wsi->ws->final) wsi->ws->owed_a_fin = 1; @@ -235,7 +240,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) if (c & 0x80) { lwsl_wsi_warn(wsi, "b63 of length must be zero"); /* kill the connection */ - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } #if defined __LP64__ wsi->ws->rx_packet_length = ((size_t)c) << 56; @@ -397,7 +402,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) * finish our close */ lwsl_wsi_parser(wsi, "seen server's close ack"); - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } lwsl_wsi_parser(wsi, "client sees server close len = %d", @@ -419,7 +424,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) LWS_CALLBACK_WS_PEER_INITIATED_CLOSE, wsi->user_space, pp, wsi->ws->rx_ubuf_head)) - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; memcpy(wsi->ws->ping_payload_buf + LWS_PRE, pp, wsi->ws->rx_ubuf_head); @@ -494,7 +499,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) lwsl_wsi_ext(wsi, "Unhandled ext opc 0x%x", wsi->ws->opcode); wsi->ws->rx_ubuf_head = 0; - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } /* @@ -543,7 +548,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) lwsl_wsi_ext(wsi, "Ext RX returned %d", n); if (n < 0) { wsi->socket_is_permanently_unusable = 1; - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } if (n == PMDR_DID_NOTHING) /* ie, not PMDR_NOTHING_WE_SHOULD_DO */ @@ -597,7 +602,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) lwsl_hexdump_wsi_info(wsi, pmdrx.eb_out.token, (unsigned int)pmdrx.eb_out.len); - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } } @@ -656,7 +661,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) /* if user code wants to close, let caller know */ if (m) - return 1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } while (pmdrx.eb_in.len #if !defined(LWS_WITHOUT_EXTENSIONS) @@ -669,16 +674,16 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) break; default: lwsl_wsi_err(wsi, "client rx illegal state"); - return 1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } - return 0; + return LWS_HPI_RET_HANDLED; illegal_ctl_length: lwsl_wsi_warn(wsi, "Control frame asking for extended length is illegal"); /* kill the connection */ - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; server_cannot_mask: lws_close_reason(wsi, @@ -688,7 +693,7 @@ int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c) lwsl_wsi_warn(wsi, "Server must not mask"); /* kill the connection */ - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } diff --git a/lib/roles/ws/client-ws.c b/lib/roles/ws/client-ws.c index bc2a84682a..ac0f578867 100644 --- a/lib/roles/ws/client-ws.c +++ b/lib/roles/ws/client-ws.c @@ -66,6 +66,11 @@ lws_create_client_ws_object(const struct lws_client_connect_info *i, } #if defined(LWS_WITH_CLIENT) + +/* + * Returns either LWS_HPI_RET_PLEASE_CLOSE_ME or LWS_HPI_RET_HANDLED + */ + int lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) { @@ -75,7 +80,7 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE) && (lwsi_state(wsi) != LRS_WAITING_SERVER_REPLY) && !lwsi_role_client(wsi)) - return 0; + return LWS_HPI_RET_HANDLED; lwsl_wsi_debug(wsi, "hs client feels it has %d in", (int)len); @@ -108,19 +113,22 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) } else *buf += len; - return 0; + return LWS_HPI_RET_HANDLED; } #if !defined(LWS_WITHOUT_EXTENSIONS) if (wsi->ws->rx_draining_ext) { int m; lwsl_wsi_info(wsi, "draining ext"); - if (lwsi_role_client(wsi)) + if (lwsi_role_client(wsi)) { m = lws_ws_client_rx_sm(wsi, 0); - else + if (m == LWS_HPI_RET_PLEASE_CLOSE_ME) + return LWS_HPI_RET_PLEASE_CLOSE_ME; + } else { m = lws_ws_rx_sm(wsi, 0, 0); - if (m < 0) - return -1; + if (m < 0) + return LWS_HPI_RET_PLEASE_CLOSE_ME; + } continue; } #endif @@ -129,16 +137,17 @@ lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len) * happened to *buf */ - if (lws_ws_client_rx_sm(wsi, *(*buf)++)) { + if (lws_ws_client_rx_sm(wsi, *(*buf)++) == + LWS_HPI_RET_PLEASE_CLOSE_ME) { lwsl_wsi_info(wsi, "client_rx_sm exited, DROPPING %d", (int)len); - return -1; + return LWS_HPI_RET_PLEASE_CLOSE_ME; } len--; } // lwsl_wsi_notice(wsi, "finished with %ld", (long)len); - return 0; + return LWS_HPI_RET_HANDLED; } #endif diff --git a/lib/roles/ws/ops-ws.c b/lib/roles/ws/ops-ws.c index 881d3f12cd..0c0339076b 100644 --- a/lib/roles/ws/ops-ws.c +++ b/lib/roles/ws/ops-ws.c @@ -1063,7 +1063,7 @@ rops_handle_POLLIN_ws(struct lws_context_per_thread *pt, struct lws *wsi, #if defined(LWS_WITH_CLIENT) if (lwsi_role_client(wsi)) { n = lws_ws_client_rx_sm(wsi, 0); - if (n < 0) + if (n == LWS_HPI_RET_PLEASE_CLOSE_ME) /* we closed wsi */ return LWS_HPI_RET_PLEASE_CLOSE_ME; } else From f5c9df12ee9848a7f46bd4b572cb84ecc77433f9 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 1 Jul 2025 07:38:53 +0100 Subject: [PATCH 266/275] openssl: direct callback to best protocol --- lib/tls/openssl/openssl-client.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 884ca02136..d0b7e5f196 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -92,6 +92,7 @@ OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) SSL *ssl; int n, err = 0; struct lws *wsi; + const struct lws_protocols *lp; /* keep old behaviour accepting self-signed server certs */ if (!preverify_ok) { @@ -184,8 +185,11 @@ OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) lws_tls_jit_trust_sort_kids(wsi, &wsi->tls.kid_chain); } #endif + lp = &(lws_get_context_protocol(wsi->a.context, 0)); + if (wsi->a.protocol) + lp = wsi->a.protocol; - n = lws_get_context_protocol(wsi->a.context, 0).callback(wsi, + n = lp->callback(wsi, LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION, x509_ctx, ssl, (unsigned int)preverify_ok); From f98cde5e007ce6750937073dc0daaa5ca4c8cf7d Mon Sep 17 00:00:00 2001 From: Marc Oertel Date: Wed, 2 Jul 2025 13:48:38 +0100 Subject: [PATCH 267/275] LICENSE: clarify licenses in summary The files involved already have proper copyright notices. This adds them to the license summary in ./LICENSE. --- LICENSE | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 917f8dcf23..e41113efd4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,7 @@ +MIT License + +Copyright (c) 2006-2025 Andy Green + Libwebsockets and included programs are provided under the terms of the MIT license shown below, with the exception that some sources are under a similar permissive license like BSD, or are explicitly CC0 / public @@ -36,6 +40,12 @@ to us so you can easily use later releases and fixes. ## MIT License applied to libwebsockets +(lib/misc/base64-decode.c, lib/misc/daemonize.c, lib/plat/windows/windows-resolv.c) + +lib/misc/base64-decode.c: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc. +lib/misc/daemonize.c: Copyright (c)2006 - 2013 Andy Green +lib/plat/windows/windows-resolv.c - Copyright (C) 2010 - 2019 Andy Green + https://opensource.org/licenses/MIT Permission is hereby granted, free of charge, to any person obtaining a copy @@ -58,6 +68,10 @@ https://opensource.org/licenses/MIT ## BSD2 +(lib/misc/ieeehalfprecision.c) + +lib/misc/ieeehalfprecision.c - Copyright: (c) 2009 by James Tursa, All Rights Reserved + ``` * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -208,4 +222,3 @@ For these and/or other purposes and motivations, and without any expectation of Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. ``` - From 04dc49e8d7688003e7fbfba11aaa72517bbac921 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 7 Jul 2025 14:03:49 +0100 Subject: [PATCH 268/275] ssh: set correct lengths for sigma and tau --- plugins/ssh-base/crypto/chacha.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/ssh-base/crypto/chacha.c b/plugins/ssh-base/crypto/chacha.c index 182280dced..0521194380 100644 --- a/plugins/ssh-base/crypto/chacha.c +++ b/plugins/ssh-base/crypto/chacha.c @@ -59,8 +59,8 @@ typedef struct chacha_ctx chacha_ctx; a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); -static const char sigma[16] = "expand 32-byte k"; -static const char tau[16] = "expand 16-byte k"; +static const char sigma[17] = "expand 32-byte k"; +static const char tau[17] = "expand 16-byte k"; void chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits) From 1d3e8685ca369faf579f74bde82de0542f8502e0 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 30 Apr 2025 06:04:50 +0100 Subject: [PATCH 269/275] vhost: track vh-protocol protocol init We may paint vhosts with plugin protocols, but that doesn't mean that the protocol is enabled on the vhost. In turn that means if we didn't do PROTOCOL_INIT, we should not do PROTOCOL_DESTROY on the vhost-protocol combo. --- lib/core-net/private-lib-core-net.h | 2 +- lib/core-net/vhost.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 579bc53258..e67865434f 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -523,7 +523,7 @@ struct lws_vhost { #if defined(LWS_WITH_TLS_SESSIONS) uint32_t tls_session_cache_max; #endif - + uint32_t protocol_init; /* bitmap indicating if protocol initialized */ #if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY) || defined(LWS_WITH_SECURE_STREAMS_CPP) int8_t ss_refcount; /**< refcount of number of ss connections with streamtypes using this diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index 74d61417e3..7faab1fd5b 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -465,6 +465,7 @@ lws_protocol_init_vhost(struct lws_vhost *vh, int *any) ) { lwsl_vhost_info(vh, "init %s.%s", vh->name, vh->protocols[n].name); + vh->protocol_init |= 1u << n; if (vh->protocols[n].callback((struct lws *)lwsa, LWS_CALLBACK_PROTOCOL_INIT, NULL, #if !defined(LWS_WITH_PLUGINS) @@ -1464,11 +1465,11 @@ __lws_vhost_destroy2(struct lws_vhost *vh) while (n < vh->count_protocols) { wsi.a.protocol = protocol; - lwsl_vhost_debug(vh, "protocol destroy"); - - if (protocol->callback) + if (protocol->callback && (vh->protocol_init & (1u << n))) { + lwsl_vhost_debug(vh, "protocol %s destroy", protocol->name); protocol->callback(&wsi, LWS_CALLBACK_PROTOCOL_DESTROY, NULL, NULL, 0); + } protocol++; n++; } From 714bb9de840473d0aa2a74914a280edd59363ee1 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 7 Jul 2025 20:43:20 +0100 Subject: [PATCH 270/275] destroy: introduce pre_natal pt dll2 For the edge case that a client wsi was created but did not get the chance to go around the event loop even once, introduce a pt dll2_owner that lists wsi that have been created in the heap, but not bound to any fds entry. __lws_wsi_create_with_role() adds the created wsi to the pt, and subsequently it's removed from the list when an fd is added to the fds. At pt destroy time, the listed wsi are walked and freed. --- lib/core-net/adopt.c | 8 ++++++++ lib/core-net/client/connect.c | 4 +++- lib/core-net/close.c | 3 +++ lib/core-net/private-lib-core-net.h | 7 +++++++ lib/core-net/vhost.c | 1 + lib/core-net/wsi.c | 11 +++++++++++ lib/core/context.c | 16 +++++++++++++--- lib/plat/unix/unix-spawn.c | 3 +++ lib/plat/windows/windows-spawn.c | 2 ++ lib/roles/dbus/dbus.c | 3 +++ lib/roles/http/server/server.c | 2 ++ lib/roles/netlink/ops-netlink.c | 1 + 12 files changed, 57 insertions(+), 4 deletions(-) diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index 579f4bfe16..ac50d8c199 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -198,12 +198,20 @@ __lws_adopt_descriptor_vhost1(struct lws_vhost *vh, lws_adoption_type type, lws_pt_unlock(pt); + /* + * We can lose him from the context pre_natal "last resort" bind now, + * because we will list him on a specific vhost + */ + + lws_dll2_remove(&new_wsi->pre_natal); + /* * he's an allocated wsi, but he's not on any fds list or child list, * join him to the vhost's list of these kinds of incomplete wsi until * he gets another identity (he may do async dns now...) */ lws_vhost_lock(new_wsi->a.vhost); + lws_dll2_add_head(&new_wsi->vh_awaiting_socket, &new_wsi->a.vhost->vh_awaiting_socket_owner); lws_vhost_unlock(new_wsi->a.vhost); diff --git a/lib/core-net/client/connect.c b/lib/core-net/client/connect.c index 23c4c36764..8e85f78a45 100644 --- a/lib/core-net/client/connect.c +++ b/lib/core-net/client/connect.c @@ -176,7 +176,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) if (!vh) { /* coverity */ lwsl_cx_err(i->context, "no vhost"); - goto bail; + goto bail; /* this frees the wsi */ } if (!strcmp(vh->name, "system")) vh = vh->vhost_next; @@ -537,6 +537,8 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) #endif bail: + lws_dll2_remove(&wsi->pre_natal); + #if defined(LWS_WITH_TLS) if (wsi->tls.ssl) lws_tls_restrict_return(wsi); diff --git a/lib/core-net/close.c b/lib/core-net/close.c index bb621a497e..cfe2b9d429 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -212,6 +212,9 @@ __lws_free_wsi(struct lws *wsi) lws_context_assert_lock_held(wsi->a.context); + /* just in case */ + lws_dll2_remove(&wsi->pre_natal); + #if defined(LWS_WITH_SECURE_STREAMS) if (wsi->for_ss) { diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index e67865434f..eb89b996ee 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -301,6 +301,11 @@ struct lws_context_per_thread { #if defined (LWS_WITH_SEQUENCER) lws_sorted_usec_list_t sul_seq_heartbeat; #endif + + lws_dll2_owner_t pre_natal_wsi_owner; /* allocated wsi not yet bound to vh + are kept on here until bound, so + they can be reaped if needed */ + #if (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)) && defined(LWS_WITH_SERVER) lws_sorted_usec_list_t sul_ah_lifecheck; #endif @@ -656,6 +661,8 @@ struct lws { lws_sorted_usec_list_t sul_validity; lws_sorted_usec_list_t sul_connect_timeout; + lws_dll2_t pre_natal; + struct lws_dll2 dll_buflist; /* guys with pending rxflow */ struct lws_dll2 same_vh_protocol; struct lws_dll2 vh_awaiting_socket; diff --git a/lib/core-net/vhost.c b/lib/core-net/vhost.c index 7faab1fd5b..780bcb4d90 100644 --- a/lib/core-net/vhost.c +++ b/lib/core-net/vhost.c @@ -1145,6 +1145,7 @@ __lws_create_event_pipes(struct lws_context *context) if (lws_wsi_inject_to_loop(pt, wsi)) goto bail; + return 0; } } diff --git a/lib/core-net/wsi.c b/lib/core-net/wsi.c index a985edb8cd..9be83d728b 100644 --- a/lib/core-net/wsi.c +++ b/lib/core-net/wsi.c @@ -283,6 +283,10 @@ lws_wsi_fault_timedclose(struct lws *wsi) /* * We need the context lock + * + * If we returned a wsi rather than NULL, it is listed on the + * context->pre_natal_owner list of wild wsi not yet part of + * a vhost or on the fd list. */ struct lws * @@ -290,6 +294,7 @@ __lws_wsi_create_with_role(struct lws_context *context, int tsi, const struct lws_role_ops *ops, lws_log_cx_t *log_cx_template) { + struct lws_context_per_thread *pt = &context->pt[tsi]; size_t s = sizeof(struct lws); struct lws *wsi; @@ -332,11 +337,16 @@ __lws_wsi_create_with_role(struct lws_context *context, int tsi, lws_fi_inherit_copy(&wsi->fic, &context->fic, "wsi", NULL); if (lws_fi(&wsi->fic, "createfail")) { + lws_dll2_remove(&wsi->pre_natal); lws_fi_destroy(&wsi->fic); lws_free(wsi); return NULL; } + lws_pt_lock(pt, __func__); /* -------------- pt { */ + lws_dll2_add_head(&wsi->pre_natal, &pt->pre_natal_wsi_owner); + lws_pt_unlock(pt); /* } pt --------------- */ + return wsi; } @@ -354,6 +364,7 @@ lws_wsi_inject_to_loop(struct lws_context_per_thread *pt, struct lws *wsi) if (__insert_wsi_socket_into_fds(pt->context, wsi)) goto bail; + lws_dll2_remove(&wsi->pre_natal); ret = 0; bail: diff --git a/lib/core/context.c b/lib/core/context.c index a733ee38c3..9d8447df0f 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -1700,10 +1700,11 @@ lws_pt_destroy(struct lws_context_per_thread *pt) #if defined(LWS_WITH_CGI) lws_ctx_t ctx = pt->context; - if (lws_rops_fidx(&role_ops_cgi, LWS_ROPS_pt_init_destroy)) - (lws_rops_func_fidx(&role_ops_cgi, LWS_ROPS_pt_init_destroy)). - pt_init_destroy(ctx, NULL, pt, 1); + if (lws_rops_fidx(&role_ops_cgi, LWS_ROPS_pt_init_destroy)) + (lws_rops_func_fidx(&role_ops_cgi, LWS_ROPS_pt_init_destroy)). + pt_init_destroy(ctx, NULL, pt, 1); #endif + vpt = (volatile struct lws_context_per_thread *)pt; ftp = vpt->foreign_pfd_list; while (ftp) { @@ -1715,6 +1716,15 @@ lws_pt_destroy(struct lws_context_per_thread *pt) lws_pt_lock(pt, __func__); + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, + lws_dll2_get_head(&pt->pre_natal_wsi_owner)) { + struct lws *wsi = lws_container_of(d, struct lws, pre_natal); + + lwsl_wsi_info(wsi, "pt pre_natal cleanup"); + __lws_free_wsi(wsi); + + } lws_end_foreach_dll_safe(d, d1); + if (pt->pipe_wsi) { lws_destroy_event_pipe(pt->pipe_wsi); pt->pipe_wsi = NULL; diff --git a/lib/plat/unix/unix-spawn.c b/lib/plat/unix/unix-spawn.c index 5a85580aae..d69339c9be 100644 --- a/lib/plat/unix/unix-spawn.c +++ b/lib/plat/unix/unix-spawn.c @@ -423,6 +423,9 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) if (__insert_wsi_socket_into_fds(context, lsp->stdwsi[n])) goto bail3; + + lws_dll2_remove(&lsp->stdwsi[n]->pre_natal); + if (i->opt_parent) { lsp->stdwsi[n]->parent = i->opt_parent; lsp->stdwsi[n]->sibling_list = i->opt_parent->child_list; diff --git a/lib/plat/windows/windows-spawn.c b/lib/plat/windows/windows-spawn.c index a7c0322e38..ba7e54de98 100644 --- a/lib/plat/windows/windows-spawn.c +++ b/lib/plat/windows/windows-spawn.c @@ -426,6 +426,8 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i) lsp->stdwsi[n]->desc.filefd = lsp->pipe_fds[n][!n]; lsp->stdwsi[n]->file_desc = 1; + lws_dll2_remove(&lsp->stdwsi[n]->pre_natal); + lwsl_debug("%s: lsp stdwsi %p: pipe idx %d -> fd %d / %d\n", __func__, lsp->stdwsi[n], n, lsp->pipe_fds[n][!!(n == 0)], diff --git a/lib/roles/dbus/dbus.c b/lib/roles/dbus/dbus.c index 34457925f8..b8b81f59d7 100644 --- a/lib/roles/dbus/dbus.c +++ b/lib/roles/dbus/dbus.c @@ -94,11 +94,14 @@ __lws_shadow_wsi(struct lws_dbus_ctx *ctx, DBusWatch *w, int fd, int create_ok) lws_vhost_bind_wsi(ctx->vh, wsi); if (__insert_wsi_socket_into_fds(ctx->vh->context, wsi)) { lwsl_err("inserting wsi socket into fds failed\n"); + lws_dll2_remove(&wsi->pre_natal); __lws_vhost_unbind_wsi(wsi); /* cx + vh lock */ lws_free(wsi); return NULL; } + lws_dll2_remove(&wsi->pre_natal); + return wsi; } diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index d793960585..795a5e6410 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -336,6 +336,8 @@ _lws_vhost_init_server_af(struct vh_sock_args *a) goto bail; } + lws_dll2_remove(&wsi->pre_natal); + lws_dll2_add_tail(&wsi->listen_list, &a->vhost->listen_wsi); lws_pt_unlock(pt); diff --git a/lib/roles/netlink/ops-netlink.c b/lib/roles/netlink/ops-netlink.c index 3782e5d6b0..0476a94a14 100644 --- a/lib/roles/netlink/ops-netlink.c +++ b/lib/roles/netlink/ops-netlink.c @@ -597,6 +597,7 @@ rops_pt_init_destroy_netlink(struct lws_context *context, __lws_lc_untag(wsi->a.context, &wsi->lc); compatible_close(wsi->desc.sockfd); bail1: + lws_dll2_remove(&wsi->pre_natal); lws_free(wsi); bail: return ret; From e83ed4eb88b77039d69189327482263f6fdf5fef Mon Sep 17 00:00:00 2001 From: Jeongik Cha Date: Fri, 18 Jul 2025 12:33:30 +0900 Subject: [PATCH 271/275] mbedtls-server: verify_option and auth_mode options should be valid verify_options in mbedtls-server is slightly different from openssl-server. So made mbedtls-server have the same semantic about verify_option. And also #2902 was the workaround fix for the 'weird' verify_option, so changed auth_mode to match verify_option's meaning. this patch is basically #3257 for 4.3-stable --- lib/tls/mbedtls/mbedtls-server.c | 2 +- lib/tls/mbedtls/wrapper/platform/ssl_pm.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/tls/mbedtls/mbedtls-server.c b/lib/tls/mbedtls/mbedtls-server.c index efd7fc8ba5..ca5ebc1597 100644 --- a/lib/tls/mbedtls/mbedtls-server.c +++ b/lib/tls/mbedtls/mbedtls-server.c @@ -39,7 +39,7 @@ lws_tls_server_client_cert_verify_config(struct lws_vhost *vh) } if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED)) - verify_options = SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; lwsl_notice("%s: vh %s requires client cert %d\n", __func__, vh->name, verify_options); diff --git a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c index b74ffe7d2b..1757a44bbd 100755 --- a/lib/tls/mbedtls/wrapper/platform/ssl_pm.c +++ b/lib/tls/mbedtls/wrapper/platform/ssl_pm.c @@ -255,9 +255,9 @@ static int ssl_pm_reload_crt(SSL *ssl) struct pkey_pm *pkey_pm = (struct pkey_pm *)ssl->cert->pkey->pkey_pm; struct x509_pm *crt_pm = (struct x509_pm *)ssl->cert->x509->x509_pm; - if (ssl->verify_mode == SSL_VERIFY_PEER) + if (ssl->verify_mode & SSL_VERIFY_PEER) mode = MBEDTLS_SSL_VERIFY_REQUIRED; - else if (ssl->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + else if (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) mode = MBEDTLS_SSL_VERIFY_OPTIONAL; else if (ssl->verify_mode == SSL_VERIFY_CLIENT_ONCE) mode = MBEDTLS_SSL_VERIFY_UNSET; @@ -994,9 +994,9 @@ void SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) #if defined(LWS_HAVE_mbedtls_ssl_set_hs_authmode) - if (ctx->verify_mode == SSL_VERIFY_PEER) + if (ctx->verify_mode & SSL_VERIFY_PEER) mode = MBEDTLS_SSL_VERIFY_REQUIRED; - else if (ctx->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + else if (ctx->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) mode = MBEDTLS_SSL_VERIFY_REQUIRED; else if (ctx->verify_mode == SSL_VERIFY_CLIENT_ONCE) mode = MBEDTLS_SSL_VERIFY_UNSET; From b9c3ed4cd1032e9b14cda733a753aad868b5382b Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 18 Sep 2025 08:15:38 +0100 Subject: [PATCH 272/275] eventfd: pipe: cleanup on ctx destruction --- lib/core-net/close.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/core-net/close.c b/lib/core-net/close.c index cfe2b9d429..4531a72ac8 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -368,8 +368,10 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, context = wsi->a.context; pt = &context->pt[(int)wsi->tsi]; - if (pt->pipe_wsi == wsi) + if (pt->pipe_wsi == wsi) { + lws_plat_pipe_close(pt->pipe_wsi); pt->pipe_wsi = NULL; + } #if defined(LWS_WITH_SYS_METRICS) && \ (defined(LWS_WITH_CLIENT) || defined(LWS_WITH_SERVER)) From ccb67db8c98e393c25c388176b73c99ac223cb15 Mon Sep 17 00:00:00 2001 From: Nozomi Network Labs Date: Wed, 24 Sep 2025 12:46:24 +0100 Subject: [PATCH 273/275] NN-2025-0102: UAF depending on upgrade allowed This document contains sensitive information collected during our security research activities related with the Libwebsockets library maintained by Andy Green (warmcat). +-------------------------------------------------------------------------------------------------------+ | Report information | +:===================================:+:===============================================================:+ | Vendor | warmcat | +-------------------------------------+-----------------------------------------------------------------+ | Vendor URL | https://libwebsockets.org/git/libwebsockets | +-------------------------------------+-----------------------------------------------------------------+ | Affected component | libwebsockets | +-------------------------------------+-----------------------------------------------------------------+ | Affected version | 4.4 | +-------------------------------------+-----------------------------------------------------------------+ | Vulnerability | CWE-416: Use After Free | +-------------------------------------+-----------------------------------------------------------------+ | Proposed CVSS v3.1 Base Score | 6.0 | +-------------------------------------+-----------------------------------------------------------------+ | Proposed CVSS v3.1 Vector | CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N | +-------------------------------------+-----------------------------------------------------------------+ +-----------------------------------------------------------------------------+ | Security Researcher(s) | +:===================================:+:=====================================:+ | Name | **Email address** | +-------------------------------------+---------------------------------------+ | Raffaele Bova | labs-advisory@nozominetworks.com | +-------------------------------------+---------------------------------------+ Libwebsockes is a C library that provides client and server implementation for various protocols (e.g., HTTP, websockets, MQTT) and more. Nozomi Networks Lab discovered a "CWE-416: Use After Free" in the latest software version of libwebsockets, specifically in the WebSocket server implementation. Depending on the use of the API, the vulnerability may allow an attacker to read or write data, that could cause a loss of integrity or availability. The issue is caused by the `lws_handshake_protocol` function, specifically when the upgrade header is not valid, the function calls `lws_http_transaction_completed`, which frees some of the data in the wsi structure, then it calls `user_callback_handle_rxflow` passing the up pointer and uses it on following strcasecmp calls. From our understanding, for this vulnerability to have a meaningful impact, a user that implements the Websocket server, must provide a user callback function which is going to handle `LWS_CALLBACK_HTTP_CONFIRM_UPGRADE`, while ignoring the length and doing operations on the up pointer. It is possible to compile the minimal websocket server using address sanitizer, to quickly verify the use after free. From our understanding of the code, if the upgrade header does not match the intended contents, then the code after the if statement when `lws_http_transaction_completed` is called, should not be executed, thus simply enclosing all that code in the else branch solves the issue. --- lib/roles/http/server/server.c | 58 +++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index 795a5e6410..2856127b49 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -2379,49 +2379,49 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len) HTTP_STATUS_FORBIDDEN, NULL) || lws_http_transaction_completed(wsi)) goto bail_nuke_ah; - } - - n = user_callback_handle_rxflow(wsi->a.protocol->callback, - wsi, LWS_CALLBACK_HTTP_CONFIRM_UPGRADE, - wsi->user_space, (char *)up, 0); + } else { + n = user_callback_handle_rxflow(wsi->a.protocol->callback, + wsi, LWS_CALLBACK_HTTP_CONFIRM_UPGRADE, + wsi->user_space, (char *)up, 0); - /* just hang up? */ + /* just hang up? */ - if (n < 0) - goto bail_nuke_ah; + if (n < 0) + goto bail_nuke_ah; - /* callback returned headers already, do t_c? */ + /* callback returned headers already, do t_c? */ - if (n > 0) { - if (lws_http_transaction_completed(wsi)) + if (n > 0) { + if (lws_http_transaction_completed(wsi)) goto bail_nuke_ah; - /* continue on */ + /* continue on */ - return 0; - } + return 0; + } - /* callback said 0, it was allowed */ + /* callback said 0, it was allowed */ - if (wsi->a.vhost->options & - LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK && - lws_confirm_host_header(wsi)) - goto bail_nuke_ah; + if (wsi->a.vhost->options & + LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK && + lws_confirm_host_header(wsi)) + goto bail_nuke_ah; - if (!strcasecmp(up, "websocket")) { + if (!strcasecmp(up, "websocket")) { #if defined(LWS_ROLE_WS) - lws_metrics_tag_wsi_add(wsi, "upg", "ws"); - lwsl_info("Upgrade to ws\n"); - goto upgrade_ws; + lws_metrics_tag_wsi_add(wsi, "upg", "ws"); + lwsl_info("Upgrade to ws\n"); + goto upgrade_ws; #endif - } + } #if defined(LWS_WITH_HTTP2) - if (!strcasecmp(up, "h2c")) { - lws_metrics_tag_wsi_add(wsi, "upg", "h2c"); - lwsl_info("Upgrade to h2c\n"); - goto upgrade_h2c; - } + if (!strcasecmp(up, "h2c")) { + lws_metrics_tag_wsi_add(wsi, "upg", "h2c"); + lwsl_info("Upgrade to h2c\n"); + goto upgrade_h2c; + } #endif + } } /* no upgrade ack... he remained as HTTP */ From 33da595a0a307b838981507482dfe5ab0ad29a58 Mon Sep 17 00:00:00 2001 From: Nozomi Network Labs Date: Wed, 24 Sep 2025 13:30:38 +0100 Subject: [PATCH 274/275] NN-2025-0103: ADNS crafted response overflow This document contains sensitive information collected during our security research activities related with the Libwebsockets library made by Andy Green (warmcat). +-------------------------------------------------------------------------------------------------------+ | Report information | +:===================================:+:===============================================================:+ | Vendor | warmcat | +-------------------------------------+-----------------------------------------------------------------+ | Vendor URL | https://libwebsockets.org/git/libwebsockets | +-------------------------------------+-----------------------------------------------------------------+ | Affected component | Ecostruxure Automation Expert | +-------------------------------------+-----------------------------------------------------------------+ | Affected version | 4.4 | +-------------------------------------+-----------------------------------------------------------------+ | Vulnerability | CWE-121: Stack-based Buffer Overflow | +-------------------------------------+-----------------------------------------------------------------+ | Proposed CVSS v3.1 Base Score | 7.5 | +-------------------------------------+-----------------------------------------------------------------+ | Proposed CVSS v3.1 Vector | CVSS:4.0/AV:A/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N | +-------------------------------------+-----------------------------------------------------------------+ +-----------------------------------------------------------------------------+ | Security Researcher(s) | +:===================================:+:=====================================:+ | Name | **Email address** | +-------------------------------------+---------------------------------------+ | Raffaele Bova | labs-advisory@nozominetworks.com | +-------------------------------------+---------------------------------------+ **\** Libwebsockes is a C library that provides client and server implementation for various protocols (e.g., HTTP, websockets, MQTT) and more. Nozomi Networks Lab discovered a "CWE-121: Stack-based Buffer Overflow" in the latest software version of libwebsockets, specifically in the async-dns component. The vulnerability allows an attacker that can inspect DNS requests made by the victim (e.g. being in the same wireless network) to forge a DNS response packet that overflows the stack and may lead to arbitrary code execution (depending on the platform and compiler options). The issue resides in `lws_adns_parse_label` function in `lib/system/async-dns/async-dns-parse.c`; this function iteratively parses a label however it does not correctly check the number of bytes written in the destination buffer. Specifically, the size of the dest output buffer is specified in the `dl` argument, however during the read of each substring of the label only the length of the current substring of the label is accounted for not overflowing the destination buffer, but previous reads are not accounted for. This means that a label of arbitrary size and content can be supplied and is copied onto the stack, however it must be split into substrings of size less than `dl`. To trigger the vulnerability an attacker must be able to sniff the DNS request packet to send a response with a matching identifier, otherwise the implantation correctly ignores the response. We have provided a harness for testing, for ease of use copy the harness in a subdirectory, for example in minimal-examples-lowlevel/api-tests/, and build it ``` cmake -B build -DLWS_WITH_SYS_ASYNC_DNS=1 -DLWS_WITH_SSL=0 -DCMAKE_C_FLAGS="-fsanitize=address" . && make -C build lws-test-async-dns ``` Then it can be run `./build/bin/lws-test-async-dns < poc_stackbof` ![Address sanitizer report of stack buffer overflow](./NN-2025-0103_image.png) We suggest keeping track of the number of bytes currently written on the dest buffer, this could be done by saving the original dest pointer, decrementing dl on each substring memcpy, or using an auxiliary variable. --- lib/system/async-dns/async-dns-parse.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/system/async-dns/async-dns-parse.c b/lib/system/async-dns/async-dns-parse.c index 577cc45876..cb2b795e98 100644 --- a/lib/system/async-dns/async-dns-parse.c +++ b/lib/system/async-dns/async-dns-parse.c @@ -35,7 +35,7 @@ lws_adns_parse_label(const uint8_t *pkt, int len, const uint8_t *ls, int budget, const uint8_t *e = pkt + len, *ols = ls; char pointer = 0, first = 1; uint8_t ll; - int n; + int n, readsize = 0; if (budget < 1) return 0; @@ -88,7 +88,7 @@ lws_adns_parse_label(const uint8_t *pkt, int len, const uint8_t *ls, int budget, return -1; } - if ((unsigned int)ll + 2 > dl) { + if ((unsigned int)(ll + 2 + readsize) > dl) { lwsl_notice("%s: qname too large\n", __func__); return -1; @@ -101,6 +101,7 @@ lws_adns_parse_label(const uint8_t *pkt, int len, const uint8_t *ls, int budget, (*dest)[ll + 1] = '\0'; *dest += ll + 1; ls += ll; + readsize += ll + 1; if (pointer) { if (*ls) From ea2da6c665d3ed9797999d2eb9b5d677150c4c4d Mon Sep 17 00:00:00 2001 From: Vaibhav Tekale Date: Tue, 17 Mar 2026 16:00:31 +0530 Subject: [PATCH 275/275] fix(websocketdll): file and product version set as per tag version --- CMakeLists.txt | 11 +++++++++++ win32port/version.rc.in | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 57c35232a4..be1fe94137 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -412,6 +412,17 @@ set(CPACK_PACKAGE_VERSION_MAJOR "4") set(CPACK_PACKAGE_VERSION_MINOR "3") set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "5") +# Override version components from git tag if available (e.g. v4.3.7 or v4.3.7-5-gabcdef) +if(GIT_HASH) + string(REGEX MATCH "^v?([0-9]+)\\.([0-9]+)\\.([0-9]+)" _GIT_VER_MATCH "${GIT_HASH}") + if(_GIT_VER_MATCH) + set(CPACK_PACKAGE_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(CPACK_PACKAGE_VERSION_MINOR "${CMAKE_MATCH_2}") + set(CPACK_PACKAGE_VERSION_PATCH_NUMBER "${CMAKE_MATCH_3}") + message("Version overridden from git tag: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH_NUMBER}") + endif() +endif() + set(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH_NUMBER}-${LWS_BUILD_HASH}") set(CPACK_PACKAGE_RELEASE 1) diff --git a/win32port/version.rc.in b/win32port/version.rc.in index 0dd48fe601..bebd2f824c 100644 --- a/win32port/version.rc.in +++ b/win32port/version.rc.in @@ -6,8 +6,8 @@ #define LWS_PACKAGE_NAME "@PACKAGE@\0" VS_VERSION_INFO VERSIONINFO - FILEVERSION LWS_NUMVERSION - PRODUCTVERSION LWS_NUMVERSION + FILEVERSION LWS_VERSION + PRODUCTVERSION LWS_VERSION FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS__WINDOWS32