Imported Upstream version 4.3.2 59/288959/1 upstream upstream/4.3.2
authorcheoleun moon <chleun.moon@samsung.com>
Mon, 27 Feb 2023 03:18:20 +0000 (12:18 +0900)
committercheoleun moon <chleun.moon@samsung.com>
Mon, 27 Feb 2023 03:19:54 +0000 (12:19 +0900)
Change-Id: I2116066af6e0d095bb4d5f7be34d86b13c137ad2

83 files changed:
.sai.json
CMakeLists.txt
cmake/FindOpenSSLbins.cmake
cmake/libwebsockets-config.cmake.in
include/libwebsockets.h
include/libwebsockets/lws-callbacks.h
include/libwebsockets/lws-http.h
include/libwebsockets/lws-logs.h
include/libwebsockets/lws-map.h
include/libwebsockets/lws-mqtt.h
include/libwebsockets/lws-network-helper.h
include/libwebsockets/lws-secure-streams-policy.h
lib/CMakeLists.txt
lib/core-net/adopt.c
lib/core-net/client/connect3.c
lib/core-net/close.c
lib/core-net/dummy-callback.c
lib/core-net/private-lib-core-net.h
lib/core-net/route.c
lib/core-net/sorted-usec-list.c
lib/core-net/wsi-timeout.c
lib/core/context.c
lib/core/logs.c
lib/core/private-lib-core.h
lib/cose/cose_sign.c
lib/misc/lejp.c
lib/plat/freertos/esp32/esp_attr.h [deleted file]
lib/plat/freertos/private-lib-plat-freertos.h
lib/plat/unix/unix-sockets.c
lib/plat/windows/windows-plugins.c
lib/plat/windows/windows-sockets.c
lib/roles/cgi/cgi-server.c
lib/roles/h1/ops-h1.c
lib/roles/h2/http2.c
lib/roles/h2/ops-h2.c
lib/roles/http/compression/stream.c
lib/roles/http/cookie.c
lib/roles/http/header.c
lib/roles/http/server/lejp-conf.c
lib/roles/http/server/server.c
lib/roles/mqtt/mqtt.c
lib/roles/mqtt/private-lib-roles-mqtt.h
lib/roles/netlink/ops-netlink.c
lib/roles/pipe/ops-pipe.c
lib/roles/raw-skt/ops-raw-skt.c
lib/secure-streams/README.md
lib/secure-streams/policy-common.c
lib/secure-streams/policy-json.c
lib/secure-streams/private-lib-secure-streams.h
lib/secure-streams/protocols/ss-h1.c
lib/secure-streams/protocols/ss-h2.c
lib/secure-streams/protocols/ss-mqtt.c
lib/secure-streams/secure-streams-client.c
lib/secure-streams/secure-streams-process.c
lib/secure-streams/secure-streams.c
lib/system/metrics/metrics.c
lib/tls/CMakeLists.txt
lib/tls/lws-genec-common.c
lib/tls/mbedtls/mbedtls-client.c
lib/tls/mbedtls/mbedtls-extensions.c
lib/tls/mbedtls/mbedtls-x509.c
lib/tls/mbedtls/wrapper/platform/ssl_pm.c
lib/tls/openssl/openssl-client.c
lib/tls/openssl/openssl-server.c
lib/tls/openssl/openssl-session.c
lib/tls/tls-client.c
lib/tls/tls-server.c
minimal-examples-lowlevel/raw/minimal-raw-client/CMakeLists.txt [new file with mode: 0644]
minimal-examples-lowlevel/raw/minimal-raw-client/main.c [new file with mode: 0644]
minimal-examples/api-tests/api-test-lws_map/main.c
minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c
minimal-examples/http-client/minimal-http-client-multi/minimal-http-client-multi.c
minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c
minimal-examples/http-server/minimal-http-server-custom-headers/minimal-http-server-custom-headers.c
minimal-examples/http-server/minimal-http-server-dynamic/minimal-http-server-dynamic.c
minimal-examples/http-server/minimal-http-server-h2-long-poll/minimal-http-server.c
minimal-examples/secure-streams/minimal-secure-streams-policy2c/minimal-secure-streams.c
plugins/acme-client/protocol_lws_acme_client.c
plugins/deaddrop/protocol_lws_deaddrop.c
plugins/protocol_fulltext_demo.c
plugins/protocol_lws_openmetrics_export.c
plugins/ssh-base/sshd.c
test-apps/test-client.c

