Integrate TLDK with NGINX
[tldk.git] / app / nginx / src / http / v2 / ngx_http_v2.h
1 /*
2  * Copyright (C) Nginx, Inc.
3  * Copyright (C) Valentin V. Bartenev
4  */
5
6
7 #ifndef _NGX_HTTP_V2_H_INCLUDED_
8 #define _NGX_HTTP_V2_H_INCLUDED_
9
10
11 #include <ngx_config.h>
12 #include <ngx_core.h>
13 #include <ngx_http.h>
14
15
16 #define NGX_HTTP_V2_ALPN_ADVERTISE       "\x02h2"
17 #define NGX_HTTP_V2_NPN_ADVERTISE        NGX_HTTP_V2_ALPN_ADVERTISE
18
19 #define NGX_HTTP_V2_STATE_BUFFER_SIZE    16
20
21 #define NGX_HTTP_V2_MAX_FRAME_SIZE       ((1 << 24) - 1)
22
23 #define NGX_HTTP_V2_INT_OCTETS           4
24 #define NGX_HTTP_V2_MAX_FIELD                                                 \
25     (127 + (1 << (NGX_HTTP_V2_INT_OCTETS - 1) * 7) - 1)
26
27 #define NGX_HTTP_V2_FRAME_HEADER_SIZE    9
28
29 /* frame types */
30 #define NGX_HTTP_V2_DATA_FRAME           0x0
31 #define NGX_HTTP_V2_HEADERS_FRAME        0x1
32 #define NGX_HTTP_V2_PRIORITY_FRAME       0x2
33 #define NGX_HTTP_V2_RST_STREAM_FRAME     0x3
34 #define NGX_HTTP_V2_SETTINGS_FRAME       0x4
35 #define NGX_HTTP_V2_PUSH_PROMISE_FRAME   0x5
36 #define NGX_HTTP_V2_PING_FRAME           0x6
37 #define NGX_HTTP_V2_GOAWAY_FRAME         0x7
38 #define NGX_HTTP_V2_WINDOW_UPDATE_FRAME  0x8
39 #define NGX_HTTP_V2_CONTINUATION_FRAME   0x9
40
41 /* frame flags */
42 #define NGX_HTTP_V2_NO_FLAG              0x00
43 #define NGX_HTTP_V2_ACK_FLAG             0x01
44 #define NGX_HTTP_V2_END_STREAM_FLAG      0x01
45 #define NGX_HTTP_V2_END_HEADERS_FLAG     0x04
46 #define NGX_HTTP_V2_PADDED_FLAG          0x08
47 #define NGX_HTTP_V2_PRIORITY_FLAG        0x20
48
49 #define NGX_HTTP_V2_MAX_WINDOW           ((1U << 31) - 1)
50 #define NGX_HTTP_V2_DEFAULT_WINDOW       65535
51
52
53 typedef struct ngx_http_v2_connection_s   ngx_http_v2_connection_t;
54 typedef struct ngx_http_v2_node_s         ngx_http_v2_node_t;
55 typedef struct ngx_http_v2_out_frame_s    ngx_http_v2_out_frame_t;
56
57
58 typedef u_char *(*ngx_http_v2_handler_pt) (ngx_http_v2_connection_t *h2c,
59     u_char *pos, u_char *end);
60
61
62 typedef struct {
63     ngx_str_t                        name;
64     ngx_str_t                        value;
65 } ngx_http_v2_header_t;
66
67
68 typedef struct {
69     ngx_uint_t                       sid;
70     size_t                           length;
71     size_t                           padding;
72     unsigned                         flags:8;
73
74     unsigned                         incomplete:1;
75     unsigned                         keep_pool:1;
76
77     /* HPACK */
78     unsigned                         parse_name:1;
79     unsigned                         parse_value:1;
80     unsigned                         index:1;
81     ngx_http_v2_header_t             header;
82     size_t                           header_limit;
83     u_char                           field_state;
84     u_char                          *field_start;
85     u_char                          *field_end;
86     size_t                           field_rest;
87     ngx_pool_t                      *pool;
88
89     ngx_http_v2_stream_t            *stream;
90
91     u_char                           buffer[NGX_HTTP_V2_STATE_BUFFER_SIZE];
92     size_t                           buffer_used;
93     ngx_http_v2_handler_pt           handler;
94 } ngx_http_v2_state_t;
95
96
97
98 typedef struct {
99     ngx_http_v2_header_t           **entries;
100
101     ngx_uint_t                       added;
102     ngx_uint_t                       deleted;
103     ngx_uint_t                       reused;
104     ngx_uint_t                       allocated;
105
106     size_t                           size;
107     size_t                           free;
108     u_char                          *storage;
109     u_char                          *pos;
110 } ngx_http_v2_hpack_t;
111
112
113 struct ngx_http_v2_connection_s {
114     ngx_connection_t                *connection;
115     ngx_http_connection_t           *http_connection;
116
117     ngx_uint_t                       processing;
118
119     size_t                           send_window;
120     size_t                           recv_window;
121     size_t                           init_window;
122
123     size_t                           frame_size;
124
125     ngx_queue_t                      waiting;
126
127     ngx_http_v2_state_t              state;
128
129     ngx_http_v2_hpack_t              hpack;
130
131     ngx_pool_t                      *pool;
132
133     ngx_http_v2_out_frame_t         *free_frames;
134     ngx_connection_t                *free_fake_connections;
135
136     ngx_http_v2_node_t             **streams_index;
137
138     ngx_http_v2_out_frame_t         *last_out;
139
140     ngx_queue_t                      dependencies;
141     ngx_queue_t                      closed;
142
143     ngx_uint_t                       last_sid;
144
145     unsigned                         closed_nodes:8;
146     unsigned                         settings_ack:1;
147     unsigned                         blocked:1;
148     unsigned                         goaway:1;
149 };
150
151
152 struct ngx_http_v2_node_s {
153     ngx_uint_t                       id;
154     ngx_http_v2_node_t              *index;
155     ngx_http_v2_node_t              *parent;
156     ngx_queue_t                      queue;
157     ngx_queue_t                      children;
158     ngx_queue_t                      reuse;
159     ngx_uint_t                       rank;
160     ngx_uint_t                       weight;
161     double                           rel_weight;
162     ngx_http_v2_stream_t            *stream;
163 };
164
165
166 struct ngx_http_v2_stream_s {
167     ngx_http_request_t              *request;
168     ngx_http_v2_connection_t        *connection;
169     ngx_http_v2_node_t              *node;
170
171     ngx_uint_t                       queued;
172
173     /*
174      * A change to SETTINGS_INITIAL_WINDOW_SIZE could cause the
175      * send_window to become negative, hence it's signed.
176      */
177     ssize_t                          send_window;
178     size_t                           recv_window;
179
180     ngx_buf_t                       *preread;
181
182     ngx_http_v2_out_frame_t         *free_frames;
183     ngx_chain_t                     *free_frame_headers;
184     ngx_chain_t                     *free_bufs;
185
186     ngx_queue_t                      queue;
187
188     ngx_array_t                     *cookies;
189
190     size_t                           header_limit;
191
192     ngx_pool_t                      *pool;
193
194     unsigned                         waiting:1;
195     unsigned                         blocked:1;
196     unsigned                         exhausted:1;
197     unsigned                         in_closed:1;
198     unsigned                         out_closed:1;
199     unsigned                         rst_sent:1;
200     unsigned                         no_flow_control:1;
201     unsigned                         skip_data:1;
202 };
203
204
205 struct ngx_http_v2_out_frame_s {
206     ngx_http_v2_out_frame_t         *next;
207     ngx_chain_t                     *first;
208     ngx_chain_t                     *last;
209     ngx_int_t                      (*handler)(ngx_http_v2_connection_t *h2c,
210                                         ngx_http_v2_out_frame_t *frame);
211
212     ngx_http_v2_stream_t            *stream;
213     size_t                           length;
214
215     unsigned                         blocked:1;
216     unsigned                         fin:1;
217 };
218
219
220 static ngx_inline void
221 ngx_http_v2_queue_frame(ngx_http_v2_connection_t *h2c,
222     ngx_http_v2_out_frame_t *frame)
223 {
224     ngx_http_v2_out_frame_t  **out;
225
226     for (out = &h2c->last_out; *out; out = &(*out)->next) {
227
228         if ((*out)->blocked || (*out)->stream == NULL) {
229             break;
230         }
231
232         if ((*out)->stream->node->rank < frame->stream->node->rank
233             || ((*out)->stream->node->rank == frame->stream->node->rank
234                 && (*out)->stream->node->rel_weight
235                    >= frame->stream->node->rel_weight))
236         {
237             break;
238         }
239     }
240
241     frame->next = *out;
242     *out = frame;
243 }
244
245
246 static ngx_inline void
247 ngx_http_v2_queue_blocked_frame(ngx_http_v2_connection_t *h2c,
248     ngx_http_v2_out_frame_t *frame)
249 {
250     ngx_http_v2_out_frame_t  **out;
251
252     for (out = &h2c->last_out; *out; out = &(*out)->next) {
253
254         if ((*out)->blocked || (*out)->stream == NULL) {
255             break;
256         }
257     }
258
259     frame->next = *out;
260     *out = frame;
261 }
262
263
264 void ngx_http_v2_init(ngx_event_t *rev);
265 void ngx_http_v2_request_headers_init(void);
266
267 ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r,
268     ngx_http_client_body_handler_pt post_handler);
269 ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r);
270
271 void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc);
272
273 ngx_int_t ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c);
274
275
276 ngx_int_t ngx_http_v2_get_indexed_header(ngx_http_v2_connection_t *h2c,
277     ngx_uint_t index, ngx_uint_t name_only);
278 ngx_int_t ngx_http_v2_add_header(ngx_http_v2_connection_t *h2c,
279     ngx_http_v2_header_t *header);
280 ngx_int_t ngx_http_v2_table_size(ngx_http_v2_connection_t *h2c, size_t size);
281
282
283 ngx_int_t ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len,
284     u_char **dst, ngx_uint_t last, ngx_log_t *log);
285 size_t ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst,
286     ngx_uint_t lower);
287
288
289 #define ngx_http_v2_prefix(bits)  ((1 << (bits)) - 1)
290
291
292 #if (NGX_HAVE_NONALIGNED)
293
294 #define ngx_http_v2_parse_uint16(p)  ntohs(*(uint16_t *) (p))
295 #define ngx_http_v2_parse_uint32(p)  ntohl(*(uint32_t *) (p))
296
297 #else
298
299 #define ngx_http_v2_parse_uint16(p)  ((p)[0] << 8 | (p)[1])
300 #define ngx_http_v2_parse_uint32(p)                                           \
301     ((uint32_t) (p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3])
302
303 #endif
304
305 #define ngx_http_v2_parse_length(p)  ((p) >> 8)
306 #define ngx_http_v2_parse_type(p)    ((p) & 0xff)
307 #define ngx_http_v2_parse_sid(p)     (ngx_http_v2_parse_uint32(p) & 0x7fffffff)
308 #define ngx_http_v2_parse_window(p)  (ngx_http_v2_parse_uint32(p) & 0x7fffffff)
309
310
311 #define ngx_http_v2_write_uint16_aligned(p, s)                                \
312     (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t))
313 #define ngx_http_v2_write_uint32_aligned(p, s)                                \
314     (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t))
315
316 #if (NGX_HAVE_NONALIGNED)
317
318 #define ngx_http_v2_write_uint16  ngx_http_v2_write_uint16_aligned
319 #define ngx_http_v2_write_uint32  ngx_http_v2_write_uint32_aligned
320
321 #else
322
323 #define ngx_http_v2_write_uint16(p, s)                                        \
324     ((p)[0] = (u_char) ((s) >> 8),                                            \
325      (p)[1] = (u_char)  (s),                                                  \
326      (p) + sizeof(uint16_t))
327
328 #define ngx_http_v2_write_uint32(p, s)                                        \
329     ((p)[0] = (u_char) ((s) >> 24),                                           \
330      (p)[1] = (u_char) ((s) >> 16),                                           \
331      (p)[2] = (u_char) ((s) >> 8),                                            \
332      (p)[3] = (u_char)  (s),                                                  \
333      (p) + sizeof(uint32_t))
334
335 #endif
336
337 #define ngx_http_v2_write_len_and_type(p, l, t)                               \
338     ngx_http_v2_write_uint32_aligned(p, (l) << 8 | (t))
339
340 #define ngx_http_v2_write_sid  ngx_http_v2_write_uint32
341
342 #endif /* _NGX_HTTP_V2_H_INCLUDED_ */