1 /* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to 8 * deal in the Software without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 * 24 * lws_sequencer is intended to help implement sequences that: 25 * 26 * - outlive a single connection lifetime, 27 * - are not associated with a particular protocol, 28 * - are not associated with a particular vhost, 29 * - must receive and issue events inside the event loop 30 * 31 * lws_sequencer-s are bound to a pt (per-thread) which for the default case of 32 * one service thread is the same as binding to an lws_context. 33 */ 34 /* 35 * retry backoff table... retry n happens after .retry_ms_table[n] ms, with 36 * the last entry used if n is greater than the number of entries. 37 * 38 * The first .conceal_count retries are concealed, but after that the failures 39 * are reported. 40 */ 41 42 typedef enum { 43 LWSSEQ_CREATED, /* sequencer created */ 44 LWSSEQ_DESTROYED, /* sequencer destroyed */ 45 LWSSEQ_TIMED_OUT, /* sequencer timeout */ 46 LWSSEQ_HEARTBEAT, /* 1Hz callback */ 47 48 LWSSEQ_WSI_CONNECTED, /* wsi we bound to us has connected */ 49 LWSSEQ_WSI_CONN_FAIL, /* wsi we bound to us has failed to connect */ 50 LWSSEQ_WSI_CONN_CLOSE, /* wsi we bound to us has closed */ 51 52 53 LWSSEQ_SS_STATE_BASE, /* secure streams owned by a sequencer provide 54 * automatic messages about state changes on 55 * the sequencer, passing the oridinal in the 56 * event argument field. The message index is 57 * LWSSEQ_SS_STATE_BASE + the enum from 58 * lws_ss_constate_t */ 59 60 LWSSEQ_USER_BASE = 100 /* define your events from here */ 61 } lws_seq_events_t; 62 63 typedef enum lws_seq_cb_return { 64 LWSSEQ_RET_CONTINUE, 65 LWSSEQ_RET_DESTROY 66 } lws_seq_cb_return_t; 67 68 /* 69 * handler for this sequencer. Return 0 if OK else nonzero to destroy the 70 * sequencer. LWSSEQ_DESTROYED will be called back to the handler so it can 71 * close / destroy any private assets associated with the sequence. 72 * 73 * The callback may return either LWSSEQ_RET_CONTINUE for the sequencer to 74 * resume or LWSSEQ_RET_DESTROY to indicate the sequence is finished. 75 * 76 * Event indexes consist of some generic ones but mainly user-defined ones 77 * starting from LWSSEQ_USER_BASE. 78 */ 79 typedef lws_seq_cb_return_t (*lws_seq_event_cb)(struct lws_sequencer *seq, 80 void *user, int event, void *data, void *aux); 81 82 typedef struct lws_seq_info { 83 struct lws_context *context; /* lws_context for seq */ 84 int tsi; /* thread service idx */ 85 size_t user_size; /* size of user alloc */ 86 void **puser; /* place ptr to user */ 87 lws_seq_event_cb cb; /* seq callback */ 88 const char *name; /* seq name */ 89 const lws_retry_bo_t *retry; /* retry policy */ 90 } lws_seq_info_t; 91 92 /** 93 * lws_seq_create() - create and bind sequencer to a pt 94 * 95 * \param info: information about sequencer to create 96 * 97 * This binds an abstract sequencer to a per-thread (by default, the single 98 * event loop of an lws_context). After the event loop starts, the sequencer 99 * will receive an LWSSEQ_CREATED event on its callback from the event loop 100 * context, where it can begin its sequence flow. 101 * 102 * Lws itself will only call the callback subsequently with LWSSEQ_DESTROYED 103 * when the sequencer is being destroyed. 104 * 105 * pt locking is used to protect the related data structures. 106 */ 107 LWS_VISIBLE LWS_EXTERN struct lws_sequencer * 108 lws_seq_create(lws_seq_info_t *info); 109 110 /** 111 * lws_seq_destroy() - destroy the sequencer 112 * 113 * \param seq: pointer to the the opaque sequencer pointer returned by 114 * lws_seq_create() 115 * 116 * This proceeds to destroy the sequencer, calling LWSSEQ_DESTROYED and then 117 * freeing the sequencer object itself. The pointed-to seq pointer will be 118 * set to NULL. 119 */ 120 LWS_VISIBLE LWS_EXTERN void 121 lws_seq_destroy(struct lws_sequencer **seq); 122 123 /** 124 * lws_seq_queue_event() - queue an event on the given sequencer 125 * 126 * \param seq: the opaque sequencer pointer returned by lws_seq_create() 127 * \param e: the event index to queue 128 * \param data: associated opaque (to lws) data to provide the callback 129 * \param aux: second opaque data to provide the callback 130 * 131 * This queues the event on a given sequencer. Queued events are delivered one 132 * per sequencer each subsequent time around the event loop, so the cb is called 133 * from the event loop thread context. 134 * 135 * Notice that because the events are delivered in order from the event loop, 136 * the scope of objects pointed to by \p data or \p aux may exceed the lifetime 137 * of the thing containing the pointed-to data. So it's usually better to pass 138 * values here. 139 */ 140 LWS_VISIBLE LWS_EXTERN int 141 lws_seq_queue_event(struct lws_sequencer *seq, lws_seq_events_t e, void *data, 142 void *aux); 143 144 /** 145 * lws_seq_check_wsi() - check if wsi still extant 146 * 147 * \param seq: the sequencer interested in the wsi 148 * \param wsi: the wsi we want to confirm hasn't closed yet 149 * 150 * Check if wsi still extant, by peeking in the message queue for a 151 * LWSSEQ_WSI_CONN_CLOSE message about wsi. (Doesn't need to do the same for 152 * CONN_FAIL since that will never have produced any messages prior to that). 153 * 154 * Use this to avoid trying to perform operations on wsi that have already 155 * closed but we didn't get to that message yet. 156 * 157 * Returns 0 if not closed yet or 1 if it has closed but we didn't process the 158 * close message yet. 159 */ 160 LWS_VISIBLE LWS_EXTERN int 161 lws_seq_check_wsi(struct lws_sequencer *seq, struct lws *wsi); 162 163 #define LWSSEQTO_NONE 0 164 165 /** 166 * lws_seq_timeout_us() - set a timeout by which the sequence must have 167 * completed by a different event or inform the 168 * sequencer 169 * 170 * \param seq: The sequencer to set the timeout on 171 * \param us: How many us in the future to fire the timeout 172 * LWS_SET_TIMER_USEC_CANCEL = cancel any existing timeout 173 * 174 * This api allows the sequencer to ask to be informed if it has not completed 175 * or disabled its timeout after secs seconds. Lws will send a LWSSEQ_TIMED_OUT 176 * event to the sequencer if the timeout expires. 177 * 178 * Typically the sequencer sets the timeout when starting a step, then waits to 179 * hear a queued event informing it the step completed or failed. The timeout 180 * provides a way to deal with the case the step neither completed nor failed 181 * within the timeout period. 182 * 183 * Lws wsi timeouts are not really suitable for this since they are focused on 184 * short-term protocol timeout protection and may be set and reset many times 185 * in one transaction. Wsi timeouts also enforce closure of the wsi when they 186 * trigger, sequencer timeouts have no side effect except to queue the 187 * LWSSEQ_TIMED_OUT message and leave it to the sequencer to decide how to 188 * react appropriately. 189 */ 190 LWS_VISIBLE LWS_EXTERN int 191 lws_seq_timeout_us(struct lws_sequencer *seq, lws_usec_t us); 192 193 /** 194 * lws_seq_from_user(): get the lws_seq_t pointer from the user ptr 195 * 196 * \param u: the sequencer user allocation returned by lws_seq_create() or 197 * provided in the sequencer callback 198 * 199 * This gets the lws_seq_t * from the sequencer user allocation pointer. 200 * Actually these are allocated at the same time in one step, with the user 201 * allocation immediately after the lws_seq_t, so lws can compute where 202 * the lws_seq_t is from having the user allocation pointer. Since the 203 * size of the lws_seq_t is unknown to user code, this helper does it for 204 * you. 205 */ 206 LWS_VISIBLE LWS_EXTERN struct lws_sequencer * 207 lws_seq_from_user(void *u); 208 209 /** 210 * lws_seq_us_since_creation(): elapsed seconds since sequencer created 211 * 212 * \param seq: pointer to the lws_seq_t 213 * 214 * Returns the number of us elapsed since the lws_seq_t was 215 * created. This is useful to calculate sequencer timeouts for the current 216 * step considering a global sequencer lifetime limit. 217 */ 218 LWS_VISIBLE LWS_EXTERN lws_usec_t 219 lws_seq_us_since_creation(struct lws_sequencer *seq); 220 221 /** 222 * lws_seq_name(): get the name of this sequencer 223 * 224 * \param seq: pointer to the lws_seq_t 225 * 226 * Returns the name given when the sequencer was created. This is useful to 227 * annotate logging when then are multiple sequencers in play. 228 */ 229 LWS_VISIBLE LWS_EXTERN const char * 230 lws_seq_name(struct lws_sequencer *seq); 231 232 /** 233 * lws_seq_get_context(): get the lws_context sequencer was created on 234 * 235 * \param seq: pointer to the lws_seq_t 236 * 237 * Returns the lws_context. Saves you having to store it if you have a seq 238 * pointer handy. 239 */ 240 LWS_VISIBLE LWS_EXTERN struct lws_context * 241 lws_seq_get_context(struct lws_sequencer *seq); 242