diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 3d4a4e2d..5d518236 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -5313,6 +5313,29 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, } \ } +#define lws_ll_fwd_insert(\ + ___new_object, /* pointer to new object */ \ + ___m_list, /* member for next list object ptr */ \ + ___list_head /* list head */ \ + ) {\ + ___new_object->___m_list = ___list_head; \ + ___list_head = ___new_object; \ + } + +#define lws_ll_fwd_remove(\ + ___type, /* type of listed object */ \ + ___m_list, /* member for next list object ptr */ \ + ___target, /* object to remove from list */ \ + ___list_head /* list head */ \ + ) { \ + lws_start_foreach_llp(___type **, ___ppss, ___list_head) { \ + if (*___ppss == ___target) { \ + *___ppss = ___target->___m_list; \ + break; \ + } \ + } lws_end_foreach_llp(___ppss, ___m_list); \ + } + /** * lws_ptr_diff(): helper to report distance between pointers as an int * @@ -6029,6 +6052,62 @@ lws_ring_bump_head(struct lws_ring *ring, size_t bytes); LWS_VISIBLE LWS_EXTERN void lws_ring_dump(struct lws_ring *ring, uint32_t *tail); + +/* + * This is a helper that combines the common pattern of needing to consume + * some ringbuffer elements, move the consumer tail on, and check if that + * has moved any ringbuffer elements out of scope, because it was the last + * consumer that had not already consumed them. + * + * Elements that go out of scope because the oldest tail is now after them + * get garbage-collected by calling the destroy_element callback on them + * defined when the ringbuffer was created. + */ + +#define lws_ring_consume_and_update_oldest_tail(\ + ___ring, /* the lws_ring object */ \ + ___type, /* type of objects with tails */ \ + ___ptail, /* ptr to tail of obj with tail doing consuming */ \ + ___count, /* count of payload objects being consumed */ \ + ___list_head, /* head of list of objects with tails */ \ + ___mtail, /* member name of tail in ___type */ \ + ___mlist /* member name of next list member ptr in ___type */ \ + ) { \ + int ___n, ___m; \ + \ + ___n = lws_ring_get_oldest_tail(___ring) == *(___ptail); \ + lws_ring_consume(___ring, ___ptail, NULL, ___count); \ + if (___n) { \ + uint32_t ___oldest; \ + ___n = 0; \ + ___oldest = *(___ptail); \ + lws_start_foreach_llp(___type **, ___ppss, ___list_head) { \ + ___m = lws_ring_get_count_waiting_elements( \ + ___ring, &(*___ppss)->tail); \ + if (___m >= ___n) { \ + ___n = ___m; \ + ___oldest = (*___ppss)->tail; \ + } \ + } lws_end_foreach_llp(___ppss, ___mlist); \ + \ + lws_ring_update_oldest_tail(___ring, ___oldest); \ + } \ +} + +/* + * This does the same as the lws_ring_consume_and_update_oldest_tail() + * helper, but for the simpler case there is only one consumer, so one + * tail, and that tail is always the oldest tail. + */ + +#define lws_ring_consume_single_tail(\ + ___ring, /* the lws_ring object */ \ + ___ptail, /* ptr to tail of obj with tail doing consuming */ \ + ___count /* count of payload objects being consumed */ \ + ) { \ + lws_ring_consume(___ring, ___ptail, NULL, ___count); \ + lws_ring_update_oldest_tail(___ring, *(___ptail)); \ +} ///@} /** \defgroup sha SHA and B64 helpers diff --git a/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c b/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c index 2c55c9e8..08ab0584 100644 --- a/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c +++ b/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c @@ -89,7 +89,6 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, lws_get_protocol(wsi)); const struct msg *pmsg; struct msg amsg; - uint32_t oldest; int n, m; switch (reason) { @@ -106,6 +105,9 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, vhd->ring = lws_ring_create(sizeof(struct msg), 8, __minimal_destroy_message); + if (!vhd->ring) + return 1; + if (connect_client(vhd)) lws_timed_callback_vh_protocol(vhd->vhost, vhd->protocol, @@ -120,21 +122,15 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_ESTABLISHED: /* add ourselves to the list of live pss held in the vhd */ - pss->pss_list = vhd->pss_list; - vhd->pss_list = pss; + lws_ll_fwd_insert(pss, pss_list, vhd->pss_list); pss->tail = lws_ring_get_oldest_tail(vhd->ring); pss->wsi = wsi; break; case LWS_CALLBACK_CLOSED: /* remove our closing pss from the list of live pss */ - lws_start_foreach_llp(struct per_session_data__minimal **, - ppss, vhd->pss_list) { - if (*ppss == pss) { - *ppss = pss->pss_list; - break; - } - } lws_end_foreach_llp(ppss, pss_list); + lws_ll_fwd_remove(struct per_session_data__minimal, pss_list, + pss, vhd->pss_list); break; case LWS_CALLBACK_SERVER_WRITEABLE: @@ -150,26 +146,15 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, return -1; } - n = lws_ring_get_oldest_tail(vhd->ring) == pss->tail; - lws_ring_consume(vhd->ring, &pss->tail, NULL, 1); - - if (n) { /* we may have been the oldest tail */ - n = 0; - oldest = pss->tail; - lws_start_foreach_llp( - struct per_session_data__minimal **, - ppss, vhd->pss_list) { - m = lws_ring_get_count_waiting_elements( - vhd->ring, &(*ppss)->tail); - if (m > n) { - n = m; - oldest = (*ppss)->tail; - } - } lws_end_foreach_llp(ppss, pss_list); - - /* this will delete any entries behind the new oldest */ - lws_ring_update_oldest_tail(vhd->ring, oldest); - } + lws_ring_consume_and_update_oldest_tail( + vhd->ring, /* lws_ring object */ + struct per_session_data__minimal, /* type of objects with tails */ + &pss->tail, /* tail of guy doing the consuming */ + 1, /* number of payload objects being consumed */ + vhd->pss_list, /* head of list of objects with tails */ + tail, /* member name of tail in objects with tails */ + pss_list /* member name of next object in objects with tails */ + ); /* more to do? */ if (lws_ring_get_element(vhd->ring, &pss->tail)) diff --git a/minimal-examples/client-ws/README.md b/minimal-examples/client-ws/README.md index 21433e09..34248bc2 100644 --- a/minimal-examples/client-ws/README.md +++ b/minimal-examples/client-ws/README.md @@ -1,3 +1,4 @@ |name|demonstrates| ---|--- -minimal-ws-client|Connects to the dumb-increment-protocol wss server at https://libwebsockets.org +minimal-ws-client-rx|Connects to the dumb-increment-protocol wss server at https://libwebsockets.org and demonstrates receiving ws data +minimal-ws-client-tx|Connects to the minimal-ws-broker example as a publisher, demonstrating sending ws data diff --git a/minimal-examples/client-ws/minimal-ws-client/CMakeLists.txt b/minimal-examples/client-ws/minimal-ws-client-rx/CMakeLists.txt similarity index 89% rename from minimal-examples/client-ws/minimal-ws-client/CMakeLists.txt rename to minimal-examples/client-ws/minimal-ws-client-rx/CMakeLists.txt index 2c8ff3de..659779b6 100644 --- a/minimal-examples/client-ws/minimal-ws-client/CMakeLists.txt +++ b/minimal-examples/client-ws/minimal-ws-client-rx/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8) -set(SAMP lws-minimal-ws-client) +set(SAMP lws-minimal-ws-client-rx) set(SRCS minimal-ws-client.c) if (UNIX) diff --git a/minimal-examples/client-ws/minimal-ws-client/README.md b/minimal-examples/client-ws/minimal-ws-client-rx/README.md similarity index 78% rename from minimal-examples/client-ws/minimal-ws-client/README.md rename to minimal-examples/client-ws/minimal-ws-client-rx/README.md index f3a0b822..5c267e1c 100644 --- a/minimal-examples/client-ws/minimal-ws-client/README.md +++ b/minimal-examples/client-ws/minimal-ws-client-rx/README.md @@ -1,4 +1,4 @@ -# lws minimal ws client +# lws minimal ws client rx ## build @@ -12,9 +12,13 @@ The application goes to https://libwebsockets.org and makes a wss connection using the dumb-increment-protocol. It shows the incrementing number it is being sent over ws as it arrives. +This example only receives things to keep it simple. See minimal-ws-client-tx +for code related to sending things. Of course rx and tx are supported in the +same protocol. + ``` -./lws-minimal-ws-client -[2018/03/14 11:57:24:0689] USER: LWS minimal ws client +./lws-minimal-ws-client-rx +[2018/03/14 11:57:24:0689] USER: LWS minimal ws client rx [2018/03/14 11:57:24:0705] NOTICE: Creating Vhost 'default' port -1, 1 protocols, IPv6 off [2018/03/14 11:57:24:0710] NOTICE: created client ssl context for default [2018/03/14 11:57:24:0788] NOTICE: lws_client_connect_2: 0x15b8310: address libwebsockets.org diff --git a/minimal-examples/client-ws/minimal-ws-client/minimal-ws-client.c b/minimal-examples/client-ws/minimal-ws-client-rx/minimal-ws-client.c similarity index 98% rename from minimal-examples/client-ws/minimal-ws-client/minimal-ws-client.c rename to minimal-examples/client-ws/minimal-ws-client-rx/minimal-ws-client.c index e3cb44d4..24393c36 100644 --- a/minimal-examples/client-ws/minimal-ws-client/minimal-ws-client.c +++ b/minimal-examples/client-ws/minimal-ws-client-rx/minimal-ws-client.c @@ -80,7 +80,7 @@ int main(int argc, char **argv) lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_USER /* | LLL_INFO */ /* | LLL_DEBUG */, NULL); - lwsl_user("LWS minimal ws client\n"); + lwsl_user("LWS minimal ws client rx\n"); memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; diff --git a/minimal-examples/server-ws/minimal-ws-broker/protocol_lws_minimal.c b/minimal-examples/server-ws/minimal-ws-broker/protocol_lws_minimal.c index bc493f35..50d9f33e 100644 --- a/minimal-examples/server-ws/minimal-ws-broker/protocol_lws_minimal.c +++ b/minimal-examples/server-ws/minimal-ws-broker/protocol_lws_minimal.c @@ -85,7 +85,6 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, lws_get_protocol(wsi)); const struct msg *pmsg; struct msg amsg; - uint32_t oldest; char buf[32]; int n, m; @@ -100,6 +99,8 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, vhd->ring = lws_ring_create(sizeof(struct msg), 8, __minimal_destroy_message); + if (!vhd->ring) + return 1; break; case LWS_CALLBACK_PROTOCOL_DESTROY: @@ -108,8 +109,7 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_ESTABLISHED: /* add ourselves to the list of live pss held in the vhd */ - pss->pss_list = vhd->pss_list; - vhd->pss_list = pss; + lws_ll_fwd_insert(pss, pss_list, vhd->pss_list); pss->tail = lws_ring_get_oldest_tail(vhd->ring); pss->wsi = wsi; if (lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI) > 0) @@ -118,13 +118,8 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_CLOSED: /* remove our closing pss from the list of live pss */ - lws_start_foreach_llp(struct per_session_data__minimal **, - ppss, vhd->pss_list) { - if (*ppss == pss) { - *ppss = pss->pss_list; - break; - } - } lws_end_foreach_llp(ppss, pss_list); + lws_ll_fwd_remove(struct per_session_data__minimal, pss_list, + pss, vhd->pss_list); break; case LWS_CALLBACK_SERVER_WRITEABLE: @@ -144,26 +139,15 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, return -1; } - n = lws_ring_get_oldest_tail(vhd->ring) == pss->tail; - lws_ring_consume(vhd->ring, &pss->tail, NULL, 1); - - if (n) { /* we may have been the oldest tail */ - n = 0; - oldest = pss->tail; - lws_start_foreach_llp( - struct per_session_data__minimal **, - ppss, vhd->pss_list) { - m = lws_ring_get_count_waiting_elements( - vhd->ring, &(*ppss)->tail); - if (m > n) { - n = m; - oldest = (*ppss)->tail; - } - } lws_end_foreach_llp(ppss, pss_list); - - /* this will delete any entries behind the new oldest */ - lws_ring_update_oldest_tail(vhd->ring, oldest); - } + lws_ring_consume_and_update_oldest_tail( + vhd->ring, /* lws_ring object */ + struct per_session_data__minimal, /* type of objects with tails */ + &pss->tail, /* tail of guy doing the consuming */ + 1, /* number of payload objects being consumed */ + vhd->pss_list, /* head of list of objects with tails */ + tail, /* member name of tail in objects with tails */ + pss_list /* member name of next object in objects with tails */ + ); /* more to do? */ if (lws_ring_get_element(vhd->ring, &pss->tail)) diff --git a/minimal-examples/server-ws/minimal-ws-server-ring/CMakeLists.txt b/minimal-examples/server-ws/minimal-ws-server-ring/CMakeLists.txt index 8dd86a04..3bfdc5ff 100644 --- a/minimal-examples/server-ws/minimal-ws-server-ring/CMakeLists.txt +++ b/minimal-examples/server-ws/minimal-ws-server-ring/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8) -set(SAMP lws-minimal-ws-server) +set(SAMP lws-minimal-ws-server-ring) set(SRCS minimal-ws-server.c) if (UNIX) diff --git a/minimal-examples/server-ws/minimal-ws-server-ring/protocol_lws_minimal.c b/minimal-examples/server-ws/minimal-ws-server-ring/protocol_lws_minimal.c index 46bb5793..f61c1414 100644 --- a/minimal-examples/server-ws/minimal-ws-server-ring/protocol_lws_minimal.c +++ b/minimal-examples/server-ws/minimal-ws-server-ring/protocol_lws_minimal.c @@ -69,7 +69,6 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, lws_get_protocol(wsi)); const struct msg *pmsg; struct msg amsg; - uint32_t oldest; int n, m; switch (reason) { @@ -83,6 +82,8 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, vhd->ring = lws_ring_create(sizeof(struct msg), 8, __minimal_destroy_message); + if (!vhd->ring) + return 1; break; case LWS_CALLBACK_PROTOCOL_DESTROY: @@ -91,21 +92,15 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_ESTABLISHED: /* add ourselves to the list of live pss held in the vhd */ - pss->pss_list = vhd->pss_list; - vhd->pss_list = pss; + lws_ll_fwd_insert(pss, pss_list, vhd->pss_list); pss->tail = lws_ring_get_oldest_tail(vhd->ring); pss->wsi = wsi; break; case LWS_CALLBACK_CLOSED: /* remove our closing pss from the list of live pss */ - lws_start_foreach_llp(struct per_session_data__minimal **, - ppss, vhd->pss_list) { - if (*ppss == pss) { - *ppss = pss->pss_list; - break; - } - } lws_end_foreach_llp(ppss, pss_list); + lws_ll_fwd_remove(struct per_session_data__minimal, pss_list, + pss, vhd->pss_list); break; case LWS_CALLBACK_SERVER_WRITEABLE: @@ -121,28 +116,17 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, return -1; } - n = lws_ring_get_oldest_tail(vhd->ring) == pss->tail; - lws_ring_consume(vhd->ring, &pss->tail, NULL, 1); + lws_ring_consume_and_update_oldest_tail( + vhd->ring, /* lws_ring object */ + struct per_session_data__minimal, /* type of objects with tails */ + &pss->tail, /* tail of guy doing the consuming */ + 1, /* number of payload objects being consumed */ + vhd->pss_list, /* head of list of objects with tails */ + tail, /* member name of tail in objects with tails */ + pss_list /* member name of next object in objects with tails */ + ); - if (n) { /* we may have been the oldest tail */ - n = 0; - oldest = pss->tail; - lws_start_foreach_llp( - struct per_session_data__minimal **, - ppss, vhd->pss_list) { - m = lws_ring_get_count_waiting_elements( - vhd->ring, &(*ppss)->tail); - if (m > n) { - n = m; - oldest = (*ppss)->tail; - } - } lws_end_foreach_llp(ppss, pss_list); - - /* this will delete any entries behind the new oldest */ - lws_ring_update_oldest_tail(vhd->ring, oldest); - } - - /* more to do? */ + /* more to do for us? */ if (lws_ring_get_element(vhd->ring, &pss->tail)) /* come back as soon as we can write more */ lws_callback_on_writable(pss->wsi); @@ -180,11 +164,6 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, } lws_end_foreach_llp(ppss, pss_list); break; - case LWS_CALLBACK_TIMER: - lwsl_notice("%s: LWS_CALLBACK_TIMER\n", __func__); - lws_set_timer(wsi, 3); - break; - default: break; } diff --git a/minimal-examples/server-ws/minimal-ws-server-threads/protocol_lws_minimal.c b/minimal-examples/server-ws/minimal-ws-server-threads/protocol_lws_minimal.c index f648c888..6bfddeda 100644 --- a/minimal-examples/server-ws/minimal-ws-server-threads/protocol_lws_minimal.c +++ b/minimal-examples/server-ws/minimal-ws-server-threads/protocol_lws_minimal.c @@ -142,7 +142,6 @@ callback_minimal(struct lws *wsi, enum lws_callback_reasons reason, lws_get_protocol(wsi)); const struct lws_protocol_vhost_options *pvo; const struct msg *pmsg; - uint32_t oldest; void *retval; int n, m, r = 0; @@ -204,21 +203,15 @@ init_fail: case LWS_CALLBACK_ESTABLISHED: /* add ourselves to the list of live pss held in the vhd */ - pss->pss_list = vhd->pss_list; - vhd->pss_list = pss; + lws_ll_fwd_insert(pss, pss_list, vhd->pss_list); pss->tail = lws_ring_get_oldest_tail(vhd->ring); pss->wsi = wsi; break; case LWS_CALLBACK_CLOSED: /* remove our closing pss from the list of live pss */ - lws_start_foreach_llp(struct per_session_data__minimal **, - ppss, vhd->pss_list) { - if (*ppss == pss) { - *ppss = pss->pss_list; - break; - } - } lws_end_foreach_llp(ppss, pss_list); + lws_ll_fwd_remove(struct per_session_data__minimal, pss_list, + pss, vhd->pss_list); break; case LWS_CALLBACK_SERVER_WRITEABLE: @@ -239,26 +232,15 @@ init_fail: return -1; } - n = lws_ring_get_oldest_tail(vhd->ring) == pss->tail; - lws_ring_consume(vhd->ring, &pss->tail, NULL, 1); - - if (n) { /* we may have been the oldest tail */ - n = 0; - oldest = pss->tail; - lws_start_foreach_llp( - struct per_session_data__minimal **, - ppss, vhd->pss_list) { - m = lws_ring_get_count_waiting_elements( - vhd->ring, &(*ppss)->tail); - if (m > n) { - n = m; - oldest = (*ppss)->tail; - } - } lws_end_foreach_llp(ppss, pss_list); - - /* this will delete any entries behind the new oldest */ - lws_ring_update_oldest_tail(vhd->ring, oldest); - } + lws_ring_consume_and_update_oldest_tail( + vhd->ring, /* lws_ring object */ + struct per_session_data__minimal, /* type of objects with tails */ + &pss->tail, /* tail of guy doing the consuming */ + 1, /* number of payload objects being consumed */ + vhd->pss_list, /* head of list of objects with tails */ + tail, /* member name of tail in objects with tails */ + pss_list /* member name of next object in objects with tails */ + ); /* more to do? */ if (lws_ring_get_element(vhd->ring, &pss->tail)) @@ -286,11 +268,6 @@ init_fail: } lws_end_foreach_llp(ppss, pss_list); break; - case LWS_CALLBACK_TIMER: - lwsl_notice("%s: LWS_CALLBACK_TIMER\n", __func__); - lws_set_timer(wsi, 3); - break; - default: break; } diff --git a/plugins/protocol_lws_mirror.c b/plugins/protocol_lws_mirror.c index 65c6459b..646afc6d 100644 --- a/plugins/protocol_lws_mirror.c +++ b/plugins/protocol_lws_mirror.c @@ -266,8 +266,7 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason, /* add our pss to list of guys bound to this mi */ - pss->same_mi_pss_list = mi->same_mi_pss_list; - mi->same_mi_pss_list = pss; + lws_ll_fwd_insert(pss, same_mi_pss_list, mi->same_mi_pss_list); /* init the pss */ @@ -291,14 +290,8 @@ bail1: lws_pthread_mutex_lock(&v->lock); /* vhost lock { */ /* remove our closing pss from its mirror instance list */ - lws_start_foreach_llp(struct per_session_data__lws_mirror **, - ppss, mi->same_mi_pss_list) { - if (*ppss == pss) { - *ppss = pss->same_mi_pss_list; - break; - } - } lws_end_foreach_llp(ppss, same_mi_pss_list); - + lws_ll_fwd_remove(struct per_session_data__lws_mirror, + same_mi_pss_list, pss, mi->same_mi_pss_list); pss->mi = NULL; if (mi->same_mi_pss_list) {