1 /*
2  * Copyright (c) 2018 Fastly Inc, Ichito Nagata
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 #ifndef h2o__http2_common_h
23 #define h2o__http2_common_h
24 
25 #include "h2o/string_.h"
26 #include "h2o/header.h"
27 #include "h2o/url.h"
28 #include "h2o/memory.h"
29 #include "h2o/cache_digests.h"
30 
31 #define H2O_HTTP2_SETTINGS_HEADER_TABLE_SIZE 1
32 #define H2O_HTTP2_SETTINGS_ENABLE_PUSH 2
33 #define H2O_HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS 3
34 #define H2O_HTTP2_SETTINGS_INITIAL_WINDOW_SIZE 4
35 #define H2O_HTTP2_SETTINGS_MAX_FRAME_SIZE 5
36 #define H2O_HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE 6
37 
38 /* defined as negated form of the error codes defined in HTTP2-spec section 7 */
39 #define H2O_HTTP2_ERROR_NONE 0
40 #define H2O_HTTP2_ERROR_PROTOCOL -1
41 #define H2O_HTTP2_ERROR_INTERNAL -2
42 #define H2O_HTTP2_ERROR_FLOW_CONTROL -3
43 #define H2O_HTTP2_ERROR_SETTINGS_TIMEOUT -4
44 #define H2O_HTTP2_ERROR_STREAM_CLOSED -5
45 #define H2O_HTTP2_ERROR_FRAME_SIZE -6
46 #define H2O_HTTP2_ERROR_REFUSED_STREAM -7
47 #define H2O_HTTP2_ERROR_CANCEL -8
48 #define H2O_HTTP2_ERROR_COMPRESSION -9
49 #define H2O_HTTP2_ERROR_CONNECT -10
50 #define H2O_HTTP2_ERROR_ENHANCE_YOUR_CALM -11
51 #define H2O_HTTP2_ERROR_INADEQUATE_SECURITY -12
52 #define H2O_HTTP2_ERROR_MAX 13
53 /* end of the HTTP2-spec defined errors */
54 #define H2O_HTTP2_ERROR_INVALID_HEADER_CHAR                                                                                        \
55     -254 /* an internal value indicating that invalid characters were found in the header name or value */
56 #define H2O_HTTP2_ERROR_INCOMPLETE -255 /* an internal value indicating that all data is not ready */
57 #define H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY -256
58 
59 typedef struct st_h2o_http2_settings_t {
60     uint32_t header_table_size;
61     uint32_t enable_push;
62     uint32_t max_concurrent_streams;
63     uint32_t initial_window_size;
64     uint32_t max_frame_size;
65 } h2o_http2_settings_t;
66 
67 extern const h2o_http2_settings_t H2O_HTTP2_SETTINGS_DEFAULT;
68 
69 int h2o_http2_update_peer_settings(h2o_http2_settings_t *settings, const uint8_t *src, size_t len, const char **err_desc);
70 
71 typedef struct st_h2o_http2_priority_t {
72     int exclusive;
73     uint32_t dependency;
74     uint16_t weight;
75 } h2o_http2_priority_t;
76 
77 extern const h2o_http2_priority_t h2o_http2_default_priority;
78 
79 #define H2O_HTTP2_DEFAULT_OUTBUF_SIZE 81920 /* the target size of each write call; connection flow control window + alpha */
80 #define H2O_HTTP2_DEFAULT_OUTBUF_SOFT_MAX_SIZE 524288 /* 512KB; stops reading if size exceeds this value */
81 #define H2O_HTTP2_DEFAULT_OUTBUF_WRITE_TIMEOUT 60000  /* 60 seconds; close if write does not complete within the period */
82 
83 /* hpack */
84 
85 typedef struct st_h2o_hpack_header_table_t {
86     /* ring buffer */
87     struct st_h2o_hpack_header_table_entry_t *entries;
88     size_t num_entries, entry_capacity, entry_start_index;
89     /* size and capacities are 32+name_len+value_len (as defined by hpack spec.) */
90     size_t hpack_size;
91     size_t hpack_capacity;     /* the value set by SETTINGS_HEADER_TABLE_SIZE _and_ dynamic table size update */
92     size_t hpack_max_capacity; /* the value set by SETTINGS_HEADER_TABLE_SIZE */
93 } h2o_hpack_header_table_t;
94 
95 typedef struct st_h2o_hpack_header_table_entry_t {
96     h2o_iovec_t *name;
97     h2o_iovec_t *value;
98     unsigned soft_errors;
99 } h2o_hpack_header_table_entry_t;
100 
101 void h2o_hpack_dispose_header_table(h2o_hpack_header_table_t *header_table);
102 
103 size_t h2o_hpack_encode_string(uint8_t *dst, const char *s, size_t len);
104 void h2o_hpack_flatten_push_promise(h2o_buffer_t **buf, h2o_hpack_header_table_t *header_table, uint32_t hpack_capacity,
105                                     uint32_t stream_id, size_t max_frame_size, const h2o_url_scheme_t *scheme,
106                                     h2o_iovec_t authority, h2o_iovec_t method, h2o_iovec_t path, const h2o_header_t *headers,
107                                     size_t num_headers, uint32_t parent_stream_id);
108 void h2o_hpack_flatten_response(h2o_buffer_t **buf, h2o_hpack_header_table_t *header_table, uint32_t hpack_capacity,
109                                 uint32_t stream_id, size_t max_frame_size, int status, const h2o_header_t *headers,
110                                 size_t num_headers, const h2o_iovec_t *server_name, size_t content_length);
111 void h2o_hpack_flatten_request(h2o_buffer_t **buf, h2o_hpack_header_table_t *header_table, uint32_t hpack_capacity,
112                                uint32_t stream_id, size_t max_frame_size, h2o_iovec_t method, h2o_url_t *url,
113                                const h2o_header_t *headers, size_t num_headers, int is_end_stream);
114 void h2o_hpack_flatten_trailers(h2o_buffer_t **buf, h2o_hpack_header_table_t *header_table, uint32_t hpack_capacity,
115                                 uint32_t stream_id, size_t max_frame_size, const h2o_header_t *headers, size_t num_headers);
116 
117 extern h2o_buffer_prototype_t h2o_http2_wbuf_buffer_prototype;
118 
119 /* frames */
120 
121 #define H2O_HTTP2_FRAME_HEADER_SIZE 9
122 
123 #define H2O_HTTP2_FRAME_TYPE_DATA 0
124 #define H2O_HTTP2_FRAME_TYPE_HEADERS 1
125 #define H2O_HTTP2_FRAME_TYPE_PRIORITY 2
126 #define H2O_HTTP2_FRAME_TYPE_RST_STREAM 3
127 #define H2O_HTTP2_FRAME_TYPE_SETTINGS 4
128 #define H2O_HTTP2_FRAME_TYPE_PUSH_PROMISE 5
129 #define H2O_HTTP2_FRAME_TYPE_PING 6
130 #define H2O_HTTP2_FRAME_TYPE_GOAWAY 7
131 #define H2O_HTTP2_FRAME_TYPE_WINDOW_UPDATE 8
132 #define H2O_HTTP2_FRAME_TYPE_CONTINUATION 9
133 #define H2O_HTTP2_FRAME_TYPE_ORIGIN 12
134 
135 #define H2O_HTTP2_FRAME_FLAG_END_STREAM 0x1
136 #define H2O_HTTP2_FRAME_FLAG_ACK 0x1
137 #define H2O_HTTP2_FRAME_FLAG_END_HEADERS 0x4
138 #define H2O_HTTP2_FRAME_FLAG_PADDED 0x8
139 #define H2O_HTTP2_FRAME_FLAG_PRIORITY 0x20
140 
141 typedef struct st_h2o_http2_frame_t {
142     uint32_t length;
143     uint8_t type;
144     uint8_t flags;
145     uint32_t stream_id;
146     const uint8_t *payload;
147 } h2o_http2_frame_t;
148 
149 typedef struct st_h2o_http2_data_payload_t {
150     const uint8_t *data;
151     size_t length;
152 } h2o_http2_data_payload_t;
153 
154 typedef struct st_h2o_http2_headers_payload_t {
155     h2o_http2_priority_t priority;
156     const uint8_t *headers;
157     size_t headers_len;
158 } h2o_http2_headers_payload_t;
159 
160 typedef struct st_h2o_http2_rst_stream_payload_t {
161     uint32_t error_code;
162 } h2o_http2_rst_stream_payload_t;
163 
164 typedef struct st_h2o_http2_ping_payload_t {
165     uint8_t data[8];
166 } h2o_http2_ping_payload_t;
167 
168 typedef struct st_h2o_http2_goaway_payload_t {
169     uint32_t last_stream_id;
170     uint32_t error_code;
171     h2o_iovec_t debug_data;
172 } h2o_http2_goaway_payload_t;
173 
174 typedef struct st_h2o_http2_window_update_payload_t {
175     uint32_t window_size_increment;
176 } h2o_http2_window_update_payload_t;
177 
178 uint8_t *h2o_http2_encode_frame_header(uint8_t *dst, size_t length, uint8_t type, uint8_t flags, int32_t stream_id);
179 
180 #define h2o_http2_encode_rst_stream_frame(buf, stream_id, errnum)                                                                  \
181     h2o_http2__encode_rst_stream_frame(buf, stream_id, (H2O_BUILD_ASSERT((errnum) > 0), errnum))
182 
183 void h2o_http2__encode_rst_stream_frame(h2o_buffer_t **buf, uint32_t stream_id, int errnum);
184 void h2o_http2_encode_ping_frame(h2o_buffer_t **buf, int is_ack, const uint8_t *data);
185 void h2o_http2_encode_goaway_frame(h2o_buffer_t **buf, uint32_t last_stream_id, int errnum, h2o_iovec_t additional_data);
186 void h2o_http2_encode_window_update_frame(h2o_buffer_t **buf, uint32_t stream_id, int32_t window_size_increment);
187 void h2o_http2_encode_origin_frame(h2o_buffer_t **buf, h2o_iovec_t payload);
188 ssize_t h2o_http2_decode_frame(h2o_http2_frame_t *frame, const uint8_t *src, size_t len, size_t max_frame_size,
189                                const char **err_desc);
190 int h2o_http2_decode_data_payload(h2o_http2_data_payload_t *payload, const h2o_http2_frame_t *frame, const char **err_desc);
191 int h2o_http2_decode_headers_payload(h2o_http2_headers_payload_t *payload, const h2o_http2_frame_t *frame, const char **err_desc);
192 int h2o_http2_decode_priority_payload(h2o_http2_priority_t *payload, const h2o_http2_frame_t *frame, const char **err_desc);
193 int h2o_http2_decode_rst_stream_payload(h2o_http2_rst_stream_payload_t *payload, const h2o_http2_frame_t *frame,
194                                         const char **err_desc);
195 int h2o_http2_decode_ping_payload(h2o_http2_ping_payload_t *payload, const h2o_http2_frame_t *frame, const char **err_desc);
196 int h2o_http2_decode_goaway_payload(h2o_http2_goaway_payload_t *payload, const h2o_http2_frame_t *frame, const char **err_desc);
197 int h2o_http2_decode_window_update_payload(h2o_http2_window_update_payload_t *paylaod, const h2o_http2_frame_t *frame,
198                                            const char **err_desc, int *err_is_stream_level);
199 
200 typedef struct st_h2o_http2_window_t {
201     ssize_t _avail;
202 } h2o_http2_window_t;
203 
204 static void h2o_http2_window_init(h2o_http2_window_t *window, uint32_t initial_window_size);
205 static int h2o_http2_window_update(h2o_http2_window_t *window, ssize_t delta);
206 static ssize_t h2o_http2_window_get_avail(h2o_http2_window_t *window);
207 static void h2o_http2_window_consume_window(h2o_http2_window_t *window, size_t bytes);
208 
209 static h2o_hpack_header_table_entry_t *h2o_hpack_header_table_get(h2o_hpack_header_table_t *table, size_t index);
210 
211 /* misc */
212 
213 static uint16_t h2o_http2_decode16u(const uint8_t *src);
214 static uint32_t h2o_http2_decode24u(const uint8_t *src);
215 static uint32_t h2o_http2_decode32u(const uint8_t *src);
216 static uint8_t *h2o_http2_encode24u(uint8_t *dst, uint32_t value);
217 static uint8_t *h2o_http2_encode32u(uint8_t *dst, uint32_t value);
218 
219 /* inline definitions */
220 
h2o_http2_window_init(h2o_http2_window_t * window,uint32_t initial_window_size)221 inline void h2o_http2_window_init(h2o_http2_window_t *window, uint32_t initial_window_size)
222 {
223     window->_avail = initial_window_size;
224 }
225 
h2o_http2_window_update(h2o_http2_window_t * window,ssize_t delta)226 inline int h2o_http2_window_update(h2o_http2_window_t *window, ssize_t delta)
227 {
228     ssize_t v = window->_avail + delta;
229     if (v > INT32_MAX)
230         return -1;
231     window->_avail = v;
232     return 0;
233 }
234 
h2o_http2_window_get_avail(h2o_http2_window_t * window)235 inline ssize_t h2o_http2_window_get_avail(h2o_http2_window_t *window)
236 {
237     return window->_avail;
238 }
239 
h2o_http2_window_consume_window(h2o_http2_window_t * window,size_t bytes)240 inline void h2o_http2_window_consume_window(h2o_http2_window_t *window, size_t bytes)
241 {
242     window->_avail -= bytes;
243 }
244 
h2o_http2_decode16u(const uint8_t * src)245 inline uint16_t h2o_http2_decode16u(const uint8_t *src)
246 {
247     return (uint16_t)src[0] << 8 | src[1];
248 }
249 
h2o_http2_decode24u(const uint8_t * src)250 inline uint32_t h2o_http2_decode24u(const uint8_t *src)
251 {
252     return (uint32_t)src[0] << 16 | (uint32_t)src[1] << 8 | src[2];
253 }
254 
h2o_http2_decode32u(const uint8_t * src)255 inline uint32_t h2o_http2_decode32u(const uint8_t *src)
256 {
257     return (uint32_t)src[0] << 24 | (uint32_t)src[1] << 16 | (uint32_t)src[2] << 8 | src[3];
258 }
259 
h2o_http2_encode24u(uint8_t * dst,uint32_t value)260 inline uint8_t *h2o_http2_encode24u(uint8_t *dst, uint32_t value)
261 {
262     *dst++ = value >> 16;
263     *dst++ = value >> 8;
264     *dst++ = value;
265     return dst;
266 }
267 
h2o_http2_encode32u(uint8_t * dst,uint32_t value)268 inline uint8_t *h2o_http2_encode32u(uint8_t *dst, uint32_t value)
269 {
270     *dst++ = value >> 24;
271     *dst++ = value >> 16;
272     *dst++ = value >> 8;
273     *dst++ = value;
274     return dst;
275 }
276 
h2o_hpack_header_table_get(h2o_hpack_header_table_t * table,size_t index)277 inline h2o_hpack_header_table_entry_t *h2o_hpack_header_table_get(h2o_hpack_header_table_t *table, size_t index)
278 {
279     size_t entry_index = (index + table->entry_start_index) % table->entry_capacity;
280     struct st_h2o_hpack_header_table_entry_t *entry = table->entries + entry_index;
281     assert(entry->name != NULL);
282     return entry;
283 }
284 
285 #endif
286