From 3216d4d0873f5cd4fbd72ea581d24e1d13c186bb Mon Sep 17 00:00:00 2001 From: Andy Green Date: Tue, 10 Nov 2020 11:27:28 +0000 Subject: [PATCH] ss: server: add foreach client cb api Server SS maintains a list of accepted client ss, add an api allowing iterating through the clients via a user callback. --- include/libwebsockets/lws-secure-streams.h | 44 +++++++++++++++---- lib/core-net/adopt.c | 13 +++++- .../private-lib-secure-streams.h | 4 ++ lib/secure-streams/protocols/ss-h1.c | 9 ++++ lib/secure-streams/protocols/ss-raw.c | 8 ++++ lib/secure-streams/protocols/ss-ws.c | 9 ++++ lib/secure-streams/secure-streams.c | 16 +++++++ libwebsockets.dox | 8 +--- scripts/dox-extra.css | 5 +++ 9 files changed, 100 insertions(+), 16 deletions(-) create mode 100644 scripts/dox-extra.css diff --git a/include/libwebsockets/lws-secure-streams.h b/include/libwebsockets/lws-secure-streams.h index 24344f421..0daadd442 100644 --- a/include/libwebsockets/lws-secure-streams.h +++ b/include/libwebsockets/lws-secure-streams.h @@ -169,6 +169,13 @@ * (*rx) with the client stream's */ +/** \defgroup secstr Secure Streams +* ##Secure Streams +* +* Secure Streams related apis +*/ +///@{ + #define LWS_SS_MTU 1540 struct lws_ss_handle; @@ -317,8 +324,8 @@ typedef lws_ss_state_return_t (*lws_sscb_tx)(void *userobj, uint8_t *buf, size_t *len, int *flags); typedef lws_ss_state_return_t (*lws_sscb_state)(void *userobj, void *h_src, - lws_ss_constate_t state, - lws_ss_tx_ordinal_t ack); + lws_ss_constate_t state, + lws_ss_tx_ordinal_t ack); typedef struct lws_ss_info { const char *streamtype; /**< type of stream we want to create */ @@ -362,7 +369,7 @@ typedef struct lws_ss_info { * name from the policy * * Requests a new secure stream described by \p ssi be created. If successful, - * the stream is created, its state callback called with LWSSSCS_CREATING, *ppss + * the stream is created, its state callback called with LWSSSCS_CREATING, \p *ppss * is set to point to the handle, and it returns 0. If it failed, it returns * nonzero. * @@ -396,7 +403,7 @@ lws_ss_create(struct lws_context *context, int tsi, const lws_ss_info_t *ssi, * * \param ppss: pointer to lws_ss_t pointer to be destroyed * - * Destroys the lws_ss_t pointed to by *ppss, and sets *ppss to NULL. + * Destroys the lws_ss_t pointed to by \p *ppss, and sets \p *ppss to NULL. */ LWS_VISIBLE LWS_EXTERN void lws_ss_destroy(struct lws_ss_handle **ppss); @@ -407,7 +414,7 @@ lws_ss_destroy(struct lws_ss_handle **ppss); * \param pss: pointer to lws_ss_t representing stream that wants to transmit * * Schedules a write on the stream represented by \p pss. When it's possible to - * write on this stream, the *tx callback will occur with an empty buffer for + * write on this stream, the \p *tx callback will occur with an empty buffer for * the stream owner to fill in. * * Returns 0 or LWSSSSRET_SS_HANDLE_DESTROYED @@ -422,7 +429,7 @@ lws_ss_request_tx(struct lws_ss_handle *pss); * \param len: the length of the write in bytes * * Schedules a write on the stream represented by \p pss. When it's possible to - * write on this stream, the *tx callback will occur with an empty buffer for + * write on this stream, the \p *tx callback will occur with an empty buffer for * the stream owner to fill in. * * This api variant should be used when it's possible the payload will go out @@ -603,7 +610,7 @@ lws_ss_set_metadata(struct lws_ss_handle *h, const char *name, * when the policy is using h1 is interpreted to add h1 headers of the given * name with the value of the metadata on the left. * - * Return 0 if *value and *len set OK, or nonzero if, eg, metadata name does + * Return 0 if \p *value and \p *len set OK, or nonzero if, eg, metadata \p name does * not exist on the streamtype. * * The pointed-to values may only exist until the next time around the event @@ -613,7 +620,7 @@ LWS_VISIBLE LWS_EXTERN int lws_ss_get_metadata(struct lws_ss_handle *h, const char *name, const void **value, size_t *len); -/* +/** * lws_ss_server_ack() - indicate how we feel about what the server has sent * * \param h: ss handle of accepted connection @@ -635,6 +642,24 @@ lws_ss_get_metadata(struct lws_ss_handle *h, const char *name, LWS_VISIBLE LWS_EXTERN void lws_ss_server_ack(struct lws_ss_handle *h, int nack); +typedef void (*lws_sssfec_cb)(struct lws_ss_handle *h, void *arg); + +/** + * lws_ss_server_foreach_client() - callback for each live client connected to server + * + * \param h: server ss handle + * \param cb: the callback + * \param arg: arg passed to callback + * + * For SERVER secure streams + * + * Call the callback \p cb once for each client ss connected to the server, + * passing \p arg as an additional callback argument each time. + */ +LWS_VISIBLE LWS_EXTERN void +lws_ss_server_foreach_client(struct lws_ss_handle *h, lws_sssfec_cb cb, + void *arg); + /** * lws_ss_change_handlers() - helper for dynamically changing stream handlers * @@ -688,3 +713,6 @@ lws_ss_add_peer_tx_credit(struct lws_ss_handle *h, int32_t add); */ LWS_VISIBLE LWS_EXTERN int lws_ss_get_est_peer_tx_credit(struct lws_ss_handle *h); + +///@} + diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index a8f61eb1e..e6aa8009b 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -243,6 +243,8 @@ bail: int lws_adopt_ss_server_accept(struct lws *new_wsi) { + struct lws_context_per_thread *pt = + &new_wsi->a.context->pt[(int)new_wsi->tsi]; lws_ss_handle_t *h; void *pv, **ppv; @@ -284,13 +286,22 @@ lws_adopt_ss_server_accept(struct lws *new_wsi) h->wsi = new_wsi; new_wsi->a.opaque_user_data = h; h->info.flags |= LWSSSINFLAGS_ACCEPTED; - new_wsi->for_ss = 1; /* indicate wsi should invalidate any ss link to it on close */ + /* indicate wsi should invalidate any ss link to it on close */ + new_wsi->for_ss = 1; // lwsl_notice("%s: opaq %p, role %s\n", __func__, // new_wsi->a.opaque_user_data, new_wsi->role_ops->name); h->policy = new_wsi->a.vhost->ss_handle->policy; + /* + * add us to the list of clients that came in from the server + */ + + lws_pt_lock(pt, __func__); + lws_dll2_add_tail(&h->cli_list, &new_wsi->a.vhost->ss_handle->src_list); + lws_pt_unlock(pt); + /* * Let's give it appropriate state notifications */ diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 0b69a6347..74f703750 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -43,8 +43,12 @@ typedef enum { typedef struct lws_ss_handle { lws_ss_info_t info; /**< copy of stream creation info */ + struct lws_dll2 list; /**< pt lists active ss */ struct lws_dll2 to_list; /**< pt lists ss with pending to-s */ +#if defined(LWS_WITH_SERVER) + struct lws_dll2 cli_list; /**< same server clients list */ +#endif struct lws_dll2_owner src_list; /**< sink's list of bound sources */ diff --git a/lib/secure-streams/protocols/ss-h1.c b/lib/secure-streams/protocols/ss-h1.c index c95a22d6d..fedc3d6d4 100644 --- a/lib/secure-streams/protocols/ss-h1.c +++ b/lib/secure-streams/protocols/ss-h1.c @@ -344,6 +344,9 @@ int secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { +#if defined(LWS_WITH_SERVER) + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; +#endif lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], #if defined(LWS_WITH_SERVER) @@ -393,6 +396,12 @@ secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, h->policy ? h->policy->streamtype : "no policy"); h->wsi = NULL; +#if defined(LWS_WITH_SERVER) + lws_pt_lock(pt, __func__); + lws_dll2_remove(&h->cli_list); + lws_pt_unlock(pt); +#endif + if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && #if defined(LWS_WITH_SERVER) !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not server */ diff --git a/lib/secure-streams/protocols/ss-raw.c b/lib/secure-streams/protocols/ss-raw.c index 7821f459b..0fe95252e 100644 --- a/lib/secure-streams/protocols/ss-raw.c +++ b/lib/secure-streams/protocols/ss-raw.c @@ -30,6 +30,9 @@ int secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { +#if defined(LWS_WITH_SERVER) + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; +#endif lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], *end = &buf[sizeof(buf) - 1]; @@ -61,6 +64,11 @@ secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user, __func__, h, h->policy ? h->policy->streamtype : "no policy"); h->wsi = NULL; +#if defined(LWS_WITH_SERVER) + lws_pt_lock(pt, __func__); + lws_dll2_remove(&h->cli_list); + lws_pt_unlock(pt); +#endif if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && #if defined(LWS_WITH_SERVER) !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not server */ diff --git a/lib/secure-streams/protocols/ss-ws.c b/lib/secure-streams/protocols/ss-ws.c index 3defb7155..2b8182c59 100644 --- a/lib/secure-streams/protocols/ss-ws.c +++ b/lib/secure-streams/protocols/ss-ws.c @@ -28,6 +28,9 @@ static int secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { +#if defined(LWS_WITH_SERVER) + struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; +#endif lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); uint8_t buf[LWS_PRE + 1400]; lws_ss_state_return_t r; @@ -65,6 +68,12 @@ secstream_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_set_opaque_user_data(h->wsi, NULL); h->wsi = NULL; +#if defined(LWS_WITH_SERVER) + lws_pt_lock(pt, __func__); + lws_dll2_remove(&h->cli_list); + lws_pt_unlock(pt); +#endif + if (reason == LWS_CALLBACK_CLIENT_CLOSED) { if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index fc89e7d1a..a0ac75d1c 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -841,6 +841,9 @@ lws_ss_destroy(lws_ss_handle_t **ppss) lws_pt_lock(pt, __func__); *ppss = NULL; lws_dll2_remove(&h->list); +#if defined(LWS_WITH_SERVER) + lws_dll2_remove(&h->cli_list); +#endif lws_dll2_remove(&h->to_list); lws_sul_cancel(&h->sul_timeout); @@ -904,6 +907,19 @@ lws_ss_server_ack(struct lws_ss_handle *h, int nack) h->txn_resp = nack; h->txn_resp_set = 1; } + +void +lws_ss_server_foreach_client(struct lws_ss_handle *h, lws_sssfec_cb cb, + void *arg) +{ + lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, h->src_list.head) { + struct lws_ss_handle *h = + lws_container_of(d, struct lws_ss_handle, cli_list); + + cb(h, arg); + + } lws_end_foreach_dll_safe(d, d1); +} #endif lws_ss_state_return_t diff --git a/libwebsockets.dox b/libwebsockets.dox index 87e7c98f4..013bda0b4 100644 --- a/libwebsockets.dox +++ b/libwebsockets.dox @@ -28,7 +28,6 @@ INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = -TCL_SUBST = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO @@ -117,7 +116,6 @@ INPUT = include/libwebsockets.h \ include/libwebsockets/lws-display.h \ include/libwebsockets/lws-dll2.h \ include/libwebsockets/lws-dsh.h \ - include/libwebsockets/lws-esp32.h \ include/libwebsockets/lws-eventlib-exports.h \ include/libwebsockets/lws-freertos.h \ include/libwebsockets/lws-fts.h \ @@ -184,8 +182,6 @@ INPUT = include/libwebsockets.h \ ./READMEs/README.crypto-apis.md \ ./READMEs/README.detailed-latency.md \ ./READMEs/README.esp32.md \ - ./READMEs/README.generic-sessions.md \ - ./READMEs/README.generic-table.md \ ./READMEs/README.h2-long-poll.md \ ./READMEs/README.http-fallback.md \ ./READMEs/README.lws_dll.md \ @@ -245,7 +241,7 @@ HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = -HTML_EXTRA_STYLESHEET = +HTML_EXTRA_STYLESHEET = scripts/dox-extra.css HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 @@ -376,12 +372,10 @@ GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES -PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES -MSCGEN_PATH = DIA_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO diff --git a/scripts/dox-extra.css b/scripts/dox-extra.css new file mode 100644 index 000000000..ca1407655 --- /dev/null +++ b/scripts/dox-extra.css @@ -0,0 +1,5 @@ +code { + text-color: #000000; + background-color: #f0f0a0; +} +