diff --git a/CMakeLists.txt b/CMakeLists.txt index f62245ae4..620469b06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1305,6 +1305,11 @@ if (LWS_WITH_HTTP_PROXY) lib/roles/http/server/rewrite.c) endif() +if (LWS_WITH_NETWORK) + list(APPEND SOURCES + lib/event-libs/common.c) +endif() + if (LWS_WITH_POLL AND LWS_WITH_NETWORK) list(APPEND SOURCES lib/event-libs/poll/poll.c) diff --git a/include/libwebsockets.h b/include/libwebsockets.h index 38789dac5..8d81d3070 100644 --- a/include/libwebsockets.h +++ b/include/libwebsockets.h @@ -42,6 +42,12 @@ extern "C" { * CARE: everything using cmake defines needs to be below here */ +#define LWS_US_PER_SEC 1000000 +#define LWS_MS_PER_SEC 1000 +#define LWS_US_PER_MS 1000 + +#define LWS_US_TO_MS(x) ((x + (LWS_US_PER_MS / 2)) / LWS_US_PER_MS) + #if defined(LWS_HAS_INTPTR_T) #include #define lws_intptr_t intptr_t diff --git a/include/libwebsockets/abstract/abstract.h b/include/libwebsockets/abstract/abstract.h index b9d856a14..d8f022842 100644 --- a/include/libwebsockets/abstract/abstract.h +++ b/include/libwebsockets/abstract/abstract.h @@ -73,7 +73,7 @@ typedef struct lws_abs { const struct lws_abs_transport *at; const lws_token_map_t *at_tokens; - lws_sequencer_t *seq; + lws_seq_t *seq; void *opaque_user_data; /* diff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h index d2eab9dec..d218e2b3f 100644 --- a/include/libwebsockets/lws-client.h +++ b/include/libwebsockets/lws-client.h @@ -49,7 +49,7 @@ enum lws_client_connect_ssl_connection_flags { * */ }; -typedef struct lws_sequencer lws_sequencer_t; +typedef struct lws_sequencer lws_seq_t; /** struct lws_client_connect_info - parameters to connect with when using * lws_client_connect_via_info() */ @@ -121,8 +121,8 @@ struct lws_client_connect_info { * tokens */ - lws_sequencer_t *seq; - /**< NULL, or an lws_sequencer_t that wants to be given messages about + lws_seq_t *seq; + /**< NULL, or an lws_seq_t that wants to be given messages about * this wsi's lifecycle as it connects, errors or closes. */ @@ -130,7 +130,7 @@ struct lws_client_connect_info { /**< 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(). * It's also provided with sequencer messages if the wsi is bound to - * an lws_sequencer_t. + * an lws_seq_t. */ /* Add new things just above here ---^ diff --git a/include/libwebsockets/lws-sequencer.h b/include/libwebsockets/lws-sequencer.h index db84325fc..b216a86c0 100644 --- a/include/libwebsockets/lws-sequencer.h +++ b/include/libwebsockets/lws-sequencer.h @@ -56,7 +56,7 @@ typedef enum lws_seq_cb_return { LWSSEQ_RET_DESTROY } lws_seq_cb_return_t; -typedef struct lws_sequencer lws_sequencer_t; /* opaque */ +typedef struct lws_sequencer lws_seq_t; /* opaque */ /* * handler for this sequencer. Return 0 if OK else nonzero to destroy the @@ -83,7 +83,7 @@ typedef struct lws_seq_info { } lws_seq_info_t; /** - * lws_sequencer_create() - create and bind sequencer to a pt + * lws_seq_create() - create and bind sequencer to a pt * * \param info: information about sequencer to create * @@ -97,26 +97,26 @@ typedef struct lws_seq_info { * * pt locking is used to protect the related data structures. */ -LWS_VISIBLE LWS_EXTERN lws_sequencer_t * -lws_sequencer_create(lws_seq_info_t *info); +LWS_VISIBLE LWS_EXTERN lws_seq_t * +lws_seq_create(lws_seq_info_t *info); /** - * lws_sequencer_destroy() - destroy the sequencer + * lws_seq_destroy() - destroy the sequencer * * \param seq: pointer to the the opaque sequencer pointer returned by - * lws_sequencer_create() + * 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_sequencer_destroy(lws_sequencer_t **seq); +lws_seq_destroy(lws_seq_t **seq); /** - * lws_sequencer_queue_event() - queue an event on the given sequencer + * lws_seq_queue_event() - queue an event on the given sequencer * - * \param seq: the opaque sequencer pointer returned by lws_sequencer_create() + * \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 @@ -131,11 +131,11 @@ lws_sequencer_destroy(lws_sequencer_t **seq); * values here. */ LWS_VISIBLE LWS_EXTERN int -lws_sequencer_queue_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data, +lws_seq_queue_event(lws_seq_t *seq, lws_seq_events_t e, void *data, void *aux); /** - * lws_sequencer_check_wsi() - check if wsi still extant + * 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 @@ -151,15 +151,17 @@ lws_sequencer_queue_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data, * close message yet. */ LWS_VISIBLE LWS_EXTERN int -lws_sequencer_check_wsi(lws_sequencer_t *seq, struct lws *wsi); +lws_seq_check_wsi(lws_seq_t *seq, struct lws *wsi); + +#define LWSSEQTO_NONE 0 /** - * lws_sequencer_timeout() - set a timeout by which the sequence must have - * completed by a different event or inform the - * sequencer + * 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 secs: How many seconds in the future to fire the timeout (0 = disable) + * \param us: How many us in the future to fire the timeout (0 = disable) * * 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 @@ -178,54 +180,54 @@ lws_sequencer_check_wsi(lws_sequencer_t *seq, struct lws *wsi); * react appropriately. */ LWS_VISIBLE LWS_EXTERN int -lws_sequencer_timeout(lws_sequencer_t *seq, int secs); +lws_seq_timeout_us(lws_seq_t *seq, lws_usec_t us); /** - * lws_sequencer_from_user(): get the lws_sequencer_t pointer from the user ptr + * lws_seq_from_user(): get the lws_seq_t pointer from the user ptr * - * \param u: the sequencer user allocation returned by lws_sequencer_create() or + * \param u: the sequencer user allocation returned by lws_seq_create() or * provided in the sequencer callback * - * This gets the lws_sequencer_t * from the sequencer user allocation pointer. + * 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_sequencer_t, so lws can compute where - * the lws_sequencer_t is from having the user allocation pointer. Since the - * size of the lws_sequencer_t is unknown to user code, this helper does it for + * 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 lws_sequencer_t * -lws_sequencer_from_user(void *u); +LWS_VISIBLE LWS_EXTERN lws_seq_t * +lws_seq_from_user(void *u); /** - * lws_sequencer_secs_since_creation(): elapsed seconds since sequencer created + * lws_seq_secs_since_creation(): elapsed seconds since sequencer created * - * \param seq: pointer to the lws_sequencer_t + * \param seq: pointer to the lws_seq_t * - * Returns the number of seconds elapsed since the lws_sequencer_t was + * Returns the number of seconds 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 int -lws_sequencer_secs_since_creation(lws_sequencer_t *seq); +lws_seq_secs_since_creation(lws_seq_t *seq); /** - * lws_sequencer_name(): get the name of this sequencer + * lws_seq_name(): get the name of this sequencer * - * \param seq: pointer to the lws_sequencer_t + * \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_sequencer_name(lws_sequencer_t *seq); +lws_seq_name(lws_seq_t *seq); /** - * lws_sequencer_get_context(): get the lws_context sequencer was created on + * lws_seq_get_context(): get the lws_context sequencer was created on * - * \param seq: pointer to the lws_sequencer_t + * \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_sequencer_get_context(lws_sequencer_t *seq); +lws_seq_get_context(lws_seq_t *seq); diff --git a/lib/abstract/test-sequencer.c b/lib/abstract/test-sequencer.c index 89eefb3fd..2872aef36 100644 --- a/lib/abstract/test-sequencer.c +++ b/lib/abstract/test-sequencer.c @@ -21,7 +21,7 @@ * * A helper for running multiple unit tests against abstract protocols. * - * An lws_sequencer_t is used to base its actions in the event loop and manage + * 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 */ @@ -35,7 +35,7 @@ struct lws_seq_test_sequencer { struct lws_context *context; struct lws_vhost *vhost; - lws_sequencer_t *unit_test_seq; + lws_seq_t *unit_test_seq; /* holds the per-test token for the unit-test transport to consume */ lws_token_map_t uttt[4]; @@ -88,7 +88,7 @@ unit_test_result_cb(const void *cb_user, int disposition) return -1; } - lws_sequencer_queue_event(s->unit_test_seq, r, NULL, NULL); + lws_seq_queue_event(s->unit_test_seq, r, NULL, NULL); ((struct lws_seq_test_sequencer *)s)->instance = NULL; @@ -115,7 +115,7 @@ test_sequencer_cb(struct lws_sequencer *seq, void *user, int event, void *data, switch ((int)event) { case LWSSEQ_CREATED: /* our sequencer just got started */ lwsl_notice("%s: %s: created\n", __func__, - lws_sequencer_name(seq)); + lws_seq_name(seq)); s->state = 0; /* first thing we'll do is the first url */ goto step; @@ -178,7 +178,7 @@ pass: s->args.results[s->state] = LPE_SUCCEEDED; done: - lws_sequencer_timeout(lws_sequencer_from_user(s), 0); + lws_seq_timeout_us(lws_seq_from_user(s), LWSSEQTO_NONE); s->state++; step: if (!s->args.tests[s->state].name) { @@ -233,7 +233,7 @@ int lws_abs_unit_test_sequencer(const lws_test_sequencer_args_t *args) { struct lws_seq_test_sequencer *s; - lws_sequencer_t *seq; + lws_seq_t *seq; lws_seq_info_t i; memset(&i, 0, sizeof(i)); @@ -247,7 +247,7 @@ lws_abs_unit_test_sequencer(const lws_test_sequencer_args_t *args) * Create a sequencer in the event loop to manage the tests */ - seq = lws_sequencer_create(&i); + seq = lws_seq_create(&i); if (!seq) { lwsl_err("%s: unable to create sequencer\n", __func__); return 1; diff --git a/lib/abstract/transports/raw-skt.c b/lib/abstract/transports/raw-skt.c index 683efad98..74f08abc7 100644 --- a/lib/abstract/transports/raw-skt.c +++ b/lib/abstract/transports/raw-skt.c @@ -97,7 +97,7 @@ callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason, * our lifecycle events */ - lws_sequencer_queue_event(wsi->seq, LWSSEQ_WSI_CONNECTED, + lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONNECTED, wsi, NULL); break; @@ -112,7 +112,7 @@ callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason, * our lifecycle events */ - lws_sequencer_queue_event(wsi->seq, LWSSEQ_WSI_CONN_FAIL, + lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONN_FAIL, wsi, NULL); goto close_path; @@ -128,7 +128,7 @@ callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason, * our lifecycle events */ - lws_sequencer_queue_event(wsi->seq, LWSSEQ_WSI_CONN_CLOSE, + lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONN_CLOSE, wsi, NULL); close_path: diff --git a/lib/abstract/transports/unit-test.c b/lib/abstract/transports/unit-test.c index 3be03ed33..c8918617d 100644 --- a/lib/abstract/transports/unit-test.c +++ b/lib/abstract/transports/unit-test.c @@ -33,7 +33,7 @@ typedef struct lws_abstxp_unit_test_priv { char note[128]; struct lws_abs *abs; - lws_sequencer_t *seq; + lws_seq_t *seq; lws_unit_test_t *current_test; lws_unit_test_packet_t *expect; lws_unit_test_packet_test_cb result_cb; @@ -78,7 +78,7 @@ lws_unit_test_packet_dispose(abs_unit_test_priv_t *priv, priv->disposition = disp; - lws_sequencer_queue_event(priv->seq, UTSEQ_MSG_DISPOSITION_KNOWN, + lws_seq_queue_event(priv->seq, UTSEQ_MSG_DISPOSITION_KNOWN, NULL, NULL); return disp; @@ -135,10 +135,10 @@ unit_test_sequencer_cb(struct lws_sequencer *seq, void *user, int event, switch ((int)event) { case LWSSEQ_CREATED: /* our sequencer just got started */ lwsl_notice("%s: %s: created\n", __func__, - lws_sequencer_name(seq)); + lws_seq_name(seq)); if (s->ai->at->client_conn(s->ai)) { lwsl_notice("%s: %s: abstract client conn failed\n", - __func__, lws_sequencer_name(seq)); + __func__, lws_seq_name(seq)); return LWSSEQ_RET_DESTROY; } @@ -257,7 +257,8 @@ ph: goto done; done: - lws_sequencer_timeout(lws_sequencer_from_user(s), 0); + lws_seq_timeout_us(lws_seq_from_user(s), + LWSSEQTO_NONE); priv->expect++; if (!priv->expect->buffer) { /* the sequence has completed */ @@ -281,7 +282,7 @@ lws_atcut_close(lws_abs_transport_inst_t *ati) lwsl_notice("%s\n", __func__); - lws_sequencer_queue_event(priv->seq, UTSEQ_MSG_CLOSING, NULL, NULL); + lws_seq_queue_event(priv->seq, UTSEQ_MSG_CLOSING, NULL, NULL); return 0; } @@ -333,7 +334,7 @@ lws_atcut_tx(lws_abs_transport_inst_t *ati, uint8_t *buf, size_t len) priv->expect++; - lws_sequencer_queue_event(priv->seq, UTSEQ_MSG_POST_TX_KICK, NULL, NULL); + lws_seq_queue_event(priv->seq, UTSEQ_MSG_POST_TX_KICK, NULL, NULL); return 0; } @@ -378,12 +379,13 @@ lws_atcut_client_conn(const lws_abs_t *abs) priv->disposition = LPE_CONTINUE; priv->note[0] = '\0'; - lws_sequencer_timeout(priv->seq, priv->current_test->max_secs); + 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_sequencer_queue_event(priv->seq, UTSEQ_MSG_CONNECTING, NULL, NULL); + lws_seq_queue_event(priv->seq, UTSEQ_MSG_CONNECTING, NULL, NULL); return 0; } @@ -402,7 +404,7 @@ lws_atcut_ask_for_writeable(lws_abs_transport_inst_t *ati) * until we have returned to the event loop, just like a real * callback_on_writable() */ - lws_sequencer_queue_event(priv->seq, UTSEQ_MSG_WRITEABLE, NULL, NULL); + lws_seq_queue_event(priv->seq, UTSEQ_MSG_WRITEABLE, NULL, NULL); return 0; } @@ -415,7 +417,7 @@ static int lws_atcut_create(lws_abs_t *ai) { abs_unit_test_priv_t *priv; - lws_sequencer_t *seq; + lws_seq_t *seq; lws_seq_info_t i; seq_priv_t *s; @@ -430,7 +432,7 @@ lws_atcut_create(lws_abs_t *ai) * Create the sequencer for the steps in a single unit test */ - seq = lws_sequencer_create(&i); + seq = lws_seq_create(&i); if (!seq) { lwsl_err("%s: unable to create sequencer\n", __func__); diff --git a/lib/core-net/private.h b/lib/core-net/private.h index 123e3a04a..d56e3bb89 100644 --- a/lib/core-net/private.h +++ b/lib/core-net/private.h @@ -288,6 +288,8 @@ struct lws_context_per_thread { struct lws_pt_tls tls; #endif + lws_usec_t last_heartbeat; + struct lws_pollfd *fds; volatile struct lws_foreign_thread_pollfd * volatile foreign_pfd_list; #ifdef _WIN32 @@ -512,7 +514,7 @@ struct lws { const struct lws_protocols *protocol; struct lws_dll same_vh_protocol; - lws_sequencer_t *seq; /* associated sequencer if any */ + lws_seq_t *seq; /* associated sequencer if any */ struct lws_dll dll_timeout; struct lws_dll dll_hrtimer; @@ -921,8 +923,8 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len); LWS_EXTERN void lws_remove_from_timeout_list(struct lws *wsi); -LWS_EXTERN int -lws_sequencer_timeout_check(struct lws_context_per_thread *pt, time_t now); +LWS_EXTERN lws_usec_t +__lws_seq_timeout_check(struct lws_context_per_thread *pt, lws_usec_t usnow); LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT lws_client_connect_2(struct lws *wsi); @@ -1040,7 +1042,7 @@ int lws_pt_do_pending_sequencer_events(struct lws_context_per_thread *pt); void -lws_sequencer_destroy_all_on_pt(struct lws_context_per_thread *pt); +lws_seq_destroy_all_on_pt(struct lws_context_per_thread *pt); LWS_EXTERN int lws_broadcast(struct lws_context *context, int reason, void *in, size_t len); @@ -1094,7 +1096,7 @@ void __lws_remove_from_timeout_list(struct lws *wsi); lws_usec_t -__lws_hrtimer_service(struct lws_context_per_thread *pt); +__lws_hrtimer_service(struct lws_context_per_thread *pt, lws_usec_t t); int diff --git a/lib/core-net/sequencer.c b/lib/core-net/sequencer.c index 1312d50ed..06d28f7f4 100644 --- a/lib/core-net/sequencer.c +++ b/lib/core-net/sequencer.c @@ -46,19 +46,19 @@ typedef struct lws_sequencer { const char *name; const lws_retry_bo_t *retry; - time_t time_created; - time_t timeout; /* 0 or time we timeout */ + lws_usec_t time_created; + lws_usec_t timeout; /* 0 or time we timeout */ char going_down; -} lws_sequencer_t; +} lws_seq_t; #define QUEUE_SANITY_LIMIT 10 -lws_sequencer_t * -lws_sequencer_create(lws_seq_info_t *i) +lws_seq_t * +lws_seq_create(lws_seq_info_t *i) { struct lws_context_per_thread *pt = &i->context->pt[i->tsi]; - lws_sequencer_t *seq = lws_zalloc(sizeof(*seq) + i->user_size, __func__); + lws_seq_t *seq = lws_zalloc(sizeof(*seq) + i->user_size, __func__); if (!seq) return NULL; @@ -78,11 +78,11 @@ lws_sequencer_create(lws_seq_info_t *i) lws_pt_unlock(pt); /* } pt ------------------------------------------ */ - time(&seq->time_created); + seq->time_created = lws_now_usecs(); /* try to queue the creation cb */ - if (lws_sequencer_queue_event(seq, LWSSEQ_CREATED, NULL, NULL)) { + if (lws_seq_queue_event(seq, LWSSEQ_CREATED, NULL, NULL)) { lws_dll2_remove(&seq->seq_list); lws_free(seq); @@ -105,9 +105,9 @@ seq_ev_destroy(struct lws_dll2 *d, void *user) } void -lws_sequencer_destroy(lws_sequencer_t **pseq) +lws_seq_destroy(lws_seq_t **pseq) { - lws_sequencer_t *seq = *pseq; + lws_seq_t *seq = *pseq; /* defeat another thread racing to add events while we are destroying */ seq->going_down = 1; @@ -129,20 +129,20 @@ lws_sequencer_destroy(lws_sequencer_t **pseq) } void -lws_sequencer_destroy_all_on_pt(struct lws_context_per_thread *pt) +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_sequencer_t *s = lws_container_of(p, lws_sequencer_t, + lws_seq_t *s = lws_container_of(p, lws_seq_t, seq_list); - lws_sequencer_destroy(&s); + lws_seq_destroy(&s); } lws_end_foreach_dll_safe(p, tp); } int -lws_sequencer_queue_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data, +lws_seq_queue_event(lws_seq_t *seq, lws_seq_events_t e, void *data, void *aux) { lws_seq_event_t *seqe; @@ -191,7 +191,7 @@ lws_sequencer_queue_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data, */ int -lws_sequencer_check_wsi(lws_sequencer_t *seq, struct lws *wsi) +lws_seq_check_wsi(lws_seq_t *seq, struct lws *wsi) { lws_seq_event_t *seqe; struct lws_dll2 *dh; @@ -220,9 +220,9 @@ lws_sequencer_check_wsi(lws_sequencer_t *seq, struct lws *wsi) */ static int -lws_sequencer_next_event(struct lws_dll2 *d, void *user) +lws_seq_next_event(struct lws_dll2 *d, void *user) { - lws_sequencer_t *seq = lws_container_of(d, lws_sequencer_t, + lws_seq_t *seq = lws_container_of(d, lws_seq_t, seq_pend_list); lws_seq_event_t *seqe; struct lws_dll2 *dh; @@ -258,7 +258,7 @@ lws_sequencer_next_event(struct lws_dll2 *d, void *user) if (n) { lwsl_info("%s: destroying seq '%s' by request\n", __func__, seq->name); - lws_sequencer_destroy(&seq); + lws_seq_destroy(&seq); return LWSSEQ_RET_DESTROY; } @@ -278,25 +278,24 @@ lws_pt_do_pending_sequencer_events(struct lws_context_per_thread *pt) return 0; return lws_dll2_foreach_safe(&pt->seq_pend_owner, NULL, - lws_sequencer_next_event); + lws_seq_next_event); } /* set secs to zero to remove timeout */ int -lws_sequencer_timeout(lws_sequencer_t *seq, int secs) +lws_seq_timeout_us(lws_seq_t *seq, lws_usec_t us) { lws_dll2_remove(&seq->seq_to_list); - if (!secs) { + if (!us) { /* we are clearing the timeout */ seq->timeout = 0; return 0; } - time(&seq->timeout); - seq->timeout += secs; + seq->timeout = lws_now_usecs() + us; /* * we sort the pt's list of sequencers with pending timeouts, so it's @@ -305,14 +304,12 @@ lws_sequencer_timeout(lws_sequencer_t *seq, int secs) lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, seq->pt->seq_to_owner.head) { - lws_sequencer_t *s = lws_container_of(p, lws_sequencer_t, - seq_to_list); + lws_seq_t *s = lws_container_of(p, lws_seq_t, seq_to_list); assert(s->timeout); /* shouldn't be on the list otherwise */ if (s->timeout >= seq->timeout) { /* drop us in before this guy */ - lws_dll2_add_before(&seq->seq_to_list, - &s->seq_to_list); + lws_dll2_add_before(&seq->seq_to_list, &s->seq_to_list); return 0; } @@ -330,61 +327,70 @@ lws_sequencer_timeout(lws_sequencer_t *seq, int secs) /* * nonpublic helper to check for and handle sequencer timeouts for a whole pt + * returns either 0 or number of us until next event (which cannot be 0 or we + * would have serviced it) */ -int -lws_sequencer_timeout_check(struct lws_context_per_thread *pt, time_t now) +lws_usec_t +__lws_seq_timeout_check(struct lws_context_per_thread *pt, lws_usec_t usnow) { + lws_usec_t future_us = 0; + lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, pt->seq_to_owner.head) { - lws_sequencer_t *s = lws_container_of(p, lws_sequencer_t, - seq_to_list); + lws_seq_t *s = lws_container_of(p, lws_seq_t, seq_to_list); assert(s->timeout); /* shouldn't be on the list otherwise */ - if (s->timeout <= now) { + if (s->timeout <= usnow) { /* seq has timed out... remove him from timeout list */ - lws_sequencer_timeout(s, 0); + lws_seq_timeout_us(s, LWSSEQTO_NONE); /* queue the message to inform the sequencer */ - lws_sequencer_queue_event(s, LWSSEQ_TIMED_OUT, - NULL, NULL); - } else + lws_seq_queue_event(s, LWSSEQ_TIMED_OUT, NULL, NULL); + } else { /* * No need to look further if we met one later than now: * the list is sorted in ascending time order */ - return 0; + future_us = usnow - s->timeout; + + break; + } } lws_end_foreach_dll_safe(p, tp); + if (usnow - pt->last_heartbeat< LWS_US_PER_SEC) + return future_us; + + pt->last_heartbeat = usnow; + /* send every sequencer a heartbeat message... it can ignore it */ lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp, pt->seq_owner.head) { - lws_sequencer_t *s = lws_container_of(p, lws_sequencer_t, - seq_list); + lws_seq_t *s = lws_container_of(p, lws_seq_t, seq_list); /* queue the message to inform the sequencer */ - lws_sequencer_queue_event(s, LWSSEQ_HEARTBEAT, NULL, NULL); + lws_seq_queue_event(s, LWSSEQ_HEARTBEAT, NULL, NULL); } lws_end_foreach_dll_safe(p, tp); - return 0; + return future_us; } -lws_sequencer_t * -lws_sequencer_from_user(void *u) +lws_seq_t * +lws_seq_from_user(void *u) { - return &((lws_sequencer_t *)u)[-1]; + return &((lws_seq_t *)u)[-1]; } const char * -lws_sequencer_name(lws_sequencer_t *seq) +lws_seq_name(lws_seq_t *seq) { return seq->name; } int -lws_sequencer_secs_since_creation(lws_sequencer_t *seq) +lws_seq_secs_since_creation(lws_seq_t *seq) { time_t now; @@ -394,7 +400,7 @@ lws_sequencer_secs_since_creation(lws_sequencer_t *seq) } struct lws_context * -lws_sequencer_get_context(lws_sequencer_t *seq) +lws_seq_get_context(lws_seq_t *seq) { return seq->pt->context; } diff --git a/lib/core-net/service.c b/lib/core-net/service.c index a14a303f8..a52942144 100644 --- a/lib/core-net/service.c +++ b/lib/core-net/service.c @@ -603,6 +603,7 @@ lws_service_periodic_checks(struct lws_context *context, lws_sockfd_type our_fd = 0, tmp_fd; struct lws *wsi; int timed_out = 0; + lws_usec_t usnow; time_t now; #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) struct allocated_headers *ah; @@ -615,14 +616,15 @@ lws_service_periodic_checks(struct lws_context *context, return -1; } - time(&now); + usnow = lws_now_usecs(); + now = usnow / LWS_US_PER_SEC; /* * handle case that system time was uninitialized when lws started * at boot, and got initialized a little later */ if (context->time_up < 1464083026 && now > 1464083026) - context->time_up = now; + context->time_up = now / LWS_US_PER_SEC; if (context->last_timeout_check_s && now - context->last_timeout_check_s > 100) { @@ -648,7 +650,7 @@ lws_service_periodic_checks(struct lws_context *context, context->last_timeout_check_s = now - 1; } - lws_sequencer_timeout_check(pt, now); + __lws_seq_timeout_check(pt, usnow); lws_pt_do_pending_sequencer_events(pt); if (!lws_compare_time_t(context, context->last_timeout_check_s, now)) @@ -1086,7 +1088,7 @@ handled: lws_service_periodic_checks(context, pollfd, tsi); lws_pt_lock(pt, __func__); - __lws_hrtimer_service(pt); + __lws_hrtimer_service(pt, lws_now_usecs()); lws_pt_unlock(pt); return 0; diff --git a/lib/core-net/wsi-timeout.c b/lib/core-net/wsi-timeout.c index 6e2d10bb4..5702badc4 100644 --- a/lib/core-net/wsi-timeout.c +++ b/lib/core-net/wsi-timeout.c @@ -82,16 +82,12 @@ lws_set_timer_usecs(struct lws *wsi, lws_usec_t usecs) __lws_set_timer_usecs(wsi, usecs); } +/* return 0 if nothing pending, or the number of us before the next event */ lws_usec_t -__lws_hrtimer_service(struct lws_context_per_thread *pt) +__lws_hrtimer_service(struct lws_context_per_thread *pt, lws_usec_t t) { - struct timeval now; struct lws *wsi; - lws_usec_t t; - - gettimeofday(&now, NULL); - t = (now.tv_sec * 1000000ll) + now.tv_usec; lws_start_foreach_dll_safe(struct lws_dll *, d, d1, pt->dll_hrtimer_head.next) { @@ -118,18 +114,16 @@ __lws_hrtimer_service(struct lws_context_per_thread *pt) /* return an estimate how many us until next timer hit */ if (!pt->dll_hrtimer_head.next) - return LWS_HRTIMER_NOWAIT; + return 0; /* there is nothing pending */ wsi = lws_container_of(pt->dll_hrtimer_head.next, struct lws, dll_hrtimer); - gettimeofday(&now, NULL); - t = (now.tv_sec * 1000000ll) + now.tv_usec; + t = lws_now_usecs(); + if (wsi->pending_timer <= t) /* in the past */ + return 1; - if (wsi->pending_timer < t) - return 0; - - return wsi->pending_timer - t; + return wsi->pending_timer - t; /* at least 1 */ } void diff --git a/lib/core/context.c b/lib/core/context.c index 31df3e616..0ed77b5e1 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -552,7 +552,7 @@ lws_context_destroy3(struct lws_context *context) for (n = 0; n < context->count_threads; n++) { struct lws_context_per_thread *pt = &context->pt[n]; - lws_sequencer_destroy_all_on_pt(pt); + lws_seq_destroy_all_on_pt(pt); if (context->event_loop_ops->destroy_pt) context->event_loop_ops->destroy_pt(context, n); diff --git a/lib/core/private.h b/lib/core/private.h index a92006647..f0d1c2817 100644 --- a/lib/core/private.h +++ b/lib/core/private.h @@ -241,8 +241,6 @@ lws_mutex_refcount_unlock(struct lws_mutex_refcount *mr); #include "core-net/private.h" #endif -#define LWS_HRTIMER_NOWAIT (0x7fffffffffffffffll) - struct lws_deferred_free { struct lws_deferred_free *next; diff --git a/lib/event-libs/common.c b/lib/event-libs/common.c new file mode 100644 index 000000000..cd902533f --- /dev/null +++ b/lib/event-libs/common.c @@ -0,0 +1,43 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010-2018 Andy Green + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation: + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include "core/private.h" + +lws_usec_t +__lws_event_service_get_earliest_wake(struct lws_context_per_thread *pt, + lws_usec_t usnow) +{ + lws_usec_t t, us = 0; + char seen = 0; + + t = __lws_hrtimer_service(pt, usnow); + if (t && (!seen || t < us)) { + us = t; + seen = 1; + } + t = __lws_seq_timeout_check(pt, usnow); + if (t && (!seen || t < us)) { + us = t; + seen = 1; + } + + return us; +} diff --git a/lib/event-libs/libev/libev.c b/lib/event-libs/libev/libev.c index 26f41a638..0f02f753c 100644 --- a/lib/event-libs/libev/libev.c +++ b/lib/event-libs/libev/libev.c @@ -29,8 +29,8 @@ lws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) lws_usec_t us; lws_pt_lock(pt, __func__); - us = __lws_hrtimer_service(pt); - if (us != LWS_HRTIMER_NOWAIT) { + us = __lws_event_service_get_earliest_wake(pt, lws_now_usecs()); + if (us) { ev_timer_set(&pt->ev.hrtimer, ((float)us) / 1000000.0, 0); ev_timer_start(pt->ev.io_loop, &pt->ev.hrtimer); } @@ -61,8 +61,8 @@ lws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents) /* account for hrtimer */ lws_pt_lock(pt, __func__); - us = __lws_hrtimer_service(pt); - if (us != LWS_HRTIMER_NOWAIT) { + us = __lws_event_service_get_earliest_wake(pt, lws_now_usecs()); + if (us) { ev_timer_set(&pt->ev.hrtimer, ((float)us) / 1000000.0, 0); ev_timer_start(pt->ev.io_loop, &pt->ev.hrtimer); } diff --git a/lib/event-libs/libevent/libevent.c b/lib/event-libs/libevent/libevent.c index e1f48a489..764eb6f47 100644 --- a/lib/event-libs/libevent/libevent.c +++ b/lib/event-libs/libevent/libevent.c @@ -29,10 +29,10 @@ lws_event_hrtimer_cb(int fd, short event, void *p) lws_usec_t us; lws_pt_lock(pt, __func__); - us = __lws_hrtimer_service(pt); - if (us != LWS_HRTIMER_NOWAIT) { - tv.tv_sec = us / 1000000; - tv.tv_usec = us - (tv.tv_sec * 1000000); + us = __lws_event_service_get_earliest_wake(pt, lws_now_usecs()); + if (us) { + tv.tv_sec = us / LWS_US_PER_SEC; + tv.tv_usec = us - (tv.tv_sec * LWS_US_PER_SEC); evtimer_add(pt->event.hrtimer, &tv); } lws_pt_unlock(pt); @@ -70,10 +70,10 @@ lws_event_idle_timer_cb(int fd, short event, void *p) /* account for hrtimer */ lws_pt_lock(pt, __func__); - us = __lws_hrtimer_service(pt); - if (us != LWS_HRTIMER_NOWAIT) { - tv.tv_sec = us / 1000000; - tv.tv_usec = us - (tv.tv_sec * 1000000); + us = __lws_event_service_get_earliest_wake(pt, lws_now_usecs()); + if (us) { + tv.tv_sec = us / LWS_US_PER_SEC; + tv.tv_usec = us - (tv.tv_sec * LWS_US_PER_SEC); evtimer_add(pt->event.hrtimer, &tv); } lws_pt_unlock(pt); diff --git a/lib/event-libs/libuv/libuv.c b/lib/event-libs/libuv/libuv.c index 3650eee47..89a9c1ce1 100644 --- a/lib/event-libs/libuv/libuv.c +++ b/lib/event-libs/libuv/libuv.c @@ -33,9 +33,10 @@ lws_uv_hrtimer_cb(uv_timer_t *timer lws_usec_t us; lws_pt_lock(pt, __func__); - us = __lws_hrtimer_service(pt); - if (us != LWS_HRTIMER_NOWAIT) - uv_timer_start(&pt->uv.hrtimer, lws_uv_hrtimer_cb, us / 1000, 0); + us = __lws_event_service_get_earliest_wake(pt, lws_now_usecs()); + if (us) + uv_timer_start(&pt->uv.hrtimer, lws_uv_hrtimer_cb, + LWS_US_TO_MS(us), 0); lws_pt_unlock(pt); } @@ -67,9 +68,10 @@ lws_uv_idle(uv_idle_t *handle /* account for hrtimer */ lws_pt_lock(pt, __func__); - us = __lws_hrtimer_service(pt); - if (us != LWS_HRTIMER_NOWAIT) - uv_timer_start(&pt->uv.hrtimer, lws_uv_hrtimer_cb, us / 1000, 0); + us = __lws_event_service_get_earliest_wake(pt, lws_now_usecs()); + if (us) + uv_timer_start(&pt->uv.hrtimer, lws_uv_hrtimer_cb, + LWS_US_TO_MS(us), 0); lws_pt_unlock(pt); /* there is nobody who needs service forcing, shut down idle */ diff --git a/lib/event-libs/private.h b/lib/event-libs/private.h index 58bca946b..da0f9c4a9 100644 --- a/lib/event-libs/private.h +++ b/lib/event-libs/private.h @@ -54,6 +54,12 @@ struct lws_event_loop_ops { unsigned int periodic_events_available:1; }; +struct lws_context_per_thread; + +lws_usec_t +__lws_event_service_get_earliest_wake(struct lws_context_per_thread *pt, + lws_usec_t usnow); + /* bring in event libs private declarations */ #if defined(LWS_WITH_POLL) diff --git a/lib/plat/esp32/esp32-service.c b/lib/plat/esp32/esp32-service.c index 5ca16a38d..056b9d0d5 100644 --- a/lib/plat/esp32/esp32-service.c +++ b/lib/plat/esp32/esp32-service.c @@ -38,6 +38,7 @@ lws_plat_service(struct lws_context *context, int timeout_ms) LWS_EXTERN int _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) { + lws_usec_t timeout_us = timeout_ms * LWS_US_PER_MS; struct lws_context_per_thread *pt; int n = -1, m, c; @@ -101,24 +102,28 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* still somebody left who wants forced service? */ if (!lws_service_adjust_timeout(context, 1, pt->tid)) /* yes... come back again quickly */ - timeout_ms = 0; + timeout_us = 0; } - if (timeout_ms) { + if (timeout_us) { + lws_usec_t t, us = lws_now_usecs(); lws_pt_lock(pt, __func__); - /* don't stay in poll wait longer than next hr timeout */ - lws_usec_t t = __lws_hrtimer_service(pt); - - if ((lws_usec_t)timeout_ms * 1000 > t) - timeout_ms = t / 1000; + /* don't stay in poll wait longer than next hr timeout... */ + t = __lws_hrtimer_service(pt, us); + if (t && timeout_us > t) + timeout_us = t; + /* ... or next sequencer timeout */ + t = __lws_seq_timeout_check(pt, us); + if (t && timeout_us > t) + timeout_us = t; lws_pt_unlock(pt); } // n = poll(pt->fds, pt->fds_count, timeout_ms); { fd_set readfds, writefds, errfds; - struct timeval tv = { timeout_ms / 1000, - (timeout_ms % 1000) * 1000 }, *ptv = &tv; + struct timeval tv = { timeout_us / LWS_US_PER_SEC, + timeout_us % LWS_US_PER_SEC }, *ptv = &tv; int max_fd = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); diff --git a/lib/plat/optee/network.c b/lib/plat/optee/network.c index a3052932a..f1f976b79 100644 --- a/lib/plat/optee/network.c +++ b/lib/plat/optee/network.c @@ -58,6 +58,7 @@ lws_poll_listen_fd(struct lws_pollfd *fd) LWS_EXTERN int _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) { + lws_usec_t timeout_us = timeout_ms * LWS_US_PER_MS; struct lws_context_per_thread *pt; int n = -1, m, c; //char buf; @@ -93,10 +94,24 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* still somebody left who wants forced service? */ if (!lws_service_adjust_timeout(context, 1, pt->tid)) /* yes... come back again quickly */ - timeout_ms = 0; + timeout_us = 0; } - n = poll(pt->fds, pt->fds_count, timeout_ms); + if (timeout_us) { + lws_usec_t t, us = lws_now_usecs(); + + lws_pt_lock(pt, __func__); + /* don't stay in poll wait longer than next hr timeout */ + t = __lws_hrtimer_service(pt, us); + if (t && timeout_us > t) + timeout_us = t; + t = __lws_seq_timeout_check(pt, us); + if (t && timeout_us > t) + timeout_us = t; + lws_pt_unlock(pt); + } + + n = poll(pt->fds, pt->fds_count, timeout_us / LWS_US_PER_MS); m = 0; diff --git a/lib/plat/unix/unix-service.c b/lib/plat/unix/unix-service.c index a94f6f5fb..83c4c3e9f 100644 --- a/lib/plat/unix/unix-service.c +++ b/lib/plat/unix/unix-service.c @@ -36,6 +36,7 @@ LWS_EXTERN int _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) { volatile struct lws_foreign_thread_pollfd *ftp, *next; + lws_usec_t timeout_us = timeout_ms * LWS_US_PER_MS; volatile struct lws_context_per_thread *vpt; struct lws_context_per_thread *pt; int n = -1, m, c; @@ -62,9 +63,9 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) memset(&_lws, 0, sizeof(_lws)); _lws.context = context; - pt->service_tid = - context->vhost_list->protocols[0].callback( - &_lws, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); + pt->service_tid = context->vhost_list->protocols[0].callback( + &_lws, LWS_CALLBACK_GET_THREAD_ID, + NULL, NULL, 0); pt->service_tid_detected = 1; } @@ -77,21 +78,24 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* still somebody left who wants forced service? */ if (!lws_service_adjust_timeout(context, 1, pt->tid)) /* yes... come back again quickly */ - timeout_ms = 0; + timeout_us = 0; } - if (timeout_ms) { + if (timeout_us) { + lws_usec_t t; + lws_pt_lock(pt, __func__); /* don't stay in poll wait longer than next hr timeout */ - lws_usec_t t = __lws_hrtimer_service(pt); - if ((lws_usec_t)timeout_ms * 1000 > t) - timeout_ms = t / 1000; + t = __lws_event_service_get_earliest_wake(pt, lws_now_usecs()); + if (t && t < timeout_us) + timeout_us = t; + lws_pt_unlock(pt); } vpt->inside_poll = 1; lws_memory_barrier(); - n = poll(pt->fds, pt->fds_count, timeout_ms); + n = poll(pt->fds, pt->fds_count, timeout_us / LWS_US_PER_MS); vpt->inside_poll = 0; lws_memory_barrier(); @@ -130,7 +134,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* we have come out of a poll wait... check the hrtimer list */ - __lws_hrtimer_service(pt); + __lws_hrtimer_service(pt, lws_now_usecs()); lws_pt_unlock(pt); diff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c index c95ff0fa0..614baea23 100644 --- a/lib/plat/windows/windows-service.c +++ b/lib/plat/windows/windows-service.c @@ -28,6 +28,7 @@ LWS_EXTERN int _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) { + lws_usec_t timeout_us = timeout_ms * LWS_US_PER_MS; struct lws_context_per_thread *pt; WSANETWORKEVENTS networkevents; struct lws_pollfd *pfd; @@ -114,18 +115,21 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* still somebody left who wants forced service? */ if (!lws_service_adjust_timeout(context, 1, pt->tid)) /* yes... come back again quickly */ - timeout_ms = 0; + timeout_us = 0; } - if (timeout_ms) { - lws_usec_t t; + if (timeout_us) { + lws_usec_t t, us = lws_now_usecs(); lws_pt_lock(pt, __func__); - /* don't stay in poll wait longer than next hr timeout */ - t = __lws_hrtimer_service(pt); - - if ((lws_usec_t)timeout_ms * 1000 > t) - timeout_ms = (int)(t / 1000); + /* don't stay in poll wait longer than next hr timeout... */ + t = __lws_hrtimer_service(pt, us); + if (t && timeout_us > t) + timeout_us = t; + /* ... or next sequencer timeout */ + t = __lws_seq_timeout_check(pt, us); + if (t && timeout_us > t) + timeout_us = t; lws_pt_unlock(pt); } @@ -137,7 +141,8 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) FD_ROUTING_INTERFACE_CHANGE | FD_ADDRESS_LIST_CHANGE); - ev = WSAWaitForMultipleEvents(1, &pt->events, FALSE, timeout_ms, FALSE); + ev = WSAWaitForMultipleEvents(1, &pt->events, FALSE, + timeout_us / LWS_US_PER_MS, FALSE); if (ev == WSA_WAIT_EVENT_0) { EnterCriticalSection(&pt->interrupt_lock); interrupt_requested = pt->interrupt_requested; diff --git a/minimal-examples/api-tests/api-test-lws_sequencer/main.c b/minimal-examples/api-tests/api-test-lws_sequencer/main.c index 7924c0c5d..04dcda2b8 100644 --- a/minimal-examples/api-tests/api-test-lws_sequencer/main.c +++ b/minimal-examples/api-tests/api-test-lws_sequencer/main.c @@ -162,7 +162,7 @@ notify: lws_set_wsi_user(wsi, NULL); s->cwsi = NULL; - lws_sequencer_queue_event(lws_sequencer_from_user(s), seq_msg, + lws_seq_queue_event(lws_seq_from_user(s), seq_msg, NULL, NULL); return 0; @@ -185,7 +185,7 @@ sequencer_start_client(struct myseq *s) lws_strncpy(uri, url_paths[s->state], sizeof(uri)); memset(&i, 0, sizeof i); - i.context = lws_sequencer_get_context(lws_sequencer_from_user(s)); + i.context = lws_seq_get_context(lws_seq_from_user(s)); if (lws_parse_uri(uri, &prot, &i.address, &i.port, &path1)) { lwsl_err("%s: uri error %s\n", __func__, uri); @@ -217,13 +217,13 @@ sequencer_start_client(struct myseq *s) /* we couldn't even get started with the client connection */ - lws_sequencer_queue_event(lws_sequencer_from_user(s), + lws_seq_queue_event(lws_seq_from_user(s), SEQ_MSG_CLIENT_FAILED, NULL, NULL); return 1; } - lws_sequencer_timeout(lws_sequencer_from_user(s), 3); + lws_seq_timeout_us(lws_seq_from_user(s), 3 * LWS_US_PER_SEC); lwsl_notice("%s: wsi %p: connecting to %s://%s:%d%s\n", __func__, s->cwsi, prot, i.address, i.port, path); @@ -297,7 +297,7 @@ sequencer_cb(struct lws_sequencer *seq, void *user, int event, s->state, s->http_resp); done: - lws_sequencer_timeout(lws_sequencer_from_user(s), 0); + lws_seq_timeout_us(lws_seq_from_user(s), LWSSEQTO_NONE); s->state++; if (s->state == LWS_ARRAY_SIZE(url_paths)) { /* the sequence has completed */ @@ -324,7 +324,7 @@ main(int argc, const char **argv) int n = 1, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; struct lws_context_creation_info info; struct lws_context *context; - lws_sequencer_t *seq; + lws_seq_t *seq; struct lws_vhost *vh; lws_seq_info_t i; struct myseq *s; @@ -378,7 +378,7 @@ main(int argc, const char **argv) i.cb = sequencer_cb; i.name = "seq"; - seq = lws_sequencer_create(&i); + seq = lws_seq_create(&i); if (!seq) { lwsl_err("%s: unable to create sequencer\n", __func__); goto bail1;