index 7ac992e..3d349e9 100644 (file)
--- a/.sai.json
+++ b/.sai.json
                "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",
index c4cd294..166d48a 100644 (file)
@@ -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)
@@ -179,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)
@@ -407,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)
@@ -849,7 +852,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)
index 3f32994..3d791f4 100644 (file)
@@ -44,7 +44,7 @@ if(OPENSSL_FOUND)
       get_filename_component(OPENSSL_EXECUTABLE_PATH ${OPENSSL_EXECUTABLE} DIRECTORY)\r
       message(VERBOSE "OPENSSL_EXECUTABLE_PATH=${OPENSSL_EXECUTABLE_PATH}")\r
       set(OPENSSL_EXECUTABLE_BIN_PATH "")\r
-      string(REGEX MATCH "^(.*)/tools/openssl$" REGEX_MATCH ${OPENSSL_EXECUTABLE_PATH})\r
+      string(REGEX MATCH "^(.*)/tools/openssl$" REGEX_MATCH "${OPENSSL_EXECUTABLE_PATH}")\r
       message(DEBUG "REGEX_MATCH=\"${REGEX_MATCH}\"")\r
       message(DEBUG "CMAKE_MATCH_1=\"${CMAKE_MATCH_1}\"")\r
       if (NOT ${REGEX_MATCH} EQUAL "")\r
index 6247b2c..8ba97e6 100644 (file)
@@ -32,6 +32,5 @@ endforeach()
 
 include(CheckIncludeFile)
 include(CheckCSourceCompiles)
-include(LwsCheckRequirements)
 set(requirements 1)
 
index 4409ee2..8fb98c3 100644 (file)
@@ -291,11 +291,18 @@ typedef int suseconds_t;
 #include <mbedtls/ssl.h>
 #include <mbedtls/entropy.h>
 #include <mbedtls/ctr_drbg.h>
+#include <mbedtls/version.h>
 
 #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 <openssl/ssl.h>
index 62848fa..fd36f7c 100644 (file)
@@ -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 ---^ ******/
 
index 2c5bd64..8576758 100644 (file)
@@ -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);
index 3f21b81..795ba55 100644 (file)
@@ -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;
 
 /**
index 4462881..cf2368a 100644 (file)
@@ -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);
 
 //@}
index 2286580..cbf8b36 100644 (file)
@@ -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,
@@ -114,6 +137,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 {
index 20a3225..09308b8 100644 (file)
@@ -33,7 +33,8 @@
 #include <lwip/sockets.h>
 #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;
index 863140d..2c81f9f 100644 (file)
@@ -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;
 
index c55c619..19dc0cf 100644 (file)
@@ -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)
@@ -334,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}
 "
index e411945..579f4bf 100644 (file)
@@ -847,13 +847,17 @@ 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;
                }
index a310216..b752330 100644 (file)
@@ -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,12 +98,14 @@ 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;
        }
 
 #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;
@@ -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);
index 1d92b39..a8dd720 100644 (file)
@@ -560,7 +560,7 @@ just_kill_connection:
        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
 
index 9552af5..d36000f 100644 (file)
@@ -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;
index 2d3f73a..0b3561f 100644 (file)
@@ -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
 
@@ -1375,7 +1375,7 @@ _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)
+#define LRR_MATCH_DST                  (1 << 2)
 
 lws_route_t *
 _lws_route_remove(struct lws_context_per_thread *pt, lws_route_t *robj, int flags);
index 2a85152..c9fdc2b 100644 (file)
@@ -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,
@@ -98,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++;
@@ -141,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 &&
@@ -149,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);
index e9b9c1f..d9af0f1 100644 (file)
@@ -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;
 
index bbaed54..b72f134 100644 (file)
@@ -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;
        }
 
index fb684e5..af818eb 100644 (file)
@@ -2009,15 +2009,18 @@ next:
                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
 
index a13c841..27b7b9f 100644 (file)
@@ -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
@@ -506,9 +516,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 +543,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
index 8ba0852..6cdc91c 100644 (file)
@@ -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
 
index d7ae64f..7c624de 100644 (file)
@@ -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 @@ inner_protected:
                        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;
index cbce4ee..b898c6f 100644 (file)
@@ -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/plat/freertos/esp32/esp_attr.h b/lib/plat/freertos/esp32/esp_attr.h
deleted file mode 100644 (file)
index 5bf9a22..0000000
+++ /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__ */
index d544e2b..67b8399 100644 (file)
@@ -59,11 +59,15 @@ gai_strerror(int);
  #include "FreeRTOS_IP.h"
 #endif
  #include "timers.h"
