comparison src/event/quic/ngx_event_quic.c @ 8751:bc910a5ec737 quic

QUIC: separate files for output and ack related processing.
author Vladimir Homutov <vl@nginx.com>
date Tue, 13 Apr 2021 14:41:20 +0300
parents 41807e581de9
children e19723c40d28
comparison
equal deleted inserted replaced
8750:41807e581de9 8751:bc910a5ec737
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 #include <ngx_sha1.h> 10 #include <ngx_sha1.h>
11 #include <ngx_event_quic_connection.h> 11 #include <ngx_event_quic_connection.h>
12 12
13 13
14 #define ngx_quic_lost_threshold(qc) \
15 ngx_max(NGX_QUIC_TIME_THR * ngx_max((qc)->latest_rtt, (qc)->avg_rtt), \
16 NGX_QUIC_TIME_GRANULARITY)
17
18 /* 14 /*
19 * 7.4. Cryptographic Message Buffering 15 * 7.4. Cryptographic Message Buffering
20 * Implementations MUST support buffering at least 4096 bytes of data 16 * Implementations MUST support buffering at least 4096 bytes of data
21 */ 17 */
22 #define NGX_QUIC_MAX_BUFFERED 65535 18 #define NGX_QUIC_MAX_BUFFERED 65535
23
24 /*
25 * Endpoints MUST discard packets that are too small to be valid QUIC
26 * packets. With the set of AEAD functions defined in [QUIC-TLS],
27 * packets that are smaller than 21 bytes are never valid.
28 */
29 #define NGX_QUIC_MIN_PKT_LEN 21
30
31 #define NGX_QUIC_MIN_SR_PACKET 43 /* 5 random + 16 srt + 22 padding */
32 #define NGX_QUIC_MAX_SR_PACKET 1200
33
34 #define NGX_QUIC_MAX_ACK_GAP 2
35 19
36 20
37 #if BORINGSSL_API_VERSION >= 10 21 #if BORINGSSL_API_VERSION >= 10
38 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn, 22 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
39 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, 23 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
48 #endif 32 #endif
49 33
50 static int ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn, 34 static int ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
51 enum ssl_encryption_level_t level, const uint8_t *data, size_t len); 35 enum ssl_encryption_level_t level, const uint8_t *data, size_t len);
52 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn); 36 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn);
53 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
54 enum ssl_encryption_level_t level, uint8_t alert);
55 37
56 38
57 static ngx_int_t ngx_quic_apply_transport_params(ngx_connection_t *c, 39 static ngx_int_t ngx_quic_apply_transport_params(ngx_connection_t *c,
58 ngx_quic_tp_t *ctp); 40 ngx_quic_tp_t *ctp);
59 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c, 41 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c,
60 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); 42 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
61 static ngx_int_t ngx_quic_send_stateless_reset(ngx_connection_t *c,
62 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
63 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c, 43 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c,
64 ngx_quic_header_t *pkt); 44 ngx_quic_header_t *pkt);
65 static ngx_int_t ngx_quic_negotiate_version(ngx_connection_t *c,
66 ngx_quic_header_t *inpkt);
67 static ngx_int_t ngx_quic_send_retry(ngx_connection_t *c,
68 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
69 static ngx_int_t ngx_quic_new_token(ngx_connection_t *c, u_char *key,
70 ngx_str_t *token, ngx_str_t *odcid, time_t expires, ngx_uint_t is_retry);
71 static void ngx_quic_address_hash(ngx_connection_t *c, ngx_uint_t no_port, 45 static void ngx_quic_address_hash(ngx_connection_t *c, ngx_uint_t no_port,
72 u_char buf[20]); 46 u_char buf[20]);
73 static ngx_int_t ngx_quic_validate_token(ngx_connection_t *c, 47 static ngx_int_t ngx_quic_validate_token(ngx_connection_t *c,
74 u_char *key, ngx_quic_header_t *pkt); 48 u_char *key, ngx_quic_header_t *pkt);
75 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c); 49 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c);
76 static ngx_inline size_t ngx_quic_max_udp_payload(ngx_connection_t *c);
77 static void ngx_quic_input_handler(ngx_event_t *rev); 50 static void ngx_quic_input_handler(ngx_event_t *rev);
78 51
79 static ngx_int_t ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc); 52 static ngx_int_t ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc);
80 static void ngx_quic_close_timer_handler(ngx_event_t *ev); 53 static void ngx_quic_close_timer_handler(ngx_event_t *ev);
81 54
83 ngx_quic_conf_t *conf); 56 ngx_quic_conf_t *conf);
84 static ngx_int_t ngx_quic_process_packet(ngx_connection_t *c, 57 static ngx_int_t ngx_quic_process_packet(ngx_connection_t *c,
85 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); 58 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
86 static ngx_int_t ngx_quic_process_payload(ngx_connection_t *c, 59 static ngx_int_t ngx_quic_process_payload(ngx_connection_t *c,
87 ngx_quic_header_t *pkt); 60 ngx_quic_header_t *pkt);
88 static ngx_int_t ngx_quic_send_early_cc(ngx_connection_t *c,
89 ngx_quic_header_t *inpkt, ngx_uint_t err, const char *reason);
90 static void ngx_quic_discard_ctx(ngx_connection_t *c, 61 static void ngx_quic_discard_ctx(ngx_connection_t *c,
91 enum ssl_encryption_level_t level); 62 enum ssl_encryption_level_t level);
92 static ngx_int_t ngx_quic_check_csid(ngx_quic_connection_t *qc, 63 static ngx_int_t ngx_quic_check_csid(ngx_quic_connection_t *qc,
93 ngx_quic_header_t *pkt); 64 ngx_quic_header_t *pkt);
94 static ngx_int_t ngx_quic_handle_frames(ngx_connection_t *c, 65 static ngx_int_t ngx_quic_handle_frames(ngx_connection_t *c,
95 ngx_quic_header_t *pkt); 66 ngx_quic_header_t *pkt);
96 static ngx_int_t ngx_quic_ack_packet(ngx_connection_t *c, 67
97 ngx_quic_header_t *pkt);
98 static ngx_int_t ngx_quic_send_ack_range(ngx_connection_t *c,
99 ngx_quic_send_ctx_t *ctx, uint64_t smallest, uint64_t largest);
100 static void ngx_quic_drop_ack_ranges(ngx_connection_t *c,
101 ngx_quic_send_ctx_t *ctx, uint64_t pn);
102 static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c,
103 ngx_quic_send_ctx_t *ctx);
104 static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c);
105 static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c);
106
107 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c,
108 ngx_quic_header_t *pkt, ngx_quic_frame_t *f);
109 static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c,
110 ngx_quic_send_ctx_t *ctx, uint64_t min, uint64_t max,
111 ngx_msec_t *send_time);
112 static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack,
113 enum ssl_encryption_level_t level, ngx_msec_t send_time);
114 68
115 static ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c, 69 static ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c,
116 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame); 70 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame);
117 ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c, 71 ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c,
118 ngx_quic_frame_t *frame, void *data); 72 ngx_quic_frame_t *frame, void *data);
119 73
120 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c);
121 static ngx_int_t ngx_quic_generate_ack(ngx_connection_t *c,
122 ngx_quic_send_ctx_t *ctx);
123 static ssize_t ngx_quic_output_packet(ngx_connection_t *c,
124 ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min);
125 static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len);
126
127 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt,
128 ngx_quic_send_ctx_t *ctx);
129 static void ngx_quic_pto_handler(ngx_event_t *ev);
130 static void ngx_quic_lost_handler(ngx_event_t *ev);
131 static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c);
132 static void ngx_quic_set_lost_timer(ngx_connection_t *c);
133 static void ngx_quic_resend_frames(ngx_connection_t *c,
134 ngx_quic_send_ctx_t *ctx);
135 static void ngx_quic_push_handler(ngx_event_t *ev); 74 static void ngx_quic_push_handler(ngx_event_t *ev);
136
137 static void ngx_quic_congestion_ack(ngx_connection_t *c,
138 ngx_quic_frame_t *frame);
139 static void ngx_quic_congestion_lost(ngx_connection_t *c,
140 ngx_quic_frame_t *frame);
141 75
142 76
143 static ngx_core_module_t ngx_quic_module_ctx = { 77 static ngx_core_module_t ngx_quic_module_ctx = {
144 ngx_string("quic"), 78 ngx_string("quic"),
145 NULL, 79 NULL,
176 }; 110 };
177 111
178 112
179 #if (NGX_DEBUG) 113 #if (NGX_DEBUG)
180 114
181 static void 115 void
182 ngx_quic_connstate_dbg(ngx_connection_t *c) 116 ngx_quic_connstate_dbg(ngx_connection_t *c)
183 { 117 {
184 u_char *p, *last; 118 u_char *p, *last;
185 ngx_quic_connection_t *qc; 119 ngx_quic_connection_t *qc;
186 u_char buf[NGX_MAX_ERROR_STR]; 120 u_char buf[NGX_MAX_ERROR_STR];
238 } 172 }
239 173
240 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 174 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
241 "quic %*s", p - buf, buf); 175 "quic %*s", p - buf, buf);
242 } 176 }
243
244 #else
245
246 #define ngx_quic_connstate_dbg(c)
247 177
248 #endif 178 #endif
249 179
250 180
251 #if BORINGSSL_API_VERSION >= 10 181 #if BORINGSSL_API_VERSION >= 10
466 #endif 396 #endif
467 return 1; 397 return 1;
468 } 398 }
469 399
470 400
471 static int
472 ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
473 uint8_t alert)
474 {
475 ngx_connection_t *c;
476 ngx_quic_connection_t *qc;
477
478 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
479
480 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
481 "quic ngx_quic_send_alert() lvl:%d alert:%d",
482 (int) level, (int) alert);
483
484 qc = ngx_quic_get_connection(c);
485 if (qc == NULL) {
486 return 1;
487 }
488
489 qc->error_level = level;
490 qc->error = NGX_QUIC_ERR_CRYPTO(alert);
491 qc->error_reason = "TLS alert";
492 qc->error_app = 0;
493 qc->error_ftype = 0;
494
495 if (ngx_quic_send_cc(c) != NGX_OK) {
496 return 0;
497 }
498
499 return 1;
500 }
501
502
503 static ngx_int_t 401 static ngx_int_t
504 ngx_quic_apply_transport_params(ngx_connection_t *c, ngx_quic_tp_t *ctp) 402 ngx_quic_apply_transport_params(ngx_connection_t *c, ngx_quic_tp_t *ctp)
505 { 403 {
506 ngx_quic_connection_t *qc; 404 ngx_quic_connection_t *qc;
507 405
720 618
721 return qc; 619 return qc;
722 } 620 }
723 621
724 622
725 static ngx_int_t
726 ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
727 ngx_quic_header_t *pkt)
728 {
729 u_char *token;
730 size_t len, max;
731 uint16_t rndbytes;
732 u_char buf[NGX_QUIC_MAX_SR_PACKET];
733
734 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
735 "quic handle stateless reset output");
736
737 if (pkt->len <= NGX_QUIC_MIN_PKT_LEN) {
738 return NGX_DECLINED;
739 }
740
741 if (pkt->len <= NGX_QUIC_MIN_SR_PACKET) {
742 len = pkt->len - 1;
743
744 } else {
745 max = ngx_min(NGX_QUIC_MAX_SR_PACKET, pkt->len * 3);
746
747 if (RAND_bytes((u_char *) &rndbytes, sizeof(rndbytes)) != 1) {
748 return NGX_ERROR;
749 }
750
751 len = (rndbytes % (max - NGX_QUIC_MIN_SR_PACKET + 1))
752 + NGX_QUIC_MIN_SR_PACKET;
753 }
754
755 if (RAND_bytes(buf, len - NGX_QUIC_SR_TOKEN_LEN) != 1) {
756 return NGX_ERROR;
757 }
758
759 buf[0] &= ~NGX_QUIC_PKT_LONG;
760 buf[0] |= NGX_QUIC_PKT_FIXED_BIT;
761
762 token = &buf[len - NGX_QUIC_SR_TOKEN_LEN];
763
764 if (ngx_quic_new_sr_token(c, &pkt->dcid, conf->sr_token_key, token)
765 != NGX_OK)
766 {
767 return NGX_ERROR;
768 }
769
770 (void) ngx_quic_send(c, buf, len);
771
772 return NGX_DECLINED;
773 }
774
775
776 ngx_int_t 623 ngx_int_t
777 ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, u_char *secret, 624 ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, u_char *secret,
778 u_char *token) 625 u_char *token)
779 { 626 {
780 ngx_str_t tmp; 627 ngx_str_t tmp;
841 688
842 return NGX_DECLINED; 689 return NGX_DECLINED;
843 } 690 }
844 691
845 692
846 static ngx_int_t 693 ngx_int_t
847 ngx_quic_negotiate_version(ngx_connection_t *c, ngx_quic_header_t *inpkt)
848 {
849 size_t len;
850 ngx_quic_header_t pkt;
851 static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
852
853 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
854 "sending version negotiation packet");
855
856 pkt.log = c->log;
857 pkt.flags = NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_FIXED_BIT;
858 pkt.dcid = inpkt->scid;
859 pkt.scid = inpkt->dcid;
860
861 len = ngx_quic_create_version_negotiation(&pkt, buf);
862
863 #ifdef NGX_QUIC_DEBUG_PACKETS
864 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
865 "quic vnego packet to send len:%uz %*xs", len, len, buf);
866 #endif
867
868 (void) ngx_quic_send(c, buf, len);
869
870 return NGX_ERROR;
871 }
872
873
874 static ngx_int_t
875 ngx_quic_send_retry(ngx_connection_t *c, ngx_quic_conf_t *conf,
876 ngx_quic_header_t *inpkt)
877 {
878 time_t expires;
879 ssize_t len;
880 ngx_str_t res, token;
881 ngx_quic_header_t pkt;
882
883 u_char buf[NGX_QUIC_RETRY_BUFFER_SIZE];
884 u_char dcid[NGX_QUIC_SERVER_CID_LEN];
885
886 expires = ngx_time() + NGX_QUIC_RETRY_TOKEN_LIFETIME;
887
888 if (ngx_quic_new_token(c, conf->av_token_key, &token, &inpkt->dcid,
889 expires, 1)
890 != NGX_OK)
891 {
892 return NGX_ERROR;
893 }
894
895 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
896 pkt.flags = NGX_QUIC_PKT_FIXED_BIT | NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_RETRY;
897 pkt.version = inpkt->version;
898 pkt.log = c->log;
899
900 pkt.odcid = inpkt->dcid;
901 pkt.dcid = inpkt->scid;
902
903 /* TODO: generate routable dcid */
904 if (RAND_bytes(dcid, NGX_QUIC_SERVER_CID_LEN) != 1) {
905 return NGX_ERROR;
906 }
907
908 pkt.scid.len = NGX_QUIC_SERVER_CID_LEN;
909 pkt.scid.data = dcid;
910
911 pkt.token = token;
912
913 res.data = buf;
914
915 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
916 return NGX_ERROR;
917 }
918
919 #ifdef NGX_QUIC_DEBUG_PACKETS
920 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
921 "quic packet to send len:%uz %xV", res.len, &res);
922 #endif
923
924 len = ngx_quic_send(c, res.data, res.len);
925 if (len == NGX_ERROR) {
926 return NGX_ERROR;
927 }
928
929 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
930 "quic retry packet sent to %xV", &pkt.dcid);
931
932 /*
933 * quic-transport 17.2.5.1: A server MUST NOT send more than one Retry
934 * packet in response to a single UDP datagram.
935 * NGX_DONE will stop quic_input() from processing further
936 */
937 return NGX_DONE;
938 }
939
940
941 static ngx_int_t
942 ngx_quic_new_token(ngx_connection_t *c, u_char *key, ngx_str_t *token, 694 ngx_quic_new_token(ngx_connection_t *c, u_char *key, ngx_str_t *token,
943 ngx_str_t *odcid, time_t exp, ngx_uint_t is_retry) 695 ngx_str_t *odcid, time_t exp, ngx_uint_t is_retry)
944 { 696 {
945 int len, iv_len; 697 int len, iv_len;
946 u_char *p, *iv; 698 u_char *p, *iv;
1262 return NGX_ERROR; 1014 return NGX_ERROR;
1263 } 1015 }
1264 #endif 1016 #endif
1265 1017
1266 return NGX_OK; 1018 return NGX_OK;
1267 }
1268
1269
1270 static ngx_inline size_t
1271 ngx_quic_max_udp_payload(ngx_connection_t *c)
1272 {
1273 /* TODO: path MTU discovery */
1274
1275 #if (NGX_HAVE_INET6)
1276 if (c->sockaddr->sa_family == AF_INET6) {
1277 return NGX_QUIC_MAX_UDP_PAYLOAD_OUT6;
1278 }
1279 #endif
1280
1281 return NGX_QUIC_MAX_UDP_PAYLOAD_OUT;
1282 } 1019 }
1283 1020
1284 1021
1285 static void 1022 static void
1286 ngx_quic_input_handler(ngx_event_t *rev) 1023 ngx_quic_input_handler(ngx_event_t *rev)
1900 1637
1901 return ngx_quic_keys_update(c, qc->keys); 1638 return ngx_quic_keys_update(c, qc->keys);
1902 } 1639 }
1903 1640
1904 1641
1905 static ngx_int_t
1906 ngx_quic_send_early_cc(ngx_connection_t *c, ngx_quic_header_t *inpkt,
1907 ngx_uint_t err, const char *reason)
1908 {
1909 ssize_t len;
1910 ngx_str_t res;
1911 ngx_quic_frame_t frame;
1912 ngx_quic_header_t pkt;
1913
1914 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
1915 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
1916
1917 ngx_memzero(&frame, sizeof(ngx_quic_frame_t));
1918 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
1919
1920 frame.level = inpkt->level;
1921 frame.type = NGX_QUIC_FT_CONNECTION_CLOSE;
1922 frame.u.close.error_code = err;
1923
1924 frame.u.close.reason.data = (u_char *) reason;
1925 frame.u.close.reason.len = ngx_strlen(reason);
1926
1927 len = ngx_quic_create_frame(NULL, &frame);
1928 if (len > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE) {
1929 return NGX_ERROR;
1930 }
1931
1932 ngx_quic_log_frame(c->log, &frame, 1);
1933
1934 len = ngx_quic_create_frame(src, &frame);
1935 if (len == -1) {
1936 return NGX_ERROR;
1937 }
1938
1939 pkt.keys = ngx_quic_keys_new(c->pool);
1940 if (pkt.keys == NULL) {
1941 return NGX_ERROR;
1942 }
1943
1944 if (ngx_quic_keys_set_initial_secret(c->pool, pkt.keys, &inpkt->dcid,
1945 inpkt->version)
1946 != NGX_OK)
1947 {
1948 return NGX_ERROR;
1949 }
1950
1951 pkt.flags = NGX_QUIC_PKT_FIXED_BIT | NGX_QUIC_PKT_LONG
1952 | NGX_QUIC_PKT_INITIAL;
1953
1954 pkt.num_len = 1;
1955 /*
1956 * pkt.num = 0;
1957 * pkt.trunc = 0;
1958 */
1959
1960 pkt.version = inpkt->version;
1961 pkt.log = c->log;
1962 pkt.level = inpkt->level;
1963 pkt.dcid = inpkt->scid;
1964 pkt.scid = inpkt->dcid;
1965 pkt.payload.data = src;
1966 pkt.payload.len = len;
1967
1968 res.data = dst;
1969
1970 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
1971 return NGX_ERROR;
1972 }
1973
1974 if (ngx_quic_send(c, res.data, res.len) == NGX_ERROR) {
1975 return NGX_ERROR;
1976 }
1977
1978 return NGX_OK;
1979 }
1980
1981
1982 static void 1642 static void
1983 ngx_quic_discard_ctx(ngx_connection_t *c, enum ssl_encryption_level_t level) 1643 ngx_quic_discard_ctx(ngx_connection_t *c, enum ssl_encryption_level_t level)
1984 { 1644 {
1985 ngx_queue_t *q; 1645 ngx_queue_t *q;
1986 ngx_quic_frame_t *f; 1646 ngx_quic_frame_t *f;
2289 return NGX_OK; 1949 return NGX_OK;
2290 } 1950 }
2291 1951
2292 1952
2293 static ngx_int_t 1953 static ngx_int_t
2294 ngx_quic_ack_packet(ngx_connection_t *c, ngx_quic_header_t *pkt)
2295 {
2296 uint64_t base, largest, smallest, gs, ge, gap, range, pn;
2297 uint64_t prev_pending;
2298 ngx_uint_t i, nr;
2299 ngx_quic_send_ctx_t *ctx;
2300 ngx_quic_ack_range_t *r;
2301 ngx_quic_connection_t *qc;
2302
2303 c->log->action = "preparing ack";
2304
2305 qc = ngx_quic_get_connection(c);
2306
2307 ctx = ngx_quic_get_send_ctx(qc, pkt->level);
2308
2309 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
2310 "quic ngx_quic_ack_packet pn:%uL largest %L fr:%uL"
2311 " nranges:%ui", pkt->pn, (int64_t) ctx->largest_range,
2312 ctx->first_range, ctx->nranges);
2313
2314 prev_pending = ctx->pending_ack;
2315
2316 if (pkt->need_ack) {
2317
2318 ngx_post_event(&qc->push, &ngx_posted_events);
2319
2320 if (ctx->send_ack == 0) {
2321 ctx->ack_delay_start = ngx_current_msec;
2322 }
2323
2324 ctx->send_ack++;
2325
2326 if (ctx->pending_ack == NGX_QUIC_UNSET_PN
2327 || ctx->pending_ack < pkt->pn)
2328 {
2329 ctx->pending_ack = pkt->pn;
2330 }
2331 }
2332
2333 base = ctx->largest_range;
2334 pn = pkt->pn;
2335
2336 if (base == NGX_QUIC_UNSET_PN) {
2337 ctx->largest_range = pn;
2338 ctx->largest_received = pkt->received;
2339 return NGX_OK;
2340 }
2341
2342 if (base == pn) {
2343 return NGX_OK;
2344 }
2345
2346 largest = base;
2347 smallest = largest - ctx->first_range;
2348
2349 if (pn > base) {
2350
2351 if (pn - base == 1) {
2352 ctx->first_range++;
2353 ctx->largest_range = pn;
2354 ctx->largest_received = pkt->received;
2355
2356 return NGX_OK;
2357
2358 } else {
2359 /* new gap in front of current largest */
2360
2361 /* no place for new range, send current range as is */
2362 if (ctx->nranges == NGX_QUIC_MAX_RANGES) {
2363
2364 if (prev_pending != NGX_QUIC_UNSET_PN) {
2365 if (ngx_quic_send_ack(c, ctx) != NGX_OK) {
2366 return NGX_ERROR;
2367 }
2368 }
2369
2370 if (prev_pending == ctx->pending_ack || !pkt->need_ack) {
2371 ctx->pending_ack = NGX_QUIC_UNSET_PN;
2372 }
2373 }
2374
2375 gap = pn - base - 2;
2376 range = ctx->first_range;
2377
2378 ctx->first_range = 0;
2379 ctx->largest_range = pn;
2380 ctx->largest_received = pkt->received;
2381
2382 /* packet is out of order, force send */
2383 if (pkt->need_ack) {
2384 ctx->send_ack = NGX_QUIC_MAX_ACK_GAP;
2385 }
2386
2387 i = 0;
2388
2389 goto insert;
2390 }
2391 }
2392
2393 /* pn < base, perform lookup in existing ranges */
2394
2395 /* packet is out of order */
2396 if (pkt->need_ack) {
2397 ctx->send_ack = NGX_QUIC_MAX_ACK_GAP;
2398 }
2399
2400 if (pn >= smallest && pn <= largest) {
2401 return NGX_OK;
2402 }
2403
2404 #if (NGX_SUPPRESS_WARN)
2405 r = NULL;
2406 #endif
2407
2408 for (i = 0; i < ctx->nranges; i++) {
2409 r = &ctx->ranges[i];
2410
2411 ge = smallest - 1;
2412 gs = ge - r->gap;
2413
2414 if (pn >= gs && pn <= ge) {
2415
2416 if (gs == ge) {
2417 /* gap size is exactly one packet, now filled */
2418
2419 /* data moves to previous range, current is removed */
2420
2421 if (i == 0) {
2422 ctx->first_range += r->range + 2;
2423
2424 } else {
2425 ctx->ranges[i - 1].range += r->range + 2;
2426 }
2427
2428 nr = ctx->nranges - i - 1;
2429 if (nr) {
2430 ngx_memmove(&ctx->ranges[i], &ctx->ranges[i + 1],
2431 sizeof(ngx_quic_ack_range_t) * nr);
2432 }
2433
2434 ctx->nranges--;
2435
2436 } else if (pn == gs) {
2437 /* current gap shrinks from tail (current range grows) */
2438 r->gap--;
2439 r->range++;
2440
2441 } else if (pn == ge) {
2442 /* current gap shrinks from head (previous range grows) */
2443 r->gap--;
2444
2445 if (i == 0) {
2446 ctx->first_range++;
2447
2448 } else {
2449 ctx->ranges[i - 1].range++;
2450 }
2451
2452 } else {
2453 /* current gap is split into two parts */
2454
2455 gap = ge - pn - 1;
2456 range = 0;
2457
2458 if (ctx->nranges == NGX_QUIC_MAX_RANGES) {
2459 if (prev_pending != NGX_QUIC_UNSET_PN) {
2460 if (ngx_quic_send_ack(c, ctx) != NGX_OK) {
2461 return NGX_ERROR;
2462 }
2463 }
2464
2465 if (prev_pending == ctx->pending_ack || !pkt->need_ack) {
2466 ctx->pending_ack = NGX_QUIC_UNSET_PN;
2467 }
2468 }
2469
2470 r->gap = pn - gs - 1;
2471 goto insert;
2472 }
2473
2474 return NGX_OK;
2475 }
2476
2477 largest = smallest - r->gap - 2;
2478 smallest = largest - r->range;
2479
2480 if (pn >= smallest && pn <= largest) {
2481 /* this packet number is already known */
2482 return NGX_OK;
2483 }
2484
2485 }
2486
2487 if (pn == smallest - 1) {
2488 /* extend first or last range */
2489
2490 if (i == 0) {
2491 ctx->first_range++;
2492
2493 } else {
2494 r->range++;
2495 }
2496
2497 return NGX_OK;
2498 }
2499
2500 /* nothing found, add new range at the tail */
2501
2502 if (ctx->nranges == NGX_QUIC_MAX_RANGES) {
2503 /* packet is too old to keep it */
2504
2505 if (pkt->need_ack) {
2506 return ngx_quic_send_ack_range(c, ctx, pn, pn);
2507 }
2508
2509 return NGX_OK;
2510 }
2511
2512 gap = smallest - 2 - pn;
2513 range = 0;
2514
2515 insert:
2516
2517 if (ctx->nranges < NGX_QUIC_MAX_RANGES) {
2518 ctx->nranges++;
2519 }
2520
2521 ngx_memmove(&ctx->ranges[i + 1], &ctx->ranges[i],
2522 sizeof(ngx_quic_ack_range_t) * (ctx->nranges - i - 1));
2523
2524 ctx->ranges[i].gap = gap;
2525 ctx->ranges[i].range = range;
2526
2527 return NGX_OK;
2528 }
2529
2530
2531 static ngx_int_t
2532 ngx_quic_send_ack_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
2533 uint64_t smallest, uint64_t largest)
2534 {
2535 ngx_quic_frame_t *frame;
2536 ngx_quic_connection_t *qc;
2537
2538 qc = ngx_quic_get_connection(c);
2539
2540 frame = ngx_quic_alloc_frame(c);
2541 if (frame == NULL) {
2542 return NGX_ERROR;
2543 }
2544
2545 frame->level = ctx->level;
2546 frame->type = NGX_QUIC_FT_ACK;
2547 frame->u.ack.largest = largest;
2548 frame->u.ack.delay = 0;
2549 frame->u.ack.range_count = 0;
2550 frame->u.ack.first_range = largest - smallest;
2551
2552 ngx_quic_queue_frame(qc, frame);
2553
2554 return NGX_OK;
2555 }
2556
2557
2558 static void
2559 ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
2560 uint64_t pn)
2561 {
2562 uint64_t base;
2563 ngx_uint_t i, smallest, largest;
2564 ngx_quic_ack_range_t *r;
2565
2566 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
2567 "quic ngx_quic_drop_ack_ranges pn:%uL largest:%uL"
2568 " fr:%uL nranges:%ui", pn, ctx->largest_range,
2569 ctx->first_range, ctx->nranges);
2570
2571 base = ctx->largest_range;
2572
2573 if (base == NGX_QUIC_UNSET_PN) {
2574 return;
2575 }
2576
2577 if (ctx->pending_ack != NGX_QUIC_UNSET_PN && pn >= ctx->pending_ack) {
2578 ctx->pending_ack = NGX_QUIC_UNSET_PN;
2579 }
2580
2581 largest = base;
2582 smallest = largest - ctx->first_range;
2583
2584 if (pn >= largest) {
2585 ctx->largest_range = NGX_QUIC_UNSET_PN;
2586 ctx->first_range = 0;
2587 ctx->nranges = 0;
2588 return;
2589 }
2590
2591 if (pn >= smallest) {
2592 ctx->first_range = largest - pn - 1;
2593 ctx->nranges = 0;
2594 return;
2595 }
2596
2597 for (i = 0; i < ctx->nranges; i++) {
2598 r = &ctx->ranges[i];
2599
2600 largest = smallest - r->gap - 2;
2601 smallest = largest - r->range;
2602
2603 if (pn >= largest) {
2604 ctx->nranges = i;
2605 return;
2606 }
2607 if (pn >= smallest) {
2608 r->range = largest - pn - 1;
2609 ctx->nranges = i + 1;
2610 return;
2611 }
2612 }
2613 }
2614
2615
2616 static ngx_int_t
2617 ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
2618 {
2619 size_t len, left;
2620 uint64_t ack_delay;
2621 ngx_buf_t *b;
2622 ngx_uint_t i;
2623 ngx_chain_t *cl, **ll;
2624 ngx_quic_frame_t *frame;
2625 ngx_quic_connection_t *qc;
2626
2627 qc = ngx_quic_get_connection(c);
2628
2629 ack_delay = ngx_current_msec - ctx->largest_received;
2630 ack_delay *= 1000;
2631 ack_delay >>= qc->tp.ack_delay_exponent;
2632
2633 frame = ngx_quic_alloc_frame(c);
2634 if (frame == NULL) {
2635 return NGX_ERROR;
2636 }
2637
2638 ll = &frame->data;
2639 b = NULL;
2640
2641 for (i = 0; i < ctx->nranges; i++) {
2642 len = ngx_quic_create_ack_range(NULL, ctx->ranges[i].gap,
2643 ctx->ranges[i].range);
2644
2645 left = b ? b->end - b->last : 0;
2646
2647 if (left < len) {
2648 cl = ngx_quic_alloc_buf(c);
2649 if (cl == NULL) {
2650 return NGX_ERROR;
2651 }
2652
2653 *ll = cl;
2654 ll = &cl->next;
2655
2656 b = cl->buf;
2657 left = b->end - b->last;
2658
2659 if (left < len) {
2660 return NGX_ERROR;
2661 }
2662 }
2663
2664 b->last += ngx_quic_create_ack_range(b->last, ctx->ranges[i].gap,
2665 ctx->ranges[i].range);
2666
2667 frame->u.ack.ranges_length += len;
2668 }
2669
2670 *ll = NULL;
2671
2672 frame->level = ctx->level;
2673 frame->type = NGX_QUIC_FT_ACK;
2674 frame->u.ack.largest = ctx->largest_range;
2675 frame->u.ack.delay = ack_delay;
2676 frame->u.ack.range_count = ctx->nranges;
2677 frame->u.ack.first_range = ctx->first_range;
2678
2679 ngx_quic_queue_frame(qc, frame);
2680
2681 return NGX_OK;
2682 }
2683
2684
2685 static ngx_int_t
2686 ngx_quic_send_cc(ngx_connection_t *c)
2687 {
2688 ngx_quic_frame_t *frame;
2689 ngx_quic_connection_t *qc;
2690
2691 qc = ngx_quic_get_connection(c);
2692
2693 if (qc->draining) {
2694 return NGX_OK;
2695 }
2696
2697 if (qc->closing
2698 && ngx_current_msec - qc->last_cc < NGX_QUIC_CC_MIN_INTERVAL)
2699 {
2700 /* dot not send CC too often */
2701 return NGX_OK;
2702 }
2703
2704 frame = ngx_quic_alloc_frame(c);
2705 if (frame == NULL) {
2706 return NGX_ERROR;
2707 }
2708
2709 frame->level = qc->error_level;
2710 frame->type = qc->error_app ? NGX_QUIC_FT_CONNECTION_CLOSE_APP
2711 : NGX_QUIC_FT_CONNECTION_CLOSE;
2712 frame->u.close.error_code = qc->error;
2713 frame->u.close.frame_type = qc->error_ftype;
2714
2715 if (qc->error_reason) {
2716 frame->u.close.reason.len = ngx_strlen(qc->error_reason);
2717 frame->u.close.reason.data = (u_char *) qc->error_reason;
2718 }
2719
2720 ngx_quic_queue_frame(qc, frame);
2721
2722 qc->last_cc = ngx_current_msec;
2723
2724 return ngx_quic_output(c);
2725 }
2726
2727
2728 static ngx_int_t
2729 ngx_quic_send_new_token(ngx_connection_t *c)
2730 {
2731 time_t expires;
2732 ngx_str_t token;
2733 ngx_quic_frame_t *frame;
2734 ngx_quic_connection_t *qc;
2735
2736 qc = ngx_quic_get_connection(c);
2737
2738 if (!qc->conf->retry) {
2739 return NGX_OK;
2740 }
2741
2742 expires = ngx_time() + NGX_QUIC_NEW_TOKEN_LIFETIME;
2743
2744 if (ngx_quic_new_token(c, qc->conf->av_token_key, &token, NULL, expires, 0)
2745 != NGX_OK)
2746 {
2747 return NGX_ERROR;
2748 }
2749
2750 frame = ngx_quic_alloc_frame(c);
2751 if (frame == NULL) {
2752 return NGX_ERROR;
2753 }
2754
2755 frame->level = ssl_encryption_application;
2756 frame->type = NGX_QUIC_FT_NEW_TOKEN;
2757 frame->u.token.length = token.len;
2758 frame->u.token.data = token.data;
2759
2760 ngx_quic_queue_frame(qc, frame);
2761
2762 return NGX_OK;
2763 }
2764
2765
2766 static ngx_int_t
2767 ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
2768 ngx_quic_frame_t *f)
2769 {
2770 ssize_t n;
2771 u_char *pos, *end;
2772 uint64_t min, max, gap, range;
2773 ngx_msec_t send_time;
2774 ngx_uint_t i;
2775 ngx_quic_send_ctx_t *ctx;
2776 ngx_quic_ack_frame_t *ack;
2777 ngx_quic_connection_t *qc;
2778
2779 qc = ngx_quic_get_connection(c);
2780
2781 ctx = ngx_quic_get_send_ctx(qc, pkt->level);
2782
2783 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
2784 "quic ngx_quic_handle_ack_frame level:%d", pkt->level);
2785
2786 ack = &f->u.ack;
2787
2788 /*
2789 * If any computed packet number is negative, an endpoint MUST
2790 * generate a connection error of type FRAME_ENCODING_ERROR.
2791 * (19.3.1)
2792 */
2793
2794 if (ack->first_range > ack->largest) {
2795 qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
2796 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2797 "quic invalid first range in ack frame");
2798 return NGX_ERROR;
2799 }
2800
2801 min = ack->largest - ack->first_range;
2802 max = ack->largest;
2803
2804 if (ngx_quic_handle_ack_frame_range(c, ctx, min, max, &send_time)
2805 != NGX_OK)
2806 {
2807 return NGX_ERROR;
2808 }
2809
2810 /* 13.2.3. Receiver Tracking of ACK Frames */
2811 if (ctx->largest_ack < max || ctx->largest_ack == NGX_QUIC_UNSET_PN) {
2812 ctx->largest_ack = max;
2813 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
2814 "quic updated largest received ack:%uL", max);
2815
2816 /*
2817 * An endpoint generates an RTT sample on receiving an
2818 * ACK frame that meets the following two conditions:
2819 *
2820 * - the largest acknowledged packet number is newly acknowledged
2821 * - at least one of the newly acknowledged packets was ack-eliciting.
2822 */
2823
2824 if (send_time != NGX_TIMER_INFINITE) {
2825 ngx_quic_rtt_sample(c, ack, pkt->level, send_time);
2826 }
2827 }
2828
2829 if (f->data) {
2830 pos = f->data->buf->pos;
2831 end = f->data->buf->last;
2832
2833 } else {
2834 pos = NULL;
2835 end = NULL;
2836 }
2837
2838 for (i = 0; i < ack->range_count; i++) {
2839
2840 n = ngx_quic_parse_ack_range(pkt->log, pos, end, &gap, &range);
2841 if (n == NGX_ERROR) {
2842 return NGX_ERROR;
2843 }
2844 pos += n;
2845
2846 if (gap + 2 > min) {
2847 qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
2848 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2849 "quic invalid range:%ui in ack frame", i);
2850 return NGX_ERROR;
2851 }
2852
2853 max = min - gap - 2;
2854
2855 if (range > max) {
2856 qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
2857 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2858 "quic invalid range:%ui in ack frame", i);
2859 return NGX_ERROR;
2860 }
2861
2862 min = max - range;
2863
2864 if (ngx_quic_handle_ack_frame_range(c, ctx, min, max, &send_time)
2865 != NGX_OK)
2866 {
2867 return NGX_ERROR;
2868 }
2869 }
2870
2871 return ngx_quic_detect_lost(c);
2872 }
2873
2874
2875 static ngx_int_t
2876 ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
2877 uint64_t min, uint64_t max, ngx_msec_t *send_time)
2878 {
2879 ngx_uint_t found;
2880 ngx_queue_t *q;
2881 ngx_quic_frame_t *f;
2882 ngx_quic_connection_t *qc;
2883
2884 qc = ngx_quic_get_connection(c);
2885
2886 *send_time = NGX_TIMER_INFINITE;
2887 found = 0;
2888
2889 q = ngx_queue_last(&ctx->sent);
2890
2891 while (q != ngx_queue_sentinel(&ctx->sent)) {
2892
2893 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
2894 q = ngx_queue_prev(q);
2895
2896 if (f->pnum >= min && f->pnum <= max) {
2897 ngx_quic_congestion_ack(c, f);
2898
2899 switch (f->type) {
2900 case NGX_QUIC_FT_ACK:
2901 case NGX_QUIC_FT_ACK_ECN:
2902 ngx_quic_drop_ack_ranges(c, ctx, f->u.ack.largest);
2903 break;
2904
2905 case NGX_QUIC_FT_STREAM0:
2906 case NGX_QUIC_FT_STREAM1:
2907 case NGX_QUIC_FT_STREAM2:
2908 case NGX_QUIC_FT_STREAM3:
2909 case NGX_QUIC_FT_STREAM4:
2910 case NGX_QUIC_FT_STREAM5:
2911 case NGX_QUIC_FT_STREAM6:
2912 case NGX_QUIC_FT_STREAM7:
2913 ngx_quic_handle_stream_ack(c, f);
2914 break;
2915 }
2916
2917 if (f->pnum == max) {
2918 *send_time = f->last;
2919 }
2920
2921 ngx_queue_remove(&f->queue);
2922 ngx_quic_free_frame(c, f);
2923 found = 1;
2924 }
2925 }
2926
2927 if (!found) {
2928
2929 if (max < ctx->pnum) {
2930 /* duplicate ACK or ACK for non-ack-eliciting frame */
2931 return NGX_OK;
2932 }
2933
2934 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2935 "quic ACK for the packet not sent");
2936
2937 qc->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
2938 qc->error_ftype = NGX_QUIC_FT_ACK;
2939 qc->error_reason = "unknown packet number";
2940
2941 return NGX_ERROR;
2942 }
2943
2944 if (!qc->push.timer_set) {
2945 ngx_post_event(&qc->push, &ngx_posted_events);
2946 }
2947
2948 qc->pto_count = 0;
2949
2950 return NGX_OK;
2951 }
2952
2953
2954 static void
2955 ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack,
2956 enum ssl_encryption_level_t level, ngx_msec_t send_time)
2957 {
2958 ngx_msec_t latest_rtt, ack_delay, adjusted_rtt, rttvar_sample;
2959 ngx_quic_connection_t *qc;
2960
2961 qc = ngx_quic_get_connection(c);
2962
2963 latest_rtt = ngx_current_msec - send_time;
2964 qc->latest_rtt = latest_rtt;
2965
2966 if (qc->min_rtt == NGX_TIMER_INFINITE) {
2967 qc->min_rtt = latest_rtt;
2968 qc->avg_rtt = latest_rtt;
2969 qc->rttvar = latest_rtt / 2;
2970
2971 } else {
2972 qc->min_rtt = ngx_min(qc->min_rtt, latest_rtt);
2973
2974 ack_delay = ack->delay * (1 << qc->ctp.ack_delay_exponent) / 1000;
2975
2976 if (c->ssl->handshaked) {
2977 ack_delay = ngx_min(ack_delay, qc->ctp.max_ack_delay);
2978 }
2979
2980 adjusted_rtt = latest_rtt;
2981
2982 if (qc->min_rtt + ack_delay < latest_rtt) {
2983 adjusted_rtt -= ack_delay;
2984 }
2985
2986 qc->avg_rtt = 0.875 * qc->avg_rtt + 0.125 * adjusted_rtt;
2987 rttvar_sample = ngx_abs((ngx_msec_int_t) (qc->avg_rtt - adjusted_rtt));
2988 qc->rttvar = 0.75 * qc->rttvar + 0.25 * rttvar_sample;
2989 }
2990
2991 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
2992 "quic rtt sample latest:%M min:%M avg:%M var:%M",
2993 latest_rtt, qc->min_rtt, qc->avg_rtt, qc->rttvar);
2994 }
2995
2996
2997 ngx_msec_t
2998 ngx_quic_pto(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
2999 {
3000 ngx_msec_t duration;
3001 ngx_quic_connection_t *qc;
3002
3003 qc = ngx_quic_get_connection(c);
3004
3005 /* PTO calculation: quic-recovery, Appendix 8 */
3006 duration = qc->avg_rtt;
3007
3008 duration += ngx_max(4 * qc->rttvar, NGX_QUIC_TIME_GRANULARITY);
3009 duration <<= qc->pto_count;
3010
3011 if (qc->congestion.in_flight == 0) { /* no in-flight packets */
3012 return duration;
3013 }
3014
3015 if (ctx->level == ssl_encryption_application && c->ssl->handshaked) {
3016 duration += qc->ctp.max_ack_delay << qc->pto_count;
3017 }
3018
3019 return duration;
3020 }
3021
3022
3023 static ngx_int_t
3024 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, 1954 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
3025 ngx_quic_frame_t *frame) 1955 ngx_quic_frame_t *frame)
3026 { 1956 {
3027 uint64_t last; 1957 uint64_t last;
3028 ngx_int_t rc; 1958 ngx_int_t rc;
3168 2098
3169 return NGX_OK; 2099 return NGX_OK;
3170 } 2100 }
3171 2101
3172 2102
3173 ngx_int_t
3174 ngx_quic_output(ngx_connection_t *c)
3175 {
3176 off_t max;
3177 size_t len, min, in_flight;
3178 ssize_t n;
3179 u_char *p;
3180 ngx_uint_t i, pad;
3181 ngx_quic_send_ctx_t *ctx;
3182 ngx_quic_congestion_t *cg;
3183 ngx_quic_connection_t *qc;
3184 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
3185
3186 c->log->action = "sending frames";
3187
3188 qc = ngx_quic_get_connection(c);
3189 cg = &qc->congestion;
3190
3191 in_flight = cg->in_flight;
3192
3193 for ( ;; ) {
3194 p = dst;
3195
3196 len = ngx_min(qc->ctp.max_udp_payload_size,
3197 NGX_QUIC_MAX_UDP_PAYLOAD_SIZE);
3198
3199 if (!qc->validated) {
3200 max = qc->received * 3;
3201 max = (c->sent >= max) ? 0 : max - c->sent;
3202 len = ngx_min(len, (size_t) max);
3203 }
3204
3205 pad = ngx_quic_get_padding_level(c);
3206
3207 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
3208
3209 ctx = &qc->send_ctx[i];
3210
3211 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) {
3212 return NGX_ERROR;
3213 }
3214
3215 min = (i == pad && p - dst < NGX_QUIC_MIN_INITIAL_SIZE)
3216 ? NGX_QUIC_MIN_INITIAL_SIZE - (p - dst) : 0;
3217
3218 n = ngx_quic_output_packet(c, ctx, p, len, min);
3219 if (n == NGX_ERROR) {
3220 return NGX_ERROR;
3221 }
3222
3223 p += n;
3224 len -= n;
3225 }
3226
3227 len = p - dst;
3228 if (len == 0) {
3229 break;
3230 }
3231
3232 n = ngx_quic_send(c, dst, len);
3233 if (n == NGX_ERROR) {
3234 return NGX_ERROR;
3235 }
3236 }
3237
3238 if (in_flight != cg->in_flight && !qc->send_timer_set && !qc->closing) {
3239 qc->send_timer_set = 1;
3240 ngx_add_timer(c->read, qc->tp.max_idle_timeout);
3241 }
3242
3243 ngx_quic_set_lost_timer(c);
3244
3245 return NGX_OK;
3246 }
3247
3248
3249 static ngx_uint_t
3250 ngx_quic_get_padding_level(ngx_connection_t *c)
3251 {
3252 ngx_queue_t *q;
3253 ngx_quic_frame_t *f;
3254 ngx_quic_send_ctx_t *ctx;
3255 ngx_quic_connection_t *qc;
3256
3257 /*
3258 * 14.1. Initial Datagram Size
3259 *
3260 * Similarly, a server MUST expand the payload of all UDP datagrams
3261 * carrying ack-eliciting Initial packets to at least the smallest
3262 * allowed maximum datagram size of 1200 bytes
3263 */
3264
3265 qc = ngx_quic_get_connection(c);
3266 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial);
3267
3268 for (q = ngx_queue_head(&ctx->frames);
3269 q != ngx_queue_sentinel(&ctx->frames);
3270 q = ngx_queue_next(q))
3271 {
3272 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3273
3274 if (f->need_ack) {
3275 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake);
3276
3277 if (ngx_queue_empty(&ctx->frames)) {
3278 return 0;
3279 }
3280
3281 return 1;
3282 }
3283 }
3284
3285 return NGX_QUIC_SEND_CTX_LAST;
3286 }
3287
3288
3289 static ngx_int_t
3290 ngx_quic_generate_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
3291 {
3292 ngx_msec_t delay;
3293 ngx_quic_connection_t *qc;
3294
3295 if (!ctx->send_ack) {
3296 return NGX_OK;
3297 }
3298
3299 if (ctx->level == ssl_encryption_application) {
3300
3301 delay = ngx_current_msec - ctx->ack_delay_start;
3302 qc = ngx_quic_get_connection(c);
3303
3304 if (ctx->send_ack < NGX_QUIC_MAX_ACK_GAP
3305 && delay < qc->tp.max_ack_delay)
3306 {
3307 if (!qc->push.timer_set && !qc->closing) {
3308 ngx_add_timer(&qc->push,
3309 qc->tp.max_ack_delay - delay);
3310 }
3311
3312 return NGX_OK;
3313 }
3314 }
3315
3316 if (ngx_quic_send_ack(c, ctx) != NGX_OK) {
3317 return NGX_ERROR;
3318 }
3319
3320 ctx->send_ack = 0;
3321
3322 return NGX_OK;
3323 }
3324
3325
3326 static ssize_t
3327 ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
3328 u_char *data, size_t max, size_t min)
3329 {
3330 size_t len, hlen, pad_len;
3331 u_char *p;
3332 ssize_t flen;
3333 ngx_str_t out, res;
3334 ngx_int_t rc;
3335 ngx_uint_t nframes;
3336 ngx_msec_t now;
3337 ngx_queue_t *q;
3338 ngx_quic_frame_t *f;
3339 ngx_quic_header_t pkt;
3340 ngx_quic_congestion_t *cg;
3341 ngx_quic_connection_t *qc;
3342 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
3343
3344 if (ngx_queue_empty(&ctx->frames)) {
3345 return 0;
3346 }
3347
3348 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
3349 "quic output %s packet max:%uz min:%uz",
3350 ngx_quic_level_name(ctx->level), max, min);
3351
3352 qc = ngx_quic_get_connection(c);
3353 cg = &qc->congestion;
3354
3355 hlen = (ctx->level == ssl_encryption_application)
3356 ? NGX_QUIC_MAX_SHORT_HEADER
3357 : NGX_QUIC_MAX_LONG_HEADER;
3358
3359 hlen += EVP_GCM_TLS_TAG_LEN;
3360 hlen -= NGX_QUIC_MAX_CID_LEN - qc->scid.len;
3361
3362 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
3363
3364 now = ngx_current_msec;
3365 nframes = 0;
3366 p = src;
3367 len = 0;
3368
3369 for (q = ngx_queue_head(&ctx->frames);
3370 q != ngx_queue_sentinel(&ctx->frames);
3371 q = ngx_queue_next(q))
3372 {
3373 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3374
3375 if (!pkt.need_ack && f->need_ack && max > cg->window) {
3376 max = cg->window;
3377 }
3378
3379 if (hlen + len >= max) {
3380 break;
3381 }
3382
3383 if (hlen + len + f->len > max) {
3384 rc = ngx_quic_split_frame(c, f, max - hlen - len);
3385
3386 if (rc == NGX_ERROR) {
3387 return NGX_ERROR;
3388 }
3389
3390 if (rc == NGX_DECLINED) {
3391 break;
3392 }
3393 }
3394
3395 if (f->need_ack) {
3396 pkt.need_ack = 1;
3397 }
3398
3399 ngx_quic_log_frame(c->log, f, 1);
3400
3401 flen = ngx_quic_create_frame(p, f);
3402 if (flen == -1) {
3403 return NGX_ERROR;
3404 }
3405
3406 len += flen;
3407 p += flen;
3408
3409 f->pnum = ctx->pnum;
3410 f->first = now;
3411 f->last = now;
3412 f->plen = 0;
3413
3414 nframes++;
3415
3416 if (f->flush) {
3417 break;
3418 }
3419 }
3420
3421 if (nframes == 0) {
3422 return 0;
3423 }
3424
3425 out.data = src;
3426 out.len = len;
3427
3428 pkt.keys = qc->keys;
3429 pkt.flags = NGX_QUIC_PKT_FIXED_BIT;
3430
3431 if (ctx->level == ssl_encryption_initial) {
3432 pkt.flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_INITIAL;
3433
3434 } else if (ctx->level == ssl_encryption_handshake) {
3435 pkt.flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_HANDSHAKE;
3436
3437 } else {
3438 if (qc->key_phase) {
3439 pkt.flags |= NGX_QUIC_PKT_KPHASE;
3440 }
3441 }
3442
3443 ngx_quic_set_packet_number(&pkt, ctx);
3444
3445 pkt.version = qc->version;
3446 pkt.log = c->log;
3447 pkt.level = ctx->level;
3448 pkt.dcid = qc->scid;
3449 pkt.scid = qc->dcid;
3450
3451 pad_len = 4;
3452
3453 if (min) {
3454 hlen = EVP_GCM_TLS_TAG_LEN
3455 + ngx_quic_create_header(&pkt, NULL, out.len, NULL);
3456
3457 if (min > hlen + pad_len) {
3458 pad_len = min - hlen;
3459 }
3460 }
3461
3462 if (out.len < pad_len) {
3463 ngx_memset(p, NGX_QUIC_FT_PADDING, pad_len - out.len);
3464 out.len = pad_len;
3465 }
3466
3467 pkt.payload = out;
3468
3469 res.data = data;
3470
3471 ngx_log_debug6(NGX_LOG_DEBUG_EVENT, c->log, 0,
3472 "quic packet tx %s bytes:%ui"
3473 " need_ack:%d number:%L encoded nl:%d trunc:0x%xD",
3474 ngx_quic_level_name(ctx->level), out.len, pkt.need_ack,
3475 pkt.number, pkt.num_len, pkt.trunc);
3476
3477 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
3478 return NGX_ERROR;
3479 }
3480
3481 ctx->pnum++;
3482
3483 if (pkt.need_ack) {
3484 /* move frames into the sent queue to wait for ack */
3485
3486 if (!qc->closing) {
3487 q = ngx_queue_head(&ctx->frames);
3488 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3489 f->plen = res.len;
3490
3491 do {
3492 q = ngx_queue_head(&ctx->frames);
3493 ngx_queue_remove(q);
3494 ngx_queue_insert_tail(&ctx->sent, q);
3495 } while (--nframes);
3496 }
3497
3498 cg->in_flight += res.len;
3499
3500 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3501 "quic congestion send if:%uz", cg->in_flight);
3502 }
3503
3504 while (nframes--) {
3505 q = ngx_queue_head(&ctx->frames);
3506 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3507
3508 ngx_queue_remove(q);
3509 ngx_quic_free_frame(c, f);
3510 }
3511
3512 return res.len;
3513 }
3514
3515
3516 static ssize_t
3517 ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len)
3518 {
3519 ngx_buf_t b;
3520 ngx_chain_t cl, *res;
3521
3522 ngx_memzero(&b, sizeof(ngx_buf_t));
3523
3524 b.pos = b.start = buf;
3525 b.last = b.end = buf + len;
3526 b.last_buf = 1;
3527 b.temporary = 1;
3528
3529 cl.buf = &b;
3530 cl.next= NULL;
3531
3532 res = c->send_chain(c, &cl, 0);
3533 if (res == NGX_CHAIN_ERROR) {
3534 return NGX_ERROR;
3535 }
3536
3537 return len;
3538 }
3539
3540
3541 static void
3542 ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_send_ctx_t *ctx)
3543 {
3544 uint64_t delta;
3545
3546 delta = ctx->pnum - ctx->largest_ack;
3547 pkt->number = ctx->pnum;
3548
3549 if (delta <= 0x7F) {
3550 pkt->num_len = 1;
3551 pkt->trunc = ctx->pnum & 0xff;
3552
3553 } else if (delta <= 0x7FFF) {
3554 pkt->num_len = 2;
3555 pkt->flags |= 0x1;
3556 pkt->trunc = ctx->pnum & 0xffff;
3557
3558 } else if (delta <= 0x7FFFFF) {
3559 pkt->num_len = 3;
3560 pkt->flags |= 0x2;
3561 pkt->trunc = ctx->pnum & 0xffffff;
3562
3563 } else {
3564 pkt->num_len = 4;
3565 pkt->flags |= 0x3;
3566 pkt->trunc = ctx->pnum & 0xffffffff;
3567 }
3568 }
3569
3570
3571 static void
3572 ngx_quic_pto_handler(ngx_event_t *ev)
3573 {
3574 ngx_uint_t i;
3575 ngx_msec_t now;
3576 ngx_queue_t *q, *next;
3577 ngx_connection_t *c;
3578 ngx_quic_frame_t *f;
3579 ngx_quic_send_ctx_t *ctx;
3580 ngx_quic_connection_t *qc;
3581
3582 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "quic pto timer");
3583
3584 c = ev->data;
3585 qc = ngx_quic_get_connection(c);
3586 now = ngx_current_msec;
3587
3588 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
3589
3590 ctx = &qc->send_ctx[i];
3591
3592 if (ngx_queue_empty(&ctx->sent)) {
3593 continue;
3594 }
3595
3596 q = ngx_queue_head(&ctx->sent);
3597 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3598
3599 if (f->pnum <= ctx->largest_ack
3600 && ctx->largest_ack != NGX_QUIC_UNSET_PN)
3601 {
3602 continue;
3603 }
3604
3605 if ((ngx_msec_int_t) (f->last + ngx_quic_pto(c, ctx) - now) > 0) {
3606 continue;
3607 }
3608
3609 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
3610 "quic pto %s pto_count:%ui",
3611 ngx_quic_level_name(ctx->level), qc->pto_count);
3612
3613 for (q = ngx_queue_head(&ctx->frames);
3614 q != ngx_queue_sentinel(&ctx->frames);
3615 /* void */)
3616 {
3617 next = ngx_queue_next(q);
3618 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3619
3620 if (f->type == NGX_QUIC_FT_PING) {
3621 ngx_queue_remove(q);
3622 ngx_quic_free_frame(c, f);
3623 }
3624
3625 q = next;
3626 }
3627
3628 for (q = ngx_queue_head(&ctx->sent);
3629 q != ngx_queue_sentinel(&ctx->sent);
3630 /* void */)
3631 {
3632 next = ngx_queue_next(q);
3633 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3634
3635 if (f->type == NGX_QUIC_FT_PING) {
3636 ngx_quic_congestion_lost(c, f);
3637 ngx_queue_remove(q);
3638 ngx_quic_free_frame(c, f);
3639 }
3640
3641 q = next;
3642 }
3643
3644 /* enforce 2 udp datagrams */
3645
3646 f = ngx_quic_alloc_frame(c);
3647 if (f == NULL) {
3648 break;
3649 }
3650
3651 f->level = ctx->level;
3652 f->type = NGX_QUIC_FT_PING;
3653 f->flush = 1;
3654
3655 ngx_quic_queue_frame(qc, f);
3656
3657 f = ngx_quic_alloc_frame(c);
3658 if (f == NULL) {
3659 break;
3660 }
3661
3662 f->level = ctx->level;
3663 f->type = NGX_QUIC_FT_PING;
3664
3665 ngx_quic_queue_frame(qc, f);
3666 }
3667
3668 qc->pto_count++;
3669
3670 ngx_quic_connstate_dbg(c);
3671 }
3672
3673
3674 static void 2103 static void
3675 ngx_quic_push_handler(ngx_event_t *ev) 2104 ngx_quic_push_handler(ngx_event_t *ev)
3676 { 2105 {
3677 ngx_connection_t *c; 2106 ngx_connection_t *c;
3678 2107
3684 ngx_quic_close_connection(c, NGX_ERROR); 2113 ngx_quic_close_connection(c, NGX_ERROR);
3685 return; 2114 return;
3686 } 2115 }
3687 2116
3688 ngx_quic_connstate_dbg(c); 2117 ngx_quic_connstate_dbg(c);
3689 }
3690
3691
3692 static
3693 void ngx_quic_lost_handler(ngx_event_t *ev)
3694 {
3695 ngx_connection_t *c;
3696
3697 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "quic lost timer");
3698
3699 c = ev->data;
3700
3701 if (ngx_quic_detect_lost(c) != NGX_OK) {
3702 ngx_quic_close_connection(c, NGX_ERROR);
3703 }
3704
3705 ngx_quic_connstate_dbg(c);
3706 }
3707
3708
3709 static ngx_int_t
3710 ngx_quic_detect_lost(ngx_connection_t *c)
3711 {
3712 ngx_uint_t i;
3713 ngx_msec_t now, wait, thr;
3714 ngx_queue_t *q;
3715 ngx_quic_frame_t *start;
3716 ngx_quic_send_ctx_t *ctx;
3717 ngx_quic_connection_t *qc;
3718
3719 qc = ngx_quic_get_connection(c);
3720 now = ngx_current_msec;
3721 thr = ngx_quic_lost_threshold(qc);
3722
3723 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
3724
3725 ctx = &qc->send_ctx[i];
3726
3727 if (ctx->largest_ack == NGX_QUIC_UNSET_PN) {
3728 continue;
3729 }
3730
3731 while (!ngx_queue_empty(&ctx->sent)) {
3732
3733 q = ngx_queue_head(&ctx->sent);
3734 start = ngx_queue_data(q, ngx_quic_frame_t, queue);
3735
3736 if (start->pnum > ctx->largest_ack) {
3737 break;
3738 }
3739
3740 wait = start->last + thr - now;
3741
3742 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
3743 "quic detect_lost pnum:%uL thr:%M wait:%i level:%d",
3744 start->pnum, thr, (ngx_int_t) wait, start->level);
3745
3746 if ((ngx_msec_int_t) wait > 0
3747 && ctx->largest_ack - start->pnum < NGX_QUIC_PKT_THR)
3748 {
3749 break;
3750 }
3751
3752 ngx_quic_resend_frames(c, ctx);
3753 }
3754 }
3755
3756 ngx_quic_set_lost_timer(c);
3757
3758 return NGX_OK;
3759 }
3760
3761
3762 static void
3763 ngx_quic_set_lost_timer(ngx_connection_t *c)
3764 {
3765 ngx_uint_t i;
3766 ngx_msec_t now;
3767 ngx_queue_t *q;
3768 ngx_msec_int_t lost, pto, w;
3769 ngx_quic_frame_t *f;
3770 ngx_quic_send_ctx_t *ctx;
3771 ngx_quic_connection_t *qc;
3772
3773 qc = ngx_quic_get_connection(c);
3774 now = ngx_current_msec;
3775
3776 lost = -1;
3777 pto = -1;
3778
3779 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
3780 ctx = &qc->send_ctx[i];
3781
3782 if (ngx_queue_empty(&ctx->sent)) {
3783 continue;
3784 }
3785
3786 if (ctx->largest_ack != NGX_QUIC_UNSET_PN) {
3787 q = ngx_queue_head(&ctx->sent);
3788 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3789 w = (ngx_msec_int_t) (f->last + ngx_quic_lost_threshold(qc) - now);
3790
3791 if (f->pnum <= ctx->largest_ack) {
3792 if (w < 0 || ctx->largest_ack - f->pnum >= NGX_QUIC_PKT_THR) {
3793 w = 0;
3794 }
3795
3796 if (lost == -1 || w < lost) {
3797 lost = w;
3798 }
3799 }
3800 }
3801
3802 q = ngx_queue_last(&ctx->sent);
3803 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3804 w = (ngx_msec_int_t) (f->last + ngx_quic_pto(c, ctx) - now);
3805
3806 if (w < 0) {
3807 w = 0;
3808 }
3809
3810 if (pto == -1 || w < pto) {
3811 pto = w;
3812 }
3813 }
3814
3815 if (qc->pto.timer_set) {
3816 ngx_del_timer(&qc->pto);
3817 }
3818
3819 if (lost != -1) {
3820 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3821 "quic lost timer lost:%M", lost);
3822
3823 qc->pto.handler = ngx_quic_lost_handler;
3824 ngx_add_timer(&qc->pto, lost);
3825 return;
3826 }
3827
3828 if (pto != -1) {
3829 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3830 "quic lost timer pto:%M", pto);
3831
3832 qc->pto.handler = ngx_quic_pto_handler;
3833 ngx_add_timer(&qc->pto, pto);
3834 return;
3835 }
3836
3837 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic lost timer unset");
3838 }
3839
3840
3841 static void
3842 ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
3843 {
3844 size_t n;
3845 ngx_buf_t *b;
3846 ngx_queue_t *q;
3847 ngx_quic_frame_t *f, *start;
3848 ngx_quic_stream_t *sn;
3849 ngx_quic_connection_t *qc;
3850
3851 qc = ngx_quic_get_connection(c);
3852 q = ngx_queue_head(&ctx->sent);
3853 start = ngx_queue_data(q, ngx_quic_frame_t, queue);
3854
3855 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3856 "quic resend packet pnum:%uL", start->pnum);
3857
3858 ngx_quic_congestion_lost(c, start);
3859
3860 do {
3861 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3862
3863 if (f->pnum != start->pnum) {
3864 break;
3865 }
3866
3867 q = ngx_queue_next(q);
3868
3869 ngx_queue_remove(&f->queue);
3870
3871 switch (f->type) {
3872 case NGX_QUIC_FT_ACK:
3873 case NGX_QUIC_FT_ACK_ECN:
3874 if (ctx->level == ssl_encryption_application) {
3875 /* force generation of most recent acknowledgment */
3876 ctx->send_ack = NGX_QUIC_MAX_ACK_GAP;
3877 }
3878
3879 ngx_quic_free_frame(c, f);
3880 break;
3881
3882 case NGX_QUIC_FT_PING:
3883 case NGX_QUIC_FT_PATH_RESPONSE:
3884 case NGX_QUIC_FT_CONNECTION_CLOSE:
3885 ngx_quic_free_frame(c, f);
3886 break;
3887
3888 case NGX_QUIC_FT_MAX_DATA:
3889 f->u.max_data.max_data = qc->streams.recv_max_data;
3890 ngx_quic_queue_frame(qc, f);
3891 break;
3892
3893 case NGX_QUIC_FT_MAX_STREAMS:
3894 case NGX_QUIC_FT_MAX_STREAMS2:
3895 f->u.max_streams.limit = f->u.max_streams.bidi
3896 ? qc->streams.client_max_streams_bidi
3897 : qc->streams.client_max_streams_uni;
3898 ngx_quic_queue_frame(qc, f);
3899 break;
3900
3901 case NGX_QUIC_FT_MAX_STREAM_DATA:
3902 sn = ngx_quic_find_stream(&qc->streams.tree,
3903 f->u.max_stream_data.id);
3904 if (sn == NULL) {
3905 ngx_quic_free_frame(c, f);
3906 break;
3907 }
3908
3909 b = sn->b;
3910 n = sn->fs.received + (b->pos - b->start) + (b->end - b->last);
3911
3912 if (f->u.max_stream_data.limit < n) {
3913 f->u.max_stream_data.limit = n;
3914 }
3915
3916 ngx_quic_queue_frame(qc, f);
3917 break;
3918
3919 case NGX_QUIC_FT_STREAM0:
3920 case NGX_QUIC_FT_STREAM1:
3921 case NGX_QUIC_FT_STREAM2:
3922 case NGX_QUIC_FT_STREAM3:
3923 case NGX_QUIC_FT_STREAM4:
3924 case NGX_QUIC_FT_STREAM5:
3925 case NGX_QUIC_FT_STREAM6:
3926 case NGX_QUIC_FT_STREAM7:
3927 sn = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id);
3928
3929 if (sn && sn->c->write->error) {
3930 /* RESET_STREAM was sent */
3931 ngx_quic_free_frame(c, f);
3932 break;
3933 }
3934
3935 /* fall through */
3936
3937 default:
3938 ngx_queue_insert_tail(&ctx->frames, &f->queue);
3939 }
3940
3941 } while (q != ngx_queue_sentinel(&ctx->sent));
3942
3943 if (qc->closing) {
3944 return;
3945 }
3946
3947 ngx_post_event(&qc->push, &ngx_posted_events);
3948 } 2118 }
3949 2119
3950 2120
3951 void 2121 void
3952 ngx_quic_shutdown_quic(ngx_connection_t *c) 2122 ngx_quic_shutdown_quic(ngx_connection_t *c)
3979 2149
3980 ngx_quic_finalize_connection(c, qc->shutdown_code, qc->shutdown_reason); 2150 ngx_quic_finalize_connection(c, qc->shutdown_code, qc->shutdown_reason);
3981 } 2151 }
3982 2152
3983 2153
3984
3985 static void
3986 ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
3987 {
3988 ngx_msec_t timer;
3989 ngx_quic_congestion_t *cg;
3990 ngx_quic_connection_t *qc;
3991
3992 if (f->plen == 0) {
3993 return;
3994 }
3995
3996 qc = ngx_quic_get_connection(c);
3997 cg = &qc->congestion;
3998
3999 cg->in_flight -= f->plen;
4000
4001 timer = f->last - cg->recovery_start;
4002
4003 if ((ngx_msec_int_t) timer <= 0) {
4004 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4005 "quic congestion ack recovery win:%uz ss:%z if:%uz",
4006 cg->window, cg->ssthresh, cg->in_flight);
4007
4008 return;
4009 }
4010
4011 if (cg->window < cg->ssthresh) {
4012 cg->window += f->plen;
4013
4014 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4015 "quic congestion slow start win:%uz ss:%z if:%uz",
4016 cg->window, cg->ssthresh, cg->in_flight);
4017
4018 } else {
4019 cg->window += qc->tp.max_udp_payload_size * f->plen / cg->window;
4020
4021 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4022 "quic congestion avoidance win:%uz ss:%z if:%uz",
4023 cg->window, cg->ssthresh, cg->in_flight);
4024 }
4025
4026 /* prevent recovery_start from wrapping */
4027
4028 timer = cg->recovery_start - ngx_current_msec + qc->tp.max_idle_timeout * 2;
4029
4030 if ((ngx_msec_int_t) timer < 0) {
4031 cg->recovery_start = ngx_current_msec - qc->tp.max_idle_timeout * 2;
4032 }
4033 }
4034
4035
4036 static void
4037 ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
4038 {
4039 ngx_msec_t timer;
4040 ngx_quic_congestion_t *cg;
4041 ngx_quic_connection_t *qc;
4042
4043 if (f->plen == 0) {
4044 return;
4045 }
4046
4047 qc = ngx_quic_get_connection(c);
4048 cg = &qc->congestion;
4049
4050 cg->in_flight -= f->plen;
4051 f->plen = 0;
4052
4053 timer = f->last - cg->recovery_start;
4054
4055 if ((ngx_msec_int_t) timer <= 0) {
4056 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4057 "quic congestion lost recovery win:%uz ss:%z if:%uz",
4058 cg->window, cg->ssthresh, cg->in_flight);
4059
4060 return;
4061 }
4062
4063 cg->recovery_start = ngx_current_msec;
4064 cg->window /= 2;
4065
4066 if (cg->window < qc->tp.max_udp_payload_size * 2) {
4067 cg->window = qc->tp.max_udp_payload_size * 2;
4068 }
4069
4070 cg->ssthresh = cg->window;
4071
4072 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4073 "quic congestion lost win:%uz ss:%z if:%uz",
4074 cg->window, cg->ssthresh, cg->in_flight);
4075 }
4076
4077
4078 uint32_t 2154 uint32_t
4079 ngx_quic_version(ngx_connection_t *c) 2155 ngx_quic_version(ngx_connection_t *c)
4080 { 2156 {
4081 uint32_t version; 2157 uint32_t version;
4082 ngx_quic_connection_t *qc; 2158 ngx_quic_connection_t *qc;