From c8b9ac4aaf39b3fa173ef3a1cadff4e15b7daac2 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 9 Feb 2022 15:47:12 +0000 Subject: [PATCH] seq: remove last vestiges Sequencer went away a while ago, remove api tests and minimal examples. Use Secure Streams to get an object with a lifetime longer than a wsi that can autonomously retry. --- .../api-test-lws_sequencer/CMakeLists.txt | 25 -- .../libwebsockets.org.cer | 32 -- .../api-tests/api-test-lws_sequencer/main.c | 399 ----------------- .../minimal-secure-streams-seq/CMakeLists.txt | 27 -- .../minimal-secure-streams-seq/README.md | 65 --- .../minimal-secure-streams.c | 410 ------------------ 6 files changed, 958 deletions(-) delete mode 100644 minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/CMakeLists.txt delete mode 100644 minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/libwebsockets.org.cer delete mode 100644 minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/main.c delete mode 100644 minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/CMakeLists.txt delete mode 100644 minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/README.md delete mode 100644 minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/minimal-secure-streams.c diff --git a/minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/CMakeLists.txt b/minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/CMakeLists.txt deleted file mode 100644 index 59333d810..000000000 --- a/minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -project(lws-api-test-lws_sequencer C) -cmake_minimum_required(VERSION 2.8.12) -find_package(libwebsockets CONFIG REQUIRED) -list(APPEND CMAKE_MODULE_PATH ${LWS_CMAKE_DIR}) -include(CheckCSourceCompiles) -include(LwsCheckRequirements) - -set(SAMP lws-api-test-lws_sequencer) -set(SRCS main.c) - -set(requirements 1) -require_lws_config(LWS_ROLE_H1 1 requirements) -require_lws_config(LWS_WITH_CLIENT 1 requirements) -require_lws_config(LWS_WITH_SEQUENCER 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/api-tests/api-test-lws_sequencer/libwebsockets.org.cer b/minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/libwebsockets.org.cer deleted file mode 100644 index 01ad0dc75..000000000 --- a/minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/libwebsockets.org.cer +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- - diff --git a/minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/main.c b/minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/main.c deleted file mode 100644 index 0db7f4009..000000000 --- a/minimal-examples-lowlevel/api-tests/api-test-lws_sequencer/main.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * lws-api-test-lws_sequencer - * - * Written in 2019 by Andy Green - * - * This file is made available under the Creative Commons CC0 1.0 - * Universal Public Domain Dedication. - * - * This api test uses the lws_sequencer api to make five http client requests - * to libwebsockets.org in sequence, from inside the event loop. The fourth - * fourth http client request is directed to port 22 where it stalls - * triggering the lws_sequencer timeout flow. The fifth is given a nonexistant - * dns name and is expected to fail. - */ - -#include - -#include - -static int interrupted, test_good = 0; - -enum { - SEQ1, - SEQ2, - SEQ3_404, - SEQ4_TIMEOUT, /* we expect to timeout */ - SEQ5_BAD_ADDRESS /* we expect the connection to fail */ -}; - -/* - * This is the user defined struct whose space is allocated along with the - * sequencer when that is created. - * - * You'd put everything your sequencer needs to do its job in here. - */ - -struct myseq { - struct lws_vhost *vhost; - struct lws *cwsi; /* client wsi for current step if any */ - - int state; /* which test we're on */ - int http_resp; -}; - -/* sequencer messages specific to this sequencer */ - -enum { - SEQ_MSG_CLIENT_FAILED = LWSSEQ_USER_BASE, - SEQ_MSG_CLIENT_DONE, -}; - -/* this is the sequence of GETs we will do */ - -static const char *url_paths[] = { - "https://libwebsockets.org/index.html", - "https://libwebsockets.org/lws.css", - "https://libwebsockets.org/404.html", - "https://libwebsockets.org:22", /* this causes us to time out */ - "https://doesntexist.invalid/" /* fail early in connect */ -}; - - -static void -sigint_handler(int sig) -{ - interrupted = 1; -} - -/* - * This is the sequencer-aware http protocol handler. It monitors the client - * http action and queues messages for the sequencer when something definitive - * happens. - */ - -static int -callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, - void *in, size_t len) -{ - struct myseq *s = (struct myseq *)user; - int seq_msg = SEQ_MSG_CLIENT_FAILED; - - switch (reason) { - - /* because we are protocols[0] ... */ - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - lwsl_notice("CLIENT_CONNECTION_ERROR: %s\n", - in ? (char *)in : "(null)"); - goto notify; - - case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: - if (!s) - return 1; - s->http_resp = (int)lws_http_client_http_response(wsi); - lwsl_info("Connected with server response: %d\n", s->http_resp); - break; - - /* chunks of chunked content, with header removed */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: - lwsl_info("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len); -#if 0 /* enable to dump the html */ - { - const char *p = in; - - while (len--) - if (*p < 0x7f) - putchar(*p++); - else - putchar('.'); - } -#endif - return 0; /* don't passthru */ - - /* uninterpreted http content */ - case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - { - char buffer[1024 + LWS_PRE]; - char *px = buffer + LWS_PRE; - int lenx = sizeof(buffer) - LWS_PRE; - - if (lws_http_client_read(wsi, &px, &lenx) < 0) - return -1; - } - return 0; /* don't passthru */ - - case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: - lwsl_notice("LWS_CALLBACK_COMPLETED_CLIENT_HTTP: wsi %p\n", - wsi); - if (!s) - return 1; - /* - * We got a definitive transaction completion - */ - seq_msg = SEQ_MSG_CLIENT_DONE; - goto notify; - - case LWS_CALLBACK_CLOSED_CLIENT_HTTP: - lwsl_info("LWS_CALLBACK_CLOSED_CLIENT_HTTP\n"); - if (!s) - return 1; - - lwsl_user("%s: wsi %p: seq failed at CLOSED_CLIENT_HTTP\n", - __func__, wsi); - goto notify; - - default: - break; - } - - return lws_callback_http_dummy(wsi, reason, user, in, len); - -notify: - /* - * We only inform the sequencer of a definitive outcome for our step. - * - * So once we have informed it, we detach ourselves from the sequencer - * and the sequencer from ourselves. Wsi may want to live on but after - * we got our result and moved on to the next test or completed, the - * sequencer doesn't want to hear from it again. - */ - if (!s) - return 1; - - lws_set_wsi_user(wsi, NULL); - s->cwsi = NULL; - lws_seq_queue_event(lws_seq_from_user(s), seq_msg, - NULL, NULL); - - return 0; -} - -static const struct lws_protocols protocols[] = { - { "seq-test-http", callback_http, 0, 0, 0, NULL, 0 }, - LWS_PROTOCOL_LIST_TERM -}; - - -static int -sequencer_start_client(struct myseq *s) -{ - struct lws_client_connect_info i; - const char *prot, *path1; - char uri[128], path[128]; - int n; - - lws_strncpy(uri, url_paths[s->state], sizeof(uri)); - - memset(&i, 0, sizeof i); - i.context = lws_seq_get_context(lws_seq_from_user(s)); - - if (lws_parse_uri(uri, &prot, &i.address, &i.port, &path1)) { - lwsl_err("%s: uri error %s\n", __func__, uri); - } - - if (!strcmp(prot, "https")) - i.ssl_connection = LCCSCF_USE_SSL; - - path[0] = '/'; - n = 1; - if (path1[0] == '/') - n = 0; - lws_strncpy(&path[n], path1, sizeof(path) - 1); - - i.path = path; - i.host = i.address; - i.origin = i.address; - i.method = "GET"; - i.vhost = s->vhost; - i.userdata = s; - - i.protocol = protocols[0].name; - i.local_protocol_name = protocols[0].name; - i.pwsi = &s->cwsi; - - if (!lws_client_connect_via_info(&i)) { - lwsl_notice("%s: connecting to %s://%s:%d%s failed\n", - __func__, prot, i.address, i.port, path); - - /* we couldn't even get started with the client connection */ - - lws_seq_queue_event(lws_seq_from_user(s), - (lws_seq_events_t)SEQ_MSG_CLIENT_FAILED, NULL, NULL); - - return 1; - } - - lws_seq_timeout_us(lws_seq_from_user(s), 3 * LWS_US_PER_SEC); - - lwsl_notice("%s: wsi %p: connecting to %s://%s:%d%s\n", __func__, - s->cwsi, prot, i.address, i.port, path); - - return 0; -} - -/* - * The sequencer callback handles queued sequencer messages in the order they - * were queued. The messages are presented from the event loop thread context - * even if they were queued from a different thread. - */ - -static lws_seq_cb_return_t -sequencer_cb(struct lws_sequencer *seq, void *user, int event, - void *data, void *aux) -{ - struct myseq *s = (struct myseq *)user; - - switch ((int)event) { - case LWSSEQ_CREATED: /* our sequencer just got started */ - s->state = SEQ1; /* first thing we'll do is the first url */ - goto step; - - case LWSSEQ_DESTROYED: - /* - * This sequencer is about to be destroyed. If we have any - * other assets in play, detach them from us. - */ - if (s->cwsi) - lws_set_wsi_user(s->cwsi, NULL); - - interrupted = 1; - break; - - case LWSSEQ_TIMED_OUT: /* current step timed out */ - if (s->state == SEQ4_TIMEOUT) { - lwsl_user("%s: test %d got expected timeout\n", - __func__, s->state); - goto done; - } - lwsl_user("%s: seq timed out at step %d\n", __func__, s->state); - return LWSSEQ_RET_DESTROY; - - case SEQ_MSG_CLIENT_FAILED: - if (s->state == SEQ5_BAD_ADDRESS) { - /* - * in this specific case, we expect to fail - */ - lwsl_user("%s: test %d failed as expected\n", - __func__, s->state); - goto done; - } - - lwsl_user("%s: seq failed at step %d\n", __func__, s->state); - - return LWSSEQ_RET_DESTROY; - - case SEQ_MSG_CLIENT_DONE: - if (s->state >= SEQ4_TIMEOUT) { - /* - * In these specific cases, done would be a failure, - * we expected to timeout or fail - */ - lwsl_user("%s: seq failed at step %d\n", __func__, - s->state); - - return LWSSEQ_RET_DESTROY; - } - lwsl_user("%s: seq done step %d (resp %d)\n", __func__, - s->state, s->http_resp); - -done: - lws_seq_timeout_us(lws_seq_from_user(s), LWSSEQTO_NONE); - s->state++; - if (s->state == LWS_ARRAY_SIZE(url_paths)) { - /* the sequence has completed */ - lwsl_user("%s: sequence completed OK\n", __func__); - - test_good = 1; - - return LWSSEQ_RET_DESTROY; - } - -step: - sequencer_start_client(s); - break; - default: - break; - } - - return LWSSEQ_RET_CONTINUE; -} - -int -main(int argc, const char **argv) -{ - int n = 1, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; - struct lws_context_creation_info info; - struct lws_context *context; - struct lws_sequencer *seq; - struct lws_vhost *vh; - lws_seq_info_t i; - struct myseq *s; - const char *p; - - /* the normal lws init */ - - signal(SIGINT, sigint_handler); - - if ((p = lws_cmdline_option(argc, argv, "-d"))) - logs = atoi(p); - - lws_set_log_level(logs, NULL); - lwsl_user("LWS API selftest: lws_sequencer\n"); - - memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ - info.port = CONTEXT_PORT_NO_LISTEN; - info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | - LWS_SERVER_OPTION_EXPLICIT_VHOSTS; - info.protocols = protocols; - -#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) - /* - * OpenSSL uses the system trust store. mbedTLS has to be told which - * CA to trust explicitly. - */ - info.client_ssl_ca_filepath = "./libwebsockets.org.cer"; -#endif - - context = lws_create_context(&info); - if (!context) { - lwsl_err("lws init failed\n"); - return 1; - } - - vh = lws_create_vhost(context, &info); - if (!vh) { - lwsl_err("Failed to create first vhost\n"); - goto bail1; - } - - /* - * Create the sequencer... when the event loop starts, it will - * receive the LWSSEQ_CREATED callback - */ - - memset(&i, 0, sizeof(i)); - i.context = context; - i.user_size = sizeof(struct myseq); - i.puser = (void **)&s; - i.cb = sequencer_cb; - i.name = "seq"; - - seq = lws_seq_create(&i); - if (!seq) { - lwsl_err("%s: unable to create sequencer\n", __func__); - goto bail1; - } - s->vhost = vh; - - /* the usual lws event loop */ - - while (n >= 0 && !interrupted) - n = lws_service(context, 0); - -bail1: - lwsl_user("Completed: %s\n", !test_good ? "FAIL" : "PASS"); - - lws_context_destroy(context); - - return !test_good; -} diff --git a/minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/CMakeLists.txt b/minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/CMakeLists.txt deleted file mode 100644 index 47317ba8a..000000000 --- a/minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -project(lws-minimal-secure-streams-seq 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-secure-streams-seq) -set(SRCS minimal-secure-streams.c) - -set(requirements 1) -require_lws_config(LWS_ROLE_H1 1 requirements) -require_lws_config(LWS_WITHOUT_CLIENT 0 requirements) -require_lws_config(LWS_WITH_SEQUENCER 1 requirements) -require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements) -require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 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/secure-streams/minimal-secure-streams-seq/README.md b/minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/README.md deleted file mode 100644 index 6af2e25d6..000000000 --- a/minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# lws minimal sequre streams seq - -The application goes to https://warmcat.com and reads index.html there. - -It does it using Secure Streams... the main code in minimal-secure-streams.c -just sets up the context and opens a secure stream of type "mintest". - -The handler for state changes and payloads for "mintest" is in ss-myss.c - -The information about how a "mintest" stream should connect and the -protocol it uses is kept separated in policy-database.c - -## build - -``` - $ cmake . && make -``` - -## usage - -Commandline option|Meaning ----|--- --d |Debug verbosity in decimal, eg, -d15 --f| Force connecting to the wrong endpoint to check backoff retry flow - -``` - $ ./lws-minimal-secure-streams-seq -[2018/03/04 14:43:20:8562] USER: LWS minimal http client -[2018/03/04 14:43:20:8571] NOTICE: Creating Vhost 'default' port -1, 1 protocols, IPv6 on -[2018/03/04 14:43:20:8616] NOTICE: created client ssl context for default -[2018/03/04 14:43:20:8617] NOTICE: lws_client_connect_2: 0x1814dc0: address warmcat.com -[2018/03/04 14:43:21:1496] NOTICE: lws_client_connect_2: 0x1814dc0: address warmcat.com -[2018/03/04 14:43:22:0154] NOTICE: lws_client_interpret_server_handshake: incoming content length 26520 -[2018/03/04 14:43:22:0154] NOTICE: lws_client_interpret_server_handshake: client connection up -[2018/03/04 14:43:22:0169] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0169] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0169] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0169] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:0174] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0174] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0174] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0174] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:0179] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0179] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0179] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:0179] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:3010] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3010] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3010] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3010] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:3015] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3015] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3015] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3015] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:3020] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3020] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3020] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3020] USER: RECEIVE_CLIENT_HTTP_READ: read 1015 -[2018/03/04 14:43:22:3022] USER: RECEIVE_CLIENT_HTTP_READ: read 1024 -[2018/03/04 14:43:22:3022] USER: RECEIVE_CLIENT_HTTP_READ: read 974 -[2018/03/04 14:43:22:3022] NOTICE: lws_http_client_read: transaction completed says -1 -[2018/03/04 14:43:23:3042] USER: Completed -``` - - diff --git a/minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/minimal-secure-streams.c b/minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/minimal-secure-streams.c deleted file mode 100644 index 0e21efb06..000000000 --- a/minimal-examples-lowlevel/secure-streams/minimal-secure-streams-seq/minimal-secure-streams.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * lws-minimal-secure-streams-seq - * - * Written in 2010-2020 by Andy Green - * - * This file is made available under the Creative Commons CC0 1.0 - * Universal Public Domain Dedication. - * - * - * This demonstrates the a minimal http client using secure streams api. - * - * It visits https://warmcat.com/ and receives the html page there. - * - * This is the "secure streams" api equivalent of minimal-http-client... - * it shows how to use a sequencer to make it easy to build more complex - * schemes on top of this example. - * - * The layering looks like this - * - * lifetime - * - * ------ app ------ process - * ---- sequencer ---- process - * --- secure stream --- process - * ------- wsi ------- connection - * - * see minimal-secure-streams for a similar example without the sequencer. - */ - -#include -#include -#include - -static int interrupted, bad = 1, flag_conn_fail, flag_h1post; -static const char * const default_ss_policy = - "{" - "\"release\":" "\"01234567\"," - "\"product\":" "\"myproduct\"," - "\"schema-version\":" "1," - "\"retry\": [" /* named backoff / retry strategies */ - "{\"default\": {" - "\"backoff\": [" "1000," - "2000," - "3000," - "5000," - "10000" - "]," - "\"conceal\":" "5," - "\"jitterpc\":" "20," - "\"svalidping\":" "300," - "\"svalidhup\":" "310" - "}}" - "]," - "\"certs\": [" /* named individual certificates in BASE64 DER */ - /* - * Need to be in order from root cert... notice sometimes as - * with Let's Encrypt there are multiple possible validation - * paths, all the pieces for one validation path must be - * given, excluding the server cert itself. Let's Encrypt - * intermediate is signed by their ISRG Root CA but also is - * cross-signed by an IdenTrust intermediate that's widely - * deployed in browsers. We use the ISRG path because that - * way we can skip the extra IdenTrust root cert. - */ - "{\"isrg_root_x1\": \"" - "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw" - "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh" - "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4" - "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu" - "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY" - "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc" - "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+" - "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U" - "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW" - "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH" - "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC" - "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv" - "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn" - "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn" - "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw" - "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI" - "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV" - "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq" - "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL" - "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ" - "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK" - "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5" - "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur" - "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC" - "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc" - "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq" - "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA" - "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d" - "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=" - "\"}" - "]," - "\"trust_stores\": [" /* named cert chains */ - "{" - "\"name\": \"le_via_isrg\"," - "\"stack\": [" - "\"isrg_root_x1\"" - "]" - "}" - "]," - "\"s\": [" /* the supported stream types */ - "{\"mintest\": {" - "\"endpoint\":" "\"warmcat.com\"," - "\"port\":" "443," - "\"protocol\":" "\"h1\"," - "\"http_method\":" "\"GET\"," - "\"http_url\":" "\"index.html\"," - "\"plugins\":" "[]," - "\"tls\":" "true," - "\"opportunistic\":" "true," - "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_isrg\"" - "}}," - "{\"mintest-fail\": {" - "\"endpoint\":" "\"warmcat.com\"," - "\"port\":" "22," - "\"protocol\":" "\"h1\"," - "\"http_method\":" "\"GET\"," - "\"http_url\":" "\"index.html\"," - "\"plugins\":" "[]," - "\"tls\":" "true," - "\"opportunistic\":" "true," - "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_isrg\"" - "}}," - "{\"minpost\": {" - "\"endpoint\":" "\"warmcat.com\"," - "\"port\":" "443," - "\"protocol\":" "\"h1\"," - "\"http_method\":" "\"POST\"," - "\"http_url\":" "\"testserver/formtest\"," - "\"plugins\":" "[]," - "\"tls\":" "true," - "\"opportunistic\":" "true," - "\"retry\":" "\"default\"," - "\"tls_trust_store\":" "\"le_via_isrg\"" - "}}" - "]" - "}" -; - -typedef struct myss { - struct lws_ss_handle *ss; - void *opaque_data; - /* ... application specific state ... */ -} myss_t; - -/* secure streams payload interface */ - -static lws_ss_state_return_t -myss_rx(void *userobj, const uint8_t *buf, size_t len, int flags) -{ -// myss_t *m = (myss_t *)userobj; - - lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags); - lwsl_hexdump_info(buf, len); - - /* - * If we received the whole message, we let the sequencer know it - * was a success - */ - if (flags & LWSSS_FLAG_EOM) { - bad = 0; - interrupted = 1; - } - - return 0; -} - -static lws_ss_state_return_t -myss_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, - int *flags) -{ - // myss_t *m = (myss_t *)userobj; - - /* in this example, we don't send any payload */ - - return 0; -} - -static lws_ss_state_return_t -myss_state(void *userobj, void *sh, lws_ss_constate_t state, - lws_ss_tx_ordinal_t ack) -{ - myss_t *m = (myss_t *)userobj; - - lwsl_user("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), - (unsigned int)ack); - - switch (state) { - case LWSSSCS_CREATING: - return lws_ss_request_tx(m->ss); - - case LWSSSCS_ALL_RETRIES_FAILED: - /* if we're out of retries, we want to close the app and FAIL */ - interrupted = 1; - break; - default: - break; - } - - return 0; -} - -typedef enum { - SEQ_IDLE, - SEQ_TRY_CONNECT, - SEQ_RECONNECT_WAIT, - SEQ_CONNECTED, -} myseq_state_t; - -typedef struct myseq { - struct lws_ss_handle *ss; - - myseq_state_t state; - int http_resp; - - uint16_t try; -} myseq_t; - -/* - * This defines the sequence of things the test app does. - */ - -static lws_seq_cb_return_t -min_sec_str_sequencer_cb(struct lws_sequencer *seq, void *user, int event, - void *v, void *a) -{ - struct myseq *s = (struct myseq *)user; - lws_ss_info_t ssi; - - switch ((int)event) { - - /* these messages are created just by virtue of being a sequencer */ - - case LWSSEQ_CREATED: /* our sequencer just got started */ - s->state = SEQ_IDLE; - lwsl_notice("%s: LWSSEQ_CREATED\n", __func__); - - /* We're making an outgoing secure stream ourselves */ - - memset(&ssi, 0, sizeof(ssi)); - ssi.handle_offset = offsetof(myss_t, ss); - ssi.opaque_user_data_offset = offsetof(myss_t, opaque_data); - ssi.rx = myss_rx; - ssi.tx = myss_tx; - ssi.state = myss_state; - ssi.user_alloc = sizeof(myss_t); - - /* requested to fail (to check backoff)? */ - if (flag_conn_fail) - ssi.streamtype = "mintest-fail"; - else - /* request to check h1 POST */ - if (flag_h1post) - ssi.streamtype = "minpost"; - else - /* default to h1 GET */ - ssi.streamtype = "mintest"; - - if (lws_ss_create(lws_seq_get_context(seq), 0, &ssi, NULL, - &s->ss, seq, NULL)) { - lwsl_err("%s: failed to create secure stream\n", - __func__); - - return LWSSEQ_RET_DESTROY; - } - break; - - case LWSSEQ_DESTROYED: - lwsl_notice("%s: LWSSEQ_DESTROYED\n", __func__); - break; - - case LWSSEQ_TIMED_OUT: /* current step timed out */ - if (s->state == SEQ_RECONNECT_WAIT) - return lws_ss_request_tx(s->ss); - break; - - /* - * These messages are created because we have a secure stream that was - * bound to this sequencer at creation time. It copies its state - * events to us as its sequencer parent. v is the lws_ss_handle_t * - */ - - case LWSSEQ_SS_STATE_BASE + LWSSSCS_CREATING: - lwsl_info("%s: seq LWSSSCS_CREATING\n", __func__); - return lws_ss_request_tx(s->ss); - - case LWSSEQ_SS_STATE_BASE + LWSSSCS_DISCONNECTED: - lwsl_info("%s: seq LWSSSCS_DISCONNECTED\n", __func__); - break; - case LWSSEQ_SS_STATE_BASE + LWSSSCS_UNREACHABLE: - lwsl_info("%s: seq LWSSSCS_UNREACHABLE\n", __func__); - break; - case LWSSEQ_SS_STATE_BASE + LWSSSCS_AUTH_FAILED: - lwsl_info("%s: seq LWSSSCS_AUTH_FAILED\n", __func__); - break; - case LWSSEQ_SS_STATE_BASE + LWSSSCS_CONNECTED: - lwsl_info("%s: seq LWSSSCS_CONNECTED\n", __func__); - break; - case LWSSEQ_SS_STATE_BASE + LWSSSCS_CONNECTING: - lwsl_info("%s: seq LWSSSCS_CONNECTING\n", __func__); - break; - case LWSSEQ_SS_STATE_BASE + LWSSSCS_DESTROYING: - lwsl_info("%s: seq LWSSSCS_DESTROYING\n", __func__); - break; - case LWSSEQ_SS_STATE_BASE + LWSSSCS_POLL: - /* somebody called lws_ss_poll() on the stream */ - lwsl_info("%s: seq LWSSSCS_POLL\n", __func__); - break; - case LWSSEQ_SS_STATE_BASE + LWSSSCS_ALL_RETRIES_FAILED: - lwsl_info("%s: seq LWSSSCS_ALL_RETRIES_FAILED\n", __func__); - interrupted = 1; - break; - case LWSSEQ_SS_STATE_BASE + LWSSSCS_QOS_ACK_REMOTE: - lwsl_info("%s: seq LWSSSCS_QOS_ACK_REMOTE\n", __func__); - break; - case LWSSEQ_SS_STATE_BASE + LWSSSCS_QOS_ACK_LOCAL: - lwsl_info("%s: seq LWSSSCS_QOS_ACK_LOCAL\n", __func__); - break; - - /* - * This is the message we send from the ss handler to inform the - * sequencer we had the payload properly - */ - - case LWSSEQ_USER_BASE: - bad = 0; - interrupted = 1; - break; - - default: - break; - } - - return LWSSEQ_RET_CONTINUE; -} - -static void -sigint_handler(int sig) -{ - interrupted = 1; -} - -int main(int argc, const char **argv) -{ - int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; - struct lws_context_creation_info info; - struct lws_context *context; - lws_seq_info_t i; - const char *p; - myseq_t *ms; - - 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 secure streams [-d][-f][--h1post]\n"); - - flag_conn_fail = !!lws_cmdline_option(argc, argv, "-f"); - flag_h1post = !!lws_cmdline_option(argc, argv, "--h1post"); - - memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ - - info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | - LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; - info.fd_limit_per_thread = 1 + 1 + 1; - info.pss_policies_json = default_ss_policy; - info.port = CONTEXT_PORT_NO_LISTEN; - - context = lws_create_context(&info); - if (!context) { - lwsl_err("lws init failed\n"); - return 1; - } - - /* - * Create the sequencer that performs the steps of the test action - * from inside the event loop. - */ - - memset(&i, 0, sizeof(i)); - i.context = context; - i.user_size = sizeof(myseq_t); - i.puser = (void **)&ms; - i.cb = min_sec_str_sequencer_cb; - i.name = "min-sec-stream-seq"; - - if (!lws_seq_create(&i)) { - lwsl_err("%s: failed to create sequencer\n", __func__); - goto bail; - } - - /* the event loop */ - - while (n >= 0 && !interrupted) - n = lws_service(context, 0); - -bail: - lws_context_destroy(context); - lwsl_user("Completed: %s\n", bad ? "failed" : "OK"); - - return bad; -}