+#if defined(LWS_ESP_PLATFORM)
  #include <esp_attr.h>
+#endif
  #include <semphr.h>
 #else
  #include "freertos/timers.h"
+#if defined(LWS_ESP_PLATFORM)
  #include <esp_attr.h>
+#endif
  #include <esp_system.h>
  #include <esp_task_wdt.h>
 #endif
index 07df994..2c1b956 100644 (file)
@@ -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);
@@ -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)
index b2153d6..313d58f 100644 (file)
@@ -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 @@ bail:
 int
 lws_plat_destroy_dl(struct lws_plugin *p)
 {
-       return uv_dlclose(&p->u.lib);
+       uv_dlclose(&p->u.lib);
+
+       return 0;
 }
 
 #endif
index ce9b719..b0e15dd 100644 (file)
@@ -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;
 
index cd039e8..a6f04fa 100644 (file)
@@ -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,
index 4590a49..769490f 100644 (file)
@@ -292,9 +292,11 @@ ws_mode:
                // 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);
                goto bail;
        }
 
index a09b97f..58e7c10 100644 (file)
@@ -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 |
index 989cb5b..0f76d17 100644 (file)
@@ -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);
 
index 9898b76..d4c72aa 100644 (file)
@@ -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
index 03b88ae..1860e87 100644 (file)
@@ -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]);
index b0d5477..032bf6b 100644 (file)
@@ -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)
index 98392d4..0f979cf 100644 (file)
@@ -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);
index c7eb94c..c98bf0d 100644 (file)
@@ -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)));
index 67d64db..aaac84b 100644 (file)
@@ -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)
@@ -1982,7 +1995,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;
        }
@@ -2027,7 +2040,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);
@@ -2091,6 +2106,13 @@ do_write:
                                    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;
 }
 
@@ -2215,6 +2237,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 +2407,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;
 
index d89f371..dc46a93 100644 (file)
@@ -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,8 +355,9 @@ 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 */
+       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;
@@ -382,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;
 };
 
 /*
@@ -437,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 */
 
index bb32048..fa3bf29 100644 (file)
@@ -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;
@@ -362,9 +371,8 @@ ana:
                        lws_pt_lock(pt, __func__);
 
                        /* returns zero on match already in table */
-                       rmat = _lws_route_remove(pt, &robj, LRR_MATCH_SRC |
-                                                           LRR_JUST_CHECK |
-                                                           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) {
@@ -519,12 +527,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
                                 ;
 
index 4d39d31..ad54a04 100644 (file)
@@ -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.
index fd4fd34..453c64e 100644 (file)
 
 #include <private-lib-core.h>
 
+#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 @@ try_pollout:
                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;
index b7a9c3d..5d707ae 100644 (file)
@@ -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.
index b782c1e..a98abae 100644 (file)
@@ -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));
index 7e5656f..e230ce5 100644 (file)
@@ -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;
index 6af59e4..cc2fc4c 100644 (file)
@@ -147,10 +147,15 @@ 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;
                        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)
index 9bfed47..d9ffe85 100644 (file)
@@ -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,
@@ -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;
@@ -560,6 +561,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 +866,8 @@ malformed:
        //      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);
index 3d1aa9c..910067a 100644 (file)
@@ -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;
 
index f13eea4..8698bee 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * libwebsockets - small server side websockets and web server implementation
  *
- * Copyright (C) 2019 - 2021 Andy Green <andy@warmcat.com>
+ * Copyright (C) 2019 - 2022 Andy Green <andy@warmcat.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -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
@@ -141,9 +142,10 @@ 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)
+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, 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;
@@ -187,26 +189,290 @@ 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;
+       mqpp.dup = !!dup;
+       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);
 
