• 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 extern const struct lws_role_ops role_ops_h2;
26 #define lwsi_role_h2(wsi) (wsi->role_ops == &role_ops_h2)
27 
28 struct http2_settings {
29 	uint32_t s[H2SET_COUNT];
30 };
31 
32 struct lws_vhost_role_h2 {
33 	struct http2_settings set;
34 };
35 
36 enum lws_h2_wellknown_frame_types {
37 	LWS_H2_FRAME_TYPE_DATA,
38 	LWS_H2_FRAME_TYPE_HEADERS,
39 	LWS_H2_FRAME_TYPE_PRIORITY,
40 	LWS_H2_FRAME_TYPE_RST_STREAM,
41 	LWS_H2_FRAME_TYPE_SETTINGS,
42 	LWS_H2_FRAME_TYPE_PUSH_PROMISE,
43 	LWS_H2_FRAME_TYPE_PING,
44 	LWS_H2_FRAME_TYPE_GOAWAY,
45 	LWS_H2_FRAME_TYPE_WINDOW_UPDATE,
46 	LWS_H2_FRAME_TYPE_CONTINUATION,
47 
48 	LWS_H2_FRAME_TYPE_COUNT /* always last */
49 };
50 
51 enum lws_h2_flags {
52 	LWS_H2_FLAG_END_STREAM = 1,
53 	LWS_H2_FLAG_END_HEADERS = 4,
54 	LWS_H2_FLAG_PADDED = 8,
55 	LWS_H2_FLAG_PRIORITY = 0x20,
56 
57 	LWS_H2_FLAG_SETTINGS_ACK = 1,
58 };
59 
60 enum lws_h2_errors {
61 	H2_ERR_NO_ERROR,		   /* Graceful shutdown */
62 	H2_ERR_PROTOCOL_ERROR,	   /* Protocol error detected */
63 	H2_ERR_INTERNAL_ERROR,	   /* Implementation fault */
64 	H2_ERR_FLOW_CONTROL_ERROR,  /* Flow-control limits exceeded */
65 	H2_ERR_SETTINGS_TIMEOUT,	   /* Settings not acknowledged */
66 	H2_ERR_STREAM_CLOSED,	   /* Frame received for closed stream */
67 	H2_ERR_FRAME_SIZE_ERROR,	   /* Frame size incorrect */
68 	H2_ERR_REFUSED_STREAM,	   /* Stream not processed */
69 	H2_ERR_CANCEL,		   /* Stream cancelled */
70 	H2_ERR_COMPRESSION_ERROR,   /* Compression state not updated */
71 	H2_ERR_CONNECT_ERROR,	   /* TCP connection error for CONNECT method */
72 	H2_ERR_ENHANCE_YOUR_CALM,   /* Processing capacity exceeded */
73 	H2_ERR_INADEQUATE_SECURITY, /* Negotiated TLS parameters not acceptable */
74 	H2_ERR_HTTP_1_1_REQUIRED,   /* Use HTTP/1.1 for the request */
75 };
76 
77 enum lws_h2_states {
78 	LWS_H2_STATE_IDLE,
79 	/*
80 	 * Send PUSH_PROMISE    -> LWS_H2_STATE_RESERVED_LOCAL
81 	 * Recv PUSH_PROMISE    -> LWS_H2_STATE_RESERVED_REMOTE
82 	 * Send HEADERS         -> LWS_H2_STATE_OPEN
83 	 * Recv HEADERS         -> LWS_H2_STATE_OPEN
84 	 *
85 	 *  - Only PUSH_PROMISE + HEADERS valid to send
86 	 *  - Only HEADERS or PRIORITY valid to receive
87 	 */
88 	LWS_H2_STATE_RESERVED_LOCAL,
89 	/*
90 	 * Send RST_STREAM      -> LWS_H2_STATE_CLOSED
91 	 * Recv RST_STREAM      -> LWS_H2_STATE_CLOSED
92 	 * Send HEADERS         -> LWS_H2_STATE_HALF_CLOSED_REMOTE
93 	 *
94 	 * - Only HEADERS, RST_STREAM, or PRIORITY valid to send
95 	 * - Only RST_STREAM, PRIORITY, or WINDOW_UPDATE valid to receive
96 	 */
97 	LWS_H2_STATE_RESERVED_REMOTE,
98 	/*
99 	 * Send RST_STREAM      -> LWS_H2_STATE_CLOSED
100 	 * Recv RST_STREAM      -> LWS_H2_STATE_CLOSED
101 	 * Recv HEADERS         -> LWS_H2_STATE_HALF_CLOSED_LOCAL
102 	 *
103 	 *  - Only RST_STREAM, WINDOW_UPDATE, or PRIORITY valid to send
104 	 *  - Only HEADERS, RST_STREAM, or PRIORITY valid to receive
105 	 */
106 	LWS_H2_STATE_OPEN,
107 	/*
108 	 * Send RST_STREAM      -> LWS_H2_STATE_CLOSED
109 	 * Recv RST_STREAM      -> LWS_H2_STATE_CLOSED
110 	 * Send END_STREAM flag -> LWS_H2_STATE_HALF_CLOSED_LOCAL
111 	 * Recv END_STREAM flag -> LWS_H2_STATE_HALF_CLOSED_REMOTE
112 	 */
113 	LWS_H2_STATE_HALF_CLOSED_REMOTE,
114 	/*
115 	 * Send RST_STREAM      -> LWS_H2_STATE_CLOSED
116 	 * Recv RST_STREAM      -> LWS_H2_STATE_CLOSED
117 	 * Send END_STREAM flag -> LWS_H2_STATE_CLOSED
118 	 *
119 	 *  - Any frame valid to send
120 	 *  - Only WINDOW_UPDATE, PRIORITY, or RST_STREAM valid to receive
121 	 */
122 	LWS_H2_STATE_HALF_CLOSED_LOCAL,
123 	/*
124 	 * Send RST_STREAM      -> LWS_H2_STATE_CLOSED
125 	 * Recv RST_STREAM      -> LWS_H2_STATE_CLOSED
126 	 * Recv END_STREAM flag -> LWS_H2_STATE_CLOSED
127 	 *
128 	 *  - Only WINDOW_UPDATE, PRIORITY, and RST_STREAM valid to send
129 	 *  - Any frame valid to receive
130 	 */
131 	LWS_H2_STATE_CLOSED,
132 	/*
133 	 *  - Only PRIORITY, WINDOW_UPDATE (IGNORE) and RST_STREAM (IGNORE)
134 	 *     may be received
135 	 *
136 	 *  - Only PRIORITY valid to send
137 	 */
138 };
139 
140 void
141 lws_h2_state(struct lws *wsi, enum lws_h2_states s);
142 
143 #define LWS_H2_STREAM_ID_MASTER 0
144 #define LWS_H2_SETTINGS_LEN 6
145 #define LWS_H2_FLAG_SETTINGS_ACK 1
146 
147 enum http2_hpack_state {
148 	HPKS_TYPE,
149 
150 	HPKS_IDX_EXT,
151 
152 	HPKS_HLEN,
153 	HPKS_HLEN_EXT,
154 
155 	HPKS_DATA,
156 };
157 
158 /*
159  * lws general parsimonious header strategy is only store values from known
160  * headers, and refer to them by index.
161  *
162  * That means if we can't map the peer header name to one that lws knows, we
163  * will drop the content but track the indexing with associated_lws_hdr_idx =
164  * LWS_HPACK_IGNORE_ENTRY.
165  */
166 
167 enum http2_hpack_type {
168 	HPKT_INDEXED_HDR_7,		/* 1xxxxxxx: just "header field" */
169 	HPKT_INDEXED_HDR_6_VALUE_INCR,  /* 01xxxxxx: NEW indexed hdr with value */
170 	HPKT_LITERAL_HDR_VALUE_INCR,	/* 01000000: NEW literal hdr with value */
171 	HPKT_INDEXED_HDR_4_VALUE,	/* 0000xxxx: indexed hdr with value */
172 	HPKT_INDEXED_HDR_4_VALUE_NEVER,	/* 0001xxxx: indexed hdr with value NEVER NEW */
173 	HPKT_LITERAL_HDR_VALUE,		/* 00000000: literal hdr with value */
174 	HPKT_LITERAL_HDR_VALUE_NEVER,	/* 00010000: literal hdr with value NEVER NEW */
175 	HPKT_SIZE_5
176 };
177 
178 #define LWS_HPACK_IGNORE_ENTRY 0xffff
179 
180 
181 struct hpack_dt_entry {
182 	char *value; /* malloc'd */
183 	uint16_t value_len;
184 	uint16_t hdr_len; /* virtual, for accounting */
185 	uint16_t lws_hdr_idx; /* LWS_HPACK_IGNORE_ENTRY = IGNORE */
186 };
187 
188 struct hpack_dynamic_table {
189 	struct hpack_dt_entry *entries; /* malloc'd */
190 	uint32_t virtual_payload_usage;
191 	uint32_t virtual_payload_max;
192 	uint16_t pos;
193 	uint16_t used_entries;
194 	uint16_t num_entries;
195 };
196 
197 enum lws_h2_protocol_send_type {
198 	LWS_PPS_NONE,
199 	LWS_H2_PPS_MY_SETTINGS,
200 	LWS_H2_PPS_ACK_SETTINGS,
201 	LWS_H2_PPS_PING,
202 	LWS_H2_PPS_PONG,
203 	LWS_H2_PPS_GOAWAY,
204 	LWS_H2_PPS_RST_STREAM,
205 	LWS_H2_PPS_UPDATE_WINDOW,
206 	LWS_H2_PPS_SETTINGS_INITIAL_UPDATE_WINDOW
207 };
208 
209 struct lws_h2_protocol_send {
210 	struct lws_h2_protocol_send *next; /* linked list */
211 	enum lws_h2_protocol_send_type type;
212 
213 	union uu {
214 		struct {
215 			char		str[32];
216 			uint32_t	highest_sid;
217 			uint32_t	err;
218 		} ga;
219 		struct {
220 			uint32_t	sid;
221 			uint32_t	err;
222 		} rs;
223 		struct {
224 			uint8_t		ping_payload[8];
225 		} ping;
226 		struct {
227 			uint32_t	sid;
228 			uint32_t	credit;
229 		} update_window;
230 	} u;
231 };
232 
233 struct lws_h2_ghost_sid {
234 	struct lws_h2_ghost_sid *next;
235 	uint32_t sid;
236 };
237 
238 /*
239  * http/2 connection info that is only used by the root connection that has
240  * the network connection.
241  *
242  * h2 tends to spawn many child connections from one network connection, so
243  * it's necessary to make members only needed by the network connection
244  * distinct and only malloc'd on network connections.
245  *
246  * There's only one HPACK parser per network connection.
247  *
248  * But there is an ah per logical child connection... the network connection
249  * fills it but it belongs to the logical child.
250  */
251 struct lws_h2_netconn {
252 	struct http2_settings our_set;
253 	struct http2_settings peer_set;
254 	struct hpack_dynamic_table hpack_dyn_table;
255 	uint8_t	ping_payload[8];
256 	uint8_t one_setting[LWS_H2_SETTINGS_LEN];
257 	char goaway_str[32]; /* for rx */
258 	struct lws *swsi;
259 	struct lws_h2_protocol_send *pps; /* linked list */
260 
261 	enum http2_hpack_state hpack;
262 	enum http2_hpack_type hpack_type;
263 
264 	unsigned int huff:1;
265 	unsigned int value:1;
266 	unsigned int unknown_header:1;
267 	unsigned int cont_exp:1;
268 	unsigned int cont_exp_headers:1;
269 	unsigned int we_told_goaway:1;
270 	unsigned int pad_length:1;
271 	unsigned int collected_priority:1;
272 	unsigned int is_first_header_char:1;
273 	unsigned int zero_huff_padding:1;
274 	unsigned int last_action_dyntable_resize:1;
275 
276 	uint32_t hdr_idx;
277 	uint32_t hpack_len;
278 	uint32_t hpack_e_dep;
279 	uint32_t count;
280 	uint32_t preamble;
281 	uint32_t length;
282 	uint32_t sid;
283 	uint32_t inside;
284 	uint32_t highest_sid;
285 	uint32_t highest_sid_opened;
286 	uint32_t cont_exp_sid;
287 	uint32_t dep;
288 	uint32_t goaway_last_sid;
289 	uint32_t goaway_err;
290 	uint32_t hpack_hdr_len;
291 
292 	uint16_t hpack_pos;
293 
294 	uint8_t frame_state;
295 	uint8_t type;
296 	uint8_t flags;
297 	uint8_t padding;
298 	uint8_t weight_temp;
299 	uint8_t huff_pad;
300 	char first_hdr_char;
301 	uint8_t hpack_m;
302 	uint8_t ext_count;
303 };
304 
305 struct _lws_h2_related {
306 
307 	struct lws_h2_netconn	*h2n; /* malloc'd for root net conn */
308 
309 	char			*pending_status_body;
310 
311 	uint8_t			h2_state; /* RFC7540 state of the connection */
312 
313 	uint8_t			END_STREAM:1;
314 	uint8_t			END_HEADERS:1;
315 	uint8_t			send_END_STREAM:1;
316 	uint8_t			long_poll:1;
317 	uint8_t			initialized:1;
318 };
319 
320 #define HTTP2_IS_TOPLEVEL_WSI(wsi) (!wsi->mux.parent_wsi)
321 
322 int
323 lws_h2_rst_stream(struct lws *wsi, uint32_t err, const char *reason);
324 struct lws * lws_h2_get_nth_child(struct lws *wsi, int n);
325 LWS_EXTERN void lws_h2_init(struct lws *wsi);
326 LWS_EXTERN int
327 lws_h2_settings(struct lws *nwsi, struct http2_settings *settings,
328 		unsigned char *buf, int len);
329 LWS_EXTERN int
330 lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t inlen,
331 	      lws_filepos_t *inused);
332 LWS_EXTERN int
333 lws_h2_do_pps_send(struct lws *wsi);
334 LWS_EXTERN int
335 lws_h2_frame_write(struct lws *wsi, int type, int flags, unsigned int sid,
336 		   unsigned int len, unsigned char *buf);
337 LWS_EXTERN struct lws *
338 lws_wsi_mux_from_id(struct lws *wsi, unsigned int sid);
339 LWS_EXTERN int
340 lws_hpack_interpret(struct lws *wsi, unsigned char c);
341 LWS_EXTERN int
342 lws_add_http2_header_by_name(struct lws *wsi,
343 			     const unsigned char *name,
344 			     const unsigned char *value, int length,
345 			     unsigned char **p, unsigned char *end);
346 LWS_EXTERN int
347 lws_add_http2_header_by_token(struct lws *wsi,
348 			      enum lws_token_indexes token,
349 			      const unsigned char *value, int length,
350 			      unsigned char **p, unsigned char *end);
351 LWS_EXTERN int
352 lws_add_http2_header_status(struct lws *wsi,
353 			    unsigned int code, unsigned char **p,
354 			    unsigned char *end);
355 LWS_EXTERN void
356 lws_hpack_destroy_dynamic_header(struct lws *wsi);
357 LWS_EXTERN int
358 lws_hpack_dynamic_size(struct lws *wsi, int size);
359 LWS_EXTERN int
360 lws_h2_goaway(struct lws *wsi, uint32_t err, const char *reason);
361 LWS_EXTERN int
362 lws_h2_tx_cr_get(struct lws *wsi);
363 LWS_EXTERN void
364 lws_h2_tx_cr_consume(struct lws *wsi, int consumed);
365 LWS_EXTERN int
366 lws_hdr_extant(struct lws *wsi, enum lws_token_indexes h);
367 LWS_EXTERN void
368 lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pss);
369 
370 LWS_EXTERN const struct http2_settings lws_h2_defaults;
371 LWS_EXTERN int
372 lws_h2_ws_handshake(struct lws *wsi);
373 LWS_EXTERN int lws_h2_issue_preface(struct lws *wsi);
374 LWS_EXTERN int
375 lws_h2_client_handshake(struct lws *wsi);
376 LWS_EXTERN struct lws *
377 lws_wsi_h2_adopt(struct lws *parent_wsi, struct lws *wsi);
378 int
379 lws_handle_POLLOUT_event_h2(struct lws *wsi);
380 int
381 lws_read_h2(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
382 struct lws_h2_protocol_send *
383 lws_h2_new_pps(enum lws_h2_protocol_send_type type);
384