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
42typedef 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
63typedef 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 */
79typedef lws_seq_cb_return_t (*lws_seq_event_cb)(struct lws_sequencer *seq,
80 void *user, int event, void *data, void *aux);
81
82typedef 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 uint8_t wakesuspend:1; /* important enough to
91 * wake system */
92} lws_seq_info_t;
93
94/**
95 * lws_seq_create() - create and bind sequencer to a pt
96 *
97 * \param info: information about sequencer to create
98 *
99 * This binds an abstract sequencer to a per-thread (by default, the single
100 * event loop of an lws_context). After the event loop starts, the sequencer
101 * will receive an LWSSEQ_CREATED event on its callback from the event loop
102 * context, where it can begin its sequence flow.
103 *
104 * Lws itself will only call the callback subsequently with LWSSEQ_DESTROYED
105 * when the sequencer is being destroyed.
106 *
107 * pt locking is used to protect the related data structures.
108 */
109LWS_VISIBLE LWS_EXTERN struct lws_sequencer *
110lws_seq_create(lws_seq_info_t *info);
111
112/**
113 * lws_seq_destroy() - destroy the sequencer
114 *
115 * \param seq: pointer to the the opaque sequencer pointer returned by
116 * lws_seq_create()
117 *
118 * This proceeds to destroy the sequencer, calling LWSSEQ_DESTROYED and then
119 * freeing the sequencer object itself. The pointed-to seq pointer will be
120 * set to NULL.
121 */
122LWS_VISIBLE LWS_EXTERN void
123lws_seq_destroy(struct lws_sequencer **seq);
124
125/**
126 * lws_seq_queue_event() - queue an event on the given sequencer
127 *
128 * \param seq: the opaque sequencer pointer returned by lws_seq_create()
129 * \param e: the event index to queue
130 * \param data: associated opaque (to lws) data to provide the callback
131 * \param aux: second opaque data to provide the callback
132 *
133 * This queues the event on a given sequencer. Queued events are delivered one
134 * per sequencer each subsequent time around the event loop, so the cb is called
135 * from the event loop thread context.
136 *
137 * Notice that because the events are delivered in order from the event loop,
138 * the scope of objects pointed to by \p data or \p aux may exceed the lifetime
139 * of the thing containing the pointed-to data. So it's usually better to pass
140 * values here.
141 */
142LWS_VISIBLE LWS_EXTERN int
143lws_seq_queue_event(struct lws_sequencer *seq, lws_seq_events_t e, void *data,
144 void *aux);
145
146/**
147 * lws_seq_check_wsi() - check if wsi still extant
148 *
149 * \param seq: the sequencer interested in the wsi
150 * \param wsi: the wsi we want to confirm hasn't closed yet
151 *
152 * Check if wsi still extant, by peeking in the message queue for a
153 * LWSSEQ_WSI_CONN_CLOSE message about wsi. (Doesn't need to do the same for
154 * CONN_FAIL since that will never have produced any messages prior to that).
155 *
156 * Use this to avoid trying to perform operations on wsi that have already
157 * closed but we didn't get to that message yet.
158 *
159 * Returns 0 if not closed yet or 1 if it has closed but we didn't process the
160 * close message yet.
161 */
162LWS_VISIBLE LWS_EXTERN int
163lws_seq_check_wsi(struct lws_sequencer *seq, struct lws *wsi);
164
165#define LWSSEQTO_NONE 0
166
167/**
168 * lws_seq_timeout_us() - set a timeout by which the sequence must have
169 * completed by a different event or inform the
170 * sequencer
171 *
172 * \param seq: The sequencer to set the timeout on
173 * \param us: How many us in the future to fire the timeout
174 * LWS_SET_TIMER_USEC_CANCEL = cancel any existing timeout
175 *
176 * This api allows the sequencer to ask to be informed if it has not completed
177 * or disabled its timeout after secs seconds. Lws will send a LWSSEQ_TIMED_OUT
178 * event to the sequencer if the timeout expires.
179 *
180 * Typically the sequencer sets the timeout when starting a step, then waits to
181 * hear a queued event informing it the step completed or failed. The timeout
182 * provides a way to deal with the case the step neither completed nor failed
183 * within the timeout period.
184 *
185 * Lws wsi timeouts are not really suitable for this since they are focused on
186 * short-term protocol timeout protection and may be set and reset many times
187 * in one transaction. Wsi timeouts also enforce closure of the wsi when they
188 * trigger, sequencer timeouts have no side effect except to queue the
189 * LWSSEQ_TIMED_OUT message and leave it to the sequencer to decide how to
190 * react appropriately.
191 */
192LWS_VISIBLE LWS_EXTERN int
193lws_seq_timeout_us(struct lws_sequencer *seq, lws_usec_t us);
194
195/**
196 * lws_seq_from_user(): get the lws_seq_t pointer from the user ptr
197 *
198 * \param u: the sequencer user allocation returned by lws_seq_create() or
199 * provided in the sequencer callback
200 *
201 * This gets the lws_seq_t * from the sequencer user allocation pointer.
202 * Actually these are allocated at the same time in one step, with the user
203 * allocation immediately after the lws_seq_t, so lws can compute where
204 * the lws_seq_t is from having the user allocation pointer. Since the
205 * size of the lws_seq_t is unknown to user code, this helper does it for
206 * you.
207 */
208LWS_VISIBLE LWS_EXTERN struct lws_sequencer *
209lws_seq_from_user(void *u);
210
211/**
212 * lws_seq_us_since_creation(): elapsed seconds since sequencer created
213 *
214 * \param seq: pointer to the lws_seq_t
215 *
216 * Returns the number of us elapsed since the lws_seq_t was
217 * created. This is useful to calculate sequencer timeouts for the current
218 * step considering a global sequencer lifetime limit.
219 */
220LWS_VISIBLE LWS_EXTERN lws_usec_t
221lws_seq_us_since_creation(struct lws_sequencer *seq);
222
223/**
224 * lws_seq_name(): get the name of this sequencer
225 *
226 * \param seq: pointer to the lws_seq_t
227 *
228 * Returns the name given when the sequencer was created. This is useful to
229 * annotate logging when then are multiple sequencers in play.
230 */
231LWS_VISIBLE LWS_EXTERN const char *
232lws_seq_name(struct lws_sequencer *seq);
233
234/**
235 * lws_seq_get_context(): get the lws_context sequencer was created on
236 *
237 * \param seq: pointer to the lws_seq_t
238 *
239 * Returns the lws_context. Saves you having to store it if you have a seq
240 * pointer handy.
241 */
242LWS_VISIBLE LWS_EXTERN struct lws_context *
243lws_seq_get_context(struct lws_sequencer *seq);
244