-       mqpp.qos = h->policy->u.mqtt.qos;
-
        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);
                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;
+}
+
+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, 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 char *
+expand_metadata(lws_ss_handle_t *h, const char* str, const char* post, size_t max_len)
+{
+       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,
+                       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_wsi_warn(wsi, "Failed to expand Shadow topic");
+
+               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_wsi_err(wsi, "Failed to send MQTT unsubsribe");
+
+               return LWSSSSRET_DISCONNECT_ME;
+       }
+       /* Expect a UNSUBACK */
+       if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
+               lwsl_wsi_err(wsi, "Unable to set LWS_POLLIN");
+
+               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 i, 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_ss_err(h, "Failed to allocate Shadow topics");
+               return -1;
+       }
+       h->u.mqtt.shadow_sub.num_topics = suffixes_len;
+       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_ss_err(h, "Failed to allocate Shadow topic");
+                       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_wsi_notice(wsi, "Unable to subscribe Shadow topics");
+
+               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;
 }
 
@@ -215,12 +481,19 @@ 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;
+       size_t used_in = 0, used_out = 0, topic_len = 0;
+       lws_mqtt_publish_param_t *pmqpp = NULL;
+       lws_ss_state_return_t r = LWSSSSRET_OK;
        uint8_t buf[LWS_PRE + 1400];
-       lws_ss_state_return_t r;
        size_t buflen = sizeof(buf) - LWS_PRE;
+       lws_ss_metadata_t *omd = NULL;
+       char *sub_topic = NULL;
+       lws_strexp_t exp;
        int f = 0;
 
+       memset(buf, 0, sizeof(buf));
+       memset(&exp, 0, sizeof(exp));
+
        switch (reason) {
 
        /* because we are protocols[0] ... */
@@ -285,6 +558,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 +603,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)
                /*
@@ -342,19 +643,91 @@ 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) {
+                       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 (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 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)
@@ -366,12 +739,22 @@ 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 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 +762,36 @@ 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:
+               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__,
+                                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:
        {
                if (!h || !h->info.tx)
@@ -393,27 +806,31 @@ 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;
-                               }
+               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);
+
+               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);
                        }
-                       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);
-               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;
@@ -434,27 +851,65 @@ 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, 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, 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);
+               }
+               return 0;
        }
 
        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->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->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;
        }
index 76ea952..075cf96 100644 (file)
@@ -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
index d5822b6..552e1d1 100644 (file)
@@ -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);
index 489543d..911f713 100644 (file)
@@ -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) |
@@ -146,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) |
@@ -614,7 +620,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 +640,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 +1078,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 +1356,7 @@ fail_creation:
 void *
 lws_ss_to_user_object(struct lws_ss_handle *h)
 {
-       return (void *)&h[1];
+       return (void *)(h + 1);
 }
 
 void
@@ -1617,9 +1623,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
index 92d5e0d..1a978cc 100644 (file)
@@ -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) {
index fd3c27f..fb9a75f 100644 (file)
@@ -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.")
@@ -375,22 +378,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 <mbedtls/x509_crt.h>\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 <mbedtls/ssl.h>\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 <mbedtls/x509_crt.h>\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 <mbedtls/ssl.h>\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)
index 0ea3fb0..8b5d30b 100644 (file)
@@ -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;
 }
index c12bbd5..187e860 100644 (file)
@@ -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);
 
@@ -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);
index dc406e8..bf275ee 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * libwebsockets - small server side websockets and web server implementation
  *
- * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
+ * Copyright (C) 2010 - 2022 Andy Green <andy@warmcat.com>
  *
  * 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);
index 2dad865..8b0ccd3 100644 (file)
@@ -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);
index 04354f6..e8a0cb2 100755 (executable)
@@ -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);
@@ -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)
@@ -660,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;
@@ -874,6 +873,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 +890,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
 }
index d8c56c5..6c8d5c1 100644 (file)
@@ -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)
index 94e8846..34a6ada 100644 (file)
@@ -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;
index d7dd04c..e27a8f3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * libwebsockets - small server side websockets and web server implementation
  *
- * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
+ * Copyright (C) 2010 - 2022 Andy Green <andy@warmcat.com>
  *
  * 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
 
index 9d93a3d..5b29923 100644 (file)
@@ -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:
index dbb5178..05055f7 100644 (file)
@@ -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/minimal-examples-lowlevel/raw/minimal-raw-client/CMakeLists.txt b/minimal-examples-lowlevel/raw/minimal-raw-client/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4ff5c55
--- /dev/null
@@ -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 (file)
index 0000000..db18a99
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * lws-minimal-raw-client
+ *
+ * Written in 2010-2022 by Andy Green <andy@warmcat.com>
+ *
+ * This file is made available under the Creative Commons CC0 1.0
+ * Universal Public Domain Dedication.
+ *
+ * This demonstrates connecting a "raw" client connection
+ */
+
+#include <libwebsockets.h>
+#include <string.h>
+#include <signal.h>
+#if !defined(WIN32)
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#if !defined(WIN32)
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#include <assert.h>
+
+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[] = { &notifier, 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;
+}
index 022c98a..c17be81 100644 (file)
@@ -11,6 +11,8 @@
 
 #include <libwebsockets.h>
 
