comparison src/event/ngx_event_quic.c @ 7691:714a19dba6af quic

Style and handlers. Cleanup in ngx_event_quic.c: + reorderded functions, structures + added missing prototypes + added separate handlers for each frame type + numerous indentation/comments/TODO fixes + removed non-implemented qc->state and corresponding enum; this requires deep thinking, stub was unused. + streams inside quic connection are now in own structure
author Vladimir Homutov <vl@nginx.com>
date Wed, 18 Mar 2020 13:02:19 +0300
parents ae35ccba7aa6
children cfc429911c0d
comparison
equal deleted inserted replaced
7690:ae35ccba7aa6 7691:714a19dba6af
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 10
11 11
12 /* TODO: real states, these are stubs */ 12 typedef struct {
13 typedef enum { 13 ngx_rbtree_node_t node;
14 NGX_QUIC_ST_INITIAL, 14 ngx_buf_t *b;
15 NGX_QUIC_ST_HANDSHAKE, 15 ngx_connection_t *c;
16 NGX_QUIC_ST_APP_DATA 16 ngx_quic_stream_t s;
17 } ngx_quic_state_t; 17 } ngx_quic_stream_node_t;
18
19
20 typedef struct {
21 ngx_rbtree_t tree;
22 ngx_rbtree_node_t sentinel;
23 ngx_msec_t timeout;
24 ngx_connection_handler_pt handler;
25 } ngx_quic_streams_t;
18 26
19 27
20 struct ngx_quic_connection_s { 28 struct ngx_quic_connection_s {
21 29 ngx_str_t scid;
22 ngx_quic_state_t state; 30 ngx_str_t dcid;
23 ngx_ssl_t *ssl; 31 ngx_str_t token;
24 32
25 ngx_quic_frame_t *frames; 33 /* current packet numbers for each namespace */
26 34 ngx_uint_t initial_pn;
27 ngx_str_t scid; 35 ngx_uint_t handshake_pn;
28 ngx_str_t dcid; 36 ngx_uint_t appdata_pn;
29 ngx_str_t token; 37
30 38 ngx_quic_secrets_t secrets;
31 /* current packet numbers for each namespace */ 39 ngx_ssl_t *ssl;
32 ngx_uint_t initial_pn; 40 ngx_quic_frame_t *frames;
33 ngx_uint_t handshake_pn; 41
34 ngx_uint_t appdata_pn; 42 ngx_quic_streams_t streams;
35
36 ngx_quic_secrets_t secrets;
37
38 /* streams */
39 ngx_rbtree_t stree;
40 ngx_rbtree_node_t stree_sentinel;
41 ngx_msec_t stream_timeout;
42 ngx_connection_handler_pt stream_handler;
43 }; 43 };
44
45
46 typedef struct {
47 ngx_rbtree_node_t node;
48 ngx_buf_t *b;
49 ngx_connection_t *c;
50 ngx_quic_stream_t s;
51 } ngx_quic_stream_node_t;
52
53
54 static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b);
55 static ngx_int_t ngx_quic_output(ngx_connection_t *c);
56
57 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl,
58 ngx_quic_header_t *pkt);
59 static void ngx_quic_close_connection(ngx_connection_t *c);
60
61 static ngx_quic_stream_node_t *ngx_quic_stream_lookup(ngx_rbtree_t *rbtree,
62 ngx_uint_t key);
63 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp,
64 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
65
66 static void ngx_quic_handshake_handler(ngx_event_t *rev);
67 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c,
68 ngx_quic_header_t *pkt);
69 static ngx_int_t ngx_quic_initial_input(ngx_connection_t *c,
70 ngx_quic_header_t *pkt);
71 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c,
72 ngx_quic_header_t *pkt);
73 44
74 45
75 #if BORINGSSL_API_VERSION >= 10 46 #if BORINGSSL_API_VERSION >= 10
76 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn, 47 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
77 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, 48 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
82 #else 53 #else
83 static int ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn, 54 static int ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
84 enum ssl_encryption_level_t level, const uint8_t *read_secret, 55 enum ssl_encryption_level_t level, const uint8_t *read_secret,
85 const uint8_t *write_secret, size_t secret_len); 56 const uint8_t *write_secret, size_t secret_len);
86 #endif 57 #endif
58
87 static int ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn, 59 static int ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
88 enum ssl_encryption_level_t level, const uint8_t *data, size_t len); 60 enum ssl_encryption_level_t level, const uint8_t *data, size_t len);
89 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn); 61 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn);
90 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, 62 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
91 enum ssl_encryption_level_t level, uint8_t alert); 63 enum ssl_encryption_level_t level, uint8_t alert);
92 64
93 65
66 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl,
67 ngx_quic_header_t *pkt);
68 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c);
69 static void ngx_quic_handshake_handler(ngx_event_t *rev);
70 static void ngx_quic_close_connection(ngx_connection_t *c);
71
72 static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b);
73 static ngx_int_t ngx_quic_initial_input(ngx_connection_t *c,
74 ngx_quic_header_t *pkt);
75 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c,
76 ngx_quic_header_t *pkt);
77 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c,
78 ngx_quic_header_t *pkt);
79 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c,
80 ngx_quic_header_t *pkt);
81
82 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c,
83 ngx_quic_header_t *pkt, ngx_quic_ack_frame_t *f);
84 static ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c,
85 ngx_quic_header_t *pkt, ngx_quic_crypto_frame_t *frame);
86 static ngx_int_t ngx_quic_handle_stream_frame(ngx_connection_t *c,
87 ngx_quic_header_t *pkt, ngx_quic_stream_frame_t *frame);
88
89 static void ngx_quic_queue_frame(ngx_quic_connection_t *qc,
90 ngx_quic_frame_t *frame);
91
92 static ngx_int_t ngx_quic_output(ngx_connection_t *c);
93 ngx_int_t ngx_quic_frames_send(ngx_connection_t *c, ngx_quic_frame_t *start,
94 ngx_quic_frame_t *end, size_t total);
95 static ngx_int_t ngx_quic_send_packet(ngx_connection_t *c,
96 ngx_quic_connection_t *qc, enum ssl_encryption_level_t level,
97 ngx_str_t *payload);
98
99
100 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp,
101 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
102 static ngx_quic_stream_node_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree,
103 ngx_uint_t key);
94 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, 104 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf,
95 size_t size); 105 size_t size);
96 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, 106 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf,
97 size_t size); 107 size_t size);
98 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c, 108 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c,
99 ngx_chain_t *in, off_t limit); 109 ngx_chain_t *in, off_t limit);
110
100 111
101 static SSL_QUIC_METHOD quic_method = { 112 static SSL_QUIC_METHOD quic_method = {
102 #if BORINGSSL_API_VERSION >= 10 113 #if BORINGSSL_API_VERSION >= 10
103 ngx_quic_set_read_secret, 114 ngx_quic_set_read_secret,
104 ngx_quic_set_write_secret, 115 ngx_quic_set_write_secret,
116 { 127 {
117 SSL_CTX_set_quic_method(ctx, &quic_method); 128 SSL_CTX_set_quic_method(ctx, &quic_method);
118 } 129 }
119 130
120 131
121 void
122 ngx_quic_run(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_msec_t timeout,
123 ngx_connection_handler_pt handler)
124 {
125 ngx_buf_t *b;
126 ngx_quic_header_t pkt;
127
128 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic handshake");
129
130 c->log->action = "QUIC handshaking";
131
132 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
133
134 b = c->buffer;
135
136 pkt.log = c->log;
137 pkt.raw = b;
138 pkt.data = b->start;
139 pkt.len = b->last - b->start;
140
141 if (ngx_quic_new_connection(c, ssl, &pkt) != NGX_OK) {
142 ngx_quic_close_connection(c);
143 return;
144 }
145
146 // we don't need stream handler for initial packet processing
147 c->quic->stream_handler = handler;
148 c->quic->stream_timeout = timeout;
149
150 ngx_add_timer(c->read, timeout);
151
152 c->read->handler = ngx_quic_handshake_handler;
153
154 return;
155 }
156
157
158 static void
159 ngx_quic_handshake_handler(ngx_event_t *rev)
160 {
161 ssize_t n;
162 ngx_connection_t *c;
163 u_char buf[512];
164 ngx_buf_t b;
165
166 b.start = buf;
167 b.end = buf + 512;
168 b.pos = b.last = b.start;
169
170 c = rev->data;
171
172 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0, "quic handshake handler");
173
174 if (rev->timedout) {
175 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
176 ngx_quic_close_connection(c);
177 return;
178 }
179
180 if (c->close) {
181 ngx_quic_close_connection(c);
182 return;
183 }
184
185 n = c->recv(c, b.start, b.end - b.start);
186
187 if (n == NGX_AGAIN) {
188 return;
189 }
190
191 if (n == NGX_ERROR) {
192 c->read->eof = 1;
193 ngx_quic_close_connection(c);
194 return;
195 }
196
197 b.last += n;
198
199 if (ngx_quic_input(c, &b) != NGX_OK) {
200 ngx_quic_close_connection(c);
201 return;
202 }
203 }
204
205
206 static void
207 ngx_quic_close_connection(ngx_connection_t *c)
208 {
209 ngx_pool_t *pool;
210
211 /* XXX wait for all streams to close */
212
213 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
214 "close quic connection: %d", c->fd);
215
216 if (c->ssl) {
217 (void) ngx_ssl_shutdown(c);
218 }
219
220 #if (NGX_STAT_STUB)
221 (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
222 #endif
223
224 c->destroyed = 1;
225
226 pool = c->pool;
227
228 ngx_close_connection(c);
229
230 ngx_destroy_pool(pool);
231 }
232
233
234 ngx_connection_t *
235 ngx_quic_create_uni_stream(ngx_connection_t *c)
236 {
237 /* XXX */
238 return NULL;
239 }
240
241
242 static ngx_int_t
243 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b)
244 {
245 u_char *p;
246 ngx_int_t rc;
247 ngx_quic_header_t pkt;
248
249 if (c->quic == NULL) {
250 // XXX: possible?
251 ngx_log_error(NGX_LOG_INFO, c->log, 0, "BUG: no QUIC in connection");
252 return NGX_ERROR;
253 }
254
255 p = b->start;
256
257 do {
258 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
259 pkt.raw = b;
260 pkt.data = p;
261 pkt.len = b->last - p;
262 pkt.log = c->log;
263
264 if (p[0] == 0) {
265 /* XXX: no idea WTF is this, just ignore */
266 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "FIREFOX: ZEROES");
267 break;
268 }
269
270 // TODO: check current state
271 if (p[0] & NGX_QUIC_PKT_LONG) {
272
273 if ((p[0] & 0xf0) == NGX_QUIC_PKT_INITIAL) {
274 rc = ngx_quic_initial_input(c, &pkt);
275
276 } else if ((p[0] & 0xf0) == NGX_QUIC_PKT_HANDSHAKE) {
277 rc = ngx_quic_handshake_input(c, &pkt);
278
279 } else {
280 ngx_log_error(NGX_LOG_INFO, c->log, 0,
281 "BUG: unknown quic state");
282 return NGX_ERROR;
283 }
284
285 } else {
286 rc = ngx_quic_app_input(c, &pkt);
287 }
288
289 if (rc == NGX_ERROR) {
290 return NGX_ERROR;
291 }
292
293 /* b->pos is at header end, adjust by actual packet length */
294 p = b->pos + pkt.len;
295 b->pos = p; /* reset b->pos to the next packet start */
296
297 } while (p < b->last);
298
299 return NGX_OK;
300 }
301
302 static ngx_int_t
303 ngx_quic_send_packet(ngx_connection_t *c, ngx_quic_connection_t *qc,
304 enum ssl_encryption_level_t level, ngx_str_t *payload)
305 {
306 ngx_str_t res;
307 ngx_quic_header_t pkt;
308
309 pkt.log = c->log;
310
311 static ngx_str_t initial_token = ngx_null_string;
312
313 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
314 ngx_quic_hexdump0(c->log, "payload", payload->data, payload->len);
315
316 pkt.level = level;
317 pkt.dcid = qc->dcid;
318 pkt.scid = qc->scid;
319
320 if (level == ssl_encryption_initial) {
321 pkt.number = &qc->initial_pn;
322 pkt.flags = NGX_QUIC_PKT_INITIAL;
323 pkt.secret = &qc->secrets.server.in;
324 pkt.token = initial_token;
325
326 } else if (level == ssl_encryption_handshake) {
327 pkt.number = &qc->handshake_pn;
328 pkt.flags = NGX_QUIC_PKT_HANDSHAKE;
329 pkt.secret = &qc->secrets.server.hs;
330
331 } else {
332 pkt.number = &qc->appdata_pn;
333 pkt.secret = &qc->secrets.server.ad;
334 }
335
336 if (ngx_quic_encrypt(c->pool, c->ssl->connection, &pkt, payload, &res)
337 != NGX_OK)
338 {
339 return NGX_ERROR;
340 }
341
342 ngx_quic_hexdump0(c->log, "packet to send", res.data, res.len);
343
344 c->send(c, res.data, res.len); // TODO: err handling
345
346 (*pkt.number)++;
347
348 return NGX_OK;
349 }
350
351
352 /* pack a group of frames [start; end) into memory p and send as single packet */
353 ngx_int_t
354 ngx_quic_frames_send(ngx_connection_t *c, ngx_quic_frame_t *start,
355 ngx_quic_frame_t *end, size_t total)
356 {
357 ssize_t len;
358 u_char *p;
359 ngx_str_t out;
360 ngx_quic_frame_t *f;
361
362 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
363 "sending frames %p...%p", start, end);
364
365 p = ngx_pnalloc(c->pool, total);
366 if (p == NULL) {
367 return NGX_ERROR;
368 }
369
370 out.data = p;
371
372 for (f = start; f != end; f = f->next) {
373
374 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "frame: %s", f->info);
375
376 len = ngx_quic_create_frame(p, p + total, f);
377 if (len == -1) {
378 return NGX_ERROR;
379 }
380
381 p += len;
382 }
383
384 out.len = p - out.data;
385
386 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
387 "packet ready: %ui bytes at level %d",
388 out.len, start->level);
389
390 // IOVEC/sendmsg_chain ?
391 if (ngx_quic_send_packet(c, c->quic, start->level, &out) != NGX_OK) {
392 return NGX_ERROR;
393 }
394
395 return NGX_OK;
396 }
397
398
399 static ngx_int_t
400 ngx_quic_output(ngx_connection_t *c)
401 {
402 size_t len;
403 ngx_uint_t lvl;
404 ngx_quic_frame_t *f, *start;
405 ngx_quic_connection_t *qc;
406
407 qc = c->quic;
408
409 if (qc->frames == NULL) {
410 return NGX_OK;
411 }
412
413 lvl = qc->frames->level;
414 start = qc->frames;
415 f = start;
416
417 do {
418 len = 0;
419
420 do {
421 /* process same-level group of frames */
422
423 len += ngx_quic_frame_len(f);// TODO: handle overflow, max size
424
425 f = f->next;
426 } while (f && f->level == lvl);
427
428
429 if (ngx_quic_frames_send(c, start, f, len) != NGX_OK) {
430 return NGX_ERROR;
431 }
432
433 if (f == NULL) {
434 break;
435 }
436
437 lvl = f->level; // TODO: must not decrease (ever, also between calls)
438 start = f;
439
440 } while (1);
441
442 qc->frames = NULL;
443
444 return NGX_OK;
445 }
446
447
448 #if BORINGSSL_API_VERSION >= 10 132 #if BORINGSSL_API_VERSION >= 10
449 133
450 static int 134 static int
451 ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn, 135 ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
452 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, 136 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
510 } 194 }
511 195
512 #endif 196 #endif
513 197
514 198
515 static void
516 ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame)
517 {
518 ngx_quic_frame_t *f;
519
520 if (qc->frames == NULL) {
521 qc->frames = frame;
522 return;
523 }
524
525 for (f = qc->frames; f->next; f = f->next) {
526 if (f->next->level > frame->level) {
527 break;
528 }
529 }
530
531 frame->next = f->next;
532 f->next = frame;
533 }
534
535
536 static int 199 static int
537 ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn, 200 ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
538 enum ssl_encryption_level_t level, const uint8_t *data, size_t len) 201 enum ssl_encryption_level_t level, const uint8_t *data, size_t len)
539 { 202 {
540 u_char *p; 203 u_char *p;
541 ngx_quic_frame_t *frame; 204 ngx_quic_frame_t *frame;
542 ngx_connection_t *c; 205 ngx_connection_t *c;
543 ngx_quic_connection_t *qc; 206 ngx_quic_connection_t *qc;
544 207
545 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); 208 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
546 qc = c->quic; 209 qc = c->quic;
547 210
548 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, 211 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
600 263
601 return 1; 264 return 1;
602 } 265 }
603 266
604 267
268 void
269 ngx_quic_run(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_msec_t timeout,
270 ngx_connection_handler_pt handler)
271 {
272 ngx_buf_t *b;
273 ngx_quic_header_t pkt;
274
275 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic handshake");
276
277 c->log->action = "QUIC handshaking";
278
279 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
280
281 b = c->buffer;
282
283 pkt.log = c->log;
284 pkt.raw = b;
285 pkt.data = b->start;
286 pkt.len = b->last - b->start;
287
288 if (ngx_quic_new_connection(c, ssl, &pkt) != NGX_OK) {
289 ngx_quic_close_connection(c);
290 return;
291 }
292
293 // we don't need stream handler for initial packet processing
294 c->quic->streams.handler = handler;
295 c->quic->streams.timeout = timeout;
296
297 ngx_add_timer(c->read, timeout);
298
299 c->read->handler = ngx_quic_handshake_handler;
300
301 return;
302 }
303
605 304
606 static ngx_int_t 305 static ngx_int_t
607 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, 306 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl,
608 ngx_quic_frame_t *frame) 307 ngx_quic_header_t *pkt)
609 { 308 {
610 int sslerr; 309 ngx_quic_connection_t *qc;
611 ssize_t n; 310
612 ngx_ssl_conn_t *ssl_conn; 311 if (ngx_buf_size(pkt->raw) < 1200) {
613 312 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram");
614 ssl_conn = c->ssl->connection; 313 return NGX_ERROR;
615 314 }
616 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 315
617 "SSL_quic_read_level: %d, SSL_quic_write_level: %d", 316 if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
618 (int) SSL_quic_read_level(ssl_conn), 317 return NGX_ERROR;
619 (int) SSL_quic_write_level(ssl_conn)); 318 }
620 319
621 320 if ((pkt->flags & 0xf0) != NGX_QUIC_PKT_INITIAL) {
622 if (!SSL_provide_quic_data(ssl_conn, SSL_quic_read_level(ssl_conn), 321 ngx_log_error(NGX_LOG_INFO, c->log, 0,
623 frame->u.crypto.data, frame->u.crypto.len)) 322 "invalid initial packet: 0x%xi", pkt->flags);
323 return NGX_ERROR;
324 }
325
326 if (ngx_quic_parse_initial_header(pkt) != NGX_OK) {
327 return NGX_ERROR;
328 }
329
330 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t));
331 if (qc == NULL) {
332 return NGX_ERROR;
333 }
334
335 ngx_rbtree_init(&qc->streams.tree, &qc->streams.sentinel,
336 ngx_quic_rbtree_insert_stream);
337
338 c->quic = qc;
339 qc->ssl = ssl;
340
341 qc->dcid.len = pkt->dcid.len;
342 qc->dcid.data = ngx_pnalloc(c->pool, pkt->dcid.len);
343 if (qc->dcid.data == NULL) {
344 return NGX_ERROR;
345 }
346 ngx_memcpy(qc->dcid.data, pkt->dcid.data, qc->dcid.len);
347
348 qc->scid.len = pkt->scid.len;
349 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len);
350 if (qc->scid.data == NULL) {
351 return NGX_ERROR;
352 }
353 ngx_memcpy(qc->scid.data, pkt->scid.data, qc->scid.len);
354
355 qc->token.len = pkt->token.len;
356 qc->token.data = ngx_pnalloc(c->pool, qc->token.len);
357 if (qc->token.data == NULL) {
358 return NGX_ERROR;
359 }
360 ngx_memcpy(qc->token.data, pkt->token.data, qc->token.len);
361
362
363 if (ngx_quic_set_initial_secret(c->pool, &qc->secrets, &qc->dcid)
364 != NGX_OK)
624 { 365 {
625 ngx_ssl_error(NGX_LOG_INFO, c->log, 0, 366 return NGX_ERROR;
626 "SSL_provide_quic_data() failed"); 367 }
627 return NGX_ERROR; 368
628 } 369 pkt->secret = &qc->secrets.client.in;
629 370 pkt->level = ssl_encryption_initial;
630 n = SSL_do_handshake(ssl_conn); 371
631 372 if (ngx_quic_decrypt(c->pool, NULL, pkt) != NGX_OK) {
632 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); 373 return NGX_ERROR;
633 374 }
634 if (n == -1) { 375
635 sslerr = SSL_get_error(ssl_conn, n); 376 if (ngx_quic_init_connection(c) != NGX_OK) {
636 377 return NGX_ERROR;
637 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", 378 }
638 sslerr); 379
639 380 return ngx_quic_payload_handler(c, pkt);
640 if (sslerr == SSL_ERROR_SSL) { 381 }
641 ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_do_handshake() failed");
642 }
643 }
644
645 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
646 "quic ssl cipher: %s", SSL_get_cipher(ssl_conn));
647
648 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
649 "SSL_quic_read_level: %d, SSL_quic_write_level: %d",
650 (int) SSL_quic_read_level(ssl_conn),
651 (int) SSL_quic_write_level(ssl_conn));
652
653 return NGX_OK;
654 }
655
656 382
657 383
658 static ngx_int_t 384 static ngx_int_t
659 ngx_quic_init_connection(ngx_connection_t *c) 385 ngx_quic_init_connection(ngx_connection_t *c)
660 { 386 {
704 430
705 return NGX_OK; 431 return NGX_OK;
706 } 432 }
707 433
708 434
709 static ssize_t 435 static void
710 ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size) 436 ngx_quic_handshake_handler(ngx_event_t *rev)
711 { 437 {
712 ssize_t len; 438 ssize_t n;
713 ngx_buf_t *b; 439 ngx_buf_t b;
714 ngx_quic_stream_t *qs; 440 ngx_connection_t *c;
715 ngx_quic_connection_t *qc; 441
716 ngx_quic_stream_node_t *sn; 442 u_char buf[512];
717 443
718 qs = c->qs; 444 b.start = buf;
719 qc = qs->parent->quic; 445 b.end = buf + 512;
720 446 b.pos = b.last = b.start;
721 // XXX: get direct pointer from stream structure? 447
722 sn = ngx_quic_stream_lookup(&qc->stree, qs->id); 448 c = rev->data;
723 449
724 if (sn == NULL) { 450 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0, "quic handshake handler");
725 return NGX_ERROR; 451
726 } 452 if (rev->timedout) {
727 453 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
728 // XXX: how to return EOF? 454 ngx_quic_close_connection(c);
729 455 return;
730 b = sn->b; 456 }
731 457
732 if (b->last - b->pos == 0) { 458 if (c->close) {
733 c->read->ready = 0; 459 ngx_quic_close_connection(c);
734 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, 460 return;
735 "quic recv() not ready"); 461 }
736 return NGX_AGAIN; // ? 462
737 } 463 n = c->recv(c, b.start, b.end - b.start);
738 464
739 len = ngx_min(b->last - b->pos, (ssize_t) size); 465 if (n == NGX_AGAIN) {
740 466 return;
741 ngx_memcpy(buf, b->pos, len); 467 }
742 468
743 b->pos += len; 469 if (n == NGX_ERROR) {
744 470 c->read->eof = 1;
745 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 471 ngx_quic_close_connection(c);
746 "quic recv: %z of %uz", len, size); 472 return;
747 473 }
748 return len; 474
749 } 475 b.last += n;
750 476
751 477 if (ngx_quic_input(c, &b) != NGX_OK) {
752 static ssize_t 478 ngx_quic_close_connection(c);
753 ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, size_t size) 479 return;
754 { 480 }
755 u_char *p; 481 }
756 ngx_connection_t *pc; 482
757 ngx_quic_frame_t *frame; 483
758 ngx_quic_stream_t *qs; 484 static void
759 ngx_quic_connection_t *qc; 485 ngx_quic_close_connection(ngx_connection_t *c)
760 ngx_quic_stream_node_t *sn; 486 {
761 487 ngx_pool_t *pool;
762 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send: %uz", size); 488
763 489 /* XXX wait for all streams to close */
764 qs = c->qs; 490
765 pc = qs->parent; 491 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
766 qc = pc->quic; 492 "close quic connection: %d", c->fd);
767 493
768 // XXX: get direct pointer from stream structure? 494 if (c->ssl) {
769 sn = ngx_quic_stream_lookup(&qc->stree, qs->id); 495 (void) ngx_ssl_shutdown(c);
770 496 }
771 if (sn == NULL) { 497
772 return NGX_ERROR; 498 #if (NGX_STAT_STUB)
773 } 499 (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
774 500 #endif
775 frame = ngx_pcalloc(pc->pool, sizeof(ngx_quic_frame_t)); 501
776 if (frame == NULL) { 502 c->destroyed = 1;
777 return 0; 503
778 } 504 pool = c->pool;
779 505
780 p = ngx_pnalloc(pc->pool, size); 506 ngx_close_connection(c);
781 if (p == NULL) { 507
782 return 0; 508 ngx_destroy_pool(pool);
783 } 509 }
784 510
785 ngx_memcpy(p, buf, size); 511
786 512 static ngx_int_t
787 frame->level = ssl_encryption_application; 513 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b)
788 frame->type = NGX_QUIC_FT_STREAM6; /* OFF=1 LEN=1 FIN=0 */ 514 {
789 frame->u.stream.off = 1; 515 u_char *p;
790 frame->u.stream.len = 1; 516 ngx_int_t rc;
791 frame->u.stream.fin = 0; 517 ngx_quic_header_t pkt;
792 518
793 frame->u.stream.type = frame->type; 519 if (c->quic == NULL) {
794 frame->u.stream.stream_id = qs->id; 520 // XXX: possible?
795 frame->u.stream.offset = c->sent; 521 ngx_log_error(NGX_LOG_INFO, c->log, 0, "BUG: no QUIC in connection");
796 frame->u.stream.length = size; 522 return NGX_ERROR;
797 frame->u.stream.data = p; 523 }
798 524
799 c->sent += size; 525 p = b->start;
800 526
801 ngx_sprintf(frame->info, "stream %xi len=%ui level=%d", 527 do {
802 qs->id, size, frame->level); 528 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
803 529 pkt.raw = b;
804 ngx_quic_queue_frame(qc, frame); 530 pkt.data = p;
805 531 pkt.len = b->last - p;
806 return size; 532 pkt.log = c->log;
807 } 533
808 534 if (p[0] == 0) {
809 535 /* XXX: no idea WTF is this, just ignore */
810 static ngx_chain_t * 536 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "FIREFOX: ZEROES");
811 ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, 537 break;
812 off_t limit) 538 }
813 { 539
814 size_t len; 540 // TODO: check current state
815 ssize_t n; 541 if (p[0] & NGX_QUIC_PKT_LONG) {
816 ngx_buf_t *b; 542
817 543 if ((p[0] & 0xf0) == NGX_QUIC_PKT_INITIAL) {
818 for ( /* void */; in; in = in->next) { 544 rc = ngx_quic_initial_input(c, &pkt);
819 b = in->buf; 545
820 546 } else if ((p[0] & 0xf0) == NGX_QUIC_PKT_HANDSHAKE) {
821 if (!ngx_buf_in_memory(b)) { 547 rc = ngx_quic_handshake_input(c, &pkt);
822 continue; 548
823 } 549 } else {
824 550 ngx_log_error(NGX_LOG_INFO, c->log, 0,
825 if (ngx_buf_size(b) == 0) { 551 "BUG: unknown quic state");
826 continue; 552 return NGX_ERROR;
827 } 553 }
828 554
829 len = b->last - b->pos; 555 } else {
830 556 rc = ngx_quic_app_input(c, &pkt);
831 n = ngx_quic_stream_send(c, b->pos, len); 557 }
832 558
833 if (n == NGX_ERROR) { 559 if (rc == NGX_ERROR) {
834 return NGX_CHAIN_ERROR; 560 return NGX_ERROR;
835 } 561 }
836 562
837 if (n == NGX_AGAIN) { 563 /* b->pos is at header end, adjust by actual packet length */
838 return in; 564 p = b->pos + pkt.len;
839 } 565 b->pos = p; /* reset b->pos to the next packet start */
840 566
841 if (n != (ssize_t) len) { 567 } while (p < b->last);
842 b->pos += n; 568
843 return in; 569 return NGX_OK;
844 } 570 }
845 } 571
846 572
847 return NULL; 573 static ngx_int_t
848 } 574 ngx_quic_initial_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
849 575 {
850 576 ngx_ssl_conn_t *ssl_conn;
851 /* process all payload from the current packet and generate ack if required */ 577 ngx_quic_connection_t *qc;
578
579 qc = c->quic;
580 ssl_conn = c->ssl->connection;
581
582 if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
583 return NGX_ERROR;
584 }
585
586 if (ngx_quic_parse_initial_header(pkt) != NGX_OK) {
587 return NGX_ERROR;
588 }
589
590 pkt->secret = &qc->secrets.client.in;
591 pkt->level = ssl_encryption_initial;
592
593 if (ngx_quic_decrypt(c->pool, ssl_conn, pkt) != NGX_OK) {
594 return NGX_ERROR;
595 }
596
597 return ngx_quic_payload_handler(c, pkt);
598 }
599
600
601 static ngx_int_t
602 ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
603 {
604 ngx_ssl_conn_t *ssl_conn;
605 ngx_quic_connection_t *qc;
606
607 qc = c->quic;
608 ssl_conn = c->ssl->connection;
609
610 /* extract cleartext data into pkt */
611 if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
612 return NGX_ERROR;
613 }
614
615 if (pkt->dcid.len != qc->dcid.len) {
616 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl");
617 return NGX_ERROR;
618 }
619
620 if (ngx_memcmp(pkt->dcid.data, qc->dcid.data, qc->dcid.len) != 0) {
621 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid");
622 return NGX_ERROR;
623 }
624
625 if (pkt->scid.len != qc->scid.len) {
626 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scidl");
627 return NGX_ERROR;
628 }
629
630 if (ngx_memcmp(pkt->scid.data, qc->scid.data, qc->scid.len) != 0) {
631 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scid");
632 return NGX_ERROR;
633 }
634
635 if ((pkt->flags & 0xf0) != NGX_QUIC_PKT_HANDSHAKE) {
636 ngx_log_error(NGX_LOG_INFO, c->log, 0,
637 "invalid packet type: 0x%xi", pkt->flags);
638 return NGX_ERROR;
639 }
640
641 if (ngx_quic_parse_handshake_header(pkt) != NGX_OK) {
642 return NGX_ERROR;
643 }
644
645 pkt->secret = &qc->secrets.client.hs;
646 pkt->level = ssl_encryption_handshake;
647
648 if (ngx_quic_decrypt(c->pool, c->ssl->connection, pkt) != NGX_OK) {
649 return NGX_ERROR;
650 }
651
652 return ngx_quic_payload_handler(c, pkt);
653 }
654
655
656 static ngx_int_t
657 ngx_quic_app_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
658 {
659 ngx_quic_connection_t *qc;
660
661 qc = c->quic;
662
663 if (qc->secrets.client.ad.key.len == 0) {
664 ngx_log_error(NGX_LOG_INFO, c->log, 0,
665 "no read keys yet, packet ignored");
666 return NGX_DECLINED;
667 }
668
669 if (ngx_quic_parse_short_header(pkt, &qc->dcid) != NGX_OK) {
670 return NGX_ERROR;
671 }
672
673 pkt->secret = &qc->secrets.client.ad;
674 pkt->level = ssl_encryption_application;
675
676 if (ngx_quic_decrypt(c->pool, c->ssl->connection, pkt) != NGX_OK) {
677 return NGX_ERROR;
678 }
679
680 return ngx_quic_payload_handler(c, pkt);
681 }
682
683
852 static ngx_int_t 684 static ngx_int_t
853 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) 685 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
854 { 686 {
855 u_char *end, *p; 687 u_char *end, *p;
856 ssize_t len; 688 ssize_t len;
857 ngx_buf_t *b; 689 ngx_uint_t ack_this, do_close;
858 ngx_log_t *log; 690 ngx_quic_frame_t frame, *ack_frame;
859 ngx_uint_t ack_this, do_close; 691 ngx_quic_connection_t *qc;
860 ngx_pool_t *pool;
861 ngx_event_t *rev, *wev;
862 ngx_quic_frame_t frame, *ack_frame;
863 ngx_quic_connection_t *qc;
864 ngx_quic_stream_node_t *sn;
865 692
866 qc = c->quic; 693 qc = c->quic;
867 694
868 p = pkt->payload.data; 695 p = pkt->payload.data;
869 end = p + pkt->payload.len; 696 end = p + pkt->payload.len;
874 while (p < end) { 701 while (p < end) {
875 702
876 len = ngx_quic_parse_frame(p, end, &frame); 703 len = ngx_quic_parse_frame(p, end, &frame);
877 if (len < 0) { 704 if (len < 0) {
878 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 705 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
879 "unknown frame type %xi", frame.type); 706 "failed to parse frame type %xi", frame.type);
880 // XXX: log here
881 return NGX_ERROR; 707 return NGX_ERROR;
882 } 708 }
883 709
884 p += len; 710 p += len;
885 711
886 switch (frame.type) { 712 switch (frame.type) {
887 713
888 case NGX_QUIC_FT_ACK: 714 case NGX_QUIC_FT_ACK:
889
890 // TODO: handle ack
891 715
892 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, 716 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
893 "ACK: { largest=%ui delay=%ui first=%ui count=%ui}", 717 "ACK: { largest=%ui delay=%ui first=%ui count=%ui}",
894 frame.u.ack.largest, 718 frame.u.ack.largest,
895 frame.u.ack.delay, 719 frame.u.ack.delay,
896 frame.u.ack.first_range, 720 frame.u.ack.first_range,
897 frame.u.ack.range_count); 721 frame.u.ack.range_count);
898 722
723 if (ngx_quic_handle_ack_frame(c, pkt, &frame.u.ack) != NGX_OK) {
724 return NGX_ERROR;
725 }
726
899 break; 727 break;
900 728
901 case NGX_QUIC_FT_CRYPTO: 729 case NGX_QUIC_FT_CRYPTO:
902 ngx_quic_hexdump0(c->log, "CRYPTO frame",
903 frame.u.crypto.data, frame.u.crypto.len);
904 730
905 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, 731 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
906 "quic CRYPTO frame length: %uL off:%uL pp:%p", 732 "quic CRYPTO frame length: %uL off:%uL pp:%p",
907 frame.u.crypto.len, frame.u.crypto.offset, 733 frame.u.crypto.len, frame.u.crypto.offset,
908 frame.u.crypto.data); 734 frame.u.crypto.data);
909 735
910 if (frame.u.crypto.offset != 0x0) { 736 ngx_quic_hexdump0(c->log, "CRYPTO frame contents",
911 ngx_log_error(NGX_LOG_INFO, c->log, 0, 737 frame.u.crypto.data, frame.u.crypto.len);
912 "crypto frame with non-zero offset"); 738
913 // TODO: support packet spanning with offsets 739
740 if (ngx_quic_handle_crypto_frame(c, pkt, &frame.u.crypto)
741 != NGX_OK)
742 {
914 return NGX_ERROR; 743 return NGX_ERROR;
915 } 744 }
916 745
917 if (ngx_quic_handle_crypto_frame(c, pkt, &frame) != NGX_OK) {
918 return NGX_ERROR;
919 }
920
921 ack_this = 1; 746 ack_this = 1;
922 747 break;
923 continue;
924 748
925 case NGX_QUIC_FT_PADDING: 749 case NGX_QUIC_FT_PADDING:
926 continue; 750 break;
927 751
928 case NGX_QUIC_FT_PING: 752 case NGX_QUIC_FT_PING:
929 ack_this = 1; 753 ack_this = 1;
930 continue; 754 break;
931 755
932 case NGX_QUIC_FT_NEW_CONNECTION_ID: 756 case NGX_QUIC_FT_NEW_CONNECTION_ID:
933 ack_this = 1; 757 ack_this = 1;
934 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, 758 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
935 "NCID: { seq=%ui retire=%ui len=%ui}", 759 "NCID: { seq=%ui retire=%ui len=%ui}",
936 frame.u.ncid.seqnum, 760 frame.u.ncid.seqnum,
937 frame.u.ncid.retire, 761 frame.u.ncid.retire,
938 frame.u.ncid.len); 762 frame.u.ncid.len);
939 continue; 763 break;
940 764
941 case NGX_QUIC_FT_CONNECTION_CLOSE: 765 case NGX_QUIC_FT_CONNECTION_CLOSE:
942 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, 766 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
943 "CONN.CLOSE: { %s (0x%xi) type=0x%xi reason='%V'}", 767 "CONN.CLOSE: { %s (0x%xi) type=0x%xi reason='%V'}",
944 ngx_quic_error_text(frame.u.close.error_code), 768 ngx_quic_error_text(frame.u.close.error_code),
956 case NGX_QUIC_FT_STREAM4: 780 case NGX_QUIC_FT_STREAM4:
957 case NGX_QUIC_FT_STREAM5: 781 case NGX_QUIC_FT_STREAM5:
958 case NGX_QUIC_FT_STREAM6: 782 case NGX_QUIC_FT_STREAM6:
959 case NGX_QUIC_FT_STREAM7: 783 case NGX_QUIC_FT_STREAM7:
960 784
961 ack_this = 1;
962
963 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0, 785 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
964 "STREAM frame 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d", 786 "STREAM frame { 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d }",
965 frame.type, 787 frame.type,
966 frame.u.stream.stream_id, 788 frame.u.stream.stream_id,
967 frame.u.stream.offset, 789 frame.u.stream.offset,
968 frame.u.stream.length, 790 frame.u.stream.length,
969 frame.u.stream.off, 791 frame.u.stream.off,
970 frame.u.stream.len, 792 frame.u.stream.len,
971 frame.u.stream.fin); 793 frame.u.stream.fin);
972 794
973 sn = ngx_quic_stream_lookup(&qc->stree, frame.u.stream.stream_id); 795 ngx_quic_hexdump0(c->log, "STREAM frame contents",
974 if (sn == NULL) { 796 frame.u.stream.data, frame.u.stream.length);
975 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "stream is new"); 797
976 798 if (ngx_quic_handle_stream_frame(c, pkt, &frame.u.stream)
977 sn = ngx_pcalloc(c->pool, sizeof(ngx_quic_stream_node_t)); 799 != NGX_OK)
978 if (sn == NULL) { 800 {
979 return NGX_ERROR; 801 return NGX_ERROR;
980 }
981
982 sn->c = ngx_get_connection(-1, c->log); // TODO: free on connection termination
983 if (sn->c == NULL) {
984 return NGX_ERROR;
985 }
986
987 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log);
988 if (pool == NULL) {
989 /* XXX free connection */
990 return NGX_ERROR;
991 }
992
993 log = ngx_palloc(pool, sizeof(ngx_log_t));
994 if (log == NULL) {
995 /* XXX free pool and connection */
996 return NGX_ERROR;
997 }
998
999 *log = *c->log;
1000 pool->log = log;
1001
1002 sn->c->log = log;
1003 sn->c->pool = pool;
1004
1005 sn->c->listening = c->listening;
1006 sn->c->sockaddr = c->sockaddr;
1007 sn->c->local_sockaddr = c->local_sockaddr;
1008
1009 rev = sn->c->read;
1010 wev = sn->c->write;
1011
1012 rev->ready = 1;
1013
1014 rev->log = c->log;
1015 wev->log = c->log;
1016
1017 sn->c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
1018
1019 sn->node.key = frame.u.stream.stream_id;
1020 sn->b = ngx_create_temp_buf(pool, 16 * 1024); // XXX enough for everyone
1021 if (sn->b == NULL) {
1022 return NGX_ERROR;
1023 }
1024 b = sn->b;
1025
1026 ngx_memcpy(b->start, frame.u.stream.data, frame.u.stream.length);
1027 b->last = b->start + frame.u.stream.length;
1028
1029 ngx_rbtree_insert(&qc->stree, &sn->node);
1030
1031 sn->s.id = frame.u.stream.stream_id;
1032 sn->s.unidirectional = (sn->s.id & 0x02) ? 1 : 0;
1033 sn->s.parent = c;
1034 sn->c->qs = &sn->s;
1035
1036 sn->c->recv = ngx_quic_stream_recv;
1037 sn->c->send = ngx_quic_stream_send;
1038 sn->c->send_chain = ngx_quic_stream_send_chain;
1039
1040 qc->stream_handler(sn->c);
1041
1042 } else {
1043 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "existing stream");
1044 b = sn->b;
1045
1046 if ((size_t) (b->end - b->pos) < frame.u.stream.length) {
1047 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1048 "no space in stream buffer");
1049 return NGX_ERROR;
1050 }
1051
1052 ngx_memcpy(b->pos, frame.u.stream.data, frame.u.stream.length);
1053 b->pos += frame.u.stream.length;
1054
1055 // TODO: ngx_post_event(&c->read, &ngx_posted_events) ???
1056 } 802 }
1057 803
1058 ngx_quic_hexdump0(c->log, "STREAM.data", 804 ack_this = 1;
1059 frame.u.stream.data, frame.u.stream.length);
1060 break; 805 break;
1061 806
1062 default: 807 default:
1063 ngx_log_error(NGX_LOG_INFO, c->log, 0, 808 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1064 "unexpected frame type 0x%xd in packet", frame.type); 809 "unsupported frame type 0x%xd in packet", frame.type);
1065 return NGX_ERROR; 810 return NGX_ERROR;
1066 } 811 }
1067 } 812 }
1068 813
1069 if (p != end) { 814 if (p != end) {
1098 843
1099 return ngx_quic_output(c); 844 return ngx_quic_output(c);
1100 } 845 }
1101 846
1102 847
848 static ngx_int_t
849 ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
850 ngx_quic_ack_frame_t *f)
851 {
852 /* TODO: handle ACK here */
853 return NGX_OK;
854 }
855
856
857 static ngx_int_t
858 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
859 ngx_quic_crypto_frame_t *f)
860 {
861 int sslerr;
862 ssize_t n;
863 ngx_ssl_conn_t *ssl_conn;
864
865 if (f->offset != 0x0) {
866 ngx_log_error(NGX_LOG_INFO, c->log, 0,
867 "crypto frame with non-zero offset");
868 // TODO: add support for crypto frames spanning packets
869 return NGX_ERROR;
870 }
871
872 ssl_conn = c->ssl->connection;
873
874 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
875 "SSL_quic_read_level: %d, SSL_quic_write_level: %d",
876 (int) SSL_quic_read_level(ssl_conn),
877 (int) SSL_quic_write_level(ssl_conn));
878
879 if (!SSL_provide_quic_data(ssl_conn, SSL_quic_read_level(ssl_conn),
880 f->data, f->len))
881 {
882 ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
883 "SSL_provide_quic_data() failed");
884 return NGX_ERROR;
885 }
886
887 n = SSL_do_handshake(ssl_conn);
888
889 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
890
891 if (n == -1) {
892 sslerr = SSL_get_error(ssl_conn, n);
893
894 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d",
895 sslerr);
896
897 if (sslerr == SSL_ERROR_SSL) {
898 ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_do_handshake() failed");
899 }
900 }
901
902 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
903 "quic ssl cipher: %s", SSL_get_cipher(ssl_conn));
904
905 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
906 "SSL_quic_read_level: %d, SSL_quic_write_level: %d",
907 (int) SSL_quic_read_level(ssl_conn),
908 (int) SSL_quic_write_level(ssl_conn));
909
910 return NGX_OK;
911 }
912
913
914 static ngx_int_t
915 ngx_quic_handle_stream_frame(ngx_connection_t *c,
916 ngx_quic_header_t *pkt, ngx_quic_stream_frame_t *f)
917 {
918 ngx_buf_t *b;
919 ngx_log_t *log;
920 ngx_pool_t *pool;
921 ngx_event_t *rev, *wev;
922 ngx_quic_connection_t *qc;
923 ngx_quic_stream_node_t *sn;
924
925 qc = c->quic;
926
927 sn = ngx_quic_find_stream(&qc->streams.tree, f->stream_id);
928
929 if (sn) {
930 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "existing stream");
931 b = sn->b;
932
933 if ((size_t) (b->end - b->pos) < f->length) {
934 ngx_log_error(NGX_LOG_INFO, c->log, 0, "no space in stream buffer");
935 return NGX_ERROR;
936 }
937
938 ngx_memcpy(b->pos, f->data, f->length);
939 b->pos += f->length;
940
941 // TODO: notify
942
943 return NGX_OK;
944 }
945
946 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "stream is new");
947
948 sn = ngx_pcalloc(c->pool, sizeof(ngx_quic_stream_node_t));
949 if (sn == NULL) {
950 return NGX_ERROR;
951 }
952
953 sn->c = ngx_get_connection(-1, c->log); // TODO: free on connection termination
954 if (sn->c == NULL) {
955 return NGX_ERROR;
956 }
957
958 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log);
959 if (pool == NULL) {
960 /* XXX free connection */
961 return NGX_ERROR;
962 }
963
964 log = ngx_palloc(pool, sizeof(ngx_log_t));
965 if (log == NULL) {
966 /* XXX free pool and connection */
967 return NGX_ERROR;
968 }
969
970 *log = *c->log;
971 pool->log = log;
972
973 sn->c->log = log;
974 sn->c->pool = pool;
975
976 sn->c->listening = c->listening;
977 sn->c->sockaddr = c->sockaddr;
978 sn->c->local_sockaddr = c->local_sockaddr;
979
980 rev = sn->c->read;
981 wev = sn->c->write;
982
983 rev->ready = 1;
984
985 rev->log = c->log;
986 wev->log = c->log;
987
988 sn->c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
989
990 sn->node.key = f->stream_id;
991 sn->b = ngx_create_temp_buf(pool, 16 * 1024); // XXX enough for everyone
992 if (sn->b == NULL) {
993 return NGX_ERROR;
994 }
995 b = sn->b;
996
997 ngx_memcpy(b->start, f->data, f->length);
998 b->last = b->start + f->length;
999
1000 ngx_rbtree_insert(&qc->streams.tree, &sn->node);
1001
1002 sn->s.id = f->stream_id;
1003 sn->s.unidirectional = (sn->s.id & 0x02) ? 1 : 0;
1004 sn->s.parent = c;
1005 sn->c->qs = &sn->s;
1006
1007 sn->c->recv = ngx_quic_stream_recv;
1008 sn->c->send = ngx_quic_stream_send;
1009 sn->c->send_chain = ngx_quic_stream_send_chain;
1010
1011 qc->streams.handler(sn->c);
1012
1013 return NGX_OK;
1014 }
1015
1016
1017 static void
1018 ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame)
1019 {
1020 ngx_quic_frame_t *f;
1021
1022 if (qc->frames == NULL) {
1023 qc->frames = frame;
1024 return;
1025 }
1026
1027 for (f = qc->frames; f->next; f = f->next) {
1028 if (f->next->level > frame->level) {
1029 break;
1030 }
1031 }
1032
1033 frame->next = f->next;
1034 f->next = frame;
1035 }
1036
1037
1038 static ngx_int_t
1039 ngx_quic_output(ngx_connection_t *c)
1040 {
1041 size_t len;
1042 ngx_uint_t lvl;
1043 ngx_quic_frame_t *f, *start;
1044 ngx_quic_connection_t *qc;
1045
1046 qc = c->quic;
1047
1048 if (qc->frames == NULL) {
1049 return NGX_OK;
1050 }
1051
1052 lvl = qc->frames->level;
1053 start = qc->frames;
1054 f = start;
1055
1056 do {
1057 len = 0;
1058
1059 do {
1060 /* process same-level group of frames */
1061
1062 len += ngx_quic_frame_len(f);// TODO: handle overflow, max size
1063
1064 f = f->next;
1065 } while (f && f->level == lvl);
1066
1067
1068 if (ngx_quic_frames_send(c, start, f, len) != NGX_OK) {
1069 return NGX_ERROR;
1070 }
1071
1072 if (f == NULL) {
1073 break;
1074 }
1075
1076 lvl = f->level; // TODO: must not decrease (ever, also between calls)
1077 start = f;
1078
1079 } while (1);
1080
1081 qc->frames = NULL;
1082
1083 return NGX_OK;
1084 }
1085
1086
1087 /* pack a group of frames [start; end) into memory p and send as single packet */
1088 ngx_int_t
1089 ngx_quic_frames_send(ngx_connection_t *c, ngx_quic_frame_t *start,
1090 ngx_quic_frame_t *end, size_t total)
1091 {
1092 ssize_t len;
1093 u_char *p;
1094 ngx_str_t out;
1095 ngx_quic_frame_t *f;
1096
1097 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1098 "sending frames %p...%p", start, end);
1099
1100 p = ngx_pnalloc(c->pool, total);
1101 if (p == NULL) {
1102 return NGX_ERROR;
1103 }
1104
1105 out.data = p;
1106
1107 for (f = start; f != end; f = f->next) {
1108
1109 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "frame: %s", f->info);
1110
1111 len = ngx_quic_create_frame(p, p + total, f);
1112 if (len == -1) {
1113 return NGX_ERROR;
1114 }
1115
1116 p += len;
1117 }
1118
1119 out.len = p - out.data;
1120
1121 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1122 "packet ready: %ui bytes at level %d",
1123 out.len, start->level);
1124
1125 // IOVEC/sendmsg_chain ?
1126 if (ngx_quic_send_packet(c, c->quic, start->level, &out) != NGX_OK) {
1127 return NGX_ERROR;
1128 }
1129
1130 return NGX_OK;
1131 }
1132
1133
1134 static ngx_int_t
1135 ngx_quic_send_packet(ngx_connection_t *c, ngx_quic_connection_t *qc,
1136 enum ssl_encryption_level_t level, ngx_str_t *payload)
1137 {
1138 ngx_str_t res;
1139 ngx_quic_header_t pkt;
1140
1141 pkt.log = c->log;
1142
1143 static ngx_str_t initial_token = ngx_null_string;
1144
1145 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
1146 ngx_quic_hexdump0(c->log, "payload", payload->data, payload->len);
1147
1148 pkt.level = level;
1149 pkt.dcid = qc->dcid;
1150 pkt.scid = qc->scid;
1151
1152 if (level == ssl_encryption_initial) {
1153 pkt.number = &qc->initial_pn;
1154 pkt.flags = NGX_QUIC_PKT_INITIAL;
1155 pkt.secret = &qc->secrets.server.in;
1156 pkt.token = initial_token;
1157
1158 } else if (level == ssl_encryption_handshake) {
1159 pkt.number = &qc->handshake_pn;
1160 pkt.flags = NGX_QUIC_PKT_HANDSHAKE;
1161 pkt.secret = &qc->secrets.server.hs;
1162
1163 } else {
1164 pkt.number = &qc->appdata_pn;
1165 pkt.secret = &qc->secrets.server.ad;
1166 }
1167
1168 if (ngx_quic_encrypt(c->pool, c->ssl->connection, &pkt, payload, &res)
1169 != NGX_OK)
1170 {
1171 return NGX_ERROR;
1172 }
1173
1174 ngx_quic_hexdump0(c->log, "packet to send", res.data, res.len);
1175
1176 c->send(c, res.data, res.len); // TODO: err handling
1177
1178 (*pkt.number)++;
1179
1180 return NGX_OK;
1181 }
1182
1183
1184 ngx_connection_t *
1185 ngx_quic_create_uni_stream(ngx_connection_t *c)
1186 {
1187 /* XXX */
1188 return NULL;
1189 }
1190
1191
1103 static void 1192 static void
1104 ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, 1193 ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp,
1105 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) 1194 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
1106 { 1195 {
1107 ngx_rbtree_node_t **p; 1196 ngx_rbtree_node_t **p;
1108 ngx_quic_stream_node_t *qn, *qnt; 1197 ngx_quic_stream_node_t *qn, *qnt;
1109 1198
1110 for ( ;; ) { 1199 for ( ;; ) {
1111 1200
1112 if (node->key < temp->key) { 1201 if (node->key < temp->key) {
1113 1202
1143 ngx_rbt_red(node); 1232 ngx_rbt_red(node);
1144 } 1233 }
1145 1234
1146 1235
1147 static ngx_quic_stream_node_t * 1236 static ngx_quic_stream_node_t *
1148 ngx_quic_stream_lookup(ngx_rbtree_t *rbtree, ngx_uint_t key) 1237 ngx_quic_find_stream(ngx_rbtree_t *rbtree, ngx_uint_t key)
1149 { 1238 {
1150 ngx_rbtree_node_t *node, *sentinel; 1239 ngx_rbtree_node_t *node, *sentinel;
1151 1240
1152 node = rbtree->root; 1241 node = rbtree->root;
1153 sentinel = rbtree->sentinel; 1242 sentinel = rbtree->sentinel;
1163 1252
1164 return NULL; 1253 return NULL;
1165 } 1254 }
1166 1255
1167 1256
1168 static ngx_int_t 1257 static ssize_t
1169 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, 1258 ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size)
1170 ngx_quic_header_t *pkt) 1259 {
1171 { 1260 ssize_t len;
1172 ngx_quic_connection_t *qc; 1261 ngx_buf_t *b;
1173 1262 ngx_quic_stream_t *qs;
1174 if (ngx_buf_size(pkt->raw) < 1200) { 1263 ngx_quic_connection_t *qc;
1175 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram"); 1264 ngx_quic_stream_node_t *sn;
1176 return NGX_ERROR; 1265
1177 } 1266 qs = c->qs;
1178 1267 qc = qs->parent->quic;
1179 if (ngx_quic_parse_long_header(pkt) != NGX_OK) { 1268
1180 return NGX_ERROR; 1269 // XXX: get direct pointer from stream structure?
1181 } 1270 sn = ngx_quic_find_stream(&qc->streams.tree, qs->id);
1182 1271
1183 if ((pkt->flags & 0xf0) != NGX_QUIC_PKT_INITIAL) { 1272 if (sn == NULL) {
1184 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1273 return NGX_ERROR;
1185 "invalid initial packet: 0x%xi", pkt->flags); 1274 }
1186 return NGX_ERROR; 1275
1187 } 1276 // XXX: how to return EOF?
1188 1277
1189 if (ngx_quic_parse_initial_header(pkt) != NGX_OK) { 1278 b = sn->b;
1190 return NGX_ERROR; 1279
1191 } 1280 if (b->last - b->pos == 0) {
1192 1281 c->read->ready = 0;
1193 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t)); 1282 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1194 if (qc == NULL) { 1283 "quic recv() not ready");
1195 return NGX_ERROR; 1284 return NGX_AGAIN; // ?
1196 } 1285 }
1197 1286
1198 ngx_rbtree_init(&qc->stree, &qc->stree_sentinel, 1287 len = ngx_min(b->last - b->pos, (ssize_t) size);
1199 ngx_quic_rbtree_insert_stream); 1288
1200 1289 ngx_memcpy(buf, b->pos, len);
1201 c->quic = qc; 1290
1202 qc->ssl = ssl; 1291 b->pos += len;
1203 1292
1204 qc->dcid.len = pkt->dcid.len; 1293 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1205 qc->dcid.data = ngx_pnalloc(c->pool, pkt->dcid.len); 1294 "quic recv: %z of %uz", len, size);
1206 if (qc->dcid.data == NULL) { 1295
1207 return NGX_ERROR; 1296 return len;
1208 } 1297 }
1209 ngx_memcpy(qc->dcid.data, pkt->dcid.data, qc->dcid.len); 1298
1210 1299
1211 qc->scid.len = pkt->scid.len; 1300 static ssize_t
1212 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len); 1301 ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, size_t size)
1213 if (qc->scid.data == NULL) { 1302 {
1214 return NGX_ERROR; 1303 u_char *p;
1215 } 1304 ngx_connection_t *pc;
1216 ngx_memcpy(qc->scid.data, pkt->scid.data, qc->scid.len); 1305 ngx_quic_frame_t *frame;
1217 1306 ngx_quic_stream_t *qs;
1218 qc->token.len = pkt->token.len; 1307 ngx_quic_connection_t *qc;
1219 qc->token.data = ngx_pnalloc(c->pool, qc->token.len); 1308 ngx_quic_stream_node_t *sn;
1220 if (qc->token.data == NULL) { 1309
1221 return NGX_ERROR; 1310 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send: %uz", size);
1222 } 1311
1223 ngx_memcpy(qc->token.data, pkt->token.data, qc->token.len); 1312 qs = c->qs;
1224 1313 pc = qs->parent;
1225 1314 qc = pc->quic;
1226 if (ngx_quic_set_initial_secret(c->pool, &qc->secrets, &qc->dcid) 1315
1227 != NGX_OK) 1316 // XXX: get direct pointer from stream structure?
1228 { 1317 sn = ngx_quic_find_stream(&qc->streams.tree, qs->id);
1229 return NGX_ERROR; 1318
1230 } 1319 if (sn == NULL) {
1231 1320 return NGX_ERROR;
1232 pkt->secret = &qc->secrets.client.in; 1321 }
1233 pkt->level = ssl_encryption_initial; 1322
1234 1323 frame = ngx_pcalloc(pc->pool, sizeof(ngx_quic_frame_t));
1235 if (ngx_quic_decrypt(c->pool, NULL, pkt) != NGX_OK) { 1324 if (frame == NULL) {
1236 return NGX_ERROR; 1325 return 0;
1237 } 1326 }
1238 1327
1239 if (ngx_quic_init_connection(c) != NGX_OK) { 1328 p = ngx_pnalloc(pc->pool, size);
1240 return NGX_ERROR; 1329 if (p == NULL) {
1241 } 1330 return 0;
1242 1331 }
1243 return ngx_quic_payload_handler(c, pkt); 1332
1244 } 1333 ngx_memcpy(p, buf, size);
1245 1334
1246 1335 frame->level = ssl_encryption_application;
1247 static ngx_int_t 1336 frame->type = NGX_QUIC_FT_STREAM6; /* OFF=1 LEN=1 FIN=0 */
1248 ngx_quic_initial_input(ngx_connection_t *c, ngx_quic_header_t *pkt) 1337 frame->u.stream.off = 1;
1249 { 1338 frame->u.stream.len = 1;
1250 ngx_ssl_conn_t *ssl_conn; 1339 frame->u.stream.fin = 0;
1251 ngx_quic_connection_t *qc; 1340
1252 1341 frame->u.stream.type = frame->type;
1253 qc = c->quic; 1342 frame->u.stream.stream_id = qs->id;
1254 ssl_conn = c->ssl->connection; 1343 frame->u.stream.offset = c->sent;
1255 1344 frame->u.stream.length = size;
1256 if (ngx_quic_parse_long_header(pkt) != NGX_OK) { 1345 frame->u.stream.data = p;
1257 return NGX_ERROR; 1346
1258 } 1347 c->sent += size;
1259 1348
1260 if (ngx_quic_parse_initial_header(pkt) != NGX_OK) { 1349 ngx_sprintf(frame->info, "stream %xi len=%ui level=%d",
1261 return NGX_ERROR; 1350 qs->id, size, frame->level);
1262 } 1351
1263 1352 ngx_quic_queue_frame(qc, frame);
1264 pkt->secret = &qc->secrets.client.in; 1353
1265 pkt->level = ssl_encryption_initial; 1354 return size;
1266 1355 }
1267 if (ngx_quic_decrypt(c->pool, ssl_conn, pkt) != NGX_OK) { 1356
1268 return NGX_ERROR; 1357
1269 } 1358 static ngx_chain_t *
1270 1359 ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in,
1271 return ngx_quic_payload_handler(c, pkt); 1360 off_t limit)
1272 } 1361 {
1273 1362 size_t len;
1274 1363 ssize_t n;
1275 static ngx_int_t 1364 ngx_buf_t *b;
1276 ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt) 1365
1277 { 1366 for ( /* void */; in; in = in->next) {
1278 ngx_ssl_conn_t *ssl_conn; 1367 b = in->buf;
1279 ngx_quic_connection_t *qc; 1368
1280 1369 if (!ngx_buf_in_memory(b)) {
1281 qc = c->quic; 1370 continue;
1282 ssl_conn = c->ssl->connection; 1371 }
1283 1372
1284 /* extract cleartext data into pkt */ 1373 if (ngx_buf_size(b) == 0) {
1285 if (ngx_quic_parse_long_header(pkt) != NGX_OK) { 1374 continue;
1286 return NGX_ERROR; 1375 }
1287 } 1376
1288 1377 len = b->last - b->pos;
1289 if (pkt->dcid.len != qc->dcid.len) { 1378
1290 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl"); 1379 n = ngx_quic_stream_send(c, b->pos, len);
1291 return NGX_ERROR; 1380
1292 } 1381 if (n == NGX_ERROR) {
1293 1382 return NGX_CHAIN_ERROR;
1294 if (ngx_memcmp(pkt->dcid.data, qc->dcid.data, qc->dcid.len) != 0) { 1383 }
1295 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid"); 1384
1296 return NGX_ERROR; 1385 if (n == NGX_AGAIN) {
1297 } 1386 return in;
1298 1387 }
1299 if (pkt->scid.len != qc->scid.len) { 1388
1300 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scidl"); 1389 if (n != (ssize_t) len) {
1301 return NGX_ERROR; 1390 b->pos += n;
1302 } 1391 return in;
1303 1392 }
1304 if (ngx_memcmp(pkt->scid.data, qc->scid.data, qc->scid.len) != 0) { 1393 }
1305 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scid"); 1394
1306 return NGX_ERROR; 1395 return NULL;
1307 } 1396 }
1308
1309 if ((pkt->flags & 0xf0) != NGX_QUIC_PKT_HANDSHAKE) {
1310 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1311 "invalid packet type: 0x%xi", pkt->flags);
1312 return NGX_ERROR;
1313 }
1314
1315 if (ngx_quic_parse_handshake_header(pkt) != NGX_OK) {
1316 return NGX_ERROR;
1317 }
1318
1319 pkt->secret = &qc->secrets.client.hs;
1320 pkt->level = ssl_encryption_handshake;
1321
1322 if (ngx_quic_decrypt(c->pool, c->ssl->connection, pkt) != NGX_OK) {
1323 return NGX_ERROR;
1324 }
1325
1326 return ngx_quic_payload_handler(c, pkt);
1327 }
1328
1329
1330 static ngx_int_t
1331 ngx_quic_app_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
1332 {
1333 ngx_quic_connection_t *qc;
1334
1335 qc = c->quic;
1336
1337 if (qc->secrets.client.ad.key.len == 0) {
1338 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1339 "no read keys yet, packet ignored");
1340 return NGX_DECLINED;
1341 }
1342
1343 if (ngx_quic_parse_short_header(pkt, &qc->dcid) != NGX_OK) {
1344 return NGX_ERROR;
1345 }
1346
1347 pkt->secret = &qc->secrets.client.ad;
1348 pkt->level = ssl_encryption_application;
1349
1350 if (ngx_quic_decrypt(c->pool, c->ssl->connection, pkt) != NGX_OK) {
1351 return NGX_ERROR;
1352 }
1353
1354 return ngx_quic_payload_handler(c, pkt);
1355 }
1356
1357