comparison src/event/ngx_event_quic.c @ 8224:ae35ccba7aa6 quic

Extracted transport part of the code into separate file. All code dealing with serializing/deserializing is moved int srv/event/ngx_event_quic_transport.c/h file. All macros for dealing with data are internal to source file. The header file exposes frame types and error codes. The exported functions are currently packet header parsers and writers and frames parser/writer. The ngx_quic_header_t structure is updated with 'log' member. This avoids passing extra argument to parsing functions that need to report errors.
author Vladimir Homutov <vl@nginx.com>
date Wed, 18 Mar 2020 12:58:27 +0300
parents 61f9b873e2e7
children 714a19dba6af
comparison
equal deleted inserted replaced
8223:61f9b873e2e7 8224:ae35ccba7aa6
5 5
6 6
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
11
12 /* 12.4. Frames and Frame Types */
13 #define NGX_QUIC_FT_PADDING 0x00
14 #define NGX_QUIC_FT_PING 0x01
15 #define NGX_QUIC_FT_ACK 0x02
16 #define NGX_QUIC_FT_ACK_ECN 0x03
17 #define NGX_QUIC_FT_RESET_STREAM 0x04
18 #define NGX_QUIC_FT_STOP_SENDING 0x05
19 #define NGX_QUIC_FT_CRYPTO 0x06
20 #define NGX_QUIC_FT_NEW_TOKEN 0x07
21 #define NGX_QUIC_FT_STREAM0 0x08
22 #define NGX_QUIC_FT_STREAM1 0x09
23 #define NGX_QUIC_FT_STREAM2 0x0A
24 #define NGX_QUIC_FT_STREAM3 0x0B
25 #define NGX_QUIC_FT_STREAM4 0x0C
26 #define NGX_QUIC_FT_STREAM5 0x0D
27 #define NGX_QUIC_FT_STREAM6 0x0E
28 #define NGX_QUIC_FT_STREAM7 0x0F
29 #define NGX_QUIC_FT_MAX_DATA 0x10
30 #define NGX_QUIC_FT_MAX_STREAM_DATA 0x11
31 #define NGX_QUIC_FT_MAX_STREAMS 0x12
32 #define NGX_QUIC_FT_MAX_STREAMS2 0x13 // XXX
33 #define NGX_QUIC_FT_DATA_BLOCKED 0x14
34 #define NGX_QUIC_FT_STREAM_DATA_BLOCKED 0x15
35 #define NGX_QUIC_FT_STREAMS_BLOCKED 0x16
36 #define NGX_QUIC_FT_STREAMS_BLOCKED2 0x17 // XXX
37 #define NGX_QUIC_FT_NEW_CONNECTION_ID 0x18
38 #define NGX_QUIC_FT_RETIRE_CONNECTION_ID 0x19
39 #define NGX_QUIC_FT_PATH_CHALLENGE 0x1a
40 #define NGX_QUIC_FT_PATH_RESPONSE 0x1b
41 #define NGX_QUIC_FT_CONNECTION_CLOSE 0x1c
42 #define NGX_QUIC_FT_CONNECTION_CLOSE2 0x1d // XXX
43 #define NGX_QUIC_FT_HANDSHAKE_DONE 0x1e
44
45 #define ngx_quic_stream_bit_off(val) (((val) & 0x04) ? 1 : 0)
46 #define ngx_quic_stream_bit_len(val) (((val) & 0x02) ? 1 : 0)
47 #define ngx_quic_stream_bit_fin(val) (((val) & 0x01) ? 1 : 0)
48
49
50 #define NGX_QUIC_ERR_NO_ERROR 0x0
51 #define NGX_QUIC_ERR_INTERNAL_ERROR 0x1
52 #define NGX_QUIC_ERR_SERVER_BUSY 0x2
53 #define NGX_QUIC_ERR_FLOW_CONTROL_ERROR 0x3
54 #define NGX_QUIC_ERR_STREAM_LIMIT_ERROR 0x4
55 #define NGX_QUIC_ERR_STREAM_STATE_ERROR 0x5
56 #define NGX_QUIC_ERR_FINAL_SIZE_ERROR 0x6
57 #define NGX_QUIC_ERR_FRAME_ENCODING_ERROR 0x7
58 #define NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR 0x8
59 #define NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR 0x9
60 #define NGX_QUIC_ERR_PROTOCOL_VIOLATION 0xA
61 #define NGX_QUIC_ERR_INVALID_TOKEN 0xB
62 /* 0xC is not defined */
63 #define NGX_QUIC_ERR_CRYPTO_BUFFER_EXCEEDED 0xD
64 #define NGX_QUIC_ERR_CRYPTO_ERROR 0x10
65
66 #define NGX_QUIC_ERR_LAST NGX_QUIC_ERR_CRYPTO_ERROR
67
68 /* literal errors indexed by corresponding value */
69 static char *ngx_quic_errors[] = {
70 "NO_ERROR",
71 "INTERNAL_ERROR",
72 "SERVER_BUSY",
73 "FLOW_CONTROL_ERROR",
74 "STREAM_LIMIT_ERROR",
75 "STREAM_STATE_ERROR",
76 "FINAL_SIZE_ERROR",
77 "FRAME_ENCODING_ERROR",
78 "TRANSPORT_PARAMETER_ERROR",
79 "CONNECTION_ID_LIMIT_ERROR",
80 "PROTOCOL_VIOLATION",
81 "INVALID_TOKEN",
82 "",
83 "CRYPTO_BUFFER_EXCEEDED",
84 "CRYPTO_ERROR",
85 };
86 10
87 11
88 /* TODO: real states, these are stubs */ 12 /* TODO: real states, these are stubs */
89 typedef enum { 13 typedef enum {
90 NGX_QUIC_ST_INITIAL, 14 NGX_QUIC_ST_INITIAL,
91 NGX_QUIC_ST_HANDSHAKE, 15 NGX_QUIC_ST_HANDSHAKE,
92 NGX_QUIC_ST_APP_DATA 16 NGX_QUIC_ST_APP_DATA
93 } ngx_quic_state_t; 17 } ngx_quic_state_t;
94
95
96 typedef struct ngx_quic_frame_s ngx_quic_frame_t;
97
98 typedef struct {
99 ngx_uint_t pn;
100
101 // input
102 uint64_t largest;
103 uint64_t delay;
104 uint64_t range_count;
105 uint64_t first_range;
106 uint64_t ranges[20];
107 /* ecn counts */
108 } ngx_quic_ack_frame_t;
109
110 typedef struct {
111 size_t offset;
112 size_t len;
113 u_char *data;
114 } ngx_quic_crypto_frame_t;
115
116
117 typedef struct {
118 uint64_t seqnum;
119 uint64_t retire;
120 uint64_t len;
121 u_char cid[20];
122 u_char srt[16];
123 } ngx_quic_ncid_t;
124
125
126 typedef struct {
127 uint8_t type;
128 uint64_t stream_id;
129 uint64_t offset;
130 uint64_t length;
131 u_char *data;
132 } ngx_quic_stream_frame_t;
133
134
135 typedef struct {
136 uint64_t error_code;
137 uint64_t frame_type;
138 ngx_str_t reason;
139 } ngx_quic_close_frame_t;
140
141
142 struct ngx_quic_frame_s {
143 ngx_uint_t type;
144 ngx_quic_level_t level;
145 ngx_quic_frame_t *next;
146 union {
147 ngx_quic_crypto_frame_t crypto;
148 ngx_quic_ack_frame_t ack;
149 ngx_quic_ncid_t ncid;
150 ngx_quic_stream_frame_t stream;
151 ngx_quic_close_frame_t close;
152 // more frames
153 } u;
154
155 u_char info[128]; // for debug purposes
156 };
157 18
158 19
159 struct ngx_quic_connection_s { 20 struct ngx_quic_connection_s {
160 21
161 ngx_quic_state_t state; 22 ngx_quic_state_t state;
227 enum ssl_encryption_level_t level, const uint8_t *data, size_t len); 88 enum ssl_encryption_level_t level, const uint8_t *data, size_t len);
228 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn); 89 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn);
229 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, 90 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
230 enum ssl_encryption_level_t level, uint8_t alert); 91 enum ssl_encryption_level_t level, uint8_t alert);
231 92
232 static ngx_int_t ngx_quic_process_long_header(ngx_connection_t *c,
233 ngx_quic_header_t *pkt);
234 static ngx_int_t ngx_quic_process_short_header(ngx_connection_t *c,
235 ngx_quic_header_t *pkt);
236 static ngx_int_t ngx_quic_process_initial_header(ngx_connection_t *c,
237 ngx_quic_header_t *pkt);
238 static ngx_int_t ngx_quic_process_handshake_header(ngx_connection_t *c,
239 ngx_quic_header_t *pkt);
240
241 static uint64_t ngx_quic_parse_int(u_char **pos);
242 93
243 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, 94 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf,
244 size_t size); 95 size_t size);
245 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, 96 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf,
246 size_t size); 97 size_t size);
280 131
281 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); 132 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
282 133
283 b = c->buffer; 134 b = c->buffer;
284 135
136 pkt.log = c->log;
285 pkt.raw = b; 137 pkt.raw = b;
286 pkt.data = b->start; 138 pkt.data = b->start;
287 pkt.len = b->last - b->start; 139 pkt.len = b->last - b->start;
288 140
289 if (ngx_quic_new_connection(c, ssl, &pkt) != NGX_OK) { 141 if (ngx_quic_new_connection(c, ssl, &pkt) != NGX_OK) {
405 do { 257 do {
406 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); 258 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
407 pkt.raw = b; 259 pkt.raw = b;
408 pkt.data = p; 260 pkt.data = p;
409 pkt.len = b->last - p; 261 pkt.len = b->last - p;
262 pkt.log = c->log;
410 263
411 if (p[0] == 0) { 264 if (p[0] == 0) {
412 /* XXX: no idea WTF is this, just ignore */ 265 /* XXX: no idea WTF is this, just ignore */
413 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "FIREFOX: ZEROES"); 266 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "FIREFOX: ZEROES");
414 break; 267 break;
446 return NGX_OK; 299 return NGX_OK;
447 } 300 }
448 301
449 static ngx_int_t 302 static ngx_int_t
450 ngx_quic_send_packet(ngx_connection_t *c, ngx_quic_connection_t *qc, 303 ngx_quic_send_packet(ngx_connection_t *c, ngx_quic_connection_t *qc,
451 ngx_quic_level_t level, ngx_str_t *payload) 304 enum ssl_encryption_level_t level, ngx_str_t *payload)
452 { 305 {
453 ngx_str_t res; 306 ngx_str_t res;
454 ngx_quic_header_t pkt; 307 ngx_quic_header_t pkt;
308
309 pkt.log = c->log;
455 310
456 static ngx_str_t initial_token = ngx_null_string; 311 static ngx_str_t initial_token = ngx_null_string;
457 312
458 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); 313 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
459 ngx_quic_hexdump0(c->log, "payload", payload->data, payload->len); 314 ngx_quic_hexdump0(c->log, "payload", payload->data, payload->len);
492 347
493 return NGX_OK; 348 return NGX_OK;
494 } 349 }
495 350
496 351
497 static size_t
498 ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack)
499 {
500 size_t len;
501
502 /* minimal ACK packet */
503
504 if (p == NULL) {
505 len = ngx_quic_varint_len(NGX_QUIC_FT_ACK);
506 len += ngx_quic_varint_len(ack->pn);
507 len += ngx_quic_varint_len(0);
508 len += ngx_quic_varint_len(0);
509 len += ngx_quic_varint_len(ack->pn);
510
511 return len;
512 }
513
514 ngx_quic_build_int(&p, NGX_QUIC_FT_ACK);
515 ngx_quic_build_int(&p, ack->pn);
516 ngx_quic_build_int(&p, 0);
517 ngx_quic_build_int(&p, 0);
518 ngx_quic_build_int(&p, ack->pn);
519
520 return 5;
521 }
522
523
524 static size_t
525 ngx_quic_create_crypto(u_char *p, ngx_quic_crypto_frame_t *crypto)
526 {
527 size_t len;
528 u_char *start;
529
530 if (p == NULL) {
531 len = ngx_quic_varint_len(NGX_QUIC_FT_CRYPTO);
532 len += ngx_quic_varint_len(crypto->offset);
533 len += ngx_quic_varint_len(crypto->len);
534 len += crypto->len;
535
536 return len;
537 }
538
539 start = p;
540
541 ngx_quic_build_int(&p, NGX_QUIC_FT_CRYPTO);
542 ngx_quic_build_int(&p, crypto->offset);
543 ngx_quic_build_int(&p, crypto->len);
544 p = ngx_cpymem(p, crypto->data, crypto->len);
545
546 return p - start;
547 }
548
549
550 static size_t
551 ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf)
552 {
553 size_t len;
554 u_char *start;
555
556 if (!ngx_quic_stream_bit_len(sf->type)) {
557 #if 0
558 ngx_log_error(NGX_LOG_INFO, c->log, 0,
559 "attempt to generate a stream frame without length");
560 #endif
561 // XXX: handle error in caller
562 return NGX_ERROR;
563 }
564
565 if (p == NULL) {
566 len = ngx_quic_varint_len(sf->type);
567
568 if (ngx_quic_stream_bit_off(sf->type)) {
569 len += ngx_quic_varint_len(sf->offset);
570 }
571
572 len += ngx_quic_varint_len(sf->stream_id);
573
574 /* length is always present in generated frames */
575 len += ngx_quic_varint_len(sf->length);
576
577 len += sf->length;
578
579 return len;
580 }
581
582 start = p;
583
584 ngx_quic_build_int(&p, sf->type);
585 ngx_quic_build_int(&p, sf->stream_id);
586
587 if (ngx_quic_stream_bit_off(sf->type)) {
588 ngx_quic_build_int(&p, sf->offset);
589 }
590
591 /* length is always present in generated frames */
592 ngx_quic_build_int(&p, sf->length);
593
594 p = ngx_cpymem(p, sf->data, sf->length);
595
596 return p - start;
597 }
598
599
600 size_t
601 ngx_quic_frame_len(ngx_quic_frame_t *frame)
602 {
603 switch (frame->type) {
604 case NGX_QUIC_FT_ACK:
605 return ngx_quic_create_ack(NULL, &frame->u.ack);
606 case NGX_QUIC_FT_CRYPTO:
607 return ngx_quic_create_crypto(NULL, &frame->u.crypto);
608
609 case NGX_QUIC_FT_STREAM0:
610 case NGX_QUIC_FT_STREAM1:
611 case NGX_QUIC_FT_STREAM2:
612 case NGX_QUIC_FT_STREAM3:
613 case NGX_QUIC_FT_STREAM4:
614 case NGX_QUIC_FT_STREAM5:
615 case NGX_QUIC_FT_STREAM6:
616 case NGX_QUIC_FT_STREAM7:
617 return ngx_quic_create_stream(NULL, &frame->u.stream);
618 default:
619 /* BUG: unsupported frame type generated */
620 return 0;
621 }
622 }
623
624
625 /* pack a group of frames [start; end) into memory p and send as single packet */ 352 /* pack a group of frames [start; end) into memory p and send as single packet */
626 ngx_int_t 353 ngx_int_t
627 ngx_quic_frames_send(ngx_connection_t *c, ngx_quic_frame_t *start, 354 ngx_quic_frames_send(ngx_connection_t *c, ngx_quic_frame_t *start,
628 ngx_quic_frame_t *end, size_t total) 355 ngx_quic_frame_t *end, size_t total)
629 { 356 {
357 ssize_t len;
630 u_char *p; 358 u_char *p;
631 ngx_str_t out; 359 ngx_str_t out;
632 ngx_quic_frame_t *f; 360 ngx_quic_frame_t *f;
633 361
634 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 362 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
643 371
644 for (f = start; f != end; f = f->next) { 372 for (f = start; f != end; f = f->next) {
645 373
646 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "frame: %s", f->info); 374 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "frame: %s", f->info);
647 375
648 switch (f->type) { 376 len = ngx_quic_create_frame(p, p + total, f);
649 case NGX_QUIC_FT_ACK: 377 if (len == -1) {
650 p += ngx_quic_create_ack(p, &f->u.ack);
651 break;
652
653 case NGX_QUIC_FT_CRYPTO:
654 p += ngx_quic_create_crypto(p, &f->u.crypto);
655 break;
656
657 case NGX_QUIC_FT_STREAM0:
658 case NGX_QUIC_FT_STREAM1:
659 case NGX_QUIC_FT_STREAM2:
660 case NGX_QUIC_FT_STREAM3:
661 case NGX_QUIC_FT_STREAM4:
662 case NGX_QUIC_FT_STREAM5:
663 case NGX_QUIC_FT_STREAM6:
664 case NGX_QUIC_FT_STREAM7:
665 p += ngx_quic_create_stream(p, &f->u.stream);
666 break;
667
668 default:
669 /* BUG: unsupported frame type generated */
670 return NGX_ERROR; 378 return NGX_ERROR;
671 } 379 }
380
381 p += len;
672 } 382 }
673 383
674 out.len = p - out.data; 384 out.len = p - out.data;
675 385
676 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 386 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
889 (int) level, (int) alert); 599 (int) level, (int) alert);
890 600
891 return 1; 601 return 1;
892 } 602 }
893 603
894
895 static ngx_int_t
896 ngx_quic_process_short_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
897 {
898 u_char *p;
899
900 p = pkt->data;
901
902 ngx_quic_hexdump0(c->log, "short input", pkt->data, pkt->len);
903
904 if ((p[0] & NGX_QUIC_PKT_LONG)) {
905 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a short packet");
906 return NGX_ERROR;
907 }
908
909 pkt->flags = *p++;
910
911 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
912 "quic flags:%xi", pkt->flags);
913
914 if (ngx_memcmp(p, c->quic->dcid.data, c->quic->dcid.len) != 0) {
915 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid");
916 return NGX_ERROR;
917 }
918
919 pkt->dcid.len = c->quic->dcid.len;
920 pkt->dcid.data = p;
921 p += pkt->dcid.len;
922
923 pkt->raw->pos = p;
924
925 return NGX_OK;
926 }
927
928
929 static ngx_int_t
930 ngx_quic_process_long_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
931 {
932 u_char *p;
933
934 p = pkt->data;
935
936 ngx_quic_hexdump0(c->log, "long input", pkt->data, pkt->len);
937
938 if (!(p[0] & NGX_QUIC_PKT_LONG)) {
939 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a long packet");
940 return NGX_ERROR;
941 }
942
943 pkt->flags = *p++;
944
945 pkt->version = ngx_quic_parse_uint32(p);
946 p += sizeof(uint32_t);
947
948 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
949 "quic flags:%xi version:%xD", pkt->flags, pkt->version);
950
951 if (pkt->version != quic_version) {
952 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unsupported quic version");
953 return NGX_ERROR;
954 }
955
956 pkt->dcid.len = *p++;
957 pkt->dcid.data = p;
958 p += pkt->dcid.len;
959
960 pkt->scid.len = *p++;
961 pkt->scid.data = p;
962 p += pkt->scid.len;
963
964 pkt->raw->pos = p;
965
966 return NGX_OK;
967 }
968
969
970 static ngx_int_t
971 ngx_quic_process_initial_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
972 {
973 u_char *p;
974 ngx_int_t plen;
975
976 p = pkt->raw->pos;
977
978 pkt->token.len = ngx_quic_parse_int(&p);
979 pkt->token.data = p;
980
981 p += pkt->token.len;
982
983 plen = ngx_quic_parse_int(&p);
984
985 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
986 "quic packet length: %d", plen);
987
988 if (plen > pkt->data + pkt->len - p) {
989 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated initial packet");
990 return NGX_ERROR;
991 }
992
993 pkt->raw->pos = p;
994 pkt->len = plen;
995
996 ngx_quic_hexdump0(c->log, "DCID", pkt->dcid.data, pkt->dcid.len);
997 ngx_quic_hexdump0(c->log, "SCID", pkt->scid.data, pkt->scid.len);
998 ngx_quic_hexdump0(c->log, "token", pkt->token.data, pkt->token.len);
999
1000 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1001 "quic packet length: %d", plen);
1002
1003 return NGX_OK;
1004 }
1005
1006 static ngx_int_t
1007 ngx_quic_process_handshake_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
1008 {
1009 u_char *p;
1010 ngx_int_t plen;
1011
1012 p = pkt->raw->pos;
1013
1014 plen = ngx_quic_parse_int(&p);
1015
1016 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1017 "quic packet length: %d", plen);
1018
1019 if (plen > pkt->data + pkt->len - p) {
1020 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated handshake packet");
1021 return NGX_ERROR;
1022 }
1023
1024 pkt->raw->pos = p;
1025 pkt->len = plen;
1026
1027 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1028 "quic packet length: %d", plen);
1029
1030 return NGX_OK;
1031 }
1032
1033
1034 ssize_t
1035 ngx_quic_read_frame(ngx_connection_t *c, u_char *start, u_char *end,
1036 ngx_quic_frame_t *frame)
1037 {
1038 u_char *p;
1039
1040 size_t npad;
1041
1042 p = start;
1043
1044 frame->type = *p++; // TODO: check overflow (p < end)
1045
1046 switch (frame->type) {
1047
1048 case NGX_QUIC_FT_CRYPTO:
1049 frame->u.crypto.offset = *p++;
1050 frame->u.crypto.len = ngx_quic_parse_int(&p);
1051 frame->u.crypto.data = p;
1052 p += frame->u.crypto.len;
1053
1054 ngx_quic_hexdump0(c->log, "CRYPTO frame",
1055 frame->u.crypto.data, frame->u.crypto.len);
1056
1057 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1058 "quic CRYPTO frame length: %uL off:%uL pp:%p",
1059 frame->u.crypto.len, frame->u.crypto.offset,
1060 frame->u.crypto.data);
1061 break;
1062
1063 case NGX_QUIC_FT_PADDING:
1064 npad = 0;
1065 while (p < end && *p == NGX_QUIC_FT_PADDING) { // XXX
1066 p++; npad++;
1067 }
1068
1069 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1070 "PADDING frame length %uL", npad);
1071
1072 break;
1073
1074 case NGX_QUIC_FT_ACK:
1075 case NGX_QUIC_FT_ACK_ECN:
1076
1077 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "ACK frame");
1078
1079 frame->u.ack.largest = ngx_quic_parse_int(&p);
1080 frame->u.ack.delay = ngx_quic_parse_int(&p);
1081 frame->u.ack.range_count =ngx_quic_parse_int(&p);
1082 frame->u.ack.first_range =ngx_quic_parse_int(&p);
1083
1084 if (frame->u.ack.range_count) {
1085 frame->u.ack.ranges[0] = ngx_quic_parse_int(&p);
1086 }
1087
1088 if (frame->type ==NGX_QUIC_FT_ACK_ECN) {
1089 return NGX_ERROR;
1090 }
1091
1092 break;
1093
1094 case NGX_QUIC_FT_PING:
1095 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "PING frame");
1096 break;
1097
1098 case NGX_QUIC_FT_NEW_CONNECTION_ID:
1099 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "NCID frame");
1100
1101 frame->u.ncid.seqnum = ngx_quic_parse_int(&p);
1102 frame->u.ncid.retire = ngx_quic_parse_int(&p);
1103 frame->u.ncid.len = *p++;
1104 ngx_memcpy(frame->u.ncid.cid, p, frame->u.ncid.len);
1105 p += frame->u.ncid.len;
1106
1107 ngx_memcpy(frame->u.ncid.srt, p, 16);
1108 p += 16;
1109
1110 break;
1111
1112 case NGX_QUIC_FT_CONNECTION_CLOSE:
1113 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "connection close frame");
1114
1115 frame->u.close.error_code = ngx_quic_parse_int(&p);
1116 frame->u.close.frame_type = ngx_quic_parse_int(&p); // not in 0x1d CC
1117 frame->u.close.reason.len = ngx_quic_parse_int(&p);
1118 frame->u.close.reason.data = p;
1119 p += frame->u.close.reason.len;
1120
1121 if (frame->u.close.error_code > NGX_QUIC_ERR_LAST) {
1122 frame->u.close.error_code = NGX_QUIC_ERR_LAST;
1123 }
1124 break;
1125
1126 case NGX_QUIC_FT_STREAM0:
1127 case NGX_QUIC_FT_STREAM1:
1128 case NGX_QUIC_FT_STREAM2:
1129 case NGX_QUIC_FT_STREAM3:
1130 case NGX_QUIC_FT_STREAM4:
1131 case NGX_QUIC_FT_STREAM5:
1132 case NGX_QUIC_FT_STREAM6:
1133 case NGX_QUIC_FT_STREAM7:
1134
1135 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1136 "STREAM frame, type: 0x%xi", frame->type);
1137
1138 frame->u.stream.type = frame->type;
1139
1140 frame->u.stream.stream_id = ngx_quic_parse_int(&p);
1141 if (frame->type & 0x04) {
1142 frame->u.stream.offset = ngx_quic_parse_int(&p);
1143 } else {
1144 frame->u.stream.offset = 0;
1145 }
1146
1147 if (frame->type & 0x02) {
1148 frame->u.stream.length = ngx_quic_parse_int(&p);
1149 } else {
1150 frame->u.stream.length = end - p; /* up to packet end */
1151 }
1152
1153 frame->u.stream.data = p;
1154
1155 p += frame->u.stream.length;
1156
1157 break;
1158
1159 default:
1160 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1161 "unknown frame type %xi", frame->type);
1162 return NGX_ERROR;
1163 }
1164
1165 return p - start;
1166 }
1167 604
1168 605
1169 static ngx_int_t 606 static ngx_int_t
1170 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, 607 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
1171 ngx_quic_frame_t *frame) 608 ngx_quic_frame_t *frame)
1347 784
1348 ngx_memcpy(p, buf, size); 785 ngx_memcpy(p, buf, size);
1349 786
1350 frame->level = ssl_encryption_application; 787 frame->level = ssl_encryption_application;
1351 frame->type = NGX_QUIC_FT_STREAM6; /* OFF=1 LEN=1 FIN=0 */ 788 frame->type = NGX_QUIC_FT_STREAM6; /* OFF=1 LEN=1 FIN=0 */
789 frame->u.stream.off = 1;
790 frame->u.stream.len = 1;
791 frame->u.stream.fin = 0;
1352 792
1353 frame->u.stream.type = frame->type; 793 frame->u.stream.type = frame->type;
1354 frame->u.stream.stream_id = qs->id; 794 frame->u.stream.stream_id = qs->id;
1355 frame->u.stream.offset = c->sent; 795 frame->u.stream.offset = c->sent;
1356 frame->u.stream.length = size; 796 frame->u.stream.length = size;
1431 ack_this = 0; 871 ack_this = 0;
1432 do_close = 0; 872 do_close = 0;
1433 873
1434 while (p < end) { 874 while (p < end) {
1435 875
1436 len = ngx_quic_read_frame(c, p, end, &frame); 876 len = ngx_quic_parse_frame(p, end, &frame);
1437 if (len < 0) { 877 if (len < 0) {
878 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
879 "unknown frame type %xi", frame.type);
880 // XXX: log here
1438 return NGX_ERROR; 881 return NGX_ERROR;
1439 } 882 }
1440 883
1441 p += len; 884 p += len;
1442 885
1454 frame.u.ack.range_count); 897 frame.u.ack.range_count);
1455 898
1456 break; 899 break;
1457 900
1458 case NGX_QUIC_FT_CRYPTO: 901 case NGX_QUIC_FT_CRYPTO:
902 ngx_quic_hexdump0(c->log, "CRYPTO frame",
903 frame.u.crypto.data, frame.u.crypto.len);
904
905 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
906 "quic CRYPTO frame length: %uL off:%uL pp:%p",
907 frame.u.crypto.len, frame.u.crypto.offset,
908 frame.u.crypto.data);
1459 909
1460 if (frame.u.crypto.offset != 0x0) { 910 if (frame.u.crypto.offset != 0x0) {
1461 ngx_log_error(NGX_LOG_INFO, c->log, 0, 911 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1462 "crypto frame with non-zero offset"); 912 "crypto frame with non-zero offset");
1463 // TODO: support packet spanning with offsets 913 // TODO: support packet spanning with offsets
1489 continue; 939 continue;
1490 940
1491 case NGX_QUIC_FT_CONNECTION_CLOSE: 941 case NGX_QUIC_FT_CONNECTION_CLOSE:
1492 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, 942 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
1493 "CONN.CLOSE: { %s (0x%xi) type=0x%xi reason='%V'}", 943 "CONN.CLOSE: { %s (0x%xi) type=0x%xi reason='%V'}",
1494 ngx_quic_errors[frame.u.close.error_code], 944 ngx_quic_error_text(frame.u.close.error_code),
1495 frame.u.close.error_code, 945 frame.u.close.error_code,
1496 frame.u.close.frame_type, 946 frame.u.close.frame_type,
1497 &frame.u.close.reason); 947 &frame.u.close.reason);
1498 948
1499 do_close = 1; 949 do_close = 1;
1514 "STREAM frame 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d", 964 "STREAM frame 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d",
1515 frame.type, 965 frame.type,
1516 frame.u.stream.stream_id, 966 frame.u.stream.stream_id,
1517 frame.u.stream.offset, 967 frame.u.stream.offset,
1518 frame.u.stream.length, 968 frame.u.stream.length,
1519 ngx_quic_stream_bit_off(frame.u.stream.type), 969 frame.u.stream.off,
1520 ngx_quic_stream_bit_len(frame.u.stream.type), 970 frame.u.stream.len,
1521 ngx_quic_stream_bit_fin(frame.u.stream.type)); 971 frame.u.stream.fin);
1522
1523 972
1524 sn = ngx_quic_stream_lookup(&qc->stree, frame.u.stream.stream_id); 973 sn = ngx_quic_stream_lookup(&qc->stree, frame.u.stream.stream_id);
1525 if (sn == NULL) { 974 if (sn == NULL) {
1526 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "stream is new"); 975 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "stream is new");
1527 976
1725 if (ngx_buf_size(pkt->raw) < 1200) { 1174 if (ngx_buf_size(pkt->raw) < 1200) {
1726 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram"); 1175 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram");
1727 return NGX_ERROR; 1176 return NGX_ERROR;
1728 } 1177 }
1729 1178
1730 if (ngx_quic_process_long_header(c, pkt) != NGX_OK) { 1179 if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
1731 return NGX_ERROR; 1180 return NGX_ERROR;
1732 } 1181 }
1733 1182
1734 if ((pkt->flags & 0xf0) != NGX_QUIC_PKT_INITIAL) { 1183 if ((pkt->flags & 0xf0) != NGX_QUIC_PKT_INITIAL) {
1735 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1184 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1736 "invalid initial packet: 0x%xi", pkt->flags); 1185 "invalid initial packet: 0x%xi", pkt->flags);
1737 return NGX_ERROR; 1186 return NGX_ERROR;
1738 } 1187 }
1739 1188
1740 if (ngx_quic_process_initial_header(c, pkt) != NGX_OK) { 1189 if (ngx_quic_parse_initial_header(pkt) != NGX_OK) {
1741 return NGX_ERROR; 1190 return NGX_ERROR;
1742 } 1191 }
1743 1192
1744 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t)); 1193 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t));
1745 if (qc == NULL) { 1194 if (qc == NULL) {
1802 ngx_quic_connection_t *qc; 1251 ngx_quic_connection_t *qc;
1803 1252
1804 qc = c->quic; 1253 qc = c->quic;
1805 ssl_conn = c->ssl->connection; 1254 ssl_conn = c->ssl->connection;
1806 1255
1807 if (ngx_quic_process_long_header(c, pkt) != NGX_OK) { 1256 if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
1808 return NGX_ERROR; 1257 return NGX_ERROR;
1809 } 1258 }
1810 1259
1811 if (ngx_quic_process_initial_header(c, pkt) != NGX_OK) { 1260 if (ngx_quic_parse_initial_header(pkt) != NGX_OK) {
1812 return NGX_ERROR; 1261 return NGX_ERROR;
1813 } 1262 }
1814 1263
1815 pkt->secret = &qc->secrets.client.in; 1264 pkt->secret = &qc->secrets.client.in;
1816 pkt->level = ssl_encryption_initial; 1265 pkt->level = ssl_encryption_initial;
1831 1280
1832 qc = c->quic; 1281 qc = c->quic;
1833 ssl_conn = c->ssl->connection; 1282 ssl_conn = c->ssl->connection;
1834 1283
1835 /* extract cleartext data into pkt */ 1284 /* extract cleartext data into pkt */
1836 if (ngx_quic_process_long_header(c, pkt) != NGX_OK) { 1285 if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
1837 return NGX_ERROR; 1286 return NGX_ERROR;
1838 } 1287 }
1839 1288
1840 if (pkt->dcid.len != qc->dcid.len) { 1289 if (pkt->dcid.len != qc->dcid.len) {
1841 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl"); 1290 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl");
1861 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1310 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1862 "invalid packet type: 0x%xi", pkt->flags); 1311 "invalid packet type: 0x%xi", pkt->flags);
1863 return NGX_ERROR; 1312 return NGX_ERROR;
1864 } 1313 }
1865 1314
1866 if (ngx_quic_process_handshake_header(c, pkt) != NGX_OK) { 1315 if (ngx_quic_parse_handshake_header(pkt) != NGX_OK) {
1867 return NGX_ERROR; 1316 return NGX_ERROR;
1868 } 1317 }
1869 1318
1870 pkt->secret = &qc->secrets.client.hs; 1319 pkt->secret = &qc->secrets.client.hs;
1871 pkt->level = ssl_encryption_handshake; 1320 pkt->level = ssl_encryption_handshake;
1889 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1338 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1890 "no read keys yet, packet ignored"); 1339 "no read keys yet, packet ignored");
1891 return NGX_DECLINED; 1340 return NGX_DECLINED;
1892 } 1341 }
1893 1342
1894 if (ngx_quic_process_short_header(c, pkt) != NGX_OK) { 1343 if (ngx_quic_parse_short_header(pkt, &qc->dcid) != NGX_OK) {
1895 return NGX_ERROR; 1344 return NGX_ERROR;
1896 } 1345 }
1897 1346
1898 pkt->secret = &qc->secrets.client.ad; 1347 pkt->secret = &qc->secrets.client.ad;
1899 pkt->level = ssl_encryption_application; 1348 pkt->level = ssl_encryption_application;
1904 1353
1905 return ngx_quic_payload_handler(c, pkt); 1354 return ngx_quic_payload_handler(c, pkt);
1906 } 1355 }
1907 1356
1908 1357
1909 uint64_t
1910 ngx_quic_parse_int(u_char **pos)
1911 {
1912 u_char *p;
1913 uint64_t value;
1914 ngx_uint_t len;
1915
1916 p = *pos;
1917 len = 1 << ((*p & 0xc0) >> 6);
1918 value = *p++ & 0x3f;
1919
1920 while (--len) {
1921 value = (value << 8) + *p++;
1922 }
1923
1924 *pos = p;
1925 return value;
1926 }
1927
1928
1929 void
1930 ngx_quic_build_int(u_char **pos, uint64_t value)
1931 {
1932 u_char *p;
1933 ngx_uint_t len;//, len2;
1934
1935 p = *pos;
1936 len = 0;
1937
1938 while (value >> ((1 << len) * 8 - 2)) {
1939 len++;
1940 }
1941
1942 *p = len << 6;
1943
1944 // len2 =
1945 len = (1 << len);
1946 len--;
1947 *p |= value >> (len * 8);
1948 p++;
1949
1950 while (len) {
1951 *p++ = value >> ((len-- - 1) * 8);
1952 }
1953
1954 *pos = p;
1955 // return len2;
1956 }
1957