+typedef struct lws_map_item lws_map_item_t;
+
 /* custom key and comparator for test 3 */
 
 typedef struct mykey {
index a4dab2a..da7cbe9 100644 (file)
@@ -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 = {
index d0d11f3..f30ee58 100644 (file)
@@ -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;
 
index 3bff115..063f8f1 100644 (file)
@@ -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) {
index d9a1f31..4ffe32c 100644 (file)
@@ -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;
index f919146..daade23 100644 (file)
@@ -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)
index c5614e5..a47be0b 100644 (file)
@@ -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) {
index f3a0b69..bb86d3d 100644 (file)
@@ -573,7 +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);
@@ -583,13 +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;
index d202085..729c448 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * libwebsockets ACME client protocol plugin
  *
- * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
+ * Copyright (C) 2010 - 2022 Andy Green <andy@warmcat.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
  * 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)
@@ -143,16 +136,16 @@ 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) {
        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 @@ pkt_add_hdrs:
                                                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 @@ pkt_add_hdrs:
                        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 @@ pkt_add_hdrs:
                                        "}",
                        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 @@ pkt_add_hdrs:
                        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 @@ pkt_add_hdrs:
                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 @@ pkt_add_hdrs:
                                        &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 @@ pkt_add_hdrs:
                break;
 
        case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE:
-               lwsl_notice("LWS_CALLBACK_CLIENT_HTTP_WRITEABLE\n");
 
                if (!ac)
                        break;
@@ -1187,7 +1165,7 @@ pkt_add_hdrs:
                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 @@ pkt_add_hdrs:
                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 @@ pkt_add_hdrs:
 
        /* 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 @@ pkt_add_hdrs:
                break;
 
        case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
-               lwsl_notice("%s: COMPLETED_CLIENT_HTTP\n", __func__);
 
                if (!ac)
                        return -1;
@@ -1281,7 +1259,7 @@ pkt_add_hdrs:
 
                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 @@ pkt_add_hdrs:
                                        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 @@ pkt_add_hdrs:
                                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 @@ pkt_add_hdrs:
                        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 @@ pkt_add_hdrs:
 
                        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 @@ pkt_add_hdrs:
                        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 @@ pkt_add_hdrs:
                                                       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 @@ poll_again:
                                                       &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 @@ poll_again:
                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 @@ poll_again:
                                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 @@ poll_again:
                                                       &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 @@ poll_again:
 
                        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 @@ poll_again:
                                                &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 @@ poll_again:
                                                       &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 @@ poll_again:
                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 @@ poll_again:
                         * 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 @@ poll_again:
                                                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 @@ poll_again:
                                                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 @@ poll_again:
                                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 @@ poll_again:
        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);
 
index 79f736c..0e51507 100644 (file)
@@ -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;
index 0d78099..35d91e1 100644 (file)
@@ -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;
index f7fb601..f6b1850 100644 (file)
@@ -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;
index 90fa3d7..cab174f 100644 (file)
@@ -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;
 
        /*
index 640fa8a..05d08ed 100644 (file)
@@ -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[50], buf[80 + LWS_PRE];
        int n;
 
        switch (reason) {