• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
25 typedef uint32_t lws_wsi_state_t;
26 
27 /*
28  * The wsi->role_ops pointer decides almost everything about what role the wsi
29  * will play, h2, raw, ws, etc.
30  *
31  * However there are a few additional flags needed that vary, such as if the
32  * role is a client or server side, if it has that concept.  And the connection
33  * fulfilling the role, has a separate dynamic state.
34  *
35  *   31           16 15      0
36  *   [  role flags ] [ state ]
37  *
38  * The role flags part is generally invariant for the lifetime of the wsi,
39  * although it can change if the connection role itself does, eg, if the
40  * connection upgrades from H1 -> WS1 the role flags may be changed at that
41  * point.
42  *
43  * The state part reflects the dynamic connection state, and the states are
44  * reused between roles.
45  *
46  * None of the internal role or state representations are made available outside
47  * of lws internals.  Even for lws internals, if you add stuff here, please keep
48  * the constants inside this header only by adding necessary helpers here and
49  * use the helpers in the actual code.  This is to ease any future refactors.
50  *
51  * Notice LWSIFR_ENCAP means we have a parent wsi that actually carries our
52  * data as a stream inside a different protocol.
53  */
54 
55 #define _RS 16
56 
57 #define LWSIFR_CLIENT		(0x1000 << _RS) /* client side */
58 #define LWSIFR_SERVER		(0x2000 << _RS) /* server side */
59 
60 #define LWSIFR_P_ENCAP_H2	(0x0100 << _RS) /* we are encapsulated by h2 */
61 
62 enum lwsi_role {
63 	LWSI_ROLE_MASK		=			     (0xffff << _RS),
64 	LWSI_ROLE_ENCAP_MASK	=			     (0x0f00 << _RS),
65 };
66 
67 #define lwsi_role(wsi) (wsi->wsistate & LWSI_ROLE_MASK)
68 #if !defined (_DEBUG)
69 #define lwsi_set_role(wsi, role) wsi->wsistate = \
70 				(wsi->wsistate & (~LWSI_ROLE_MASK)) | role
71 #else
72 void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role);
73 #endif
74 
75 #define lwsi_role_client(wsi) (!!(wsi->wsistate & LWSIFR_CLIENT))
76 #define lwsi_role_server(wsi) (!!(wsi->wsistate & LWSIFR_SERVER))
77 #define lwsi_role_h2_ENCAPSULATION(wsi) \
78 		((wsi->wsistate & LWSI_ROLE_ENCAP_MASK) == LWSIFR_P_ENCAP_H2)
79 
80 /* Pollout wants a callback in this state */
81 #define LWSIFS_POCB		(0x100)
82 /* Before any protocol connection was established */
83 #define LWSIFS_NOT_EST		(0x200)
84 
85 enum lwsi_state {
86 
87 	/* Phase 1: pre-transport */
88 
89 	LRS_UNCONNECTED				= LWSIFS_NOT_EST | 0,
90 	LRS_WAITING_DNS				= LWSIFS_NOT_EST | 1,
91 	LRS_WAITING_CONNECT			= LWSIFS_NOT_EST | 2,
92 
93 	/* Phase 2: establishing intermediaries on top of transport */
94 
95 	LRS_WAITING_PROXY_REPLY			= LWSIFS_NOT_EST | 3,
96 	LRS_WAITING_SSL				= LWSIFS_NOT_EST | 4,
97 	LRS_WAITING_SOCKS_GREETING_REPLY	= LWSIFS_NOT_EST | 5,
98 	LRS_WAITING_SOCKS_CONNECT_REPLY		= LWSIFS_NOT_EST | 6,
99 	LRS_WAITING_SOCKS_AUTH_REPLY		= LWSIFS_NOT_EST | 7,
100 
101 	/* Phase 3: establishing tls tunnel */
102 
103 	LRS_SSL_INIT				= LWSIFS_NOT_EST | 8,
104 	LRS_SSL_ACK_PENDING			= LWSIFS_NOT_EST | 9,
105 	LRS_PRE_WS_SERVING_ACCEPT		= LWSIFS_NOT_EST | 10,
106 
107 	/* Phase 4: connected */
108 
109 	LRS_WAITING_SERVER_REPLY		= LWSIFS_NOT_EST | 11,
110 	LRS_H2_AWAIT_PREFACE			= LWSIFS_NOT_EST | 12,
111 	LRS_H2_AWAIT_SETTINGS			= LWSIFS_NOT_EST |
112 						  LWSIFS_POCB | 13,
113 	LRS_MQTTC_IDLE				= LWSIFS_POCB | 33,
114 	LRS_MQTTC_AWAIT_CONNACK			= 34,
115 
116 	/* Phase 5: protocol logically established */
117 
118 	LRS_H2_CLIENT_SEND_SETTINGS		= LWSIFS_POCB | 14,
119 	LRS_H2_WAITING_TO_SEND_HEADERS		= LWSIFS_POCB | 15,
120 	LRS_DEFERRING_ACTION			= LWSIFS_POCB | 16,
121 	LRS_IDLING				= 17,
122 	LRS_H1C_ISSUE_HANDSHAKE			= 18,
123 	LRS_H1C_ISSUE_HANDSHAKE2		= 19,
124 	LRS_ISSUE_HTTP_BODY			= 20,
125 	LRS_ISSUING_FILE			= 21,
126 	LRS_HEADERS				= 22,
127 	LRS_BODY				= 23,
128 	LRS_DISCARD_BODY			= 24,
129 	LRS_ESTABLISHED				= LWSIFS_POCB | 25,
130 
131 	/* we are established, but we have embarked on serving a single
132 	 * transaction.  Other transaction input may be pending, but we will
133 	 * not service it while we are busy dealing with the current
134 	 * transaction.
135 	 *
136 	 * When we complete the current transaction, we would reset our state
137 	 * back to ESTABLISHED and start to process the next transaction.
138 	 */
139 	LRS_DOING_TRANSACTION			= LWSIFS_POCB | 26,
140 
141 	/* Phase 6: finishing */
142 
143 	LRS_WAITING_TO_SEND_CLOSE		= LWSIFS_POCB | 27,
144 	LRS_RETURNED_CLOSE			= LWSIFS_POCB | 28,
145 	LRS_AWAITING_CLOSE_ACK			= LWSIFS_POCB | 29,
146 	LRS_FLUSHING_BEFORE_CLOSE		= LWSIFS_POCB | 30,
147 	LRS_SHUTDOWN				= 31,
148 
149 	/* Phase 7: dead */
150 
151 	LRS_DEAD_SOCKET				= 32,
152 
153 	LRS_MASK				= 0xffff
154 };
155 
156 #define lwsi_state(wsi) ((enum lwsi_state)(wsi->wsistate & LRS_MASK))
157 #define lwsi_state_PRE_CLOSE(wsi) \
158 		((enum lwsi_state)(wsi->wsistate_pre_close & LRS_MASK))
159 #define lwsi_state_est(wsi) (!(wsi->wsistate & LWSIFS_NOT_EST))
160 #define lwsi_state_est_PRE_CLOSE(wsi) \
161 		(!(wsi->wsistate_pre_close & LWSIFS_NOT_EST))
162 #define lwsi_state_can_handle_POLLOUT(wsi) (wsi->wsistate & LWSIFS_POCB)
163 #if !defined (_DEBUG)
164 #define lwsi_set_state(wsi, lrs) wsi->wsistate = \
165 			  (wsi->wsistate & (~LRS_MASK)) | lrs
166 #else
167 void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs);
168 #endif
169 
170 #define _LWS_ADOPT_FINISH (1 << 24)
171 
172 /*
173  * internal role-specific ops
174  */
175 struct lws_context_per_thread;
176 struct lws_role_ops {
177 	const char *name;
178 	const char *alpn;
179 	/*
180 	 * After http headers have parsed, this is the last chance for a role
181 	 * to upgrade the connection to something else using the headers.
182 	 * ws-over-h2 is upgraded from h2 like this.
183 	 */
184 	int (*check_upgrades)(struct lws *wsi);
185 	/* role-specific context init during context creation */
186 	int (*pt_init_destroy)(struct lws_context *context,
187 			    const struct lws_context_creation_info *info,
188 			    struct lws_context_per_thread *pt, int destroy);
189 	/* role-specific per-vhost init during vhost creation */
190 	int (*init_vhost)(struct lws_vhost *vh,
191 			  const struct lws_context_creation_info *info);
192 	/* role-specific per-vhost destructor during vhost destroy */
193 	int (*destroy_vhost)(struct lws_vhost *vh);
194 	/* chance for the role to force POLLIN without network activity */
195 	int (*service_flag_pending)(struct lws_context *context, int tsi);
196 	/* an fd using this role has POLLIN signalled */
197 	int (*handle_POLLIN)(struct lws_context_per_thread *pt, struct lws *wsi,
198 			     struct lws_pollfd *pollfd);
199 	/* an fd using the role wanted a POLLOUT callback and now has it */
200 	int (*handle_POLLOUT)(struct lws *wsi);
201 	/* perform user pollout */
202 	int (*perform_user_POLLOUT)(struct lws *wsi);
203 	/* do effective callback on writeable */
204 	int (*callback_on_writable)(struct lws *wsi);
205 	/* connection-specific tx credit in bytes */
206 	int (*tx_credit)(struct lws *wsi, char peer_to_us, int add);
207 	/* role-specific write formatting */
208 	int (*write_role_protocol)(struct lws *wsi, unsigned char *buf,
209 				   size_t len, enum lws_write_protocol *wp);
210 
211 	/* get encapsulation parent */
212 	struct lws * (*encapsulation_parent)(struct lws *wsi);
213 
214 	/* role-specific destructor */
215 	int (*alpn_negotiated)(struct lws *wsi, const char *alpn);
216 
217 	/* chance for the role to handle close in the protocol */
218 	int (*close_via_role_protocol)(struct lws *wsi,
219 				       enum lws_close_status reason);
220 	/* role-specific close processing */
221 	int (*close_role)(struct lws_context_per_thread *pt, struct lws *wsi);
222 	/* role-specific connection close processing */
223 	int (*close_kill_connection)(struct lws *wsi,
224 				     enum lws_close_status reason);
225 	/* role-specific destructor */
226 	int (*destroy_role)(struct lws *wsi);
227 
228 	/* role-specific socket-adopt */
229 	int (*adoption_bind)(struct lws *wsi, int type, const char *prot);
230 	/* role-specific client-bind:
231 	 * ret 1 = bound, 0 = not bound, -1 = fail out
232 	 * i may be NULL, indicating client_bind is being called after
233 	 * a successful bind earlier, to finalize the binding.  In that
234 	 * case ret 0 = OK, 1 = fail, wsi needs freeing, -1 = fail, wsi freed */
235 	int (*client_bind)(struct lws *wsi,
236 			   const struct lws_client_connect_info *i);
237 	/* isvalid = 0: request a role-specific keepalive (PING etc)
238 	 *         = 1: reset any related validity timer */
239 	int (*issue_keepalive)(struct lws *wsi, int isvalid);
240 
241 	/*
242 	 * the callback reasons for adoption for client, server
243 	 * (just client applies if no concept of client or server)
244 	 */
245 	uint16_t adoption_cb[2];
246 	/*
247 	 * the callback reasons for adoption for client, server
248 	 * (just client applies if no concept of client or server)
249 	 */
250 	uint16_t rx_cb[2];
251 	/*
252 	 * the callback reasons for WRITEABLE for client, server
253 	 * (just client applies if no concept of client or server)
254 	 */
255 	uint16_t writeable_cb[2];
256 	/*
257 	 * the callback reasons for CLOSE for client, server
258 	 * (just client applies if no concept of client or server)
259 	 */
260 	uint16_t close_cb[2];
261 	/*
262 	 * the callback reasons for protocol bind for client, server
263 	 * (just client applies if no concept of client or server)
264 	 */
265 	uint16_t protocol_bind_cb[2];
266 	/*
267 	 * the callback reasons for protocol unbind for client, server
268 	 * (just client applies if no concept of client or server)
269 	 */
270 	uint16_t protocol_unbind_cb[2];
271 
272 	unsigned int file_handle:1; /* role operates on files not sockets */
273 };
274 
275 /* core roles */
276 extern const struct lws_role_ops role_ops_raw_skt, role_ops_raw_file,
277 				 role_ops_listen, role_ops_pipe;
278 
279 /* bring in role private declarations */
280 
281 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
282  #include "private-lib-roles-http.h"
283 #else
284  #define lwsi_role_http(wsi) (0)
285 #endif
286 
287 #if defined(LWS_ROLE_H1)
288  #include "private-lib-roles-h1.h"
289 #else
290  #define lwsi_role_h1(wsi) (0)
291 #endif
292 
293 #if defined(LWS_ROLE_H2)
294  #include "private-lib-roles-h2.h"
295 #else
296  #define lwsi_role_h2(wsi) (0)
297 #endif
298 
299 #if defined(LWS_ROLE_WS)
300  #include "private-lib-roles-ws.h"
301 #else
302  #define lwsi_role_ws(wsi) (0)
303 #endif
304 
305 #if defined(LWS_ROLE_CGI)
306  #include "private-lib-roles-cgi.h"
307 #else
308  #define lwsi_role_cgi(wsi) (0)
309 #endif
310 
311 #if defined(LWS_ROLE_DBUS)
312  #include "private-lib-roles-dbus.h"
313 #else
314  #define lwsi_role_dbus(wsi) (0)
315 #endif
316 
317 #if defined(LWS_ROLE_RAW_PROXY)
318  #include "private-lib-roles-raw-proxy.h"
319 #else
320  #define lwsi_role_raw_proxy(wsi) (0)
321 #endif
322 
323 #if defined(LWS_ROLE_MQTT)
324  #include "mqtt/private-lib-roles-mqtt.h"
325 #else
326  #define lwsi_role_mqtt(wsi) (0)
327 #endif
328 
329 enum {
330 	LWS_HP_RET_BAIL_OK,
331 	LWS_HP_RET_BAIL_DIE,
332 	LWS_HP_RET_USER_SERVICE,
333 	LWS_HP_RET_DROP_POLLOUT,
334 
335 	LWS_HPI_RET_WSI_ALREADY_DIED,	/* we closed it */
336 	LWS_HPI_RET_HANDLED,		/* no probs */
337 	LWS_HPI_RET_PLEASE_CLOSE_ME,	/* close it for us */
338 
339 	LWS_UPG_RET_DONE,
340 	LWS_UPG_RET_CONTINUE,
341 	LWS_UPG_RET_BAIL
342 };
343 
344 int
345 lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot);
346 
347 struct lws *
348 lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback, ssize_t plen);
349 
350 struct lws *
351 lws_client_connect_3_connect(struct lws *wsi, const char *ads,
352 			const struct addrinfo *result, int n, void *opaque);
353