mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
lws_set_timer
This adds a new api lws_set_timer(wsi, secs), which schedules a callback LWS_CALLBACK_TIMER secs seconds into the future. The timer can be continuously deferred by calling lws_set_timer() again before it expires. Calling lws_set_timer(wsi, -1) cancels any pending timer.
This commit is contained in:
parent
8487279e64
commit
7d59122b5f
6 changed files with 125 additions and 15 deletions
|
@ -131,6 +131,12 @@ lws_free_wsi(struct lws *wsi)
|
|||
lws_free(wsi);
|
||||
}
|
||||
|
||||
int
|
||||
lws_should_be_on_timeout_list(struct lws *wsi)
|
||||
{
|
||||
return wsi->timer_active || wsi->pending_timeout;
|
||||
}
|
||||
|
||||
void
|
||||
lws_remove_from_timeout_list(struct lws *wsi)
|
||||
{
|
||||
|
@ -149,9 +155,55 @@ lws_remove_from_timeout_list(struct lws *wsi)
|
|||
/* we're out of the list, we should not point anywhere any more */
|
||||
wsi->timeout_list_prev = NULL;
|
||||
wsi->timeout_list = NULL;
|
||||
|
||||
lws_pt_unlock(pt);
|
||||
}
|
||||
|
||||
static void
|
||||
lws_add_to_timeout_list(struct lws *wsi)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||
|
||||
if (wsi->timeout_list_prev)
|
||||
return;
|
||||
|
||||
/* our next guy is current first guy */
|
||||
wsi->timeout_list = pt->timeout_list;
|
||||
/* if there is a next guy, set his prev ptr to our next ptr */
|
||||
if (wsi->timeout_list)
|
||||
wsi->timeout_list->timeout_list_prev = &wsi->timeout_list;
|
||||
/* our prev ptr is first ptr */
|
||||
wsi->timeout_list_prev = &pt->timeout_list;
|
||||
/* set the first guy to be us */
|
||||
*wsi->timeout_list_prev = wsi;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_set_timer(struct lws *wsi, int secs)
|
||||
{
|
||||
time_t now;
|
||||
|
||||
if (secs < 0) {
|
||||
wsi->timer_active = 0;
|
||||
|
||||
if (!lws_should_be_on_timeout_list(wsi))
|
||||
lws_remove_from_timeout_list(wsi);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
time(&now);
|
||||
|
||||
wsi->pending_timer_limit = secs;
|
||||
wsi->pending_timer_set = now;
|
||||
|
||||
if (!wsi->timer_active) {
|
||||
wsi->timer_active = 1;
|
||||
if (!wsi->pending_timeout)
|
||||
lws_add_to_timeout_list(wsi);
|
||||
}
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
|
||||
{
|
||||
|
@ -169,17 +221,8 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
|
|||
|
||||
time(&now);
|
||||
|
||||
if (reason && !wsi->timeout_list_prev) {
|
||||
/* our next guy is current first guy */
|
||||
wsi->timeout_list = pt->timeout_list;
|
||||
/* if there is a next guy, set his prev ptr to our next ptr */
|
||||
if (wsi->timeout_list)
|
||||
wsi->timeout_list->timeout_list_prev = &wsi->timeout_list;
|
||||
/* our prev ptr is first ptr */
|
||||
wsi->timeout_list_prev = &pt->timeout_list;
|
||||
/* set the first guy to be us */
|
||||
*wsi->timeout_list_prev = wsi;
|
||||
}
|
||||
if (reason)
|
||||
lws_add_to_timeout_list(wsi);
|
||||
|
||||
lwsl_debug("%s: %p: %d secs\n", __func__, wsi, secs);
|
||||
wsi->pending_timeout_limit = secs;
|
||||
|
@ -188,7 +231,7 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
|
|||
|
||||
lws_pt_unlock(pt);
|
||||
|
||||
if (!reason)
|
||||
if (!reason && !lws_should_be_on_timeout_list(wsi))
|
||||
lws_remove_from_timeout_list(wsi);
|
||||
}
|
||||
|
||||
|
|
|
@ -1354,6 +1354,12 @@ enum lws_callback_reasons {
|
|||
* protocol wants to take some action with this information.
|
||||
* \p in is the lws_vhost and \p len is the number of days left
|
||||
* before it expires, as a (ssize_t) */
|
||||
LWS_CALLBACK_TIMER = 73,
|
||||
/**< When the time elapsed after a call to lws_set_timer(wsi, secs)
|
||||
* is up, the wsi will get one of these callbacks. The deadline
|
||||
* can be continuously extended into the future by later calls
|
||||
* to lws_set_timer() before the deadline expires, or cancelled by
|
||||
* lws_set_timer(wsi, -1); */
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
|
||||
|
@ -4404,6 +4410,22 @@ enum pending_timeout {
|
|||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
|
||||
|
||||
/**
|
||||
* lws_set_timer() - schedules a callback on the wsi in the future
|
||||
*
|
||||
* \param wsi: Websocket connection instance
|
||||
* \param secs: -1 removes any existing scheduled callback, otherwise the
|
||||
* number of seconds in the future the callback will occur at.
|
||||
*
|
||||
* When the deadline expires, the wsi will get a callback of type
|
||||
* LWS_CALLBACK_TIMER and the timer is exhausted. The deadline may be
|
||||
* continuously deferred by further calls to lws_set_timer() with a later
|
||||
* deadline, or cancelled by lws_set_timer(wsi, -1)
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_set_timer(struct lws *wsi, int secs);
|
||||
|
||||
///@}
|
||||
|
||||
/*! \defgroup sending-data Sending data
|
||||
|
|
|
@ -1831,6 +1831,7 @@ struct lws {
|
|||
#endif
|
||||
const struct lws_protocols *protocol;
|
||||
struct lws **same_vh_protocol_prev, *same_vh_protocol_next;
|
||||
/* we get on the list if either the timeout or the timer is valid */
|
||||
struct lws *timeout_list;
|
||||
struct lws **timeout_list_prev;
|
||||
#if defined(LWS_WITH_PEER_LIMITS)
|
||||
|
@ -1873,6 +1874,7 @@ struct lws {
|
|||
#endif
|
||||
#endif
|
||||
time_t pending_timeout_set;
|
||||
time_t pending_timer_set;
|
||||
|
||||
/* ints */
|
||||
int position_in_fds_table;
|
||||
|
@ -1915,6 +1917,8 @@ struct lws {
|
|||
unsigned int rxflow_will_be_applied:1;
|
||||
unsigned int event_pipe:1;
|
||||
|
||||
unsigned int timer_active:1;
|
||||
|
||||
#ifdef LWS_WITH_ACCESS_LOG
|
||||
unsigned int access_log_pending:1;
|
||||
#endif
|
||||
|
@ -1944,6 +1948,7 @@ struct lws {
|
|||
unsigned short c_port;
|
||||
#endif
|
||||
unsigned short pending_timeout_limit;
|
||||
unsigned short pending_timer_limit;
|
||||
|
||||
uint8_t state; /* enum lws_connection_states */
|
||||
uint8_t mode; /* enum connection_mode */
|
||||
|
@ -2002,6 +2007,9 @@ remove_wsi_socket_from_fds(struct lws *wsi);
|
|||
LWS_EXTERN int
|
||||
lws_rxflow_cache(struct lws *wsi, unsigned char *buf, int n, int len);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_should_be_on_timeout_list(struct lws *wsi);
|
||||
|
||||
#ifndef LWS_LATENCY
|
||||
static inline void
|
||||
lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
|
||||
|
|
|
@ -579,14 +579,36 @@ lws_service_timeout_check(struct lws *wsi, time_t sec)
|
|||
if (lws_ext_cb_active(wsi, LWS_EXT_CB_1HZ, NULL, sec) < 0)
|
||||
return 0;
|
||||
|
||||
if (!wsi->pending_timeout)
|
||||
return 0;
|
||||
/*
|
||||
* is there a timer callback we should be doing?
|
||||
*/
|
||||
|
||||
if (wsi->timer_active &&
|
||||
lws_compare_time_t(wsi->context, sec, wsi->pending_timer_set) >
|
||||
wsi->pending_timer_limit) {
|
||||
wsi->timer_active = 0;
|
||||
|
||||
if (wsi->protocol &&
|
||||
wsi->protocol->callback(wsi, LWS_CALLBACK_TIMER,
|
||||
wsi->user_space, NULL, 0)) {
|
||||
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lws_should_be_on_timeout_list(wsi)) {
|
||||
lws_remove_from_timeout_list(wsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if we went beyond the allowed time, kill the
|
||||
* connection
|
||||
*/
|
||||
if (lws_compare_time_t(wsi->context, sec, wsi->pending_timeout_set) >
|
||||
if (wsi->pending_timeout &&
|
||||
lws_compare_time_t(wsi->context, sec, wsi->pending_timeout_set) >
|
||||
wsi->pending_timeout_limit) {
|
||||
|
||||
if (wsi->desc.sockfd != LWS_SOCK_INVALID &&
|
||||
|
|
|
@ -91,6 +91,8 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
pss->number = 0;
|
||||
/* just to test the timer api */
|
||||
// lws_set_timer(wsi, 3);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
|
@ -115,6 +117,11 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_TIMER:
|
||||
lwsl_notice("%s: LWS_CALLBACK_TIMER\n", __func__);
|
||||
lws_set_timer(wsi, 3);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
pss->number = 0;
|
||||
/* just to test the timer api */
|
||||
lws_set_timer(wsi, 3);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
|
@ -62,6 +64,12 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_TIMER:
|
||||
lwsl_notice("%s: LWS_CALLBACK_TIMER\n", __func__);
|
||||
lws_set_timer(wsi, 3);
|
||||
break;
|
||||
|
||||
/*
|
||||
* this just demonstrates how to use the protocol filter. If you won't
|
||||
* study and reject connections based on header content, you don't need
|
||||
|
|
Loading…
Add table
Reference in a new issue