2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 * This is included from core/private.h if LWS_ROLE_H2
24 extern struct lws_role_ops role_ops_h2;
25 #define lwsi_role_h2(wsi) (wsi->role_ops == &role_ops_h2)
27 enum lws_h2_settings {
28 H2SET_HEADER_TABLE_SIZE = 1,
30 H2SET_MAX_CONCURRENT_STREAMS,
31 H2SET_INITIAL_WINDOW_SIZE,
33 H2SET_MAX_HEADER_LIST_SIZE,
35 H2SET_ENABLE_CONNECT_PROTOCOL, /* defined in mcmanus-httpbis-h2-ws-02 */
37 H2SET_COUNT /* always last */
40 struct http2_settings {
41 uint32_t s[H2SET_COUNT];
44 struct lws_vhost_role_h2 {
45 struct http2_settings set;
48 enum lws_h2_wellknown_frame_types {
49 LWS_H2_FRAME_TYPE_DATA,
50 LWS_H2_FRAME_TYPE_HEADERS,
51 LWS_H2_FRAME_TYPE_PRIORITY,
52 LWS_H2_FRAME_TYPE_RST_STREAM,
53 LWS_H2_FRAME_TYPE_SETTINGS,
54 LWS_H2_FRAME_TYPE_PUSH_PROMISE,
55 LWS_H2_FRAME_TYPE_PING,
56 LWS_H2_FRAME_TYPE_GOAWAY,
57 LWS_H2_FRAME_TYPE_WINDOW_UPDATE,
58 LWS_H2_FRAME_TYPE_CONTINUATION,
60 LWS_H2_FRAME_TYPE_COUNT /* always last */
64 LWS_H2_FLAG_END_STREAM = 1,
65 LWS_H2_FLAG_END_HEADERS = 4,
66 LWS_H2_FLAG_PADDED = 8,
67 LWS_H2_FLAG_PRIORITY = 0x20,
69 LWS_H2_FLAG_SETTINGS_ACK = 1,
73 H2_ERR_NO_ERROR, /* Graceful shutdown */
74 H2_ERR_PROTOCOL_ERROR, /* Protocol error detected */
75 H2_ERR_INTERNAL_ERROR, /* Implementation fault */
76 H2_ERR_FLOW_CONTROL_ERROR, /* Flow-control limits exceeded */
77 H2_ERR_SETTINGS_TIMEOUT, /* Settings not acknowledged */
78 H2_ERR_STREAM_CLOSED, /* Frame received for closed stream */
79 H2_ERR_FRAME_SIZE_ERROR, /* Frame size incorrect */
80 H2_ERR_REFUSED_STREAM, /* Stream not processed */
81 H2_ERR_CANCEL, /* Stream cancelled */
82 H2_ERR_COMPRESSION_ERROR, /* Compression state not updated */
83 H2_ERR_CONNECT_ERROR, /* TCP connection error for CONNECT method */
84 H2_ERR_ENHANCE_YOUR_CALM, /* Processing capacity exceeded */
85 H2_ERR_INADEQUATE_SECURITY, /* Negotiated TLS parameters not acceptable */
86 H2_ERR_HTTP_1_1_REQUIRED, /* Use HTTP/1.1 for the request */
92 * Send PUSH_PROMISE -> LWS_H2_STATE_RESERVED_LOCAL
93 * Recv PUSH_PROMISE -> LWS_H2_STATE_RESERVED_REMOTE
94 * Send HEADERS -> LWS_H2_STATE_OPEN
95 * Recv HEADERS -> LWS_H2_STATE_OPEN
97 * - Only PUSH_PROMISE + HEADERS valid to send
98 * - Only HEADERS or PRIORITY valid to receive
100 LWS_H2_STATE_RESERVED_LOCAL,
102 * Send RST_STREAM -> LWS_H2_STATE_CLOSED
103 * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
104 * Send HEADERS -> LWS_H2_STATE_HALF_CLOSED_REMOTE
106 * - Only HEADERS, RST_STREAM, or PRIORITY valid to send
107 * - Only RST_STREAM, PRIORITY, or WINDOW_UPDATE valid to receive
109 LWS_H2_STATE_RESERVED_REMOTE,
111 * Send RST_STREAM -> LWS_H2_STATE_CLOSED
112 * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
113 * Recv HEADERS -> LWS_H2_STATE_HALF_CLOSED_LOCAL
115 * - Only RST_STREAM, WINDOW_UPDATE, or PRIORITY valid to send
116 * - Only HEADERS, RST_STREAM, or PRIORITY valid to receive
120 * Send RST_STREAM -> LWS_H2_STATE_CLOSED
121 * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
122 * Send END_STREAM flag -> LWS_H2_STATE_HALF_CLOSED_LOCAL
123 * Recv END_STREAM flag -> LWS_H2_STATE_HALF_CLOSED_REMOTE
125 LWS_H2_STATE_HALF_CLOSED_REMOTE,
127 * Send RST_STREAM -> LWS_H2_STATE_CLOSED
128 * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
129 * Send END_STREAM flag -> LWS_H2_STATE_CLOSED
131 * - Any frame valid to send
132 * - Only WINDOW_UPDATE, PRIORITY, or RST_STREAM valid to receive
134 LWS_H2_STATE_HALF_CLOSED_LOCAL,
136 * Send RST_STREAM -> LWS_H2_STATE_CLOSED
137 * Recv RST_STREAM -> LWS_H2_STATE_CLOSED
138 * Recv END_STREAM flag -> LWS_H2_STATE_CLOSED
140 * - Only WINDOW_UPDATE, PRIORITY, and RST_STREAM valid to send
141 * - Any frame valid to receive
145 * - Only PRIORITY, WINDOW_UPDATE (IGNORE) and RST_STREAM (IGNORE)
148 * - Only PRIORITY valid to send
153 lws_h2_state(struct lws *wsi, enum lws_h2_states s);
155 #define LWS_H2_STREAM_ID_MASTER 0
156 #define LWS_H2_SETTINGS_LEN 6
157 #define LWS_H2_FLAG_SETTINGS_ACK 1
159 enum http2_hpack_state {
171 * lws general parsimonious header strategy is only store values from known
172 * headers, and refer to them by index.
174 * That means if we can't map the peer header name to one that lws knows, we
175 * will drop the content but track the indexing with associated_lws_hdr_idx =
176 * LWS_HPACK_IGNORE_ENTRY.
179 enum http2_hpack_type {
180 HPKT_INDEXED_HDR_7, /* 1xxxxxxx: just "header field" */
181 HPKT_INDEXED_HDR_6_VALUE_INCR, /* 01xxxxxx: NEW indexed hdr with value */
182 HPKT_LITERAL_HDR_VALUE_INCR, /* 01000000: NEW literal hdr with value */
183 HPKT_INDEXED_HDR_4_VALUE, /* 0000xxxx: indexed hdr with value */
184 HPKT_INDEXED_HDR_4_VALUE_NEVER, /* 0001xxxx: indexed hdr with value NEVER NEW */
185 HPKT_LITERAL_HDR_VALUE, /* 00000000: literal hdr with value */
186 HPKT_LITERAL_HDR_VALUE_NEVER, /* 00010000: literal hdr with value NEVER NEW */
190 #define LWS_HPACK_IGNORE_ENTRY 0xffff
193 struct hpack_dt_entry {
194 char *value; /* malloc'd */
196 uint16_t hdr_len; /* virtual, for accounting */
197 uint16_t lws_hdr_idx; /* LWS_HPACK_IGNORE_ENTRY = IGNORE */
200 struct hpack_dynamic_table {
201 struct hpack_dt_entry *entries; /* malloc'd */
202 uint32_t virtual_payload_usage;
203 uint32_t virtual_payload_max;
205 uint16_t used_entries;
206 uint16_t num_entries;
209 enum lws_h2_protocol_send_type {
211 LWS_H2_PPS_MY_SETTINGS,
212 LWS_H2_PPS_ACK_SETTINGS,
215 LWS_H2_PPS_RST_STREAM,
216 LWS_H2_PPS_UPDATE_WINDOW,
219 struct lws_h2_protocol_send {
220 struct lws_h2_protocol_send *next; /* linked list */
221 enum lws_h2_protocol_send_type type;
226 uint32_t highest_sid;
234 uint8_t ping_payload[8];
243 struct lws_h2_ghost_sid {
244 struct lws_h2_ghost_sid *next;
249 * http/2 connection info that is only used by the root connection that has
250 * the network connection.
252 * h2 tends to spawn many child connections from one network connection, so
253 * it's necessary to make members only needed by the network connection
254 * distinct and only malloc'd on network connections.
256 * There's only one HPACK parser per network connection.
258 * But there is an ah per logical child connection... the network connection
259 * fills it but it belongs to the logical child.
261 struct lws_h2_netconn {
262 struct http2_settings set;
263 struct hpack_dynamic_table hpack_dyn_table;
264 uint8_t ping_payload[8];
265 uint8_t one_setting[LWS_H2_SETTINGS_LEN];
266 char goaway_str[32]; /* for rx */
268 struct lws_h2_protocol_send *pps; /* linked list */
270 enum http2_hpack_state hpack;
271 enum http2_hpack_type hpack_type;
274 unsigned int value:1;
275 unsigned int unknown_header:1;
276 unsigned int cont_exp:1;
277 unsigned int cont_exp_headers:1;
278 unsigned int we_told_goaway:1;
279 unsigned int pad_length:1;
280 unsigned int collected_priority:1;
281 unsigned int is_first_header_char:1;
282 unsigned int zero_huff_padding:1;
283 unsigned int last_action_dyntable_resize:1;
287 uint32_t hpack_e_dep;
293 uint32_t highest_sid;
294 uint32_t highest_sid_opened;
295 uint32_t cont_exp_sid;
297 uint32_t goaway_last_sid;
299 uint32_t hpack_hdr_len;
314 struct _lws_h2_related {
316 struct lws_h2_netconn *h2n; /* malloc'd for root net conn */
317 struct lws *parent_wsi;
318 struct lws *child_list;
319 struct lws *sibling_list;
321 char *pending_status_body;
326 unsigned int child_count;
328 uint32_t dependent_on;
330 unsigned int END_STREAM:1;
331 unsigned int END_HEADERS:1;
332 unsigned int send_END_STREAM:1;
333 unsigned int GOING_AWAY;
334 unsigned int requested_POLLOUT:1;
335 unsigned int skint:1;
337 uint16_t round_robin_POLLOUT;
338 uint16_t count_POLLOUT_children;
340 uint8_t h2_state; /* the RFC7540 state of the connection */
345 #define HTTP2_IS_TOPLEVEL_WSI(wsi) (!wsi->h2.parent_wsi)
348 lws_h2_rst_stream(struct lws *wsi, uint32_t err, const char *reason);
349 struct lws * lws_h2_get_nth_child(struct lws *wsi, int n);
350 LWS_EXTERN void lws_h2_init(struct lws *wsi);
352 lws_h2_settings(struct lws *nwsi, struct http2_settings *settings,
353 unsigned char *buf, int len);
355 lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t inlen,
356 lws_filepos_t *inused);
358 lws_h2_do_pps_send(struct lws *wsi);
360 lws_h2_frame_write(struct lws *wsi, int type, int flags, unsigned int sid,
361 unsigned int len, unsigned char *buf);
362 LWS_EXTERN struct lws *
363 lws_h2_wsi_from_id(struct lws *wsi, unsigned int sid);
365 lws_hpack_interpret(struct lws *wsi, unsigned char c);
367 lws_add_http2_header_by_name(struct lws *wsi,
368 const unsigned char *name,
369 const unsigned char *value, int length,
370 unsigned char **p, unsigned char *end);
372 lws_add_http2_header_by_token(struct lws *wsi,
373 enum lws_token_indexes token,
374 const unsigned char *value, int length,
375 unsigned char **p, unsigned char *end);
377 lws_add_http2_header_status(struct lws *wsi,
378 unsigned int code, unsigned char **p,
381 lws_hpack_destroy_dynamic_header(struct lws *wsi);
383 lws_hpack_dynamic_size(struct lws *wsi, int size);
385 lws_h2_goaway(struct lws *wsi, uint32_t err, const char *reason);
387 lws_h2_tx_cr_get(struct lws *wsi);
389 lws_h2_tx_cr_consume(struct lws *wsi, int consumed);
391 lws_hdr_extant(struct lws *wsi, enum lws_token_indexes h);
393 lws_pps_schedule(struct lws *wsi, struct lws_h2_protocol_send *pss);
395 LWS_EXTERN const struct http2_settings lws_h2_defaults;
397 lws_h2_ws_handshake(struct lws *wsi);
398 LWS_EXTERN int lws_h2_issue_preface(struct lws *wsi);
400 lws_h2_client_handshake(struct lws *wsi);
401 LWS_EXTERN struct lws *
402 lws_wsi_h2_adopt(struct lws *parent_wsi, struct lws *wsi);
404 lws_handle_POLLOUT_event_h2(struct lws *wsi);
406 lws_read_h2(struct lws *wsi, unsigned char *buf, lws_filepos_t len);