From f5edf9d75a3f90962fb2bd06ad5699138eec243f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 10 Oct 2021 08:45:30 +0100 Subject: [PATCH] remove: lws_sequencer lws_sequencer and lws_abstract were both false starts trying to do the functionality of secure streams. Since Secure Streams does a better job for both and there are no known out-of-tree users of them, let's remove them and focus on Secure Streams. --- CMakeLists-implied-options.txt | 1 - CMakeLists.txt | 1 - READMEs/README.lws_sequencer.md | 149 ----- include/libwebsockets.h | 7 - include/libwebsockets/abstract/abstract.h | 138 ----- include/libwebsockets/abstract/protocols.h | 88 --- .../libwebsockets/abstract/protocols/smtp.h | 115 ---- include/libwebsockets/abstract/transports.h | 65 --- .../abstract/transports/raw-skt.h | 29 - .../abstract/transports/unit-test.h | 81 --- include/libwebsockets/lws-client.h | 5 - .../libwebsockets/lws-secure-streams-client.h | 15 +- include/libwebsockets/lws-secure-streams.h | 15 +- include/libwebsockets/lws-sequencer.h | 243 -------- lib/CMakeLists.txt | 3 - lib/abstract/CMakeLists.txt | 57 -- lib/abstract/README.md | 170 ------ lib/abstract/abstract.c | 355 ------------ lib/abstract/private-lib-abstract.h | 55 -- .../private-lib-abstract-protocols-smtp.h | 24 - lib/abstract/protocols/smtp/smtp-sequencer.c | 323 ----------- lib/abstract/protocols/smtp/smtp.c | 382 ------------- lib/abstract/test-sequencer.c | 274 --------- lib/abstract/transports/raw-skt.c | 408 ------------- lib/abstract/transports/unit-test.c | 540 ------------------ lib/core-net/CMakeLists.txt | 5 - lib/core-net/client/connect.c | 1 - lib/core-net/private-lib-core-net.h | 5 - lib/core-net/sequencer.c | 335 ----------- lib/core/context.c | 12 +- .../private-lib-secure-streams.h | 1 - lib/secure-streams/secure-streams.c | 20 +- lib/secure-streams/serialized/client/sspc.c | 2 +- 33 files changed, 5 insertions(+), 3919 deletions(-) delete mode 100644 READMEs/README.lws_sequencer.md delete mode 100644 include/libwebsockets/abstract/abstract.h delete mode 100644 include/libwebsockets/abstract/protocols.h delete mode 100644 include/libwebsockets/abstract/protocols/smtp.h delete mode 100644 include/libwebsockets/abstract/transports.h delete mode 100644 include/libwebsockets/abstract/transports/raw-skt.h delete mode 100644 include/libwebsockets/abstract/transports/unit-test.h delete mode 100644 include/libwebsockets/lws-sequencer.h delete mode 100644 lib/abstract/CMakeLists.txt delete mode 100644 lib/abstract/README.md delete mode 100644 lib/abstract/abstract.c delete mode 100644 lib/abstract/private-lib-abstract.h delete mode 100644 lib/abstract/protocols/smtp/private-lib-abstract-protocols-smtp.h delete mode 100644 lib/abstract/protocols/smtp/smtp-sequencer.c delete mode 100644 lib/abstract/protocols/smtp/smtp.c delete mode 100644 lib/abstract/test-sequencer.c delete mode 100644 lib/abstract/transports/raw-skt.c delete mode 100644 lib/abstract/transports/unit-test.c delete mode 100644 lib/core-net/sequencer.c diff --git a/CMakeLists-implied-options.txt b/CMakeLists-implied-options.txt index 9579b1a12..acb29cf7d 100644 --- a/CMakeLists-implied-options.txt +++ b/CMakeLists-implied-options.txt @@ -154,7 +154,6 @@ if (NOT LWS_WITH_NETWORK) set(LWS_WITH_HTTP_STREAM_COMPRESSION 0) set(LWS_WITH_HTTP_BROTLI 0) set(LWS_WITH_POLL 0) - set(LWS_WITH_SEQUENCER 0) set(LWS_ROLE_DBUS 0) set(LWS_WITH_LWS_DSH 0) set(LWS_WITH_THREADPOOL 0) diff --git a/CMakeLists.txt b/CMakeLists.txt index c619f3c51..f679dc9f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -296,7 +296,6 @@ option(LWS_WITH_LEJP_CONF "With LEJP configuration parser as used by lwsws" OFF) option(LWS_WITH_ZLIB "Include zlib support (required for extensions)" OFF) option(LWS_WITH_BUNDLED_ZLIB "Use bundled zlib version (Windows only)" ${LWS_WITH_BUNDLED_ZLIB_DEFAULT}) option(LWS_WITH_MINIZ "Use miniz instead of zlib" OFF) -option(LWS_WITH_SEQUENCER "lws_seq_t support" OFF) option(LWS_WITH_EXTERNAL_POLL "Support external POLL integration using callback messages (not recommended)" OFF) option(LWS_WITH_LWS_DSH "Support lws_dsh_t Disordered Shared Heap" OFF) option(LWS_CLIENT_HTTP_PROXYING "Support external http proxies for client connections" ON) diff --git a/READMEs/README.lws_sequencer.md b/READMEs/README.lws_sequencer.md deleted file mode 100644 index 9a3b676d6..000000000 --- a/READMEs/README.lws_sequencer.md +++ /dev/null @@ -1,149 +0,0 @@ -# `struct lws_sequencer` introduction - -Often a single network action like a client GET is just part of a -larger series of actions, perhaps involving different connections. - -Since lws operates inside an event loop, if the outer sequencing -doesn't, it can be awkward to synchronize these steps with what's -happening on the network with a particular connection on the event -loop thread. - -![lws_sequencer](/doc-assets/lws_sequencer.svg) - -`struct lws_sequencer` provides a generic way to stage multi-step -operations from inside the event loop. Because it participates -in the event loop similar to a wsi, it always operates from the -service thread context and can access structures that share the -service thread without locking. It can also provide its own -higher-level timeout handling. - -Naturally you can have many of them running in the same event -loop operating independently. - -Sequencers themselves bind to a pt (per-thread) service thread, -by default there's only one of these and it's the same as saying -they bind to an `lws_context`. The sequencer callback may create -wsi which in turn are bound to a vhost, but the sequencer itself -is above all that. - -## Sequencer timeouts - -The sequencer additionally maintains its own second-resolution timeout -checked by lws for the step being sequenced... this is independent of -any lws wsi timeouts which tend to be set and reset for very short-term -timeout protection inside one transaction. - -The sequencer timeout operates separately and above any wsi timeout, and -is typically only reset by the sequencer callback when it receives an -event indicating a step completed or failed, or it sets up the next sequence -step. - -If the sequencer timeout expires, then the sequencer receives a queued -`LWSSEQ_TIMED_OUT` message informing it, and it can take corrective action -or schedule a retry of the step. This message is queued and sent normally -under the service thread context and in order of receipt. - -Unlike lws timeouts which force the wsi to close, the sequencer timeout -only sends the message. This allows the timeout to be used to, eg, wait -out a retry cooloff period and then start the retry when the -`LWSSEQ_TIMED_OUT` is received, according to the state of the sequencer. - -## Creating an `struct lws_sequencer` - -``` -typedef struct lws_seq_info { - struct lws_context *context; /* lws_context for seq */ - int tsi; /* thread service idx */ - size_t user_size; /* size of user alloc */ - void **puser; /* place ptr to user */ - lws_seq_event_cb cb; /* seq callback */ - const char *name; /* seq name */ - const lws_retry_bo_t *retry; /* retry policy */ -} lws_seq_info_t; -``` - -``` -struct lws_sequencer * -lws_sequencer_create(lws_seq_info_t *info); -``` - -When created, in lws the sequencer objects are bound to a 'per-thread', -which is by default the same as to say bound to the `lws_context`. You -can tag them with an opaque user data pointer, and they are also bound to -a user-specified callback which handles sequencer events - -``` -typedef int (*lws_seq_event_cb)(struct lws_sequencer *seq, void *user_data, - lws_seq_events_t event, void *data); -``` - -`struct lws_sequencer` objects are private to lws and opaque to the user. A small -set of apis lets you perform operations on the pointer returned by the -create api. - -## Queueing events on a sequencer - -Each sequencer object can be passed "events", which are held on a per-sequencer -queue and handled strictly in the order they arrived on subsequent event loops. -`LWSSEQ_CREATED` and `LWSSEQ_DESTROYED` events are produced by lws reflecting -the sequencer's lifecycle, but otherwise the event indexes have a user-defined -meaning and are queued on the sequencer by user code for eventual consumption -by user code in the sequencer callback. - -Pending events are removed from the sequencer queues and sent to the sequencer -callback from inside the event loop at a rate of one per event loop wait. - -## Destroying sequencers - -`struct lws_sequencer` objects are cleaned up during context destruction if they are -still around. - -Normally the sequencer callback receives a queued message that -informs it that it's either failed at the current step, or succeeded and that -was the last step, and requests that it should be destroyed by returning -`LWSSEQ_RET_DESTROY` from the sequencer callback. - -## Lifecycle considerations - -Sequencers may spawn additional assets like client wsi as part of the sequenced -actions... the lifecycle of the sequencer and the assets overlap but do not -necessarily depend on each other... that is a wsi created by the sequencer may -outlive the sequencer. - -It's important therefore to detach assets from the sequencer and the sequencer -from the assets when each step is over and the asset is "out of scope" for the -sequencer. It doesn't necessarily mean closing the assets, just making sure -pointers are invalidated. For example, if a client wsi held a pointer to the -sequencer as its `.user_data`, when the wsi is out of scope for the sequencer -it can set it to NULL, eg, `lws_set_wsi_user(wsi, NULL);`. - -Under some conditions wsi may want to hang around a bit to see if there is a -subsequent client wsi transaction they can be reused on. They will clean -themselves up when they time out. - -## Watching wsi lifecycle from a sequencer - -When a sequencer is creating a wsi as part of its sequence, it will be very -interested in lifecycle events. At client wsi creation time, the sequencer -callback can set info->seq to itself in order to receive lifecycle messages -about its wsi. - -|message|meaning| -|---|---| -|`LWSSEQ_WSI_CONNECTED`|The wsi has become connected| -|`LWSSEQ_WSI_CONN_FAIL`|The wsi has failed to connect| -|`LWSSEQ_WSI_CONN_CLOSE`|The wsi had been connected, but has now closed| - -By receiving these, the sequencer can understand when it should attempt -reconnections or that it cannot progress the sequence. - -When dealing with wsi that were created by the sequencer, they may close at -any time, eg, be closed by the remote peer or an intermediary. The -`LWSSEQ_WSI_CONN_CLOSE` message may have been queued but since they are -strictly handled in the order they arrived, before it was -handled an earlier message may want to cause some api to be called on -the now-free()-d wsi. To detect this situation safely, there is a -sequencer api `lws_sequencer_check_wsi()` which peeks the message -buffer and returns nonzero if it later contains an `LWSSEQ_WSI_CONN_CLOSE` -already. - diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 793cef574..411587c08 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -54,7 +54,6 @@ extern "C" { /* place for one-shot opaque forward references */ typedef struct lws_context * lws_ctx_t; -struct lws_sequencer; struct lws_dsh; /* @@ -664,7 +663,6 @@ struct lws; #include #include #include -#include #include #include #include @@ -672,11 +670,6 @@ struct lws; #include #include -#if !defined(LWS_PLAT_FREERTOS) -#include - -#include -#endif #include #if defined(LWS_WITH_TLS) diff --git a/include/libwebsockets/abstract/abstract.h b/include/libwebsockets/abstract/abstract.h deleted file mode 100644 index c312a1f5a..000000000 --- a/include/libwebsockets/abstract/abstract.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * These are used to optionally pass an array of index = C string, binary array, - * or ulong tokens to the abstract transport or protocol. For example if it's - * raw socket transport, then the DNS address to connect to and the port are - * passed using these when the client created and bound to the transport. - */ - -typedef struct lws_token_map { - union { - const char *value; - uint8_t *bvalue; - unsigned long lvalue; - } u; - short name_index; /* 0 here indicates end of array */ - short length_or_zero; -} lws_token_map_t; - -/* - * The indvidual protocols and transports define their own name_index-es which - * are meaningful to them. Define index 0 globally as the end of an array of - * them, and provide bases so user protocol and transport ones don't overlap. - */ - -enum { - LTMI_END_OF_ARRAY, - - LTMI_PROTOCOL_BASE = 2048, - - LTMI_TRANSPORT_BASE = 4096 -}; - -struct lws_abs_transport; -struct lws_abs_protocol; -typedef struct lws_abs lws_abs_t; - -LWS_VISIBLE LWS_EXTERN const lws_token_map_t * -lws_abs_get_token(const lws_token_map_t *token_map, short name_index); - -/* - * the combination of a protocol, transport, and token maps for each - */ - -typedef void lws_abs_transport_inst_t; -typedef void lws_abs_protocol_inst_t; - -/** - * lws_abstract_alloc() - allocate and configure an lws_abs_t - * - * \param vhost: the struct lws_vhost to bind to - * \param user: opaque user pointer - * \param abstract_path: "protocol.transport" names - * \param ap_tokens: tokens for protocol options - * \param at_tokens: tokens for transport - * \param seq: optional sequencer we should bind to, or NULL - * \param opaque_user_data: data given in sequencer callback, if any - * - * Returns an allocated lws_abs_t pointer set up with the other arguments. - * - * Doesn't create a connection instance, just allocates the lws_abs_t and - * sets it up with the arguments. - * - * Returns NULL is there's any problem. - */ -LWS_VISIBLE LWS_EXTERN lws_abs_t * -lws_abstract_alloc(struct lws_vhost *vhost, void *user, - const char *abstract_path, const lws_token_map_t *ap_tokens, - const lws_token_map_t *at_tokens, struct lws_sequencer *seq, - void *opaque_user_data); - -/** - * lws_abstract_free() - free an allocated lws_abs_t - * - * \param pabs: pointer to the lws_abs_t * to free - * - * Frees and sets the pointer to NULL. - */ - -LWS_VISIBLE LWS_EXTERN void -lws_abstract_free(lws_abs_t **pabs); - -/** - * lws_abs_bind_and_create_instance - use an abstract protocol and transport - * - * \param abs: the lws_abs_t describing the combination desired - * - * This instantiates an abstract protocol and abstract transport bound together. - * A single heap allocation is made for the combination and the protocol and - * transport creation ops are called on it. The ap_tokens and at_tokens - * are consulted by the creation ops to decide the details of the protocol and - * transport for the instance. - */ -LWS_VISIBLE LWS_EXTERN lws_abs_t * -lws_abs_bind_and_create_instance(const lws_abs_t *ai); - -/** - * lws_abs_destroy_instance() - destroys an instance - * - * \param ai: pointer to the ai pointer to destroy - * - * This is for destroying an instance created by - * lws_abs_bind_and_create_instance() above. - * - * Calls the protocol and transport destroy operations on the instance, then - * frees the combined allocation in one step. The pointer ai is set to NULL. - */ -LWS_VISIBLE LWS_EXTERN void -lws_abs_destroy_instance(lws_abs_t **ai); - -/* - * bring in all the protocols and transports definitions - */ - -#include -#include diff --git a/include/libwebsockets/abstract/protocols.h b/include/libwebsockets/abstract/protocols.h deleted file mode 100644 index 77900203d..000000000 --- a/include/libwebsockets/abstract/protocols.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * Information about how this protocol handles multiple use of connections. - * - * .flags of 0 indicates each connection must start with a fresh transport. - * - * Flags can be used to indicate the protocol itself supports different - * kinds of multiple use. However the actual use or not of these may depend on - * negotiation with the remote peer. - * - * LWS_AP_FLAG_PIPELINE_TRANSACTIONS: other instances can be queued on one - * with an existing connection and get a - * chance to "hot take over" the existing - * transport in turn, like h1 keepalive - * pipelining - * - * LWS_AP_FLAG_MUXABLE_STREAM: an existing connection can absorb more child - * connections and mux them as separate child - * streams ongoing, like h2 - */ - -enum { - LWS_AP_FLAG_PIPELINE_TRANSACTIONS = (1 << 0), - LWS_AP_FLAG_MUXABLE_STREAM = (1 << 1), -}; - -typedef struct lws_abs_protocol { - const char *name; - int alloc; - int flags; - - int (*create)(const struct lws_abs *ai); - void (*destroy)(lws_abs_protocol_inst_t **d); - int (*compare)(lws_abs_t *abs1, lws_abs_t *abs2); - - /* events the transport invokes (handled by abstract protocol) */ - - int (*accept)(lws_abs_protocol_inst_t *d); - int (*rx)(lws_abs_protocol_inst_t *d, const uint8_t *b, size_t l); - int (*writeable)(lws_abs_protocol_inst_t *d, size_t budget); - int (*closed)(lws_abs_protocol_inst_t *d); - int (*heartbeat)(lws_abs_protocol_inst_t *d); - - /* as parent, we get a notification a new child / queue entry - * bound to us... this is the parent lws_abs_t as arg */ - int (*child_bind)(lws_abs_t *abs); -} lws_abs_protocol_t; - -/** - * lws_abs_protocol_get_by_name() - returns a pointer to the named protocol ops - * - * \param name: the name of the abstract protocol - * - * Returns a pointer to the named protocol ops struct if available, otherwise - * NULL. - */ -LWS_VISIBLE LWS_EXTERN const lws_abs_protocol_t * -lws_abs_protocol_get_by_name(const char *name); - -/* - * bring in public api pieces from protocols - */ - -#include - diff --git a/include/libwebsockets/abstract/protocols/smtp.h b/include/libwebsockets/abstract/protocols/smtp.h deleted file mode 100644 index 90b69c6e8..000000000 --- a/include/libwebsockets/abstract/protocols/smtp.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/** \defgroup smtp SMTP related functions - * ##SMTP related functions - * \ingroup lwsapi - * - * These apis let you communicate with a local SMTP server to send email from - * lws. It handles all the SMTP sequencing and protocol actions. - * - * Your system should have postfix, sendmail or another MTA listening on port - * 25 and able to send email using the "mail" commandline app. Usually distro - * MTAs are configured for this by default. - * - * You can either use the abstract protocol layer directly, or instead use the - * provided smtp sequencer... this takes care of creating the protocol - * connections, and provides and email queue and retry management. - */ -//@{ - -#if defined(LWS_WITH_SMTP) - -enum { - LTMI_PSMTP_V_HELO = LTMI_PROTOCOL_BASE, /* u.value */ - - LTMI_PSMTP_V_LWS_SMTP_EMAIL_T, /* u.value */ -}; - -enum { - LWS_SMTP_DISPOSITION_SENT, - LWS_SMTP_DISPOSITION_FAILED, - LWS_SMTP_DISPOSITION_FAILED_DESTROY -}; - -typedef struct lws_smtp_sequencer_args { - const char helo[32]; - struct lws_vhost *vhost; - time_t retry_interval; - time_t delivery_timeout; - size_t email_queue_max; - size_t max_content_size; -} lws_smtp_sequencer_args_t; - -typedef struct lws_smtp_sequencer lws_smtp_sequencer_t; -typedef struct lws_smtp_email lws_smtp_email_t; - -LWS_VISIBLE LWS_EXTERN lws_smtp_sequencer_t * -lws_smtp_sequencer_create(const lws_smtp_sequencer_args_t *args); - -LWS_VISIBLE LWS_EXTERN void -lws_smtp_sequencer_destroy(lws_smtp_sequencer_t *s); - -typedef int (*lws_smtp_cb_t)(void *e, void *d, int disp, const void *b, size_t l); -typedef struct lws_smtp_email lws_smtp_email_t; - -/** - * lws_smtpc_add_email() - Allocates and queues an email object - * - * \param s: smtp sequencer to queue on - * \param payload: the email payload string, with headers and terminating . - * \param payload_len: size in bytes of the payload string - * \param sender: the sender name and email - * \param recipient: the recipient name and email - * \param data: opaque user data returned in the done callback - * \param done: callback called when the email send succeeded or failed - * - * Allocates an email object and copies the payload, sender and recipient into - * it and initializes it. Returns NULL if OOM, otherwise the allocated email - * object. - * - * Because it copies the arguments into an allocated buffer, the original - * arguments can be safely destroyed after calling this. - * - * The done() callback must free the email object. It doesn't have to free any - * individual members. - */ -LWS_VISIBLE LWS_EXTERN int -lws_smtpc_add_email(lws_smtp_sequencer_t *s, const char *payload, - size_t payload_len, const char *sender, - const char *recipient, void *data, lws_smtp_cb_t done); - -/** - * lws_smtpc_free_email() - Add email to the list of ones being sent - * - * \param e: email to queue for sending on \p c - * - * Adds an email to the linked-list of emails to send - */ -LWS_VISIBLE LWS_EXTERN int -lws_smtpc_free_email(lws_smtp_email_t *e); - - -#endif -//@} diff --git a/include/libwebsockets/abstract/transports.h b/include/libwebsockets/abstract/transports.h deleted file mode 100644 index e9d7aa568..000000000 --- a/include/libwebsockets/abstract/transports.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * Abstract transport ops - */ - -typedef struct lws_abs_transport { - const char *name; - int alloc; - - int (*create)(lws_abs_t *abs); - void (*destroy)(lws_abs_transport_inst_t **d); - - /* check if the transport settings for these connections are the same */ - int (*compare)(lws_abs_t *abs1, lws_abs_t *abs2); - - /* events the abstract protocol invokes (handled by transport) */ - - int (*tx)(lws_abs_transport_inst_t *d, uint8_t *buf, size_t len); - int (*client_conn)(const lws_abs_t *abs); - int (*close)(lws_abs_transport_inst_t *d); - int (*ask_for_writeable)(lws_abs_transport_inst_t *d); - int (*set_timeout)(lws_abs_transport_inst_t *d, int reason, int secs); - int (*state)(lws_abs_transport_inst_t *d); -} lws_abs_transport_t; - -/** - * lws_abs_protocol_get_by_name() - returns a pointer to the named protocol ops - * - * \param name: the name of the abstract protocol - * - * Returns a pointer to the named protocol ops struct if available, otherwise - * NULL. - */ -LWS_VISIBLE LWS_EXTERN const lws_abs_transport_t * -lws_abs_transport_get_by_name(const char *name); - -/* - * bring in public api pieces from transports - */ - -#include -#include diff --git a/include/libwebsockets/abstract/transports/raw-skt.h b/include/libwebsockets/abstract/transports/raw-skt.h deleted file mode 100644 index beff9a3fa..000000000 --- a/include/libwebsockets/abstract/transports/raw-skt.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -enum { - LTMI_PEER_V_DNS_ADDRESS = LTMI_TRANSPORT_BASE, /* u.value */ - LTMI_PEER_LV_PORT, /* u.lvalue */ - LTMI_PEER_LV_TLS_FLAGS, /* u.lvalue */ -}; diff --git a/include/libwebsockets/abstract/transports/unit-test.h b/include/libwebsockets/abstract/transports/unit-test.h deleted file mode 100644 index 2213f29a7..000000000 --- a/include/libwebsockets/abstract/transports/unit-test.h +++ /dev/null @@ -1,81 +0,0 @@ - /* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * This is an abstract transport useful for unit testing abstract protocols. - * - * Instead of passing data anywhere, you give the transport a list of packets - * to deliver and packets you expect back from the abstract protocol it's - * bound to. - */ - -enum { - LWS_AUT_EXPECT_TEST_END = (1 << 0), - LWS_AUT_EXPECT_LOCAL_CLOSE = (1 << 1), - LWS_AUT_EXPECT_DO_REMOTE_CLOSE = (1 << 2), - LWS_AUT_EXPECT_TX /* expect this as tx from protocol */ = (1 << 3), - LWS_AUT_EXPECT_RX /* present this as rx to protocol */ = (1 << 4), - LWS_AUT_EXPECT_SHOULD_FAIL = (1 << 5), - LWS_AUT_EXPECT_SHOULD_TIMEOUT = (1 << 6), -}; - -typedef enum { - LPE_CONTINUE, - LPE_SUCCEEDED, - LPE_FAILED, - LPE_FAILED_UNEXPECTED_TIMEOUT, - LPE_FAILED_UNEXPECTED_PASS, - LPE_FAILED_UNEXPECTED_CLOSE, - LPE_SKIPPED, - LPE_CLOSING -} lws_unit_test_packet_disposition; - -typedef int (*lws_unit_test_packet_test_cb)(const void *cb_user, int disposition); -typedef int (*lws_unit_test_packet_cb)(lws_abs_t *instance); - -/* each step in the unit test */ - -typedef struct lws_unit_test_packet { - void *buffer; - lws_unit_test_packet_cb pre; - size_t len; - - uint32_t flags; -} lws_unit_test_packet_t; - -/* each unit test */ - -typedef struct lws_unit_test { - const char * name; /* NULL indicates end of test array */ - lws_unit_test_packet_t * expect_array; - int max_secs; -} lws_unit_test_t; - -enum { - LTMI_PEER_V_EXPECT_TEST = LTMI_TRANSPORT_BASE, /* u.value */ - LTMI_PEER_V_EXPECT_RESULT_CB, /* u.value */ - LTMI_PEER_V_EXPECT_RESULT_CB_ARG, /* u.value */ -}; - -LWS_VISIBLE LWS_EXTERN const char * -lws_unit_test_result_name(int in); - diff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h index 8727cf56b..69deb85c2 100644 --- a/include/libwebsockets/lws-client.h +++ b/include/libwebsockets/lws-client.h @@ -171,11 +171,6 @@ struct lws_client_connect_info { * tokens */ - struct lws_sequencer *seq; - /**< NULL, or an lws_seq_t that wants to be given messages about - * this wsi's lifecycle as it connects, errors or closes. - */ - void *opaque_user_data; /**< This data has no meaning to lws but is applied to the client wsi * and can be retrieved by user code with lws_get_opaque_user_data(). diff --git a/include/libwebsockets/lws-secure-streams-client.h b/include/libwebsockets/lws-secure-streams-client.h index 3683d70f9..4e0852f21 100644 --- a/include/libwebsockets/lws-secure-streams-client.h +++ b/include/libwebsockets/lws-secure-streams-client.h @@ -201,7 +201,7 @@ struct lws_context_standalone; LWS_VISIBLE LWS_EXTERN int lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, void *opaque_user_data, struct lws_sspc_handle **ppss, - struct lws_sequencer *seq_owner, const char **ppayload_fmt); + void *reserved, const char **ppayload_fmt); /** * lws_sspc_destroy() - Destroy secure stream @@ -256,19 +256,6 @@ lws_sspc_request_tx_len(struct lws_sspc_handle *h, unsigned long len); LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t lws_sspc_client_connect(struct lws_sspc_handle *h); -/** - * lws_sspc_get_sequencer() - Return parent sequencer pointer if any - * - * \param h: secure streams handle - * - * Returns NULL if the secure stream is not associated with a sequencer. - * Otherwise returns a pointer to the owning sequencer. You can use this to - * identify which sequencer to direct messages to, from the secure stream - * callback. - */ -LWS_VISIBLE LWS_EXTERN struct lws_sequencer * -lws_sspc_get_sequencer(struct lws_sspc_handle *h); - /** * lws_sspc_proxy_create() - Start a unix domain socket proxy for Secure Streams * diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index 39fc50e4e..771fd4175 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -309,7 +309,7 @@ typedef struct lws_ss_info { LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, void *opaque_user_data, struct lws_ss_handle **ppss, - struct lws_sequencer *seq_owner, const char **ppayload_fmt); + void *reserved, const char **ppayload_fmt); /** * lws_ss_destroy() - Destroy secure stream @@ -367,19 +367,6 @@ lws_ss_request_tx_len(struct lws_ss_handle *pss, unsigned long len); LWS_VISIBLE LWS_EXTERN lws_ss_state_return_t LWS_WARN_UNUSED_RESULT lws_ss_client_connect(struct lws_ss_handle *h); -/** - * lws_ss_get_sequencer() - Return parent sequencer pointer if any - * - * \param h: secure streams handle - * - * Returns NULL if the secure stream is not associated with a sequencer. - * Otherwise returns a pointer to the owning sequencer. You can use this to - * identify which sequencer to direct messages to, from the secure stream - * callback. - */ -LWS_VISIBLE LWS_EXTERN struct lws_sequencer * -lws_ss_get_sequencer(struct lws_ss_handle *h); - /** * lws_ss_proxy_create() - Start a unix domain socket proxy for Secure Streams * diff --git a/include/libwebsockets/lws-sequencer.h b/include/libwebsockets/lws-sequencer.h deleted file mode 100644 index 7189788b9..000000000 --- a/include/libwebsockets/lws-sequencer.h +++ /dev/null @@ -1,243 +0,0 @@ - /* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * lws_sequencer is intended to help implement sequences that: - * - * - outlive a single connection lifetime, - * - are not associated with a particular protocol, - * - are not associated with a particular vhost, - * - must receive and issue events inside the event loop - * - * lws_sequencer-s are bound to a pt (per-thread) which for the default case of - * one service thread is the same as binding to an lws_context. - */ -/* - * retry backoff table... retry n happens after .retry_ms_table[n] ms, with - * the last entry used if n is greater than the number of entries. - * - * The first .conceal_count retries are concealed, but after that the failures - * are reported. - */ - -typedef enum { - LWSSEQ_CREATED, /* sequencer created */ - LWSSEQ_DESTROYED, /* sequencer destroyed */ - LWSSEQ_TIMED_OUT, /* sequencer timeout */ - LWSSEQ_HEARTBEAT, /* 1Hz callback */ - - LWSSEQ_WSI_CONNECTED, /* wsi we bound to us has connected */ - LWSSEQ_WSI_CONN_FAIL, /* wsi we bound to us has failed to connect */ - LWSSEQ_WSI_CONN_CLOSE, /* wsi we bound to us has closed */ - - - LWSSEQ_SS_STATE_BASE, /* secure streams owned by a sequencer provide - * automatic messages about state changes on - * the sequencer, passing the oridinal in the - * event argument field. The message index is - * LWSSEQ_SS_STATE_BASE + the enum from - * lws_ss_constate_t */ - - LWSSEQ_USER_BASE = 100 /* define your events from here */ -} lws_seq_events_t; - -typedef enum lws_seq_cb_return { - LWSSEQ_RET_CONTINUE, - LWSSEQ_RET_DESTROY -} lws_seq_cb_return_t; - -/* - * handler for this sequencer. Return 0 if OK else nonzero to destroy the - * sequencer. LWSSEQ_DESTROYED will be called back to the handler so it can - * close / destroy any private assets associated with the sequence. - * - * The callback may return either LWSSEQ_RET_CONTINUE for the sequencer to - * resume or LWSSEQ_RET_DESTROY to indicate the sequence is finished. - * - * Event indexes consist of some generic ones but mainly user-defined ones - * starting from LWSSEQ_USER_BASE. - */ -typedef lws_seq_cb_return_t (*lws_seq_event_cb)(struct lws_sequencer *seq, - void *user, int event, void *data, void *aux); - -typedef struct lws_seq_info { - struct lws_context *context; /* lws_context for seq */ - int tsi; /* thread service idx */ - size_t user_size; /* size of user alloc */ - void **puser; /* place ptr to user */ - lws_seq_event_cb cb; /* seq callback */ - const char *name; /* seq name */ - const lws_retry_bo_t *retry; /* retry policy */ - uint8_t wakesuspend:1; /* important enough to - * wake system */ -} lws_seq_info_t; - -/** - * lws_seq_create() - create and bind sequencer to a pt - * - * \param info: information about sequencer to create - * - * This binds an abstract sequencer to a per-thread (by default, the single - * event loop of an lws_context). After the event loop starts, the sequencer - * will receive an LWSSEQ_CREATED event on its callback from the event loop - * context, where it can begin its sequence flow. - * - * Lws itself will only call the callback subsequently with LWSSEQ_DESTROYED - * when the sequencer is being destroyed. - * - * pt locking is used to protect the related data structures. - */ -LWS_VISIBLE LWS_EXTERN struct lws_sequencer * -lws_seq_create(lws_seq_info_t *info); - -/** - * lws_seq_destroy() - destroy the sequencer - * - * \param seq: pointer to the the opaque sequencer pointer returned by - * lws_seq_create() - * - * This proceeds to destroy the sequencer, calling LWSSEQ_DESTROYED and then - * freeing the sequencer object itself. The pointed-to seq pointer will be - * set to NULL. - */ -LWS_VISIBLE LWS_EXTERN void -lws_seq_destroy(struct lws_sequencer **seq); - -/** - * lws_seq_queue_event() - queue an event on the given sequencer - * - * \param seq: the opaque sequencer pointer returned by lws_seq_create() - * \param e: the event index to queue - * \param data: associated opaque (to lws) data to provide the callback - * \param aux: second opaque data to provide the callback - * - * This queues the event on a given sequencer. Queued events are delivered one - * per sequencer each subsequent time around the event loop, so the cb is called - * from the event loop thread context. - * - * Notice that because the events are delivered in order from the event loop, - * the scope of objects pointed to by \p data or \p aux may exceed the lifetime - * of the thing containing the pointed-to data. So it's usually better to pass - * values here. - */ -LWS_VISIBLE LWS_EXTERN int -lws_seq_queue_event(struct lws_sequencer *seq, lws_seq_events_t e, void *data, - void *aux); - -/** - * lws_seq_check_wsi() - check if wsi still extant - * - * \param seq: the sequencer interested in the wsi - * \param wsi: the wsi we want to confirm hasn't closed yet - * - * Check if wsi still extant, by peeking in the message queue for a - * LWSSEQ_WSI_CONN_CLOSE message about wsi. (Doesn't need to do the same for - * CONN_FAIL since that will never have produced any messages prior to that). - * - * Use this to avoid trying to perform operations on wsi that have already - * closed but we didn't get to that message yet. - * - * Returns 0 if not closed yet or 1 if it has closed but we didn't process the - * close message yet. - */ -LWS_VISIBLE LWS_EXTERN int -lws_seq_check_wsi(struct lws_sequencer *seq, struct lws *wsi); - -#define LWSSEQTO_NONE 0 - -/** - * lws_seq_timeout_us() - set a timeout by which the sequence must have - * completed by a different event or inform the - * sequencer - * - * \param seq: The sequencer to set the timeout on - * \param us: How many us in the future to fire the timeout - * LWS_SET_TIMER_USEC_CANCEL = cancel any existing timeout - * - * This api allows the sequencer to ask to be informed if it has not completed - * or disabled its timeout after secs seconds. Lws will send a LWSSEQ_TIMED_OUT - * event to the sequencer if the timeout expires. - * - * Typically the sequencer sets the timeout when starting a step, then waits to - * hear a queued event informing it the step completed or failed. The timeout - * provides a way to deal with the case the step neither completed nor failed - * within the timeout period. - * - * Lws wsi timeouts are not really suitable for this since they are focused on - * short-term protocol timeout protection and may be set and reset many times - * in one transaction. Wsi timeouts also enforce closure of the wsi when they - * trigger, sequencer timeouts have no side effect except to queue the - * LWSSEQ_TIMED_OUT message and leave it to the sequencer to decide how to - * react appropriately. - */ -LWS_VISIBLE LWS_EXTERN int -lws_seq_timeout_us(struct lws_sequencer *seq, lws_usec_t us); - -/** - * lws_seq_from_user(): get the lws_seq_t pointer from the user ptr - * - * \param u: the sequencer user allocation returned by lws_seq_create() or - * provided in the sequencer callback - * - * This gets the lws_seq_t * from the sequencer user allocation pointer. - * Actually these are allocated at the same time in one step, with the user - * allocation immediately after the lws_seq_t, so lws can compute where - * the lws_seq_t is from having the user allocation pointer. Since the - * size of the lws_seq_t is unknown to user code, this helper does it for - * you. - */ -LWS_VISIBLE LWS_EXTERN struct lws_sequencer * -lws_seq_from_user(void *u); - -/** - * lws_seq_us_since_creation(): elapsed seconds since sequencer created - * - * \param seq: pointer to the lws_seq_t - * - * Returns the number of us elapsed since the lws_seq_t was - * created. This is useful to calculate sequencer timeouts for the current - * step considering a global sequencer lifetime limit. - */ -LWS_VISIBLE LWS_EXTERN lws_usec_t -lws_seq_us_since_creation(struct lws_sequencer *seq); - -/** - * lws_seq_name(): get the name of this sequencer - * - * \param seq: pointer to the lws_seq_t - * - * Returns the name given when the sequencer was created. This is useful to - * annotate logging when then are multiple sequencers in play. - */ -LWS_VISIBLE LWS_EXTERN const char * -lws_seq_name(struct lws_sequencer *seq); - -/** - * lws_seq_get_context(): get the lws_context sequencer was created on - * - * \param seq: pointer to the lws_seq_t - * - * Returns the lws_context. Saves you having to store it if you have a seq - * pointer handy. - */ -LWS_VISIBLE LWS_EXTERN struct lws_context * -lws_seq_get_context(struct lws_sequencer *seq); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 2156979f9..20b7e50a0 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -139,9 +139,6 @@ endif() if (LWS_WITH_NETWORK) add_subdir_include_dirs(core-net) - if (LWS_WITH_ABSTRACT) - add_subdir_include_dirs(abstract) - endif() add_subdir_include_dirs(roles) endif() diff --git a/lib/abstract/CMakeLists.txt b/lib/abstract/CMakeLists.txt deleted file mode 100644 index 3496c6eea..000000000 --- a/lib/abstract/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -# -# libwebsockets - small server side websockets and web server implementation -# -# Copyright (C) 2010 - 2020 Andy Green -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -# The strategy is to only export to PARENT_SCOPE -# -# - changes to LIB_LIST -# - changes to SOURCES -# - includes via include_directories -# -# and keep everything else private - -include_directories(.) - -list(APPEND SOURCES - abstract/abstract.c -) -if (LWS_WITH_SEQUENCER) - list(APPEND SOURCES - abstract/test-sequencer.c) -endif() - -list(APPEND SOURCES - abstract/transports/unit-test.c) - -#if (LWS_WITH_SMTP) -# list(APPEND SOURCES -# abstract/protocols/smtp/smtp.c -# abstract/protocols/smtp/smtp-sequencer.c -# ) -#endif() - -# -# Keep explicit parent scope exports at end -# - -exports_to_parent_scope() - diff --git a/lib/abstract/README.md b/lib/abstract/README.md deleted file mode 100644 index 865b69843..000000000 --- a/lib/abstract/README.md +++ /dev/null @@ -1,170 +0,0 @@ -# Abstract protocols and transports - -## Overview - -Until now protocol implementations in lws have been done directly -to the network-related apis inside lws. - -In an effort to separate out completely network implementation -details from protocol specification, lws now supports -"abstract protocols" and "abstract transports". - -![lws_abstract overview](/doc-assets/abstract-overview.svg) - -The concept is that the implementation is split into two separate -chunks of code hidden behind "ops" structs... the "abstract protocol" -implementation is responsible for the logical protocol operation -and reads and writes only memory buffers. - -The "abstract transport" implementation is responsible for sending -and receiving buffers on some kind of transport, and again is hidden -behind a standardized ops struct. - -In the system, both the abstract protocols and transports are -found by their name. - -An actual "connection" is created by calling a generic api -`lws_abs_bind_and_create_instance()` to instantiate the -combination of a protocol and a transport. - -This makes it possible to confidently offer the same protocol on -completely different transports, eg, like serial, or to wire -up the protocol implementation to a test jig sending canned -test vectors and confirming the response at buffer level, without -any network. The abstract protocol itself has no relationship -to the transport at all and is completely unchanged by changes -to the transport. - -In addition, generic tokens to control settings in both the -protocol and the transport are passed in at instantiation-time, -eg, controlling the IP address targeted by the transport. - -lws SMTP client support has been rewritten to use the new scheme, -and lws provides a raw socket transport built-in. - -## Public API - -The public api for defining abstract protocols and transports is -found at - - - [abstract.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/abstract/abstract.h) - - [protocols.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/abstract/protocols.h) - - [transports.h](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/abstract/transports.h) - -### `lws_abs_t` - -The main structure that defines the abstraction is `lws_abs_t`, -this is a name and then pointers to the protocol and transport, -optional tokens to control both the protocol and transport, -and pointers to private allocations for both the -protocol and transport when instantiated. - -The transport is selected using - -``` -LWS_VISIBLE LWS_EXTERN const lws_abs_transport_t * -lws_abs_transport_get_by_name(const char *name); -``` - -and similarly the protocol by - -``` -LWS_VISIBLE LWS_EXTERN const lws_abs_protocol_t * -lws_abs_protocol_get_by_name(const char *name); -``` - -At the moment only "`raw-skt`" is defined as an lws built-in, athough -you can also create your own mock transport the same way for creating -test jigs. - -|transport op|meaning| -|---|---| -|`tx()`|transmit a buffer| -|`client_conn()`|start a connection to a peer| -|`close()`|request to close the connection to a peer| -|`ask_for_writeable()`|request a `writeable()` callback when tx can be used| -|`set_timeout()`|set a timeout that will close the connection if reached| -|`state()`|check if the connection is established and can carry traffic| - -These are called by the protocol to get things done and make queries -through the abstract transport. - -|protocol op|meaning| -|---|---| -|`accept()`|The peer has accepted the transport connection| -|`rx()`|The peer has sent us some payload| -|`writeable()`|The connection to the peer can take more tx| -|`closed()`|The connection to the peer has closed| -|`heartbeat()`|Called periodically even when no network events| - -These are called by the transport to inform the protocol of events -and traffic. - -### Instantiation - -The user fills an lws_abs_t and passes a pointer to it to -`lws_abs_bind_and_create_instance()` to create an instantiation -of the protocol + transport. - -### `lws_token_map_t` - -The abstract protocol has no idea about a network or network addresses -or ports or whatever... it may not even be hooked up to one. - -If the transport it is bound to wants things like that, they are passed -in using an array of `lws_token_map_t` at instantiation time. - -For example this is passed to the raw socket protocol in the smtp client -minimal example to control where it would connect to: - -``` -static const lws_token_map_t smtp_abs_tokens[] = { -{ - .u = { .value = "127.0.0.1" }, - .name_index = LTMI_PEER_DNS_ADDRESS, -}, { - .u = { .lvalue = 25l }, - .name_index = LTMI_PEER_PORT, -}}; -``` - -## Steps for adding new abstract protocols - - - add the public header in `./include/libwebsockets/abstract/protocols/` - - add a directory under `./lib/abstract/protocols/` - - add your protocol sources in the new directory - - in CMakeLists.txt: - - add an `LWS_WITH_xxx` for your protocol - - search for "using any abstract protocol" and add your `LWS_WITH_xxx` to - the if so it also sets `LWS_WITH_ABSTRACT` if any set - - add a clause to append your source to SOURCES if `LWS_WITH_xxx` enabled - - add your `lws_abs_protocol` to the list `available_abs_protocols` in - `./lib/abstract/abstract.c` - -## Steps for adding new abstract transports - - - add the public header in `./include/libwebsockets/abstract/transports/` - - add your transport sources under `./lib/abstract/transports/` - - in CMakeLists.txt append your transport sources to SOURCES if `LWS_WITH_ABSTRACT` - and any other cmake conditionals - - add an extern for your transport `lws_protocols` in `./lib/core-net/private.h` - - add your transport `lws_protocols` to `available_abstract_protocols` in - `./lib/core-net/vhost.c` - - add your `lws_abs_transport` to the list `available_abs_transports` in - `./lib/abstract/abstract.c` - -# Protocol testing - -## unit tests - -lws features an abstract transport designed to facilitate unit testing. This -contains an lws_sequencer that performs the steps of tests involving sending the -protocol test vector buffers and confirming the response of the protocol matches -the test vectors. - -## test-sequencer - -test-sequencer is a helper that sequences running an array of unit tests and -collects the statistics and gives a PASS / FAIL result. - -See the SMTP client api test for an example of how to use. diff --git a/lib/abstract/abstract.c b/lib/abstract/abstract.c deleted file mode 100644 index cbf3db2fe..000000000 --- a/lib/abstract/abstract.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -extern const lws_abs_transport_t lws_abs_transport_cli_raw_skt, - lws_abs_transport_cli_unit_test; -#if defined(LWS_WITH_SMTP) -extern const lws_abs_protocol_t lws_abs_protocol_smtp; -#endif -#if defined(LWS_WITH_MQTT) -extern const lws_abs_protocol_t lws_abs_protocol_mqttc; -#endif - -static const lws_abs_transport_t * const available_abs_transports[] = { - &lws_abs_transport_cli_raw_skt, - &lws_abs_transport_cli_unit_test, -}; - -#if defined(LWS_WITH_ABSTRACT) -static const lws_abs_protocol_t * const available_abs_protocols[] = { -#if defined(LWS_WITH_SMTP) - &lws_abs_protocol_smtp, -#endif -#if defined(LWS_WITH_MQTT) - &lws_abs_protocol_mqttc, -#endif -}; -#endif - -const lws_abs_transport_t * -lws_abs_transport_get_by_name(const char *name) -{ - int n; - - for (n = 0; n < (int)LWS_ARRAY_SIZE(available_abs_transports); n++) - if (!strcmp(name, available_abs_transports[n]->name)) - return available_abs_transports[n]; - - lwsl_err("%s: cannot find '%s'\n", __func__, name); - - return NULL; -} - -const lws_abs_protocol_t * -lws_abs_protocol_get_by_name(const char *name) -{ -#if defined(LWS_WITH_ABSTRACT) - int n; - - for (n = 0; n < (int)LWS_ARRAY_SIZE(available_abs_protocols); n++) - if (!strcmp(name, available_abs_protocols[n]->name)) - return available_abs_protocols[n]; -#endif - lwsl_err("%s: cannot find '%s'\n", __func__, name); - - return NULL; -} - -const lws_token_map_t * -lws_abs_get_token(const lws_token_map_t *token_map, short name_index) -{ - if (!token_map) - return NULL; - - do { - if (token_map->name_index == name_index) - return token_map; - token_map++; - } while (token_map->name_index); - - return NULL; -} - -static int -lws_abstract_compare_connection(lws_abs_t *abs1, lws_abs_t *abs2) -{ - /* it has to be using the same protocol */ - if (abs1->ap != abs2->ap) - return 1; - - /* protocol has to allow some kind of binding */ - if (!abs1->ap->flags) - return 1; - - /* it has to be using the same transport */ - if (abs1->at != abs2->at) - return 1; - - /* - * The transport must feel the endpoint and conditions in use match the - * requested endpoint and conditions... and the transport type must be - * willing to allow it - */ - if (abs1->at->compare(abs1, abs2)) - return 1; - - /* - * The protocol must feel they are in compatible modes if any - * (and the protocol type must be willing to allow it) - */ - if (abs1->ap->compare(abs1, abs2)) - return 1; - - /* - * If no objection by now, we can say there's already a comparable - * connection and both the protocol and transport feel we can make - * use of it. - */ - - return 0; -} - -static int -find_compatible(struct lws_dll2 *d, void *user) -{ - lws_abs_t *ai1 = (lws_abs_t *)user, - *ai2 = lws_container_of(d, lws_abs_t, abstract_instances); - - if (!lws_abstract_compare_connection(ai1, ai2)) { - /* we can bind to it */ - lws_dll2_add_tail(&ai1->bound, &ai2->children_owner); - - return 1; - } - - return 0; -} - -lws_abs_t * -lws_abs_bind_and_create_instance(const lws_abs_t *abs) -{ - size_t size = sizeof(lws_abs_t) + abs->ap->alloc + abs->at->alloc; - lws_abs_t *ai; - int n; - - /* - * since we know we will allocate the lws_abs_t, the protocol's - * instance allocation, and the transport's instance allocation, - * we merge it into a single heap allocation - */ - ai = lws_malloc(size, "abs inst"); - if (!ai) - return NULL; - - *ai = *abs; - ai->ati = NULL; - - ai->api = (char *)ai + sizeof(lws_abs_t); - - if (!ai->ap->flags) /* protocol only understands single connections */ - goto fresh; - - lws_vhost_lock(ai->vh); /* ----------------------------------- vh { */ - - /* - * Let's have a look for any already-connected transport we can use - */ - - n = lws_dll2_foreach_safe(&ai->vh->abstract_instances_owner, ai, - find_compatible); - - lws_vhost_unlock(ai->vh); /* } vh --------------------------------- */ - - if (n) - goto vh_list_add; - - /* there's no existing connection doing what we want */ - -fresh: - - ai->ati = (char *)ai->api + abs->ap->alloc; - if (ai->at->create(ai)) { - ai->ati = NULL; - goto bail; - } - -vh_list_add: - /* add us to the vhost's dll2 of instances */ - - lws_dll2_clear(&ai->abstract_instances); - lws_dll2_add_head(&ai->abstract_instances, - &ai->vh->abstract_instances_owner); - - if (ai->ap->create(ai)) { - ai->api = NULL; - goto bail; - } - - if (ai->bound.owner) { /* we are a piggybacker */ - lws_abs_t *ai2 = lws_container_of(ai->bound.owner, lws_abs_t, - children_owner); - /* - * Provide an 'event' in the parent context to start handling - * the bind if it's otherwise idle. We give the parent abs - * because we don't know if we're "next" or whatever. Just that - * a child joined him and he should look into his child - * situation in case he was waiting for one to appear. - */ - if (ai2->ap->child_bind(ai2)) { - lwsl_info("%s: anticpated child bind fail\n", __func__); - lws_dll2_remove(&ai->bound); - - goto bail; - } - } - - return ai; - -bail: - lws_abs_destroy_instance(&ai); - - return NULL; -} - -/* - * We get called to clean up each child that was still bound to a parent - * at the time the parent is getting destroyed. - */ - -static void -__lws_abs_destroy_instance2(lws_abs_t **ai) -{ - lws_abs_t *a = *ai; - - if (a->api) - a->ap->destroy(&a->api); - if (a->ati) - a->at->destroy(&a->ati); - - lws_dll2_remove(&a->abstract_instances); - - *ai = NULL; - free(a); -} - -static int -__reap_children(struct lws_dll2 *d, void *user) -{ - lws_abs_t *ac = lws_container_of(d, lws_abs_t, bound); - - lws_dll2_foreach_safe(&ac->children_owner, NULL, __reap_children); - - /* then destroy ourselves */ - - __lws_abs_destroy_instance2(&ac); - - return 0; -} - -void -lws_abs_destroy_instance(lws_abs_t **ai) -{ - lws_abs_t *a = *ai; - - /* destroy child instances that are bound to us first... */ - - lws_vhost_lock(a->vh); /* ----------------------------------- vh { */ - - lws_dll2_foreach_safe(&a->children_owner, NULL, __reap_children); - - /* ...then destroy ourselves */ - - __lws_abs_destroy_instance2(ai); - - lws_vhost_unlock(a->vh); /* } vh --------------------------------- */ -} - -lws_abs_t * -lws_abstract_alloc(struct lws_vhost *vhost, void *user, - const char *abstract_path, const lws_token_map_t *ap_tokens, - const lws_token_map_t *at_tokens, struct lws_sequencer *seq, - void *opaque_user_data) -{ - lws_abs_t *abs = lws_zalloc(sizeof(*abs), __func__); - struct lws_tokenize ts; - lws_tokenize_elem e; - char tmp[30]; - - if (!abs) - return NULL; - - lws_tokenize_init(&ts, abstract_path, LWS_TOKENIZE_F_MINUS_NONTERM); - - e = lws_tokenize(&ts); - if (e != LWS_TOKZE_TOKEN) - goto abs_path_problem; - - if (lws_tokenize_cstr(&ts, tmp, sizeof(tmp))) - goto abs_path_problem; - - abs->ap = lws_abs_protocol_get_by_name(tmp); - if (!abs->ap) - goto abs_path_problem; - - e = lws_tokenize(&ts); - if (e != LWS_TOKZE_DELIMITER) - goto abs_path_problem; - - e = lws_tokenize(&ts); - if (e != LWS_TOKZE_TOKEN) - goto abs_path_problem; - - if (lws_tokenize_cstr(&ts, tmp, sizeof(tmp))) - goto abs_path_problem; - - abs->at = lws_abs_transport_get_by_name(tmp); - if (!abs->at) - goto abs_path_problem; - - abs->vh = vhost; - abs->ap_tokens = ap_tokens; - abs->at_tokens = at_tokens; - abs->seq = seq; - abs->opaque_user_data = opaque_user_data; - - lwsl_info("%s: allocated %s\n", __func__, abstract_path); - - return abs; - -abs_path_problem: - lwsl_err("%s: bad abs path '%s'\n", __func__, abstract_path); - lws_free_set_NULL(abs); - - return NULL; -} - -void -lws_abstract_free(lws_abs_t **pabs) -{ - if (*pabs) - lws_free_set_NULL(*pabs); -} diff --git a/lib/abstract/private-lib-abstract.h b/lib/abstract/private-lib-abstract.h deleted file mode 100644 index 0204b5032..000000000 --- a/lib/abstract/private-lib-abstract.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#if !defined(__PRIVATE_LIB_ABSTRACT_H__) -#define __PRIVATE_LIB_ABSTRACT_H__ - -typedef struct lws_token_map lws_token_map_t; -typedef void lws_abs_transport_inst_t; -typedef void lws_abs_protocol_inst_t; - -typedef struct lws_abs { - void *user; - struct lws_vhost *vh; - - const struct lws_abs_protocol *ap; - const lws_token_map_t *ap_tokens; - const struct lws_abs_transport *at; - const lws_token_map_t *at_tokens; - - struct lws_sequencer *seq; - void *opaque_user_data; - - /* vh lock */ - struct lws_dll2_owner children_owner; /* our children / queue */ - /* vh lock */ - struct lws_dll2 bound; /* parent or encapsulator */ - /* vh lock */ - struct lws_dll2 abstract_instances; - lws_abs_transport_inst_t *ati; - lws_abs_protocol_inst_t *api; -} lws_abs_t; - -#endif - diff --git a/lib/abstract/protocols/smtp/private-lib-abstract-protocols-smtp.h b/lib/abstract/protocols/smtp/private-lib-abstract-protocols-smtp.h deleted file mode 100644 index 0498e08f1..000000000 --- a/lib/abstract/protocols/smtp/private-lib-abstract-protocols-smtp.h +++ /dev/null @@ -1,24 +0,0 @@ -#define LWS_SMTP_MAX_EMAIL_LEN 32 - - -/* - * These are allocated on to the heap with an over-allocation to hold the - * payload at the end - */ - -typedef struct lws_smtp_email { - struct lws_dll2 list; - void *data; - - char from[LWS_SMTP_MAX_EMAIL_LEN]; - char to[LWS_SMTP_MAX_EMAIL_LEN]; - - time_t added; - time_t last_try; - - lws_smtp_cb_t done; - - int tries; - - /* email payload follows */ -} lws_smtp_email_t; diff --git a/lib/abstract/protocols/smtp/smtp-sequencer.c b/lib/abstract/protocols/smtp/smtp-sequencer.c deleted file mode 100644 index 24d8f44fe..000000000 --- a/lib/abstract/protocols/smtp/smtp-sequencer.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Abstract SMTP support for libwebsockets - SMTP sequencer - * - * Copyright (C) 2016-2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * This sequencer sits above the abstract protocol, and manages queueing, - * retrying mail transmission, and retry limits. - * - * Having the sequencer means that, eg, we can manage retries after complete - * connection failure. - * - * Connections to the smtp server are serialized - */ - -#include "private-lib-core.h" -#include "private-lib-abstract-protocols-smtp.h" - -typedef enum { - LSMTPSS_DISCONNECTED, - LSMTPSS_CONNECTING, - LSMTPSS_CONNECTED, - LSMTPSS_BUSY, -} smtpss_connstate_t; - -typedef struct lws_smtp_sequencer { - struct lws_dll2_owner emails_owner; /* email queue */ - - lws_abs_t *abs, *instance; - lws_smtp_sequencer_args_t args; - struct lws_sequencer *seq; - - smtpss_connstate_t connstate; - - time_t email_connect_started; - - /* holds the HELO for the smtp protocol to consume */ - lws_token_map_t apt[3]; -} lws_smtp_sequencer_t; - -/* sequencer messages specific to this sequencer */ - -enum { - SEQ_MSG_CLIENT_FAILED = LWSSEQ_USER_BASE, - SEQ_MSG_CLIENT_DONE, -}; - -/* - * We're going to bind to the raw-skt transport, so tell that what we want it - * to connect to - */ - -static const lws_token_map_t smtp_rs_transport_tokens[] = { - { - .u = { .value = "127.0.0.1" }, - .name_index = LTMI_PEER_V_DNS_ADDRESS, - }, { - .u = { .lvalue = 25 }, - .name_index = LTMI_PEER_LV_PORT, - }, { - } -}; - -static void -lws_smtpc_kick_internal(lws_smtp_sequencer_t *s) -{ - lws_smtp_email_t *e; - lws_dll2_t *d; - char buf[64]; - int n; - lws_dll2_t *pd2; - - pd2 = lws_dll2_get_head(&s->emails_owner); - if (!pd2) - return; - - e = lws_container_of(pd2, lws_smtp_email_t, list); - if (!e) - return; - - /* Is there something to do? If so, we need a connection... */ - - if (s->connstate == LSMTPSS_DISCONNECTED) { - - s->apt[0].u.value = s->args.helo; - s->apt[0].name_index = LTMI_PSMTP_V_HELO; - s->apt[1].u.value = (void *)e; - s->apt[1].name_index = LTMI_PSMTP_V_LWS_SMTP_EMAIL_T; - - /* - * create and connect the smtp protocol + transport - */ - - s->abs = lws_abstract_alloc(s->args.vhost, NULL, "smtp.raw_skt", - s->apt, smtp_rs_transport_tokens, - s->seq, NULL); - if (!s->abs) - return; - - s->instance = lws_abs_bind_and_create_instance(s->abs); - if (!s->instance) { - lws_abstract_free(&s->abs); - lwsl_err("%s: failed to create SMTP client\n", __func__); - - goto bail1; - } - - s->connstate = LSMTPSS_CONNECTING; - lws_seq_timeout_us(s->seq, 10 * LWS_USEC_PER_SEC); - return; - } - - /* ask the transport if we have a connection to the server ongoing */ - - if (s->abs->at->state(s->abs->ati)) { - /* - * there's a connection, it could be still trying to connect - * or established - */ - s->abs->at->ask_for_writeable(s->abs->ati); - - return; - } - - /* there's no existing connection */ - - lws_smtpc_state_transition(c, LGSSMTP_CONNECTING); - - if (s->abs->at->client_conn(s->abs)) { - lwsl_err("%s: failed to connect\n", __func__); - - return; - } - - e->tries++; - e->last_try = lws_now_secs(); -} - - -/* - * The callback we get from the smtp protocol... we use this to drive - * decisions about destroy email, retry and fail. - * - * Sequencer will handle it via the event loop. - */ - -static int -email_result(void *e, void *d, int disp, void *b, size_t l) -{ - lws_smtp_sequencer_t *s = (lws_smtp_sequencer_t *)d; - - lws_sequencer_event(s->seq, LWSSEQ_USER_BASE + disp, e); - - return 0; -} - -static int -cleanup(struct lws_dll2 *d, void *user) -{ - lws_smtp_email_t *e; - - e = lws_container_of(d, lws_smtp_email_t, list); - if (e->done) - e->done(e, "destroying", 10); - - lws_dll2_remove(d); - lws_free(e); - - return 0; -} - -static lws_seq_cb_return_t -smtp_sequencer_cb(struct lws_sequencer *seq, void *user, int event, void *data) -{ - struct lws_smtp_sequencer_t *s = (struct lws_smtp_sequencer_t *)user; - - switch ((int)event) { - case LWSSEQ_CREATED: /* our sequencer just got started */ - lwsl_notice("%s: %s: created\n", __func__, - lws_sequencer_name(seq)); - s->connstate = LSMTPSS_DISCONNECTED; - s->state = 0; /* first thing we'll do is the first url */ - goto step; - - case LWSSEQ_DESTROYED: - lws_dll2_foreach_safe(&s->pending_owner, NULL, cleanup); - break; - - case LWSSEQ_TIMED_OUT: - lwsl_notice("%s: LWSSEQ_TIMED_OUT\n", __func__); - break; - - case LWSSEQ_USER_BASE + LWS_SMTP_DISPOSITION_SENT: - lws_smtpc_free_email(data); - break; - - case LWSSEQ_WSI_CONNECTED: - s->connstate = LSMTPSS_CONNECTED; - lws_smtpc_kick_internal(s); - break; - - case LWSSEQ_WSI_CONN_FAIL: - case LWSSEQ_WSI_CONN_CLOSE: - s->connstate = LSMTPSS_DISCONNECTED; - lws_smtpc_kick_internal(s); - break; - - case SEQ_MSG_SENT: - break; - - default: - break; - } - - return LWSSEQ_RET_CONTINUE; -} - -/* - * Creates an lws_sequencer to manage the test sequence - */ - -lws_smtp_sequencer_t * -lws_smtp_sequencer_create(const lws_smtp_sequencer_args_t *args) -{ - lws_smtp_sequencer_t *s; - struct lws_sequencer *seq; - - /* - * Create a sequencer in the event loop to manage the SMTP queue - */ - - seq = lws_sequencer_create(args->vhost->context, 0, - sizeof(lws_smtp_sequencer_t), (void **)&s, - smtp_sequencer_cb, "smtp-seq"); - if (!seq) { - lwsl_err("%s: unable to create sequencer\n", __func__); - return NULL; - } - - s->abs = *args->abs; - s->args = *args; - s->seq = seq; - - /* set defaults in our copy of the args */ - - if (!s->args.helo[0]) - strcpy(s->args.helo, "default-helo"); - if (!s->args.email_queue_max) - s->args.email_queue_max = 8; - if (!s->args.retry_interval) - s->args.retry_interval = 15 * 60; - if (!s->args.delivery_timeout) - s->args.delivery_timeout = 12 * 60 * 60; - - return s; -} - -void -lws_smtp_sequencer_destroy(lws_smtp_sequencer_t *s) -{ - /* sequencer destruction destroys all assets */ - lws_sequencer_destroy(&s->seq); -} - -int -lws_smtpc_add_email(lws_smtp_sequencer_t *s, const char *payload, - size_t payload_len, const char *sender, - const char *recipient, void *data, lws_smtp_cb_t done) -{ - lws_smtp_email_t *e; - - if (s->emails_owner.count > s->args.email_queue_max) { - lwsl_err("%s: email queue at limit of %d\n", __func__, - (int)s->args.email_queue_max); - - return 1; - } - - if (!done) - return 1; - - e = malloc(sizeof(*e) + payload_len + 1); - if (!e) - return 1; - - memset(e, 0, sizeof(*e)); - - e->data = data; - e->done = done; - - lws_strncpy(e->from, sender, sizeof(e->from)); - lws_strncpy(e->to, recipient, sizeof(e->to)); - - memcpy((char *)&e[1], payload, payload_len + 1); - - e->added = lws_now_secs(); - e->last_try = 0; - e->tries = 0; - - lws_dll2_clear(&e->list); - lws_dll2_add_tail(&e->list, &s->emails_owner); - - lws_smtpc_kick_internal(s); - - return 0; -} diff --git a/lib/abstract/protocols/smtp/smtp.c b/lib/abstract/protocols/smtp/smtp.c deleted file mode 100644 index e0a955596..000000000 --- a/lib/abstract/protocols/smtp/smtp.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "private-lib-core.h" -#include "private-lib-abstract.h" - -/** enum lwsgs_smtp_states - where we are in SMTP protocol sequence */ -typedef enum lwsgs_smtp_states { - LGSSMTP_IDLE, /**< awaiting new email */ - LGSSMTP_CONNECTING, /**< opening tcp connection to MTA */ - LGSSMTP_CONNECTED, /**< tcp connection to MTA is connected */ - /* (server sends greeting) */ - LGSSMTP_SENT_HELO, /**< sent the HELO */ - - LGSSMTP_SENT_FROM, /**< sent FROM */ - LGSSMTP_SENT_TO, /**< sent TO */ - LGSSMTP_SENT_DATA, /**< sent DATA request */ - LGSSMTP_SENT_BODY, /**< sent the email body */ - - /* - * (server sends, eg, "250 Ok: queued as 12345") - * at this point we can return to LGSSMTP_SENT_HELO and send a - * new email, or continue below to QUIT, or just wait - */ - - LGSSMTP_SENT_QUIT, /**< sent the session quit */ - - /* (server sends, eg, "221 Bye" and closes the connection) */ -} lwsgs_smtp_states_t; - -/** abstract protocol instance data */ - -typedef struct lws_smtp_client_protocol { - const struct lws_abs *abs; - lwsgs_smtp_states_t estate; - - lws_smtp_email_t *e; /* the email we are trying to send */ - const char *helo; - - unsigned char send_pending:1; -} lws_smtpcp_t; - -static const short retcodes[] = { - 0, /* idle */ - 0, /* connecting */ - 220, /* connected */ - 250, /* helo */ - 250, /* from */ - 250, /* to */ - 354, /* data */ - 250, /* body */ - 221, /* quit */ -}; - -static void -lws_smtpc_state_transition(lws_smtpcp_t *c, lwsgs_smtp_states_t s) -{ - lwsl_debug("%s: cli %p: state %d -> %d\n", __func__, c, c->estate, s); - c->estate = s; -} - -static lws_smtp_email_t * -lws_smtpc_get_email(lws_smtpcp_t *c) -{ - const lws_token_map_t *tm; - - /* ... the email we want to send */ - tm = lws_abs_get_token(c->abs->ap_tokens, LTMI_PSMTP_V_LWS_SMTP_EMAIL_T); - if (!tm) { - assert(0); - - return NULL; - } - - return (lws_smtp_email_t *)tm->u.value; -} - -/* - * Called when something happened so that we know now the final disposition of - * the email send attempt, for good or ill. - * - * Inform the owner via the done callback and set up the next queued one if any. - * - * Returns nonzero if we queued a new one - */ - -static int -lws_smtpc_email_disposition(lws_smtpcp_t *c, int disp, const void *buf, - size_t len) -{ - lws_smtpcp_t *ch; - lws_abs_t *ach; - lws_dll2_t *d; - - lws_smtpc_state_transition(c, LGSSMTP_SENT_HELO); - - /* lifetime of the email object is handled by done callback */ - c->e->done(c->e, c->e->data, disp, buf, len); - c->e = NULL; - - /* this may not be the time to try to send anything else... */ - - if (disp == LWS_SMTP_DISPOSITION_FAILED_DESTROY) - return 0; - - /* ... otherwise... do we have another queued? */ - - d = lws_dll2_get_tail(&c->abs->children_owner); - if (!d) - return 0; - - ach = lws_container_of(d, lws_abs_t, bound); - ch = (lws_smtpcp_t *)ach->api; - - c->e = lws_smtpc_get_email(ch); - - /* since we took it on, remove it from the queue */ - lws_dll2_remove(d); - - return 1; -} - -/* - * we became connected - */ - -static int -lws_smtpc_abs_accept(lws_abs_protocol_inst_t *api) -{ - lws_smtpcp_t *c = (lws_smtpcp_t *)api; - - /* we have become connected in the tcp sense */ - - lws_smtpc_state_transition(c, LGSSMTP_CONNECTED); - - /* - * From the accept(), the next thing that should happen is the SMTP - * server sends its greeting like "220 smtp2.example.com ESMTP Postfix", - * we'll hear about it in the rx callback, or time out - */ - - c->abs->at->set_timeout(c->abs->ati, - PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, 3); - - return 0; -} - -static int -lws_smtpc_abs_rx(lws_abs_protocol_inst_t *api, const uint8_t *buf, size_t len) -{ - lws_smtpcp_t *c = (lws_smtpcp_t *)api; - char dotstar[96], at[5]; - int n; - - c->abs->at->set_timeout(c->abs->ati, NO_PENDING_TIMEOUT, 0); - - lws_strncpy(at, (const char *)buf, sizeof(at)); - n = atoi(at); - - switch (c->estate) { - case LGSSMTP_CONNECTED: - if (n != 220) { - /* - * The server did not properly greet us... we can't - * even get started, so fail the transport connection - * (and anything queued on it) - */ - - lws_strnncpy(dotstar, (const char *)buf, len, sizeof(dotstar)); - lwsl_err("%s: server: %s\n", __func__, dotstar); - - return 1; - } - break; - - case LGSSMTP_SENT_BODY: - /* - * We finished one way or another... let's prepare to send a - * new one... or wait until server hangs up on us - */ - if (!lws_smtpc_email_disposition(c, - n == 250 ? LWS_SMTP_DISPOSITION_SENT : - LWS_SMTP_DISPOSITION_FAILED, - "destroyed", 0)) - return 0; /* become idle */ - - break; /* ask to send */ - - case LGSSMTP_SENT_QUIT: - lwsl_debug("%s: done\n", __func__); - lws_smtpc_state_transition(c, LGSSMTP_IDLE); - - return 1; - - default: - if (n != retcodes[c->estate]) { - lws_strnncpy(dotstar, buf, len, sizeof(dotstar)); - lwsl_notice("%s: bad response: %d (state %d) %s\n", - __func__, n, c->estate, dotstar); - - lws_smtpc_email_disposition(c, - LWS_SMTP_DISPOSITION_FAILED, buf, len); - - return 0; - } - break; - } - - c->send_pending = 1; - c->abs->at->ask_for_writeable(c->abs->ati); - - return 0; -} - -static int -lws_smtpc_abs_writeable(lws_abs_protocol_inst_t *api, size_t budget) -{ - char b[256 + LWS_PRE], *p = b + LWS_PRE; - lws_smtpcp_t *c = (lws_smtpcp_t *)api; - int n; - - if (!c->send_pending || !c->e) - return 0; - - c->send_pending = 0; - - lwsl_debug("%s: writing response for state %d\n", __func__, c->estate); - - switch (c->estate) { - case LGSSMTP_CONNECTED: - n = lws_snprintf(p, sizeof(b) - LWS_PRE, "HELO %s\n", c->helo); - lws_smtpc_state_transition(c, LGSSMTP_SENT_HELO); - break; - - case LGSSMTP_SENT_HELO: - n = lws_snprintf(p, sizeof(b) - LWS_PRE, "MAIL FROM: <%s>\n", - c->e->from); - lws_smtpc_state_transition(c, LGSSMTP_SENT_FROM); - break; - - case LGSSMTP_SENT_FROM: - n = lws_snprintf(p, sizeof(b) - LWS_PRE, - "RCPT TO: <%s>\n", c->e->to); - lws_smtpc_state_transition(c, LGSSMTP_SENT_TO); - break; - - case LGSSMTP_SENT_TO: - n = lws_snprintf(p, sizeof(b) - LWS_PRE, "DATA\n"); - lws_smtpc_state_transition(c, LGSSMTP_SENT_DATA); - break; - - case LGSSMTP_SENT_DATA: - p = (char *)&c->e[1]; - n = strlen(p); - lws_smtpc_state_transition(c, LGSSMTP_SENT_BODY); - break; - - case LGSSMTP_SENT_BODY: - n = lws_snprintf(p, sizeof(b) - LWS_PRE, "quit\n"); - lws_smtpc_state_transition(c, LGSSMTP_SENT_QUIT); - break; - - case LGSSMTP_SENT_QUIT: - return 0; - - default: - return 0; - } - - //puts(p); - c->abs->at->tx(c->abs->ati, (uint8_t *)p, n); - - return 0; -} - -static int -lws_smtpc_abs_closed(lws_abs_protocol_inst_t *api) -{ - lws_smtpcp_t *c = (lws_smtpcp_t *)api; - - if (c) - lws_smtpc_state_transition(c, LGSSMTP_IDLE); - - return 0; -} - -/* - * Creating for initial transport and for piggybacking on another transport - * both get created here the same. But piggybackers have ai->bound attached. - */ - -static int -lws_smtpc_create(const lws_abs_t *ai) -{ - lws_smtpcp_t *c = (lws_smtpcp_t *)ai->api; - - memset(c, 0, sizeof(*c)); - - c->abs = ai; - c->e = lws_smtpc_get_email(c); - - lws_smtpc_state_transition(c, lws_dll2_is_detached(&ai->bound) ? - LGSSMTP_CONNECTING : LGSSMTP_IDLE); - - /* If we are initiating the transport, we will get an accept() next... - * - * If we are piggybacking, the parent will get a .child_bind() after - * this to give it a chance to act on us joining (eg, it was completely - * idle and we joined). - */ - - return 0; -} - -static void -lws_smtpc_destroy(lws_abs_protocol_inst_t **_c) -{ - lws_smtpcp_t *c = (lws_smtpcp_t *)*_c; - - if (!c) - return; - - /* so if we are still holding on to c->e, we have failed to send it */ - if (c->e) - lws_smtpc_email_disposition(c, - LWS_SMTP_DISPOSITION_FAILED_DESTROY, "destroyed", 0); - - *_c = NULL; -} - -static int -lws_smtpc_compare(lws_abs_t *abs1, lws_abs_t *abs2) -{ - return 0; -} - -static int -lws_smtpc_child_bind(lws_abs_t *abs) -{ - return 0; -} - -/* events the transport invokes (handled by abstract protocol) */ - -const lws_abs_protocol_t lws_abs_protocol_smtp = { - .name = "smtp", - .alloc = sizeof(lws_smtpcp_t), - .flags = LWSABSPR_FLAG_PIPELINE, - - .create = lws_smtpc_create, - .destroy = lws_smtpc_destroy, - .compare = lws_smtpc_compare, - - .accept = lws_smtpc_abs_accept, - .rx = lws_smtpc_abs_rx, - .writeable = lws_smtpc_abs_writeable, - .closed = lws_smtpc_abs_closed, - .heartbeat = NULL, - - .child_bind = lws_smtpc_child_bind, -}; diff --git a/lib/abstract/test-sequencer.c b/lib/abstract/test-sequencer.c deleted file mode 100644 index c4fa67750..000000000 --- a/lib/abstract/test-sequencer.c +++ /dev/null @@ -1,274 +0,0 @@ - /* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * A helper for running multiple unit tests against abstract protocols. - * - * An lws_seq_t is used to base its actions in the event loop and manage - * the sequencing of multiple tests. A new abstract connection is instantiated - * for each test using te - */ - -#include - -struct lws_seq_test_sequencer { - lws_abs_t original_abs; - - lws_test_sequencer_args_t args; - - struct lws_context *context; - struct lws_vhost *vhost; - struct lws_sequencer *unit_test_seq; - - /* holds the per-test token for the unit-test transport to consume */ - lws_token_map_t uttt[4]; - - lws_abs_t *instance; - - int state; -}; - -/* sequencer messages specific to this sequencer */ - -enum { - SEQ_MSG_PASS = LWSSEQ_USER_BASE, - SEQ_MSG_FAIL, - SEQ_MSG_FAIL_TIMEOUT, -}; - -/* - * We get called back when the unit test transport has decided if the test - * passed or failed. We get the priv, and report to the sequencer message queue - * what the result was. - */ - -static int -unit_test_result_cb(const void *cb_user, int disposition) -{ - const struct lws_seq_test_sequencer *s = - (const struct lws_seq_test_sequencer *)cb_user; - int r; - - lwsl_debug("%s: disp %d\n", __func__, disposition); - - switch (disposition) { - case LPE_FAILED_UNEXPECTED_PASS: - case LPE_FAILED_UNEXPECTED_CLOSE: - case LPE_FAILED: - r = SEQ_MSG_FAIL; - break; - - case LPE_FAILED_UNEXPECTED_TIMEOUT: - r = SEQ_MSG_FAIL_TIMEOUT; - break; - - case LPE_SUCCEEDED: - r = SEQ_MSG_PASS; - break; - - default: - assert(0); - return -1; - } - - lws_seq_queue_event(s->unit_test_seq, r, NULL, NULL); - - ((struct lws_seq_test_sequencer *)s)->instance = NULL; - - return 0; -} - -/* - * We receive the unit test result callback's messages via the message queue. - * - * We log the results and always move on to the next test until there are no - * more tests. - */ - -static lws_seq_cb_return_t -test_sequencer_cb(struct lws_sequencer *seq, void *user, int event, void *data, - void *aux) -{ - struct lws_seq_test_sequencer *s = - (struct lws_seq_test_sequencer *)user; - lws_unit_test_packet_t *exp = (lws_unit_test_packet_t *) - s->args.tests[s->state].expect_array; - lws_abs_t test_abs; - - switch ((int)event) { - case LWSSEQ_CREATED: /* our sequencer just got started */ - lwsl_notice("%s: %s: created\n", __func__, - lws_seq_name(seq)); - s->state = 0; /* first thing we'll do is the first url */ - goto step; - - case LWSSEQ_DESTROYED: - /* - * We are going down... if we have a child unit test sequencer - * still around inform and destroy it - */ - if (s->instance) { - s->instance->at->close(s->instance); - s->instance = NULL; - } - break; - - case SEQ_MSG_FAIL_TIMEOUT: /* current step timed out */ - if (exp->flags & LWS_AUT_EXPECT_SHOULD_TIMEOUT) { - lwsl_user("%s: test %d got expected timeout\n", - __func__, s->state); - - goto pass; - } - lwsl_user("%s: seq timed out at step %d\n", __func__, s->state); - - s->args.results[s->state] = LPE_FAILED_UNEXPECTED_TIMEOUT; - goto done; /* always move on to the next test */ - - case SEQ_MSG_FAIL: - if (exp->flags & LWS_AUT_EXPECT_SHOULD_FAIL) { - /* - * in this case, we expected to fail like this, it's OK - */ - lwsl_user("%s: test %d failed as expected\n", - __func__, s->state); - - goto pass; /* always move on to the next test */ - } - - lwsl_user("%s: seq failed at step %d\n", __func__, s->state); - - s->args.results[s->state] = LPE_FAILED; - goto done; /* always move on to the next test */ - - case SEQ_MSG_PASS: - if (exp->flags & (LWS_AUT_EXPECT_SHOULD_FAIL | - LWS_AUT_EXPECT_SHOULD_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); - - s->args.results[s->state] = LPE_FAILED_UNEXPECTED_PASS; - - goto done; /* always move on to the next test */ - } - lwsl_info("%s: seq done test %d\n", __func__, s->state); -pass: - (*s->args.count_passes)++; - s->args.results[s->state] = LPE_SUCCEEDED; - -done: - lws_seq_timeout_us(lws_seq_from_user(s), LWSSEQTO_NONE); - s->state++; -step: - if (!s->args.tests[s->state].name) { - /* the sequence has completed */ - lwsl_user("%s: sequence completed OK\n", __func__); - - if (s->args.cb) - s->args.cb(s->args.cb_user); - - return LWSSEQ_RET_DESTROY; - } - lwsl_info("%s: starting test %d\n", __func__, s->state); - - if (s->state >= s->args.results_max) { - lwsl_err("%s: results array is too small\n", __func__); - - return LWSSEQ_RET_DESTROY; - } - test_abs = s->original_abs; - s->uttt[0].name_index = LTMI_PEER_V_EXPECT_TEST; - s->uttt[0].u.value = (void *)&s->args.tests[s->state]; - s->uttt[1].name_index = LTMI_PEER_V_EXPECT_RESULT_CB; - s->uttt[1].u.value = (void *)unit_test_result_cb; - s->uttt[2].name_index = LTMI_PEER_V_EXPECT_RESULT_CB_ARG; - s->uttt[2].u.value = (void *)s; - /* give the unit test transport the test tokens */ - test_abs.at_tokens = s->uttt; - - s->instance = lws_abs_bind_and_create_instance(&test_abs); - if (!s->instance) { - lwsl_notice("%s: failed to create step %d unit test\n", - __func__, s->state); - - return LWSSEQ_RET_DESTROY; - } - (*s->args.count_tests)++; - break; - - default: - break; - } - - return LWSSEQ_RET_CONTINUE; -} - - -/* - * Creates an lws_sequencer to manage the test sequence - */ - -int -lws_abs_unit_test_sequencer(const lws_test_sequencer_args_t *args) -{ - struct lws_seq_test_sequencer *s; - struct lws_sequencer *seq; - lws_seq_info_t i; - - memset(&i, 0, sizeof(i)); - i.context = args->abs->vh->context; - i.user_size = sizeof(struct lws_seq_test_sequencer); - i.puser = (void **)&s; - i.cb = test_sequencer_cb; - i.name = "test-seq"; - - /* - * Create a sequencer in the event loop to manage the tests - */ - - seq = lws_seq_create(&i); - if (!seq) { - lwsl_err("%s: unable to create sequencer\n", __func__); - return 1; - } - - /* - * Take a copy of the original lws_abs_t we were passed so we can use - * it as the basis of the lws_abs_t we create the individual tests with - */ - s->original_abs = *args->abs; - - s->args = *args; - - s->context = args->abs->vh->context; - s->vhost = args->abs->vh; - s->unit_test_seq = seq; - - *s->args.count_tests = 0; - *s->args.count_passes = 0; - - return 0; -} diff --git a/lib/abstract/transports/raw-skt.c b/lib/abstract/transports/raw-skt.c deleted file mode 100644 index fec2db73a..000000000 --- a/lib/abstract/transports/raw-skt.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "private-lib-core.h" -#include "private-lib-abstract.h" - -typedef struct lws_abstxp_raw_skt_priv { - struct lws_abs *abs; - struct lws *wsi; - - lws_dll2_t same_abs_transport_list; - - uint8_t established:1; - uint8_t connecting:1; -} abs_raw_skt_priv_t; - -struct vhd { - lws_dll2_owner_t owner; -}; - -static int -heartbeat_cb(struct lws_dll2 *d, void *user) -{ - abs_raw_skt_priv_t *priv = lws_container_of(d, abs_raw_skt_priv_t, - same_abs_transport_list); - - if (priv->abs->ap->heartbeat) - priv->abs->ap->heartbeat(priv->abs->api); - - return 0; -} - -static int -callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)user; - struct vhd *vhd = (struct vhd *) - lws_protocol_vh_priv_get(lws_get_vhost(wsi), - lws_get_protocol(wsi)); - - switch (reason) { - case LWS_CALLBACK_PROTOCOL_INIT: - vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), - lws_get_protocol(wsi), sizeof(struct vhd)); - if (!vhd) - return 1; - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 1); - break; - - case LWS_CALLBACK_USER: - /* - * This comes at 1Hz without a wsi context, so there is no - * valid priv. We need to track the live abstract objects that - * are using our abstract protocol, and pass the heartbeat - * through to the ones that care. - */ - if (!vhd) - break; - - lws_dll2_foreach_safe(&vhd->owner, NULL, heartbeat_cb); - - lws_timed_callback_vh_protocol(lws_get_vhost(wsi), - lws_get_protocol(wsi), - LWS_CALLBACK_USER, 1); - break; - - case LWS_CALLBACK_RAW_CONNECTED: - lwsl_debug("LWS_CALLBACK_RAW_CONNECTED\n"); - priv->connecting = 0; - priv->established = 1; - if (priv->abs->ap->accept) - priv->abs->ap->accept(priv->abs->api); - if (wsi->seq) - /* - * we are bound to a sequencer who wants to know about - * our lifecycle events - */ - - lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONNECTED, - wsi, NULL); - break; - - case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: - lwsl_user("CONNECTION_ERROR\n"); - if (in) - lwsl_user(" %s\n", (const char *)in); - - if (wsi->seq) - /* - * we are bound to a sequencer who wants to know about - * our lifecycle events - */ - - lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONN_FAIL, - wsi, NULL); - - goto close_path; - - /* fallthru */ - case LWS_CALLBACK_RAW_CLOSE: - if (!user) - break; - - if (wsi->seq) - /* - * we are bound to a sequencer who wants to know about - * our lifecycle events - */ - - lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONN_CLOSE, - wsi, NULL); - -close_path: - lwsl_debug("LWS_CALLBACK_RAW_CLOSE\n"); - priv->established = 0; - priv->connecting = 0; - if (priv->abs && priv->abs->ap->closed) - priv->abs->ap->closed(priv->abs->api); - lws_set_wsi_user(wsi, NULL); - break; - - case LWS_CALLBACK_RAW_RX: - lwsl_debug("LWS_CALLBACK_RAW_RX (%d)\n", (int)len); - return !!priv->abs->ap->rx(priv->abs->api, in, len); - - case LWS_CALLBACK_RAW_WRITEABLE: - lwsl_debug("LWS_CALLBACK_RAW_WRITEABLE\n"); - priv->abs->ap->writeable(priv->abs->api, - lws_get_peer_write_allowance(priv->wsi)); - break; - - case LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL: - lws_dll2_add_tail(&priv->same_abs_transport_list, &vhd->owner); - break; - - case LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL: - lws_dll2_remove(&priv->same_abs_transport_list); - break; - - default: - break; - } - - return 0; -} - -static int -lws_atcrs_close(lws_abs_transport_inst_t *ati) -{ - abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati; - struct lws *wsi = priv->wsi; - - if (!priv->wsi) - return 0; - - if (!lws_raw_transaction_completed(priv->wsi)) - return 0; - - priv->wsi = NULL; - lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC); - - /* priv is destroyed in the CLOSE callback */ - - return 0; -} - - -const struct lws_protocols protocol_abs_client_raw_skt = { - "lws-abs-cli-raw-skt", callback_abs_client_raw_skt, - 0, 1024, 1024, NULL, 0 -}; - -static int -lws_atcrs_tx(lws_abs_transport_inst_t *ati, uint8_t *buf, size_t len) -{ - abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati; - - if (!priv->wsi) { - lwsl_err("%s: NULL priv->wsi\n", __func__); - return 1; - } - - lwsl_debug("%s: priv %p, wsi %p, ro %p\n", __func__, - priv, priv->wsi, priv->wsi->role_ops); - - if (lws_write(priv->wsi, buf, len, LWS_WRITE_RAW) < 0) - lws_atcrs_close(ati); - - return 0; -} - -#if defined(LWS_WITH_CLIENT) -static int -lws_atcrs_client_conn(const lws_abs_t *abs) -{ - abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)abs->ati; - struct lws_client_connect_info i; - const lws_token_map_t *tm; - - if (priv->connecting) - return 0; - - if (priv->established) { - lws_set_timeout(priv->wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5); - - return 0; - } - - memset(&i, 0, sizeof(i)); - - /* address and port are passed-in using the abstract transport tokens */ - - tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_V_DNS_ADDRESS); - if (!tm) { - lwsl_notice("%s: raw_skt needs LTMI_PEER_V_DNS_ADDRESS\n", - __func__); - - return 1; - } - i.address = tm->u.value; - - tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_LV_PORT); - if (!tm) { - lwsl_notice("%s: raw_skt needs LTMI_PEER_LV_PORT\n", __func__); - - return 1; - } - i.port = tm->u.lvalue; - - /* optional */ - i.ssl_connection = 0; - tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_LV_TLS_FLAGS); - if (tm) - i.ssl_connection = tm->u.lvalue; - - - lwsl_debug("%s: raw_skt priv %p connecting to %s:%u %p\n", - __func__, priv, i.address, i.port, abs->vh->context); - - i.path = ""; - i.method = "RAW"; - i.vhost = abs->vh; - i.userdata = priv; - i.host = i.address; - i.pwsi = &priv->wsi; - i.origin = i.address; - i.context = abs->vh->context; - i.local_protocol_name = "lws-abs-cli-raw-skt"; - i.seq = abs->seq; - i.opaque_user_data = abs->opaque_user_data; - - /* - * the protocol itself has some natural attributes we should pass on - */ - - if (abs->ap->flags & LWS_AP_FLAG_PIPELINE_TRANSACTIONS) - i.ssl_connection |= LCCSCF_PIPELINE; - - if (abs->ap->flags & LWS_AP_FLAG_MUXABLE_STREAM) - i.ssl_connection |= LCCSCF_MUXABLE_STREAM; - - priv->wsi = lws_client_connect_via_info(&i); - if (!priv->wsi) - return 1; - - priv->connecting = 1; - - return 0; -} -#endif - -static int -lws_atcrs_ask_for_writeable(lws_abs_transport_inst_t *ati) -{ - abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati; - - if (!priv->wsi || !priv->established) - return 1; - - lws_callback_on_writable(priv->wsi); - - return 0; -} - -static int -lws_atcrs_create(struct lws_abs *ai) -{ - abs_raw_skt_priv_t *at = (abs_raw_skt_priv_t *)ai->ati; - - memset(at, 0, sizeof(*at)); - at->abs = ai; - - return 0; -} - -static void -lws_atcrs_destroy(lws_abs_transport_inst_t **pati) -{ - /* - * For ourselves, we don't free anything because the abstract layer - * combined our allocation with that of the abs instance, and it will - * free the whole thing after this. - */ - *pati = NULL; -} - -static int -lws_atcrs_set_timeout(lws_abs_transport_inst_t *ati, int reason, int secs) -{ - abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati; - - lws_set_timeout(priv->wsi, reason, secs); - - return 0; -} - -static int -lws_atcrs_state(lws_abs_transport_inst_t *ati) -{ - abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati; - - if (!priv || !priv->wsi || (!priv->established && !priv->connecting)) - return 0; - - return 1; -} - -static int -lws_atcrs_compare(lws_abs_t *abs1, lws_abs_t *abs2) -{ - const lws_token_map_t *tm1, *tm2; - - tm1 = lws_abs_get_token(abs1->at_tokens, LTMI_PEER_V_DNS_ADDRESS); - tm2 = lws_abs_get_token(abs2->at_tokens, LTMI_PEER_V_DNS_ADDRESS); - - /* Address token is mandatory and must match */ - if (!tm1 || !tm2 || strcmp(tm1->u.value, tm2->u.value)) - return 1; - - /* Port token is mandatory and must match */ - tm1 = lws_abs_get_token(abs1->at_tokens, LTMI_PEER_LV_PORT); - tm2 = lws_abs_get_token(abs2->at_tokens, LTMI_PEER_LV_PORT); - if (!tm1 || !tm2 || tm1->u.lvalue != tm2->u.lvalue) - return 1; - - /* TLS is optional... */ - tm1 = lws_abs_get_token(abs1->at_tokens, LTMI_PEER_LV_TLS_FLAGS); - tm2 = lws_abs_get_token(abs2->at_tokens, LTMI_PEER_LV_TLS_FLAGS); - - /* ... but both must have the same situation with it given or not... */ - if (!!tm1 != !!tm2) - return 1; - - /* if not using TLS, then that's enough to call it */ - if (!tm1) - return 0; - - /* ...and if there are tls flags, both must have the same tls flags */ - if (tm1->u.lvalue != tm2->u.lvalue) - return 1; - - /* ... and both must use the same client tls ctx / vhost */ - return abs1->vh != abs2->vh; -} - -const lws_abs_transport_t lws_abs_transport_cli_raw_skt = { - .name = "raw_skt", - .alloc = sizeof(abs_raw_skt_priv_t), - - .create = lws_atcrs_create, - .destroy = lws_atcrs_destroy, - .compare = lws_atcrs_compare, - - .tx = lws_atcrs_tx, -#if !defined(LWS_WITH_CLIENT) - .client_conn = NULL, -#else - .client_conn = lws_atcrs_client_conn, -#endif - .close = lws_atcrs_close, - .ask_for_writeable = lws_atcrs_ask_for_writeable, - .set_timeout = lws_atcrs_set_timeout, - .state = lws_atcrs_state, -}; diff --git a/lib/abstract/transports/unit-test.c b/lib/abstract/transports/unit-test.c deleted file mode 100644 index 25052d815..000000000 --- a/lib/abstract/transports/unit-test.c +++ /dev/null @@ -1,540 +0,0 @@ - /* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * An abstract transport that is useful for unit testing an abstract protocol. - * It doesn't actually connect to anything, but checks the protocol's response - * to provided canned packets from an array of test vectors. - */ - -#include "private-lib-core.h" -#include "private-lib-abstract.h" - -/* this is the transport priv instantiated at abs->ati */ - -typedef struct lws_abstxp_unit_test_priv { - char note[128]; - struct lws_abs *abs; - - struct lws_sequencer *seq; - lws_unit_test_t *current_test; - lws_unit_test_packet_t *expect; - lws_unit_test_packet_test_cb result_cb; - const void *result_cb_arg; - - lws_unit_test_packet_disposition disposition; - /* synthesized protocol timeout */ - time_t timeout; - - uint8_t established:1; - uint8_t connecting:1; -} abs_unit_test_priv_t; - -typedef struct seq_priv { - lws_abs_t *ai; -} seq_priv_t; - -enum { - UTSEQ_MSG_WRITEABLE = LWSSEQ_USER_BASE, - UTSEQ_MSG_CLOSING, - UTSEQ_MSG_TIMEOUT, - UTSEQ_MSG_CONNECTING, - UTSEQ_MSG_POST_TX_KICK, - UTSEQ_MSG_DISPOSITION_KNOWN -}; - -/* - * A definitive result has appeared for the current test - */ - -static lws_unit_test_packet_disposition -lws_unit_test_packet_dispose(abs_unit_test_priv_t *priv, - lws_unit_test_packet_disposition disp, - const char *note) -{ - assert(priv->disposition == LPE_CONTINUE); - - lwsl_info("%s: %d\n", __func__, disp); - - if (note) - lws_strncpy(priv->note, note, sizeof(priv->note)); - - priv->disposition = disp; - - lws_seq_queue_event(priv->seq, UTSEQ_MSG_DISPOSITION_KNOWN, - NULL, NULL); - - return disp; -} - -/* - * start on the next step of the test - */ - -lws_unit_test_packet_disposition -process_expect(abs_unit_test_priv_t *priv) -{ - assert(priv->disposition == LPE_CONTINUE); - - while (priv->expect->flags & LWS_AUT_EXPECT_RX && - priv->disposition == LPE_CONTINUE) { - int f = priv->expect->flags & LWS_AUT_EXPECT_LOCAL_CLOSE, s; - - if (priv->expect->pre) - priv->expect->pre(priv->abs); - - lwsl_info("%s: rx()\n", __func__); - lwsl_hexdump_debug(priv->expect->buffer, priv->expect->len); - s = priv->abs->ap->rx(priv->abs->api, priv->expect->buffer, - priv->expect->len); - - if (!!f != !!s) { - lwsl_notice("%s: expected rx return %d, got %d\n", - __func__, !!f, s); - - return lws_unit_test_packet_dispose(priv, LPE_FAILED, - "rx unexpected return"); - } - - if (priv->expect->flags & LWS_AUT_EXPECT_TEST_END) { - lws_unit_test_packet_dispose(priv, LPE_SUCCEEDED, NULL); - break; - } - - priv->expect++; - } - - return LPE_CONTINUE; -} - -static lws_seq_cb_return_t -unit_test_sequencer_cb(struct lws_sequencer *seq, void *user, int event, - void *data, void *aux) -{ - seq_priv_t *s = (seq_priv_t *)user; - abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)s->ai->ati; - time_t now; - - switch ((int)event) { - case LWSSEQ_CREATED: /* our sequencer just got started */ - lwsl_notice("%s: %s: created\n", __func__, - lws_seq_name(seq)); - if (s->ai->at->client_conn(s->ai)) { - lwsl_notice("%s: %s: abstract client conn failed\n", - __func__, lws_seq_name(seq)); - - return LWSSEQ_RET_DESTROY; - } - break; - - case LWSSEQ_DESTROYED: - /* - * This sequencer is about to be destroyed. If we have any - * other assets in play, detach them from us. - */ - - if (priv->abs) - lws_abs_destroy_instance(&priv->abs); - - break; - - case LWSSEQ_HEARTBEAT: - - /* synthesize a wsi-style timeout */ - - if (!priv->timeout) - goto ph; - - time(&now); - - if (now <= priv->timeout) - goto ph; - - if (priv->expect->flags & LWS_AUT_EXPECT_SHOULD_TIMEOUT) { - lwsl_user("%s: test got expected timeout\n", - __func__); - lws_unit_test_packet_dispose(priv, - LPE_FAILED_UNEXPECTED_TIMEOUT, NULL); - - return LWSSEQ_RET_DESTROY; - } - lwsl_user("%s: seq timed out\n", __func__); - -ph: - if (priv->abs->ap->heartbeat) - priv->abs->ap->heartbeat(priv->abs->api); - break; - - case UTSEQ_MSG_DISPOSITION_KNOWN: - - lwsl_info("%s: %s: DISPOSITION_KNOWN %s: %s\n", __func__, - priv->abs->ap->name, - priv->current_test->name, - priv->disposition == LPE_SUCCEEDED ? "OK" : "FAIL"); - - /* - * if the test has a callback, call it back to let it - * know the result - */ - if (priv->result_cb) - priv->result_cb(priv->result_cb_arg, priv->disposition); - - return LWSSEQ_RET_DESTROY; - - case UTSEQ_MSG_CONNECTING: - lwsl_debug("UTSEQ_MSG_CONNECTING\n"); - - if (priv->abs->ap->accept) - priv->abs->ap->accept(priv->abs->api); - - priv->established = 1; - - /* fallthru */ - - case UTSEQ_MSG_POST_TX_KICK: - if (priv->disposition) - break; - - if (process_expect(priv) != LPE_CONTINUE) { - lwsl_notice("%s: UTSEQ_MSG_POST_TX_KICK failed\n", - __func__); - return LWSSEQ_RET_DESTROY; - } - break; - - case UTSEQ_MSG_WRITEABLE: - /* - * inform the protocol our transport is writeable now - */ - priv->abs->ap->writeable(priv->abs->api, 1024); - break; - - case UTSEQ_MSG_CLOSING: - - if (!(priv->expect->flags & LWS_AUT_EXPECT_LOCAL_CLOSE)) { - lwsl_user("%s: got unexpected close\n", __func__); - - lws_unit_test_packet_dispose(priv, - LPE_FAILED_UNEXPECTED_CLOSE, NULL); - goto done; - } - - /* tell the abstract protocol we are closing on them */ - - if (priv->abs && priv->abs->ap->closed) - priv->abs->ap->closed(priv->abs->api); - - goto done; - - case UTSEQ_MSG_TIMEOUT: /* current step timed out */ - - s->ai->at->close(s->ai->ati); - - if (!(priv->expect->flags & LWS_AUT_EXPECT_SHOULD_TIMEOUT)) { - lwsl_user("%s: got unexpected timeout\n", __func__); - - lws_unit_test_packet_dispose(priv, - LPE_FAILED_UNEXPECTED_TIMEOUT, NULL); - return LWSSEQ_RET_DESTROY; - } - goto done; - -done: - lws_seq_timeout_us(lws_seq_from_user(s), - LWSSEQTO_NONE); - priv->expect++; - if (!priv->expect->buffer) { - /* the sequence has completed */ - lwsl_user("%s: sequence completed OK\n", __func__); - - return LWSSEQ_RET_DESTROY; - } - break; - - default: - break; - } - - return LWSSEQ_RET_CONTINUE; -} - -static int -lws_atcut_close(lws_abs_transport_inst_t *ati) -{ - abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)ati; - - lwsl_notice("%s\n", __func__); - - lws_seq_queue_event(priv->seq, UTSEQ_MSG_CLOSING, NULL, NULL); - - return 0; -} - -static int -lws_atcut_tx(lws_abs_transport_inst_t *ati, uint8_t *buf, size_t len) -{ - abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)ati; - - assert(priv->disposition == LPE_CONTINUE); - - lwsl_info("%s: received tx\n", __func__); - - if (priv->expect->pre) - priv->expect->pre(priv->abs); - - if (!(priv->expect->flags & LWS_AUT_EXPECT_TX)) { - lwsl_notice("%s: unexpected tx\n", __func__); - lwsl_hexdump_notice(buf, len); - lws_unit_test_packet_dispose(priv, LPE_FAILED, "unexpected tx"); - - return 1; - } - - if (len != priv->expect->len) { - lwsl_notice("%s: unexpected tx len %zu, expected %zu\n", - __func__, len, priv->expect->len); - lws_unit_test_packet_dispose(priv, LPE_FAILED, - "tx len mismatch"); - - return 1; - } - - if (memcmp(buf, priv->expect->buffer, len)) { - lwsl_notice("%s: tx mismatch (exp / actual)\n", __func__); - lwsl_hexdump_debug(priv->expect->buffer, len); - lwsl_hexdump_debug(buf, len); - lws_unit_test_packet_dispose(priv, LPE_FAILED, - "tx data mismatch"); - - return 1; - } - - if (priv->expect->flags & LWS_AUT_EXPECT_TEST_END) { - lws_unit_test_packet_dispose(priv, LPE_SUCCEEDED, NULL); - - return 1; - } - - priv->expect++; - - lws_seq_queue_event(priv->seq, UTSEQ_MSG_POST_TX_KICK, NULL, NULL); - - return 0; -} - -#if defined(LWS_WITH_CLIENT) -static int -lws_atcut_client_conn(const lws_abs_t *abs) -{ - abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)abs->ati; - const lws_token_map_t *tm; - - if (priv->established) { - lwsl_err("%s: already established\n", __func__); - return 1; - } - - /* set up the test start pieces... the array of test expects... */ - - tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_V_EXPECT_TEST); - if (!tm) { - lwsl_notice("%s: unit_test needs LTMI_PEER_V_EXPECT_TEST\n", - __func__); - - return 1; - } - priv->current_test = (lws_unit_test_t *)tm->u.value; - - /* ... and the callback to deliver the result to */ - tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_V_EXPECT_RESULT_CB); - if (tm) - priv->result_cb = (lws_unit_test_packet_test_cb)tm->u.value; - else - priv->result_cb = NULL; - - /* ... and the arg to deliver it with */ - tm = lws_abs_get_token(abs->at_tokens, - LTMI_PEER_V_EXPECT_RESULT_CB_ARG); - if (tm) - priv->result_cb_arg = tm->u.value; - - priv->expect = priv->current_test->expect_array; - priv->disposition = LPE_CONTINUE; - priv->note[0] = '\0'; - - lws_seq_timeout_us(priv->seq, priv->current_test->max_secs * - LWS_US_PER_SEC); - - lwsl_notice("%s: %s: test '%s': start\n", __func__, abs->ap->name, - priv->current_test->name); - - lws_seq_queue_event(priv->seq, UTSEQ_MSG_CONNECTING, NULL, NULL); - - return 0; -} -#endif - -static int -lws_atcut_ask_for_writeable(lws_abs_transport_inst_t *ati) -{ - abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)ati; - - if (!priv->established) - return 1; - - /* - * Queue a writeable event... this won't be handled by teh sequencer - * until we have returned to the event loop, just like a real - * callback_on_writable() - */ - lws_seq_queue_event(priv->seq, UTSEQ_MSG_WRITEABLE, NULL, NULL); - - return 0; -} - -/* - * An abstract protocol + transport has been instantiated - */ - -static int -lws_atcut_create(lws_abs_t *ai) -{ - abs_unit_test_priv_t *priv; - struct lws_sequencer *seq; - lws_seq_info_t i; - seq_priv_t *s; - - memset(&i, 0, sizeof(i)); - i.context = ai->vh->context; - i.user_size = sizeof(*s); - i.puser = (void **)&s; - i.cb = unit_test_sequencer_cb; - i.name = "unit-test-seq"; - - /* - * Create the sequencer for the steps in a single unit test - */ - - seq = lws_seq_create(&i); - if (!seq) { - lwsl_err("%s: unable to create sequencer\n", __func__); - - return 1; - } - - priv = ai->ati; - memset(s, 0, sizeof(*s)); - memset(priv, 0, sizeof(*priv)); - - /* the sequencer priv just points to the lws_abs_t */ - s->ai = ai; - priv->abs = ai; - priv->seq = seq; - - return 0; -} - -static void -lws_atcut_destroy(lws_abs_transport_inst_t **pati) -{ - /* - * We don't free anything because the abstract layer combined our - * allocation with that of the instance, and it will free the whole - * thing after this. - */ - *pati = NULL; -} - -static int -lws_atcut_set_timeout(lws_abs_transport_inst_t *ati, int reason, int secs) -{ - abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)ati; - time_t now; - - time(&now); - - if (secs) - priv->timeout = now + secs; - else - priv->timeout = 0; - - return 0; -} - -static int -lws_atcut_state(lws_abs_transport_inst_t *ati) -{ - abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)ati; - - if (!priv || (!priv->established && !priv->connecting)) - return 0; - - return 1; -} - -static const char *dnames[] = { - "INCOMPLETE", - "PASS", - "FAIL", - "FAIL(TIMEOUT)", - "FAIL(UNEXPECTED PASS)", - "FAIL(UNEXPECTED CLOSE)", - "SKIPPED" - "?", - "?" -}; - - -const char * -lws_unit_test_result_name(int in) -{ - if (in < 0 || in > (int)LWS_ARRAY_SIZE(dnames)) - return "unknown"; - - return dnames[in]; -} - -static int -lws_atcut_compare(lws_abs_t *abs1, lws_abs_t *abs2) -{ - return 0; -} - -const lws_abs_transport_t lws_abs_transport_cli_unit_test = { - .name = "unit_test", - .alloc = sizeof(abs_unit_test_priv_t), - - .create = lws_atcut_create, - .destroy = lws_atcut_destroy, - .compare = lws_atcut_compare, - - .tx = lws_atcut_tx, -#if !defined(LWS_WITH_CLIENT) - .client_conn = NULL, -#else - .client_conn = lws_atcut_client_conn, -#endif - .close = lws_atcut_close, - .ask_for_writeable = lws_atcut_ask_for_writeable, - .set_timeout = lws_atcut_set_timeout, - .state = lws_atcut_state, -}; diff --git a/lib/core-net/CMakeLists.txt b/lib/core-net/CMakeLists.txt index 262728970..43a47ca14 100644 --- a/lib/core-net/CMakeLists.txt +++ b/lib/core-net/CMakeLists.txt @@ -56,11 +56,6 @@ if (LWS_WITH_LWS_DSH) core-net/lws-dsh.c) endif() -if (LWS_WITH_SEQUENCER) - list(APPEND SOURCES - core-net/sequencer.c) -endif() - if (LWS_WITH_CLIENT) list(APPEND SOURCES core-net/client/client.c diff --git a/lib/core-net/client/connect.c b/lib/core-net/client/connect.c index 89db49d91..23b8fb1b3 100644 --- a/lib/core-net/client/connect.c +++ b/lib/core-net/client/connect.c @@ -234,7 +234,6 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) else wsi->keep_warm_secs = 5; - wsi->seq = i->seq; wsi->flags = i->ssl_connection; wsi->c_pri = i->priority; diff --git a/lib/core-net/private-lib-core-net.h b/lib/core-net/private-lib-core-net.h index 3f5073110..3cce68ac4 100644 --- a/lib/core-net/private-lib-core-net.h +++ b/lib/core-net/private-lib-core-net.h @@ -284,7 +284,6 @@ struct lws_context_per_thread { pthread_t self; #endif struct lws_dll2_owner dll_buflist_owner; /* guys with pending rxflow */ - struct lws_dll2_owner seq_owner; /* list of lws_sequencer-s */ lws_dll2_owner_t attach_owner; /* pending lws_attach */ #if defined(LWS_WITH_SECURE_STREAMS) @@ -298,9 +297,6 @@ struct lws_context_per_thread { struct lws_dll2_owner pt_sul_owner[LWS_COUNT_PT_SUL_OWNERS]; -#if defined (LWS_WITH_SEQUENCER) - lws_sorted_usec_list_t sul_seq_heartbeat; -#endif #if (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)) && defined(LWS_WITH_SERVER) lws_sorted_usec_list_t sul_ah_lifecheck; #endif @@ -701,7 +697,6 @@ struct lws { struct lws *child_list; /* points to first child */ struct lws *sibling_list; /* subsequent children at same level */ const struct lws_role_ops *role_ops; - struct lws_sequencer *seq; /* associated sequencer if any */ const lws_retry_bo_t *retry_policy; lws_log_cx_t *log_cx; diff --git a/lib/core-net/sequencer.c b/lib/core-net/sequencer.c deleted file mode 100644 index aa6a0cbce..000000000 --- a/lib/core-net/sequencer.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010 - 2019 Andy Green - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "private-lib-core.h" - -/* - * per pending event - */ -typedef struct lws_seq_event { - struct lws_dll2 seq_event_list; - - void *data; - void *aux; - lws_seq_events_t e; -} lws_seq_event_t; - -/* - * per sequencer - */ -typedef struct lws_sequencer { - struct lws_dll2 seq_list; - - lws_sorted_usec_list_t sul_timeout; - lws_sorted_usec_list_t sul_pending; - - struct lws_dll2_owner seq_event_owner; - struct lws_context_per_thread *pt; - lws_seq_event_cb cb; - const char *name; - const lws_retry_bo_t *retry; - - lws_usec_t time_created; - lws_usec_t timeout; /* 0 or time we timeout */ - - uint8_t going_down:1; - uint8_t wakesuspend:1; -} lws_seq_t; - -#define QUEUE_SANITY_LIMIT 10 - -static void -lws_sul_seq_heartbeat_cb(lws_sorted_usec_list_t *sul) -{ - struct lws_context_per_thread *pt = lws_container_of(sul, - struct lws_context_per_thread, sul_seq_heartbeat); - - /* send every sequencer a heartbeat message... it can ignore it */ - - lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, - lws_dll2_get_head(&pt->seq_owner)) { - lws_seq_t *s = lws_container_of(p, lws_seq_t, seq_list); - - /* queue the message to inform the sequencer */ - lws_seq_queue_event(s, LWSSEQ_HEARTBEAT, NULL, NULL); - - } lws_end_foreach_dll_safe(p, tp); - - /* schedule the next one */ - - __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], - &pt->sul_seq_heartbeat, LWS_US_PER_SEC); -} - -int -lws_seq_pt_init(struct lws_context_per_thread *pt) -{ - pt->sul_seq_heartbeat.cb = lws_sul_seq_heartbeat_cb; - - /* schedule the first heartbeat */ - __lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED], - &pt->sul_seq_heartbeat, LWS_US_PER_SEC); - - return 0; -} - -lws_seq_t * -lws_seq_create(lws_seq_info_t *i) -{ - struct lws_context_per_thread *pt = &i->context->pt[i->tsi]; - lws_seq_t *seq = lws_zalloc(sizeof(*seq) + i->user_size, __func__); - - if (!seq) - return NULL; - - seq->cb = i->cb; - seq->pt = pt; - seq->name = i->name; - seq->retry = i->retry; - seq->wakesuspend = i->wakesuspend; - - *i->puser = (void *)&seq[1]; - - /* add the sequencer to the pt */ - - lws_pt_lock(pt, __func__); /* ---------------------------------- pt { */ - - lws_dll2_add_tail(&seq->seq_list, &pt->seq_owner); - - lws_pt_unlock(pt); /* } pt ------------------------------------------ */ - - seq->time_created = lws_now_usecs(); - - /* try to queue the creation cb */ - - if (lws_seq_queue_event(seq, LWSSEQ_CREATED, NULL, NULL)) { - lws_dll2_remove(&seq->seq_list); - lws_free(seq); - - return NULL; - } - - return seq; -} - -static int -seq_ev_destroy(struct lws_dll2 *d, void *user) -{ - lws_seq_event_t *seqe = lws_container_of(d, lws_seq_event_t, - seq_event_list); - - lws_dll2_remove(&seqe->seq_event_list); - lws_free(seqe); - - return 0; -} - -void -lws_seq_destroy(lws_seq_t **pseq) -{ - lws_seq_t *seq = *pseq; - - /* defeat another thread racing to add events while we are destroying */ - seq->going_down = 1; - - seq->cb(seq, (void *)&seq[1], LWSSEQ_DESTROYED, NULL, NULL); - - lws_pt_lock(seq->pt, __func__); /* -------------------------- pt { */ - - lws_dll2_remove(&seq->seq_list); - lws_dll2_remove(&seq->sul_timeout.list); - lws_dll2_remove(&seq->sul_pending.list); - /* remove and destroy any pending events */ - lws_dll2_foreach_safe(&seq->seq_event_owner, NULL, seq_ev_destroy); - - lws_pt_unlock(seq->pt); /* } pt ---------------------------------- */ - - - lws_free_set_NULL(seq); -} - -void -lws_seq_destroy_all_on_pt(struct lws_context_per_thread *pt) -{ - lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, - pt->seq_owner.head) { - lws_seq_t *s = lws_container_of(p, lws_seq_t, - seq_list); - - lws_seq_destroy(&s); - - } lws_end_foreach_dll_safe(p, tp); -} - -static void -lws_seq_sul_pending_cb(lws_sorted_usec_list_t *sul) -{ - lws_seq_t *seq = lws_container_of(sul, lws_seq_t, sul_pending); - lws_seq_event_t *seqe; - struct lws_dll2 *dh; - int n; - - if (!seq->seq_event_owner.count) - return; - - /* events are only added at tail, so no race possible yet... */ - - dh = lws_dll2_get_head(&seq->seq_event_owner); - seqe = lws_container_of(dh, lws_seq_event_t, seq_event_list); - - n = (int)seq->cb(seq, (void *)&seq[1], (int)seqe->e, seqe->data, seqe->aux); - - /* ... have to lock here though, because we will change the list */ - - lws_pt_lock(seq->pt, __func__); /* ----------------------------- pt { */ - - /* detach event from sequencer event list and free it */ - lws_dll2_remove(&seqe->seq_event_list); - lws_free(seqe); - lws_pt_unlock(seq->pt); /* } pt ------------------------------------- */ - - if (n) { - lwsl_info("%s: destroying seq '%s' by request\n", __func__, - seq->name); - lws_seq_destroy(&seq); - } -} - -int -lws_seq_queue_event(lws_seq_t *seq, lws_seq_events_t e, void *data, void *aux) -{ - lws_seq_event_t *seqe; - - if (!seq || seq->going_down) - return 1; - - seqe = lws_zalloc(sizeof(*seqe), __func__); - if (!seqe) - return 1; - - seqe->e = e; - seqe->data = data; - seqe->aux = aux; - - // lwsl_notice("%s: seq %s: event %d\n", __func__, seq->name, e); - - lws_pt_lock(seq->pt, __func__); /* ----------------------------- pt { */ - - if (seq->seq_event_owner.count > QUEUE_SANITY_LIMIT) { - lwsl_err("%s: more than %d events queued\n", __func__, - QUEUE_SANITY_LIMIT); - } - - lws_dll2_add_tail(&seqe->seq_event_list, &seq->seq_event_owner); - - seq->sul_pending.cb = lws_seq_sul_pending_cb; - __lws_sul_insert_us(&seq->pt->pt_sul_owner[seq->wakesuspend], - &seq->sul_pending, 1); - - lws_pt_unlock(seq->pt); /* } pt ------------------------------------- */ - - return 0; -} - -/* - * Check if wsi still extant, by peeking in the message queue for a - * LWSSEQ_WSI_CONN_CLOSE message about wsi. (Doesn't need to do the same for - * CONN_FAIL since that will never have produced any messages prior to that). - * - * Use this to avoid trying to perform operations on wsi that have already - * closed but we didn't get to that message yet. - * - * Returns 0 if not closed yet or 1 if it has closed but we didn't process the - * close message yet. - */ - -int -lws_seq_check_wsi(lws_seq_t *seq, struct lws *wsi) -{ - lws_seq_event_t *seqe; - struct lws_dll2 *dh; - - lws_pt_lock(seq->pt, __func__); /* ----------------------------- pt { */ - - dh = lws_dll2_get_head(&seq->seq_event_owner); - while (dh) { - seqe = lws_container_of(dh, lws_seq_event_t, seq_event_list); - - if (seqe->e == LWSSEQ_WSI_CONN_CLOSE && seqe->data == wsi) - break; - - dh = dh->next; - } - - lws_pt_unlock(seq->pt); /* } pt ------------------------------------- */ - - return !!dh; -} - - -static void -lws_seq_sul_timeout_cb(lws_sorted_usec_list_t *sul) -{ - lws_seq_t *s = lws_container_of(sul, lws_seq_t, sul_timeout); - - lws_seq_queue_event(s, LWSSEQ_TIMED_OUT, NULL, NULL); -} - -/* set us to LWS_SET_TIMER_USEC_CANCEL to remove timeout */ - -int -lws_seq_timeout_us(lws_seq_t *seq, lws_usec_t us) -{ - seq->sul_timeout.cb = lws_seq_sul_timeout_cb; - /* list is always at the very top of the sul */ - __lws_sul_insert_us(&seq->pt->pt_sul_owner[seq->wakesuspend], - (lws_sorted_usec_list_t *)&seq->sul_timeout.list, us); - - return 0; -} - -lws_seq_t * -lws_seq_from_user(void *u) -{ - return &((lws_seq_t *)u)[-1]; -} - -const char * -lws_seq_name(lws_seq_t *seq) -{ - return seq->name; -} - -lws_usec_t -lws_seq_us_since_creation(lws_seq_t *seq) -{ - return lws_now_usecs() - seq->time_created; -} - -struct lws_context * -lws_seq_get_context(lws_seq_t *seq) -{ - return seq->pt->context; -} - diff --git a/lib/core/context.c b/lib/core/context.c index de0504c90..2994d1eca 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -1140,9 +1140,6 @@ lws_create_context(const struct lws_context_creation_info *info) context->pt[n].http.ah_pool_length = 0; #endif lws_pt_mutex_init(&context->pt[n]); -#if defined(LWS_WITH_SEQUENCER) - lws_seq_pt_init(&context->pt[n]); -#endif #if defined(LWS_WITH_CGI) if (lws_rops_fidx(&role_ops_cgi, LWS_ROPS_pt_init_destroy)) @@ -1712,11 +1709,6 @@ lws_pt_destroy(struct lws_context_per_thread *pt) lws_dll2_foreach_safe(&pt->ss_client_owner, NULL, lws_sspc_destroy_dll); #endif -#if defined(LWS_WITH_SEQUENCER) - lws_seq_destroy_all_on_pt(pt); -#endif - - #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) while (pt->http.ah_list) _lws_destroy_ah(pt, pt->http.ah_list); @@ -2048,9 +2040,7 @@ next: struct lws_context_per_thread *pt = &context->pt[n]; (void)pt; -#if defined(LWS_WITH_SEQUENCER) - lws_seq_destroy_all_on_pt(pt); -#endif + LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) { if (lws_rops_fidx(ar, LWS_ROPS_pt_init_destroy)) (lws_rops_func_fidx(ar, LWS_ROPS_pt_init_destroy)). diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index dd01bdb6d..a75b7ff40 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -76,7 +76,6 @@ typedef struct lws_ss_handle { struct lws_context *context; /**< lws context we are created on */ const lws_ss_policy_t *policy; /**< system policy for stream */ - struct lws_sequencer *seq; /**< owning sequencer if any */ struct lws *wsi; /**< the stream wsi if any */ struct lws_sss_proxy_conn *conn_if_sspc_onw; diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 6bf1964ff..b905e7d64 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -417,16 +417,6 @@ lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) if (cs == LWSSSCS_DISCONNECTED) h->ss_dangling_connected = 0; -#if defined(LWS_WITH_SEQUENCER) - /* - * A parent sequencer for the ss is optional, if we have one, keep it - * informed of state changes on the ss connection - */ - if (h->seq && cs != LWSSSCS_DESTROYING) - lws_seq_queue_event(h->seq, LWSSEQ_SS_STATE_BASE + cs, - (void *)h, NULL); -#endif - if (h->info.state) { h->h_in_svc = h; r = h->info.state(ss_to_userobj(h), NULL, cs, @@ -820,7 +810,6 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw) i.host = i.address; i.origin = i.address; i.opaque_user_data = h; - i.seq = h->seq; i.retry_and_idle_policy = h->policy->retry_bo; i.sys_tls_client_cert = h->policy->client_cert; @@ -938,7 +927,7 @@ lws_ss_client_connect(lws_ss_handle_t *h) int lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, void *opaque_user_data, lws_ss_handle_t **ppss, - struct lws_sequencer *seq_owner, const char **ppayload_fmt) + void *reserved, const char **ppayload_fmt) { struct lws_context_per_thread *pt = &context->pt[tsi]; const lws_ss_policy_t *pol; @@ -1068,7 +1057,6 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, h->policy = pol; h->context = context; h->tsi = (uint8_t)tsi; - h->seq = seq_owner; if (h->info.flags & LWSSSINFLAGS_PROXIED) h->proxy_onward = 1; @@ -1678,12 +1666,6 @@ lws_ss_cancel_notify_dll(struct lws_dll2 *d, void *user) return 0; } -struct lws_sequencer * -lws_ss_get_sequencer(lws_ss_handle_t *h) -{ - return h->seq; -} - struct lws_context * lws_ss_get_context(struct lws_ss_handle *h) { diff --git a/lib/secure-streams/serialized/client/sspc.c b/lib/secure-streams/serialized/client/sspc.c index 8586615c9..d9669e6f1 100644 --- a/lib/secure-streams/serialized/client/sspc.c +++ b/lib/secure-streams/serialized/client/sspc.c @@ -282,7 +282,7 @@ lws_sspc_event_helper(lws_sspc_handle_t *h, lws_ss_constate_t cs, int lws_sspc_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, void *opaque_user_data, lws_sspc_handle_t **ppss, - struct lws_sequencer *seq_owner, const char **ppayload_fmt) + void *reserved, const char **ppayload_fmt) { lws_sspc_handle_t *h; uint8_t *ua;