mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-30 00:00:16 +01:00
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.
This commit is contained in:
parent
445651b2c6
commit
c8b9ac4aaf
6 changed files with 0 additions and 958 deletions
|
@ -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()
|
|
|
@ -1,32 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
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
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
|
|
|
@ -1,399 +0,0 @@
|
||||||
/*
|
|
||||||
* lws-api-test-lws_sequencer
|
|
||||||
*
|
|
||||||
* Written in 2019 by Andy Green <andy@warmcat.com>
|
|
||||||
*
|
|
||||||
* 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 <libwebsockets.h>
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -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()
|
|
|
@ -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 <loglevel>|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
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -1,410 +0,0 @@
|
||||||
/*
|
|
||||||
* lws-minimal-secure-streams-seq
|
|
||||||
*
|
|
||||||
* Written in 2010-2020 by Andy Green <andy@warmcat.com>
|
|
||||||
*
|
|
||||||
* 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 <libwebsockets.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
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<verbosity>][-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;
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue