comparison src/event/quic/ngx_event_quic.c @ 8673:046c951e393a quic

QUIC: moved all quic sources into src/event/quic.
author Vladimir Homutov <vl@nginx.com>
date Fri, 25 Dec 2020 14:01:28 +0300
parents src/event/ngx_event_quic.c@b14338acbf9d
children 2c7f927f7999
comparison
equal deleted inserted replaced
8672:13c537def699 8673:046c951e393a
1
2 /*
3 * Copyright (C) Nginx, Inc.
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
10 #include <ngx_event_quic_transport.h>
11 #include <ngx_event_quic_protection.h>
12
13
14 /* 0-RTT and 1-RTT data exist in the same packet number space,
15 * so we have 3 packet number spaces:
16 *
17 * 0 - Initial
18 * 1 - Handshake
19 * 2 - 0-RTT and 1-RTT
20 */
21 #define ngx_quic_get_send_ctx(qc, level) \
22 ((level) == ssl_encryption_initial) ? &((qc)->send_ctx[0]) \
23 : (((level) == ssl_encryption_handshake) ? &((qc)->send_ctx[1]) \
24 : &((qc)->send_ctx[2]))
25
26 #define NGX_QUIC_SEND_CTX_LAST (NGX_QUIC_ENCRYPTION_LAST - 1)
27
28 /*
29 * 7.4. Cryptographic Message Buffering
30 * Implementations MUST support buffering at least 4096 bytes of data
31 */
32 #define NGX_QUIC_MAX_BUFFERED 65535
33
34 #define NGX_QUIC_STREAM_GONE (void *) -1
35
36 #define NGX_QUIC_UNSET_PN (uint64_t) -1
37
38 /*
39 * Endpoints MUST discard packets that are too small to be valid QUIC
40 * packets. With the set of AEAD functions defined in [QUIC-TLS],
41 * packets that are smaller than 21 bytes are never valid.
42 */
43 #define NGX_QUIC_MIN_PKT_LEN 21
44
45 #define NGX_QUIC_MIN_SR_PACKET 43 /* 5 random + 16 srt + 22 padding */
46 #define NGX_QUIC_MAX_SR_PACKET 1200
47
48 #define NGX_QUIC_MAX_ACK_GAP 2
49
50
51 typedef struct {
52 ngx_rbtree_t tree;
53 ngx_rbtree_node_t sentinel;
54
55 uint64_t received;
56 uint64_t sent;
57 uint64_t recv_max_data;
58 uint64_t send_max_data;
59
60 uint64_t server_max_streams_uni;
61 uint64_t server_max_streams_bidi;
62 uint64_t server_streams_uni;
63 uint64_t server_streams_bidi;
64
65 uint64_t client_max_streams_uni;
66 uint64_t client_max_streams_bidi;
67 uint64_t client_streams_uni;
68 uint64_t client_streams_bidi;
69 } ngx_quic_streams_t;
70
71
72 typedef struct {
73 size_t in_flight;
74 size_t window;
75 size_t ssthresh;
76 ngx_msec_t recovery_start;
77 } ngx_quic_congestion_t;
78
79
80 /*
81 * 12.3. Packet Numbers
82 *
83 * Conceptually, a packet number space is the context in which a packet
84 * can be processed and acknowledged. Initial packets can only be sent
85 * with Initial packet protection keys and acknowledged in packets which
86 * are also Initial packets.
87 */
88 typedef struct {
89 enum ssl_encryption_level_t level;
90
91 uint64_t pnum; /* to be sent */
92 uint64_t largest_ack; /* received from peer */
93 uint64_t largest_pn; /* received from peer */
94
95 ngx_queue_t frames;
96 ngx_queue_t sent;
97
98 uint64_t pending_ack; /* non sent ack-eliciting */
99 uint64_t largest_range;
100 uint64_t first_range;
101 ngx_msec_t largest_received;
102 ngx_msec_t ack_delay_start;
103 ngx_uint_t nranges;
104 ngx_quic_ack_range_t ranges[NGX_QUIC_MAX_RANGES];
105 ngx_uint_t send_ack;
106 } ngx_quic_send_ctx_t;
107
108
109 typedef struct {
110 ngx_udp_connection_t udp;
111
112 uint32_t version;
113 ngx_str_t scid; /* initial client ID */
114 ngx_str_t dcid; /* server (our own) ID */
115 ngx_str_t odcid; /* original server ID */
116 ngx_str_t token;
117
118 struct sockaddr *sockaddr;
119 socklen_t socklen;
120
121 ngx_queue_t client_ids;
122 ngx_queue_t server_ids;
123 ngx_queue_t free_client_ids;
124 ngx_queue_t free_server_ids;
125 ngx_uint_t nclient_ids;
126 ngx_uint_t nserver_ids;
127 uint64_t max_retired_seqnum;
128 uint64_t client_seqnum;
129 uint64_t server_seqnum;
130
131 ngx_uint_t client_tp_done;
132 ngx_quic_tp_t tp;
133 ngx_quic_tp_t ctp;
134
135 ngx_quic_send_ctx_t send_ctx[NGX_QUIC_SEND_CTX_LAST];
136
137 ngx_quic_frames_stream_t crypto[NGX_QUIC_ENCRYPTION_LAST];
138
139 ngx_quic_keys_t *keys;
140
141 ngx_quic_conf_t *conf;
142
143 ngx_event_t push;
144 ngx_event_t pto;
145 ngx_event_t close;
146 ngx_msec_t last_cc;
147
148 ngx_msec_t latest_rtt;
149 ngx_msec_t avg_rtt;
150 ngx_msec_t min_rtt;
151 ngx_msec_t rttvar;
152
153 ngx_uint_t pto_count;
154
155 ngx_queue_t free_frames;
156 ngx_chain_t *free_bufs;
157 ngx_buf_t *free_shadow_bufs;
158
159 #ifdef NGX_QUIC_DEBUG_ALLOC
160 ngx_uint_t nframes;
161 ngx_uint_t nbufs;
162 #endif
163
164 ngx_quic_streams_t streams;
165 ngx_quic_congestion_t congestion;
166 off_t received;
167
168 ngx_uint_t error;
169 enum ssl_encryption_level_t error_level;
170 ngx_uint_t error_ftype;
171 const char *error_reason;
172
173 unsigned error_app:1;
174 unsigned send_timer_set:1;
175 unsigned closing:1;
176 unsigned draining:1;
177 unsigned key_phase:1;
178 unsigned in_retry:1;
179 unsigned initialized:1;
180 unsigned validated:1;
181 } ngx_quic_connection_t;
182
183
184 typedef struct {
185 ngx_queue_t queue;
186 uint64_t seqnum;
187 size_t len;
188 u_char id[NGX_QUIC_CID_LEN_MAX];
189 u_char sr_token[NGX_QUIC_SR_TOKEN_LEN];
190 } ngx_quic_client_id_t;
191
192
193 typedef struct {
194 ngx_udp_connection_t udp;
195 ngx_queue_t queue;
196 uint64_t seqnum;
197 size_t len;
198 u_char id[NGX_QUIC_CID_LEN_MAX];
199 } ngx_quic_server_id_t;
200
201
202 typedef ngx_int_t (*ngx_quic_frame_handler_pt)(ngx_connection_t *c,
203 ngx_quic_frame_t *frame, void *data);
204
205
206 #if BORINGSSL_API_VERSION >= 10
207 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
208 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
209 const uint8_t *secret, size_t secret_len);
210 static int ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn,
211 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
212 const uint8_t *secret, size_t secret_len);
213 #else
214 static int ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
215 enum ssl_encryption_level_t level, const uint8_t *read_secret,
216 const uint8_t *write_secret, size_t secret_len);
217 #endif
218
219 static int ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
220 enum ssl_encryption_level_t level, const uint8_t *data, size_t len);
221 static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn);
222 static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
223 enum ssl_encryption_level_t level, uint8_t alert);
224
225
226 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c,
227 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
228 static ngx_int_t ngx_quic_send_stateless_reset(ngx_connection_t *c,
229 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
230 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c,
231 ngx_quic_header_t *pkt);
232 static ngx_int_t ngx_quic_negotiate_version(ngx_connection_t *c,
233 ngx_quic_header_t *inpkt);
234 static ngx_int_t ngx_quic_create_server_id(ngx_connection_t *c, u_char *id);
235 static ngx_int_t ngx_quic_send_retry(ngx_connection_t *c);
236 static ngx_int_t ngx_quic_new_token(ngx_connection_t *c, ngx_str_t *token);
237 static ngx_int_t ngx_quic_validate_token(ngx_connection_t *c,
238 ngx_quic_header_t *pkt);
239 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c);
240 static ngx_inline size_t ngx_quic_max_udp_payload(ngx_connection_t *c);
241 static void ngx_quic_input_handler(ngx_event_t *rev);
242
243 static void ngx_quic_close_connection(ngx_connection_t *c, ngx_int_t rc);
244 static ngx_int_t ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc);
245 static void ngx_quic_close_timer_handler(ngx_event_t *ev);
246 static ngx_int_t ngx_quic_close_streams(ngx_connection_t *c,
247 ngx_quic_connection_t *qc);
248
249 static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b,
250 ngx_quic_conf_t *conf);
251 static ngx_int_t ngx_quic_process_packet(ngx_connection_t *c,
252 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
253 static ngx_int_t ngx_quic_init_secrets(ngx_connection_t *c);
254 static void ngx_quic_discard_ctx(ngx_connection_t *c,
255 enum ssl_encryption_level_t level);
256 static ngx_int_t ngx_quic_check_peer(ngx_quic_connection_t *qc,
257 ngx_quic_header_t *pkt);
258 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c,
259 ngx_quic_header_t *pkt);
260 static ngx_int_t ngx_quic_ack_packet(ngx_connection_t *c,
261 ngx_quic_header_t *pkt);
262 static ngx_int_t ngx_quic_send_ack_range(ngx_connection_t *c,
263 ngx_quic_send_ctx_t *ctx, uint64_t smallest, uint64_t largest);
264 static void ngx_quic_drop_ack_ranges(ngx_connection_t *c,
265 ngx_quic_send_ctx_t *ctx, uint64_t pn);
266 static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c,
267 ngx_quic_send_ctx_t *ctx);
268 static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c);
269 static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c);
270
271 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c,
272 ngx_quic_header_t *pkt, ngx_quic_frame_t *f);
273 static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c,
274 ngx_quic_send_ctx_t *ctx, uint64_t min, uint64_t max,
275 ngx_msec_t *send_time);
276 static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack,
277 enum ssl_encryption_level_t level, ngx_msec_t send_time);
278 static ngx_inline ngx_msec_t ngx_quic_pto(ngx_connection_t *c,
279 ngx_quic_send_ctx_t *ctx);
280 static void ngx_quic_handle_stream_ack(ngx_connection_t *c,
281 ngx_quic_frame_t *f);
282
283 static ngx_int_t ngx_quic_handle_ordered_frame(ngx_connection_t *c,
284 ngx_quic_frames_stream_t *fs, ngx_quic_frame_t *frame,
285 ngx_quic_frame_handler_pt handler, void *data);
286 static ngx_int_t ngx_quic_adjust_frame_offset(ngx_connection_t *c,
287 ngx_quic_frame_t *f, uint64_t offset_in);
288 static ngx_int_t ngx_quic_buffer_frame(ngx_connection_t *c,
289 ngx_quic_frames_stream_t *stream, ngx_quic_frame_t *f);
290
291 static ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c,
292 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame);
293 static ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c,
294 ngx_quic_frame_t *frame, void *data);
295 static ngx_int_t ngx_quic_handle_stream_frame(ngx_connection_t *c,
296 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame);
297 static ngx_int_t ngx_quic_stream_input(ngx_connection_t *c,
298 ngx_quic_frame_t *frame, void *data);
299
300 static ngx_int_t ngx_quic_handle_max_data_frame(ngx_connection_t *c,
301 ngx_quic_max_data_frame_t *f);
302 static ngx_int_t ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c,
303 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f);
304 static ngx_int_t ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c,
305 ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f);
306 static ngx_int_t ngx_quic_handle_max_stream_data_frame(ngx_connection_t *c,
307 ngx_quic_header_t *pkt, ngx_quic_max_stream_data_frame_t *f);
308 static ngx_int_t ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
309 ngx_quic_header_t *pkt, ngx_quic_reset_stream_frame_t *f);
310 static ngx_int_t ngx_quic_handle_stop_sending_frame(ngx_connection_t *c,
311 ngx_quic_header_t *pkt, ngx_quic_stop_sending_frame_t *f);
312 static ngx_int_t ngx_quic_handle_max_streams_frame(ngx_connection_t *c,
313 ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f);
314 static ngx_int_t ngx_quic_handle_path_challenge_frame(ngx_connection_t *c,
315 ngx_quic_header_t *pkt, ngx_quic_path_challenge_frame_t *f);
316 static ngx_int_t ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c,
317 ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f);
318 static ngx_int_t ngx_quic_retire_connection_id(ngx_connection_t *c,
319 enum ssl_encryption_level_t level, uint64_t seqnum);
320 static ngx_int_t ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c,
321 ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f);
322 static ngx_int_t ngx_quic_issue_server_ids(ngx_connection_t *c);
323 static void ngx_quic_clear_temp_server_ids(ngx_connection_t *c);
324 static ngx_quic_server_id_t *ngx_quic_insert_server_id(ngx_connection_t *c,
325 ngx_str_t *id);
326 static ngx_quic_client_id_t *ngx_quic_alloc_client_id(ngx_connection_t *c,
327 ngx_quic_connection_t *qc);
328 static ngx_quic_server_id_t *ngx_quic_alloc_server_id(ngx_connection_t *c,
329 ngx_quic_connection_t *qc);
330
331 static void ngx_quic_queue_frame(ngx_quic_connection_t *qc,
332 ngx_quic_frame_t *frame);
333
334 static ngx_int_t ngx_quic_output(ngx_connection_t *c);
335 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c);
336 static ngx_int_t ngx_quic_generate_ack(ngx_connection_t *c,
337 ngx_quic_send_ctx_t *ctx);
338 static ssize_t ngx_quic_output_packet(ngx_connection_t *c,
339 ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min);
340 static ngx_int_t ngx_quic_split_frame(ngx_connection_t *c, ngx_quic_frame_t *f,
341 size_t len);
342 static void ngx_quic_free_frames(ngx_connection_t *c, ngx_queue_t *frames);
343 static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len);
344
345 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt,
346 ngx_quic_send_ctx_t *ctx);
347 static void ngx_quic_pto_handler(ngx_event_t *ev);
348 static void ngx_quic_lost_handler(ngx_event_t *ev);
349 static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c);
350 static void ngx_quic_resend_frames(ngx_connection_t *c,
351 ngx_quic_send_ctx_t *ctx);
352 static void ngx_quic_push_handler(ngx_event_t *ev);
353
354 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp,
355 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
356 static ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree,
357 uint64_t id);
358 static ngx_quic_stream_t *ngx_quic_create_client_stream(ngx_connection_t *c,
359 uint64_t id);
360 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c,
361 uint64_t id, size_t rcvbuf_size);
362 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf,
363 size_t size);
364 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf,
365 size_t size);
366 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c,
367 ngx_chain_t *in, off_t limit);
368 static size_t ngx_quic_max_stream_flow(ngx_connection_t *c);
369 static void ngx_quic_stream_cleanup_handler(void *data);
370 static ngx_quic_frame_t *ngx_quic_alloc_frame(ngx_connection_t *c);
371 static void ngx_quic_free_frame(ngx_connection_t *c, ngx_quic_frame_t *frame);
372
373 static void ngx_quic_congestion_ack(ngx_connection_t *c,
374 ngx_quic_frame_t *frame);
375 static void ngx_quic_congestion_lost(ngx_connection_t *c,
376 ngx_quic_frame_t *frame);
377
378 static ngx_chain_t *ngx_quic_alloc_buf(ngx_connection_t *c);
379 static void ngx_quic_free_bufs(ngx_connection_t *c, ngx_chain_t *in);
380 static ngx_chain_t *ngx_quic_copy_buf(ngx_connection_t *c, u_char *data,
381 size_t len);
382 static ngx_chain_t *ngx_quic_copy_chain(ngx_connection_t *c, ngx_chain_t *in,
383 size_t limit);
384 static ngx_chain_t *ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in,
385 size_t len);
386
387
388 static SSL_QUIC_METHOD quic_method = {
389 #if BORINGSSL_API_VERSION >= 10
390 ngx_quic_set_read_secret,
391 ngx_quic_set_write_secret,
392 #else
393 ngx_quic_set_encryption_secrets,
394 #endif
395 ngx_quic_add_handshake_data,
396 ngx_quic_flush_flight,
397 ngx_quic_send_alert,
398 };
399
400
401 #if (NGX_DEBUG)
402
403 static void
404 ngx_quic_log_frame(ngx_log_t *log, ngx_quic_frame_t *f, ngx_uint_t tx)
405 {
406 u_char *p, *last, *pos, *end;
407 ssize_t n;
408 uint64_t gap, range, largest, smallest;
409 ngx_uint_t i;
410 u_char buf[NGX_MAX_ERROR_STR];
411
412 p = buf;
413 last = buf + sizeof(buf);
414
415 switch (f->type) {
416
417 case NGX_QUIC_FT_CRYPTO:
418 p = ngx_slprintf(p, last, "CRYPTO len:%uL off:%uL",
419 f->u.crypto.length, f->u.crypto.offset);
420 break;
421
422 case NGX_QUIC_FT_PADDING:
423 p = ngx_slprintf(p, last, "PADDING");
424 break;
425
426 case NGX_QUIC_FT_ACK:
427 case NGX_QUIC_FT_ACK_ECN:
428
429 p = ngx_slprintf(p, last, "ACK n:%ui delay:%uL ",
430 f->u.ack.range_count, f->u.ack.delay);
431
432 if (f->data) {
433 pos = f->data->buf->pos;
434 end = f->data->buf->end;
435
436 } else {
437 pos = NULL;
438 end = NULL;
439 }
440
441 largest = f->u.ack.largest;
442 smallest = f->u.ack.largest - f->u.ack.first_range;
443
444 if (largest == smallest) {
445 p = ngx_slprintf(p, last, "%uL", largest);
446
447 } else {
448 p = ngx_slprintf(p, last, "%uL-%uL", largest, smallest);
449 }
450
451 for (i = 0; i < f->u.ack.range_count; i++) {
452 n = ngx_quic_parse_ack_range(log, pos, end, &gap, &range);
453 if (n == NGX_ERROR) {
454 break;
455 }
456
457 pos += n;
458
459 largest = smallest - gap - 2;
460 smallest = largest - range;
461
462 if (largest == smallest) {
463 p = ngx_slprintf(p, last, " %uL", largest);
464
465 } else {
466 p = ngx_slprintf(p, last, " %uL-%uL", largest, smallest);
467 }
468 }
469
470 if (f->type == NGX_QUIC_FT_ACK_ECN) {
471 p = ngx_slprintf(p, last, " ECN counters ect0:%uL ect1:%uL ce:%uL",
472 f->u.ack.ect0, f->u.ack.ect1, f->u.ack.ce);
473 }
474 break;
475
476 case NGX_QUIC_FT_PING:
477 p = ngx_slprintf(p, last, "PING");
478 break;
479
480 case NGX_QUIC_FT_NEW_CONNECTION_ID:
481 p = ngx_slprintf(p, last,
482 "NEW_CONNECTION_ID seq:%uL retire:%uL len:%ud",
483 f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len);
484 break;
485
486 case NGX_QUIC_FT_RETIRE_CONNECTION_ID:
487 p = ngx_slprintf(p, last, "RETIRE_CONNECTION_ID seqnum:%uL",
488 f->u.retire_cid.sequence_number);
489 break;
490
491 case NGX_QUIC_FT_CONNECTION_CLOSE:
492 case NGX_QUIC_FT_CONNECTION_CLOSE_APP:
493 p = ngx_slprintf(p, last, "CONNECTION_CLOSE%s err:%ui",
494 f->u.close.app ? "_APP" : "", f->u.close.error_code);
495
496 if (f->u.close.reason.len) {
497 p = ngx_slprintf(p, last, " %V", &f->u.close.reason);
498 }
499
500 if (f->type == NGX_QUIC_FT_CONNECTION_CLOSE) {
501 p = ngx_slprintf(p, last, " ft:%ui", f->u.close.frame_type);
502 }
503
504
505 break;
506
507 case NGX_QUIC_FT_STREAM0:
508 case NGX_QUIC_FT_STREAM1:
509 case NGX_QUIC_FT_STREAM2:
510 case NGX_QUIC_FT_STREAM3:
511 case NGX_QUIC_FT_STREAM4:
512 case NGX_QUIC_FT_STREAM5:
513 case NGX_QUIC_FT_STREAM6:
514 case NGX_QUIC_FT_STREAM7:
515
516 p = ngx_slprintf(p, last, "STREAM id:0x%xL", f->u.stream.stream_id);
517
518 if (f->u.stream.off) {
519 p = ngx_slprintf(p, last, " off:%uL", f->u.stream.offset);
520 }
521
522 if (f->u.stream.len) {
523 p = ngx_slprintf(p, last, " len:%uL", f->u.stream.length);
524 }
525
526 if (f->u.stream.fin) {
527 p = ngx_slprintf(p, last, " fin:1");
528 }
529
530 #ifdef NGX_QUIC_DEBUG_FRAMES
531 {
532 ngx_chain_t *cl;
533
534 p = ngx_slprintf(p, last, " data:");
535
536 for (cl = f->data; cl; cl = cl->next) {
537 p = ngx_slprintf(p, last, "%*xs",
538 cl->buf->last - cl->buf->pos, cl->buf->pos);
539 }
540 }
541 #endif
542
543 break;
544
545 case NGX_QUIC_FT_MAX_DATA:
546 p = ngx_slprintf(p, last, "MAX_DATA max_data:%uL on recv",
547 f->u.max_data.max_data);
548 break;
549
550 case NGX_QUIC_FT_RESET_STREAM:
551 p = ngx_slprintf(p, last, "RESET_STREAM"
552 " id:0x%xL error_code:0x%xL final_size:0x%xL",
553 f->u.reset_stream.id, f->u.reset_stream.error_code,
554 f->u.reset_stream.final_size);
555 break;
556
557 case NGX_QUIC_FT_STOP_SENDING:
558 p = ngx_slprintf(p, last, "STOP_SENDING id:0x%xL err:0x%xL",
559 f->u.stop_sending.id, f->u.stop_sending.error_code);
560 break;
561
562 case NGX_QUIC_FT_STREAMS_BLOCKED:
563 case NGX_QUIC_FT_STREAMS_BLOCKED2:
564 p = ngx_slprintf(p, last, "STREAMS_BLOCKED limit:%uL bidi:%ui",
565 f->u.streams_blocked.limit, f->u.streams_blocked.bidi);
566 break;
567
568 case NGX_QUIC_FT_MAX_STREAMS:
569 case NGX_QUIC_FT_MAX_STREAMS2:
570 p = ngx_slprintf(p, last, "MAX_STREAMS limit:%uL bidi:%ui",
571 f->u.max_streams.limit, f->u.max_streams.bidi);
572 break;
573
574 case NGX_QUIC_FT_MAX_STREAM_DATA:
575 p = ngx_slprintf(p, last, "MAX_STREAM_DATA id:0x%xL limit:%uL",
576 f->u.max_stream_data.id, f->u.max_stream_data.limit);
577 break;
578
579
580 case NGX_QUIC_FT_DATA_BLOCKED:
581 p = ngx_slprintf(p, last, "DATA_BLOCKED limit:%uL",
582 f->u.data_blocked.limit);
583 break;
584
585 case NGX_QUIC_FT_STREAM_DATA_BLOCKED:
586 p = ngx_slprintf(p, last, "STREAM_DATA_BLOCKED id:0x%xL limit:%uL",
587 f->u.stream_data_blocked.id,
588 f->u.stream_data_blocked.limit);
589 break;
590
591 case NGX_QUIC_FT_PATH_CHALLENGE:
592 p = ngx_slprintf(p, last, "PATH_CHALLENGE data:0x%*xs",
593 sizeof(f->u.path_challenge.data),
594 f->u.path_challenge.data);
595 break;
596
597 case NGX_QUIC_FT_PATH_RESPONSE:
598 p = ngx_slprintf(p, last, "PATH_RESPONSE data:0x%*xs",
599 sizeof(f->u.path_challenge.data),
600 f->u.path_challenge.data);
601 break;
602
603 case NGX_QUIC_FT_NEW_TOKEN:
604 p = ngx_slprintf(p, last, "NEW_TOKEN");
605 break;
606
607 case NGX_QUIC_FT_HANDSHAKE_DONE:
608 p = ngx_slprintf(p, last, "HANDSHAKE DONE");
609 break;
610
611 default:
612 p = ngx_slprintf(p, last, "unknown type 0x%xi", f->type);
613 break;
614 }
615
616 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0, "quic frame %s %s %*s",
617 tx ? "tx" : "rx", ngx_quic_level_name(f->level),
618 p - buf, buf);
619 }
620
621
622 static void
623 ngx_quic_connstate_dbg(ngx_connection_t *c)
624 {
625 u_char *p, *last;
626 ngx_quic_connection_t *qc;
627 u_char buf[NGX_MAX_ERROR_STR];
628
629 p = buf;
630 last = p + sizeof(buf);
631
632 qc = ngx_quic_get_connection(c);
633
634 p = ngx_slprintf(p, last, "state:");
635
636 if (qc) {
637
638 if (qc->error) {
639 p = ngx_slprintf(p, last, "%s", qc->error_app ? " app" : "");
640 p = ngx_slprintf(p, last, " error:%ui", qc->error);
641
642 if (qc->error_reason) {
643 p = ngx_slprintf(p, last, " \"%s\"", qc->error_reason);
644 }
645 }
646
647 p = ngx_slprintf(p, last, "%s", qc->closing ? " closing" : "");
648 p = ngx_slprintf(p, last, "%s", qc->draining ? " draining" : "");
649 p = ngx_slprintf(p, last, "%s", qc->key_phase ? " kp" : "");
650 p = ngx_slprintf(p, last, "%s", qc->in_retry ? " retry" : "");
651 p = ngx_slprintf(p, last, "%s", qc->validated? " valid" : "");
652
653 } else {
654 p = ngx_slprintf(p, last, " early");
655 }
656
657 if (c->read->timer_set) {
658 p = ngx_slprintf(p, last,
659 qc && qc->send_timer_set ? " send:%M" : " read:%M",
660 c->read->timer.key - ngx_current_msec);
661 }
662
663 if (qc) {
664
665 if (qc->push.timer_set) {
666 p = ngx_slprintf(p, last, " push:%M",
667 qc->push.timer.key - ngx_current_msec);
668 }
669
670 if (qc->pto.timer_set) {
671 p = ngx_slprintf(p, last, " pto:%M",
672 qc->pto.timer.key - ngx_current_msec);
673 }
674
675 if (qc->close.timer_set) {
676 p = ngx_slprintf(p, last, " close:%M",
677 qc->close.timer.key - ngx_current_msec);
678 }
679 }
680
681 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
682 "quic %*s", p - buf, buf);
683 }
684
685 #else
686
687 #define ngx_quic_log_frame(log, f, tx)
688 #define ngx_quic_connstate_dbg(c)
689
690 #endif
691
692
693 #if BORINGSSL_API_VERSION >= 10
694
695 static int
696 ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
697 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
698 const uint8_t *rsecret, size_t secret_len)
699 {
700 ngx_connection_t *c;
701 ngx_quic_connection_t *qc;
702
703 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
704 qc = ngx_quic_get_connection(c);
705
706 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
707 "quic ngx_quic_set_read_secret() level:%d", level);
708 #ifdef NGX_QUIC_DEBUG_CRYPTO
709 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
710 "quic read secret len:%uz %*xs", secret_len,
711 secret_len, rsecret);
712 #endif
713
714 return ngx_quic_keys_set_encryption_secret(c->pool, 0, qc->keys, level,
715 cipher, rsecret, secret_len);
716 }
717
718
719 static int
720 ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn,
721 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
722 const uint8_t *wsecret, size_t secret_len)
723 {
724 ngx_connection_t *c;
725 ngx_quic_connection_t *qc;
726
727 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
728 qc = ngx_quic_get_connection(c);
729
730 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
731 "quic ngx_quic_set_write_secret() level:%d", level);
732 #ifdef NGX_QUIC_DEBUG_CRYPTO
733 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
734 "quic write secret len:%uz %*xs", secret_len,
735 secret_len, wsecret);
736 #endif
737
738 return ngx_quic_keys_set_encryption_secret(c->pool, 1, qc->keys, level,
739 cipher, wsecret, secret_len);
740 }
741
742 #else
743
744 static int
745 ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
746 enum ssl_encryption_level_t level, const uint8_t *rsecret,
747 const uint8_t *wsecret, size_t secret_len)
748 {
749 ngx_connection_t *c;
750 const SSL_CIPHER *cipher;
751 ngx_quic_connection_t *qc;
752
753 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
754 qc = ngx_quic_get_connection(c);
755
756 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
757 "quic ngx_quic_set_encryption_secrets() level:%d", level);
758 #ifdef NGX_QUIC_DEBUG_CRYPTO
759 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
760 "quic read secret len:%uz %*xs", secret_len,
761 secret_len, rsecret);
762 #endif
763
764 cipher = SSL_get_current_cipher(ssl_conn);
765
766 if (ngx_quic_keys_set_encryption_secret(c->pool, 0, qc->keys, level,
767 cipher, rsecret, secret_len)
768 != 1)
769 {
770 return 0;
771 }
772
773 if (level == ssl_encryption_early_data) {
774 return 1;
775 }
776
777 #ifdef NGX_QUIC_DEBUG_CRYPTO
778 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
779 "quic write secret len:%uz %*xs", secret_len,
780 secret_len, wsecret);
781 #endif
782
783 return ngx_quic_keys_set_encryption_secret(c->pool, 1, qc->keys, level,
784 cipher, wsecret, secret_len);
785 }
786
787 #endif
788
789
790 static int
791 ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
792 enum ssl_encryption_level_t level, const uint8_t *data, size_t len)
793 {
794 u_char *p, *end;
795 size_t client_params_len;
796 const uint8_t *client_params;
797 ngx_quic_frame_t *frame;
798 ngx_connection_t *c;
799 ngx_quic_connection_t *qc;
800 ngx_quic_frames_stream_t *fs;
801
802 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
803 qc = ngx_quic_get_connection(c);
804
805 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
806 "quic ngx_quic_add_handshake_data");
807
808 if (!qc->client_tp_done) {
809 /*
810 * things to do once during handshake: check ALPN and transport
811 * parameters; we want to break handshake if something is wrong
812 * here;
813 */
814
815 #if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
816 if (qc->conf->require_alpn) {
817 unsigned int len;
818 const unsigned char *data;
819
820 SSL_get0_alpn_selected(ssl_conn, &data, &len);
821
822 if (len == 0) {
823 qc->error = 0x100 + SSL_AD_NO_APPLICATION_PROTOCOL;
824 qc->error_reason = "unsupported protocol in ALPN extension";
825
826 ngx_log_error(NGX_LOG_INFO, c->log, 0,
827 "quic unsupported protocol in ALPN extension");
828 return 0;
829 }
830 }
831 #endif
832
833 SSL_get_peer_quic_transport_params(ssl_conn, &client_params,
834 &client_params_len);
835
836 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
837 "quic SSL_get_peer_quic_transport_params():"
838 " params_len:%ui", client_params_len);
839
840 if (client_params_len == 0) {
841 /* quic-tls 8.2 */
842 qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_MISSING_EXTENSION);
843 qc->error_reason = "missing transport parameters";
844
845 ngx_log_error(NGX_LOG_INFO, c->log, 0,
846 "missing transport parameters");
847 return 0;
848 }
849
850 p = (u_char *) client_params;
851 end = p + client_params_len;
852
853 if (ngx_quic_parse_transport_params(p, end, &qc->ctp, c->log)
854 != NGX_OK)
855 {
856 qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
857 qc->error_reason = "failed to process transport parameters";
858
859 return 0;
860 }
861
862 if (qc->ctp.max_idle_timeout > 0
863 && qc->ctp.max_idle_timeout < qc->tp.max_idle_timeout)
864 {
865 qc->tp.max_idle_timeout = qc->ctp.max_idle_timeout;
866 }
867
868 if (qc->ctp.max_udp_payload_size < NGX_QUIC_MIN_INITIAL_SIZE
869 || qc->ctp.max_udp_payload_size > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE)
870 {
871 qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
872 qc->error_reason = "invalid maximum packet size";
873
874 ngx_log_error(NGX_LOG_INFO, c->log, 0,
875 "quic maximum packet size is invalid");
876 return 0;
877 }
878
879 if (qc->ctp.max_udp_payload_size > ngx_quic_max_udp_payload(c)) {
880 qc->ctp.max_udp_payload_size = ngx_quic_max_udp_payload(c);
881 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
882 "quic client maximum packet size truncated");
883 }
884
885 #if (NGX_QUIC_DRAFT_VERSION >= 28)
886 if (qc->scid.len != qc->ctp.initial_scid.len
887 || ngx_memcmp(qc->scid.data, qc->ctp.initial_scid.data,
888 qc->scid.len) != 0)
889 {
890 ngx_log_error(NGX_LOG_INFO, c->log, 0,
891 "quic client initial_source_connection_id "
892 "mismatch");
893 return 0;
894 }
895 #endif
896
897 qc->streams.server_max_streams_bidi = qc->ctp.initial_max_streams_bidi;
898 qc->streams.server_max_streams_uni = qc->ctp.initial_max_streams_uni;
899
900 qc->client_tp_done = 1;
901 }
902
903 fs = &qc->crypto[level];
904
905 frame = ngx_quic_alloc_frame(c);
906 if (frame == NULL) {
907 return 0;
908 }
909
910 frame->data = ngx_quic_copy_buf(c, (u_char *) data, len);
911 if (frame->data == NGX_CHAIN_ERROR) {
912 return 0;
913 }
914
915 frame->level = level;
916 frame->type = NGX_QUIC_FT_CRYPTO;
917 frame->u.crypto.offset = fs->sent;
918 frame->u.crypto.length = len;
919
920 fs->sent += len;
921
922 ngx_quic_queue_frame(qc, frame);
923
924 return 1;
925 }
926
927
928 static int
929 ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn)
930 {
931 #if (NGX_DEBUG)
932 ngx_connection_t *c;
933
934 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
935
936 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
937 "quic ngx_quic_flush_flight()");
938 #endif
939 return 1;
940 }
941
942
943 static int
944 ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
945 uint8_t alert)
946 {
947 ngx_connection_t *c;
948 ngx_quic_connection_t *qc;
949
950 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
951
952 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
953 "quic ngx_quic_send_alert() lvl:%d alert:%d",
954 (int) level, (int) alert);
955
956 qc = ngx_quic_get_connection(c);
957 if (qc == NULL) {
958 return 1;
959 }
960
961 qc->error_level = level;
962 qc->error = NGX_QUIC_ERR_CRYPTO(alert);
963 qc->error_reason = "TLS alert";
964 qc->error_app = 0;
965 qc->error_ftype = 0;
966
967 if (ngx_quic_send_cc(c) != NGX_OK) {
968 return 0;
969 }
970
971 return 1;
972 }
973
974
975 void
976 ngx_quic_run(ngx_connection_t *c, ngx_quic_conf_t *conf)
977 {
978 ngx_int_t rc;
979 ngx_quic_connection_t *qc;
980
981 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic run");
982
983 rc = ngx_quic_input(c, c->buffer, conf);
984 if (rc != NGX_OK) {
985 ngx_quic_close_connection(c, rc == NGX_DECLINED ? NGX_DONE : NGX_ERROR);
986 return;
987 }
988
989 qc = ngx_quic_get_connection(c);
990
991 ngx_add_timer(c->read, qc->in_retry ? NGX_QUIC_RETRY_TIMEOUT
992 : qc->tp.max_idle_timeout);
993
994 c->read->handler = ngx_quic_input_handler;
995
996 ngx_quic_connstate_dbg(c);
997 return;
998 }
999
1000
1001 static ngx_quic_connection_t *
1002 ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf,
1003 ngx_quic_header_t *pkt)
1004 {
1005 ngx_uint_t i;
1006 ngx_quic_tp_t *ctp;
1007 ngx_quic_client_id_t *cid;
1008 ngx_quic_connection_t *qc;
1009
1010 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t));
1011 if (qc == NULL) {
1012 return NULL;
1013 }
1014
1015 qc->keys = ngx_quic_keys_new(c->pool);
1016 if (qc->keys == NULL) {
1017 return NULL;
1018 }
1019
1020 qc->version = pkt->version;
1021
1022 ngx_rbtree_init(&qc->streams.tree, &qc->streams.sentinel,
1023 ngx_quic_rbtree_insert_stream);
1024
1025 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
1026 ngx_queue_init(&qc->send_ctx[i].frames);
1027 ngx_queue_init(&qc->send_ctx[i].sent);
1028 qc->send_ctx[i].largest_pn = NGX_QUIC_UNSET_PN;
1029 qc->send_ctx[i].largest_ack = NGX_QUIC_UNSET_PN;
1030 qc->send_ctx[i].largest_range = NGX_QUIC_UNSET_PN;
1031 qc->send_ctx[i].pending_ack = NGX_QUIC_UNSET_PN;
1032 }
1033
1034 qc->send_ctx[0].level = ssl_encryption_initial;
1035 qc->send_ctx[1].level = ssl_encryption_handshake;
1036 qc->send_ctx[2].level = ssl_encryption_application;
1037
1038 for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) {
1039 ngx_queue_init(&qc->crypto[i].frames);
1040 }
1041
1042 ngx_queue_init(&qc->free_frames);
1043 ngx_queue_init(&qc->client_ids);
1044 ngx_queue_init(&qc->server_ids);
1045 ngx_queue_init(&qc->free_client_ids);
1046 ngx_queue_init(&qc->free_server_ids);
1047
1048 qc->avg_rtt = NGX_QUIC_INITIAL_RTT;
1049 qc->rttvar = NGX_QUIC_INITIAL_RTT / 2;
1050 qc->min_rtt = NGX_TIMER_INFINITE;
1051
1052 /*
1053 * qc->latest_rtt = 0
1054 * qc->nclient_ids = 0
1055 * qc->nserver_ids = 0
1056 * qc->max_retired_seqnum = 0
1057 */
1058
1059 qc->received = pkt->raw->last - pkt->raw->start;
1060
1061 qc->pto.log = c->log;
1062 qc->pto.data = c;
1063 qc->pto.handler = ngx_quic_pto_handler;
1064 qc->pto.cancelable = 1;
1065
1066 qc->push.log = c->log;
1067 qc->push.data = c;
1068 qc->push.handler = ngx_quic_push_handler;
1069 qc->push.cancelable = 1;
1070
1071 qc->conf = conf;
1072 qc->tp = conf->tp;
1073
1074 if (qc->tp.disable_active_migration) {
1075 qc->sockaddr = ngx_palloc(c->pool, c->socklen);
1076 if (qc->sockaddr == NULL) {
1077 return NULL;
1078 }
1079
1080 ngx_memcpy(qc->sockaddr, c->sockaddr, c->socklen);
1081 qc->socklen = c->socklen;
1082 }
1083
1084 ctp = &qc->ctp;
1085 ctp->max_udp_payload_size = ngx_quic_max_udp_payload(c);
1086 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT;
1087 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY;
1088
1089 qc->streams.recv_max_data = qc->tp.initial_max_data;
1090
1091 qc->streams.client_max_streams_uni = qc->tp.initial_max_streams_uni;
1092 qc->streams.client_max_streams_bidi = qc->tp.initial_max_streams_bidi;
1093
1094 qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size,
1095 ngx_max(2 * qc->tp.max_udp_payload_size,
1096 14720));
1097 qc->congestion.ssthresh = (size_t) -1;
1098 qc->congestion.recovery_start = ngx_current_msec;
1099
1100 qc->odcid.len = pkt->dcid.len;
1101 qc->odcid.data = ngx_pstrdup(c->pool, &pkt->dcid);
1102 if (qc->odcid.data == NULL) {
1103 return NULL;
1104 }
1105
1106 qc->dcid.len = NGX_QUIC_SERVER_CID_LEN;
1107 qc->dcid.data = ngx_pnalloc(c->pool, qc->dcid.len);
1108 if (qc->dcid.data == NULL) {
1109 return NULL;
1110 }
1111
1112 if (ngx_quic_create_server_id(c, qc->dcid.data) != NGX_OK) {
1113 return NULL;
1114 }
1115
1116 #if (NGX_QUIC_DRAFT_VERSION >= 28)
1117 qc->tp.original_dcid = qc->odcid;
1118 #endif
1119 qc->tp.initial_scid = qc->dcid;
1120
1121 qc->scid.len = pkt->scid.len;
1122 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len);
1123 if (qc->scid.data == NULL) {
1124 return NULL;
1125 }
1126 ngx_memcpy(qc->scid.data, pkt->scid.data, qc->scid.len);
1127
1128 cid = ngx_quic_alloc_client_id(c, qc);
1129 if (cid == NULL) {
1130 return NULL;
1131 }
1132
1133 cid->seqnum = 0;
1134 cid->len = pkt->scid.len;
1135 ngx_memcpy(cid->id, pkt->scid.data, pkt->scid.len);
1136
1137 ngx_queue_insert_tail(&qc->client_ids, &cid->queue);
1138 qc->nclient_ids++;
1139 qc->client_seqnum = 0;
1140
1141 qc->server_seqnum = NGX_QUIC_UNSET_PN;
1142
1143 return qc;
1144 }
1145
1146
1147 static ngx_int_t
1148 ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
1149 ngx_quic_header_t *pkt)
1150 {
1151 u_char *token;
1152 size_t len, max;
1153 uint16_t rndbytes;
1154 u_char buf[NGX_QUIC_MAX_SR_PACKET];
1155
1156 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1157 "quic handle stateless reset output");
1158
1159 if (pkt->len <= NGX_QUIC_MIN_PKT_LEN) {
1160 return NGX_DECLINED;
1161 }
1162
1163 if (pkt->len <= NGX_QUIC_MIN_SR_PACKET) {
1164 len = pkt->len - 1;
1165
1166 } else {
1167 max = ngx_min(NGX_QUIC_MAX_SR_PACKET, pkt->len * 3);
1168
1169 if (RAND_bytes((u_char *) &rndbytes, sizeof(rndbytes)) != 1) {
1170 return NGX_ERROR;
1171 }
1172
1173 len = (rndbytes % (max - NGX_QUIC_MIN_SR_PACKET + 1))
1174 + NGX_QUIC_MIN_SR_PACKET;
1175 }
1176
1177 if (RAND_bytes(buf, len - NGX_QUIC_SR_TOKEN_LEN) != 1) {
1178 return NGX_ERROR;
1179 }
1180
1181 buf[0] &= ~NGX_QUIC_PKT_LONG;
1182 buf[0] |= NGX_QUIC_PKT_FIXED_BIT;
1183
1184 token = &buf[len - NGX_QUIC_SR_TOKEN_LEN];
1185
1186 if (ngx_quic_new_sr_token(c, &pkt->dcid, &conf->sr_token_key, token)
1187 != NGX_OK)
1188 {
1189 return NGX_ERROR;
1190 }
1191
1192 (void) ngx_quic_send(c, buf, len);
1193
1194 return NGX_DECLINED;
1195 }
1196
1197
1198 static ngx_int_t
1199 ngx_quic_process_stateless_reset(ngx_connection_t *c, ngx_quic_header_t *pkt)
1200 {
1201 u_char *tail, ch;
1202 ngx_uint_t i;
1203 ngx_queue_t *q;
1204 ngx_quic_client_id_t *cid;
1205 ngx_quic_connection_t *qc;
1206
1207 qc = ngx_quic_get_connection(c);
1208
1209 /* A stateless reset uses an entire UDP datagram */
1210 if (pkt->raw->start != pkt->data) {
1211 return NGX_DECLINED;
1212 }
1213
1214 tail = pkt->raw->last - NGX_QUIC_SR_TOKEN_LEN;
1215
1216 for (q = ngx_queue_head(&qc->client_ids);
1217 q != ngx_queue_sentinel(&qc->client_ids);
1218 q = ngx_queue_next(q))
1219 {
1220 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
1221
1222 if (cid->seqnum == 0) {
1223 /* no stateless reset token in initial connection id */
1224 continue;
1225 }
1226
1227 /* constant time comparison */
1228
1229 for (ch = 0, i = 0; i < NGX_QUIC_SR_TOKEN_LEN; i++) {
1230 ch |= tail[i] ^ cid->sr_token[i];
1231 }
1232
1233 if (ch == 0) {
1234 return NGX_OK;
1235 }
1236 }
1237
1238 return NGX_DECLINED;
1239 }
1240
1241
1242 static ngx_int_t
1243 ngx_quic_negotiate_version(ngx_connection_t *c, ngx_quic_header_t *inpkt)
1244 {
1245 size_t len;
1246 ngx_quic_header_t pkt;
1247 static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
1248
1249 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1250 "sending version negotiation packet");
1251
1252 pkt.log = c->log;
1253 pkt.flags = NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_FIXED_BIT;
1254 pkt.dcid = inpkt->scid;
1255 pkt.scid = inpkt->dcid;
1256
1257 len = ngx_quic_create_version_negotiation(&pkt, buf);
1258
1259 #ifdef NGX_QUIC_DEBUG_PACKETS
1260 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1261 "quic vnego packet to send len:%uz %*xs", len, len, buf);
1262 #endif
1263
1264 (void) ngx_quic_send(c, buf, len);
1265
1266 return NGX_ERROR;
1267 }
1268
1269
1270 static ngx_int_t
1271 ngx_quic_create_server_id(ngx_connection_t *c, u_char *id)
1272 {
1273 if (RAND_bytes(id, NGX_QUIC_SERVER_CID_LEN) != 1) {
1274 return NGX_ERROR;
1275 }
1276
1277 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1278 "quic create server id %*xs",
1279 (size_t) NGX_QUIC_SERVER_CID_LEN, id);
1280 return NGX_OK;
1281 }
1282
1283
1284 static ngx_int_t
1285 ngx_quic_send_retry(ngx_connection_t *c)
1286 {
1287 ssize_t len;
1288 ngx_str_t res, token;
1289 ngx_quic_header_t pkt;
1290 ngx_quic_connection_t *qc;
1291 u_char buf[NGX_QUIC_RETRY_BUFFER_SIZE];
1292
1293 qc = ngx_quic_get_connection(c);
1294
1295 if (ngx_quic_new_token(c, &token) != NGX_OK) {
1296 return NGX_ERROR;
1297 }
1298
1299 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
1300 pkt.flags = NGX_QUIC_PKT_FIXED_BIT | NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_RETRY;
1301 pkt.version = qc->version;
1302 pkt.log = c->log;
1303 pkt.odcid = qc->odcid;
1304 pkt.dcid = qc->scid;
1305 pkt.scid = qc->dcid;
1306 pkt.token = token;
1307
1308 res.data = buf;
1309
1310 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
1311 return NGX_ERROR;
1312 }
1313
1314 #ifdef NGX_QUIC_DEBUG_PACKETS
1315 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1316 "quic packet to send len:%uz %xV", res.len, &res);
1317 #endif
1318
1319 len = ngx_quic_send(c, res.data, res.len);
1320 if (len == NGX_ERROR) {
1321 return NGX_ERROR;
1322 }
1323
1324 qc->token = token;
1325 #if (NGX_QUIC_DRAFT_VERSION < 28)
1326 qc->tp.original_dcid = qc->odcid;
1327 #endif
1328 qc->tp.retry_scid = qc->dcid;
1329 qc->in_retry = 1;
1330
1331 if (ngx_quic_insert_server_id(c, &qc->dcid) == NULL) {
1332 return NGX_ERROR;
1333 }
1334
1335 return NGX_OK;
1336 }
1337
1338
1339 static ngx_int_t
1340 ngx_quic_new_token(ngx_connection_t *c, ngx_str_t *token)
1341 {
1342 int len, iv_len;
1343 u_char *data, *p, *key, *iv;
1344 ngx_msec_t now;
1345 EVP_CIPHER_CTX *ctx;
1346 const EVP_CIPHER *cipher;
1347 struct sockaddr_in *sin;
1348 #if (NGX_HAVE_INET6)
1349 struct sockaddr_in6 *sin6;
1350 #endif
1351 ngx_quic_connection_t *qc;
1352 u_char in[NGX_QUIC_MAX_TOKEN_SIZE];
1353
1354 switch (c->sockaddr->sa_family) {
1355
1356 #if (NGX_HAVE_INET6)
1357 case AF_INET6:
1358 sin6 = (struct sockaddr_in6 *) c->sockaddr;
1359
1360 len = sizeof(struct in6_addr);
1361 data = sin6->sin6_addr.s6_addr;
1362
1363 break;
1364 #endif
1365
1366 #if (NGX_HAVE_UNIX_DOMAIN)
1367 case AF_UNIX:
1368
1369 len = ngx_min(c->addr_text.len, NGX_QUIC_MAX_TOKEN_SIZE - sizeof(now));
1370 data = c->addr_text.data;
1371
1372 break;
1373 #endif
1374
1375 default: /* AF_INET */
1376 sin = (struct sockaddr_in *) c->sockaddr;
1377
1378 len = sizeof(in_addr_t);
1379 data = (u_char *) &sin->sin_addr;
1380
1381 break;
1382 }
1383
1384 p = ngx_cpymem(in, data, len);
1385
1386 now = ngx_current_msec;
1387 len += sizeof(now);
1388 ngx_memcpy(p, &now, sizeof(now));
1389
1390 cipher = EVP_aes_256_cbc();
1391 iv_len = EVP_CIPHER_iv_length(cipher);
1392
1393 token->len = iv_len + len + EVP_CIPHER_block_size(cipher);
1394 token->data = ngx_pnalloc(c->pool, token->len);
1395 if (token->data == NULL) {
1396 return NGX_ERROR;
1397 }
1398
1399 ctx = EVP_CIPHER_CTX_new();
1400 if (ctx == NULL) {
1401 return NGX_ERROR;
1402 }
1403
1404 qc = ngx_quic_get_connection(c);
1405 key = qc->conf->token_key;
1406 iv = token->data;
1407
1408 if (RAND_bytes(iv, iv_len) <= 0
1409 || !EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv))
1410 {
1411 EVP_CIPHER_CTX_free(ctx);
1412 return NGX_ERROR;
1413 }
1414
1415 token->len = iv_len;
1416
1417 if (EVP_EncryptUpdate(ctx, token->data + token->len, &len, in, len) != 1) {
1418 EVP_CIPHER_CTX_free(ctx);
1419 return NGX_ERROR;
1420 }
1421
1422 token->len += len;
1423
1424 if (EVP_EncryptFinal_ex(ctx, token->data + token->len, &len) <= 0) {
1425 EVP_CIPHER_CTX_free(ctx);
1426 return NGX_ERROR;
1427 }
1428
1429 token->len += len;
1430
1431 EVP_CIPHER_CTX_free(ctx);
1432
1433 #ifdef NGX_QUIC_DEBUG_PACKETS
1434 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1435 "quic new token len:%uz %xV", token->len, token);
1436 #endif
1437
1438 return NGX_OK;
1439 }
1440
1441
1442 static ngx_int_t
1443 ngx_quic_validate_token(ngx_connection_t *c, ngx_quic_header_t *pkt)
1444 {
1445 int len, tlen, iv_len;
1446 u_char *key, *iv, *p, *data;
1447 ngx_msec_t msec;
1448 EVP_CIPHER_CTX *ctx;
1449 const EVP_CIPHER *cipher;
1450 struct sockaddr_in *sin;
1451 #if (NGX_HAVE_INET6)
1452 struct sockaddr_in6 *sin6;
1453 #endif
1454 ngx_quic_connection_t *qc;
1455 u_char tdec[NGX_QUIC_MAX_TOKEN_SIZE];
1456
1457 qc = ngx_quic_get_connection(c);
1458
1459 /* Retry token */
1460
1461 if (qc->token.len) {
1462 if (pkt->token.len != qc->token.len) {
1463 goto bad_token;
1464 }
1465
1466 if (ngx_memcmp(pkt->token.data, qc->token.data, pkt->token.len) != 0) {
1467 goto bad_token;
1468 }
1469
1470 return NGX_OK;
1471 }
1472
1473 /* NEW_TOKEN in a previous connection */
1474
1475 cipher = EVP_aes_256_cbc();
1476 key = qc->conf->token_key;
1477 iv = pkt->token.data;
1478 iv_len = EVP_CIPHER_iv_length(cipher);
1479
1480 /* sanity checks */
1481
1482 if (pkt->token.len < (size_t) iv_len + EVP_CIPHER_block_size(cipher)) {
1483 goto bad_token;
1484 }
1485
1486 if (pkt->token.len > (size_t) iv_len + NGX_QUIC_MAX_TOKEN_SIZE) {
1487 goto bad_token;
1488 }
1489
1490 ctx = EVP_CIPHER_CTX_new();
1491 if (ctx == NULL) {
1492 return NGX_ERROR;
1493 }
1494
1495 if (!EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv)) {
1496 EVP_CIPHER_CTX_free(ctx);
1497 return NGX_ERROR;
1498 }
1499
1500 p = pkt->token.data + iv_len;
1501 len = pkt->token.len - iv_len;
1502
1503 if (EVP_DecryptUpdate(ctx, tdec, &len, p, len) != 1) {
1504 EVP_CIPHER_CTX_free(ctx);
1505 goto bad_token;
1506 }
1507
1508 if (EVP_DecryptFinal_ex(ctx, tdec + len, &tlen) <= 0) {
1509 EVP_CIPHER_CTX_free(ctx);
1510 goto bad_token;
1511 }
1512
1513 EVP_CIPHER_CTX_free(ctx);
1514
1515 switch (c->sockaddr->sa_family) {
1516
1517 #if (NGX_HAVE_INET6)
1518 case AF_INET6:
1519 sin6 = (struct sockaddr_in6 *) c->sockaddr;
1520
1521 len = sizeof(struct in6_addr);
1522 data = sin6->sin6_addr.s6_addr;
1523
1524 break;
1525 #endif
1526
1527 #if (NGX_HAVE_UNIX_DOMAIN)
1528 case AF_UNIX:
1529
1530 len = ngx_min(c->addr_text.len, NGX_QUIC_MAX_TOKEN_SIZE - sizeof(msec));
1531 data = c->addr_text.data;
1532
1533 break;
1534 #endif
1535
1536 default: /* AF_INET */
1537 sin = (struct sockaddr_in *) c->sockaddr;
1538
1539 len = sizeof(in_addr_t);
1540 data = (u_char *) &sin->sin_addr;
1541
1542 break;
1543 }
1544
1545 if (ngx_memcmp(tdec, data, len) != 0) {
1546 goto bad_token;
1547 }
1548
1549 ngx_memcpy(&msec, tdec + len, sizeof(msec));
1550
1551 if (ngx_current_msec - msec > NGX_QUIC_RETRY_LIFETIME) {
1552 ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic expired token");
1553 return NGX_DECLINED;
1554 }
1555
1556 return NGX_OK;
1557
1558 bad_token:
1559
1560 ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic invalid token");
1561
1562 qc->error = NGX_QUIC_ERR_INVALID_TOKEN;
1563 qc->error_reason = "invalid_token";
1564
1565 return NGX_DECLINED;
1566 }
1567
1568
1569 static ngx_int_t
1570 ngx_quic_init_connection(ngx_connection_t *c)
1571 {
1572 u_char *p;
1573 size_t clen;
1574 ssize_t len;
1575 ngx_ssl_conn_t *ssl_conn;
1576 ngx_quic_connection_t *qc;
1577
1578 qc = ngx_quic_get_connection(c);
1579
1580 if (ngx_ssl_create_connection(qc->conf->ssl, c, NGX_SSL_BUFFER) != NGX_OK) {
1581 return NGX_ERROR;
1582 }
1583
1584 c->ssl->no_wait_shutdown = 1;
1585
1586 ssl_conn = c->ssl->connection;
1587
1588 if (SSL_set_quic_method(ssl_conn, &quic_method) == 0) {
1589 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1590 "quic SSL_set_quic_method() failed");
1591 return NGX_ERROR;
1592 }
1593
1594 #ifdef SSL_READ_EARLY_DATA_SUCCESS
1595 if (SSL_CTX_get_max_early_data(qc->conf->ssl->ctx)) {
1596 SSL_set_quic_early_data_enabled(ssl_conn, 1);
1597 }
1598 #endif
1599
1600 if (ngx_quic_new_sr_token(c, &qc->dcid, &qc->conf->sr_token_key,
1601 qc->tp.sr_token)
1602 != NGX_OK)
1603 {
1604 return NGX_ERROR;
1605 }
1606
1607 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1608 "quic stateless reset token %*xs",
1609 (size_t) NGX_QUIC_SR_TOKEN_LEN, qc->tp.sr_token);
1610
1611 len = ngx_quic_create_transport_params(NULL, NULL, &qc->tp, &clen);
1612 /* always succeeds */
1613
1614 p = ngx_pnalloc(c->pool, len);
1615 if (p == NULL) {
1616 return NGX_ERROR;
1617 }
1618
1619 len = ngx_quic_create_transport_params(p, p + len, &qc->tp, NULL);
1620 if (len < 0) {
1621 return NGX_ERROR;
1622 }
1623
1624 #ifdef NGX_QUIC_DEBUG_PACKETS
1625 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1626 "quic transport parameters len:%uz %*xs", len, len, p);
1627 #endif
1628
1629 if (SSL_set_quic_transport_params(ssl_conn, p, len) == 0) {
1630 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1631 "quic SSL_set_quic_transport_params() failed");
1632 return NGX_ERROR;
1633 }
1634
1635 #if NGX_OPENSSL_QUIC_ZRTT_CTX
1636 if (SSL_set_quic_early_data_context(ssl_conn, p, clen) == 0) {
1637 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1638 "quic SSL_set_quic_early_data_context() failed");
1639 return NGX_ERROR;
1640 }
1641 #endif
1642
1643 return NGX_OK;
1644 }
1645
1646
1647 static ngx_inline size_t
1648 ngx_quic_max_udp_payload(ngx_connection_t *c)
1649 {
1650 /* TODO: path MTU discovery */
1651
1652 #if (NGX_HAVE_INET6)
1653 if (c->sockaddr->sa_family == AF_INET6) {
1654 return NGX_QUIC_MAX_UDP_PAYLOAD_OUT6;
1655 }
1656 #endif
1657
1658 return NGX_QUIC_MAX_UDP_PAYLOAD_OUT;
1659 }
1660
1661
1662 static void
1663 ngx_quic_input_handler(ngx_event_t *rev)
1664 {
1665 ssize_t n;
1666 ngx_int_t rc;
1667 ngx_buf_t b;
1668 ngx_connection_t *c;
1669 ngx_quic_connection_t *qc;
1670 static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
1671
1672 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0, "quic input handler");
1673
1674 ngx_memzero(&b, sizeof(ngx_buf_t));
1675 b.start = buf;
1676 b.end = buf + sizeof(buf);
1677 b.pos = b.last = b.start;
1678 b.memory = 1;
1679
1680 c = rev->data;
1681 qc = ngx_quic_get_connection(c);
1682
1683 c->log->action = "handling quic input";
1684
1685 if (rev->timedout) {
1686 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
1687 "quic client timed out");
1688 ngx_quic_close_connection(c, NGX_DONE);
1689 return;
1690 }
1691
1692 if (c->close) {
1693 qc->error_reason = "graceful shutdown";
1694 ngx_quic_close_connection(c, NGX_OK);
1695 return;
1696 }
1697
1698 n = c->recv(c, b.start, b.end - b.start);
1699
1700 if (n == NGX_AGAIN) {
1701 if (qc->closing) {
1702 ngx_quic_close_connection(c, NGX_OK);
1703 }
1704 return;
1705 }
1706
1707 if (n == NGX_ERROR) {
1708 c->read->eof = 1;
1709 ngx_quic_close_connection(c, NGX_ERROR);
1710 return;
1711 }
1712
1713 if (qc->tp.disable_active_migration) {
1714 if (c->socklen != qc->socklen
1715 || ngx_memcmp(c->sockaddr, qc->sockaddr, c->socklen) != 0)
1716 {
1717 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1718 "quic dropping packet from new address");
1719 return;
1720 }
1721 }
1722
1723 b.last += n;
1724 qc->received += n;
1725
1726 rc = ngx_quic_input(c, &b, NULL);
1727
1728 if (rc == NGX_ERROR) {
1729 ngx_quic_close_connection(c, NGX_ERROR);
1730 return;
1731 }
1732
1733 if (rc == NGX_DECLINED) {
1734 return;
1735 }
1736
1737 /* rc == NGX_OK */
1738
1739 qc->send_timer_set = 0;
1740 ngx_add_timer(rev, qc->tp.max_idle_timeout);
1741
1742 ngx_quic_connstate_dbg(c);
1743 }
1744
1745
1746 static void
1747 ngx_quic_close_connection(ngx_connection_t *c, ngx_int_t rc)
1748 {
1749 ngx_pool_t *pool;
1750 ngx_quic_connection_t *qc;
1751
1752 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1753 "quic ngx_quic_close_connection rc:%i", rc);
1754
1755 qc = ngx_quic_get_connection(c);
1756
1757 if (qc == NULL) {
1758 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1759 "quic close connection early error");
1760
1761 } else if (ngx_quic_close_quic(c, rc) == NGX_AGAIN) {
1762 return;
1763 }
1764
1765 if (c->ssl) {
1766 (void) ngx_ssl_shutdown(c);
1767 }
1768
1769 if (c->read->timer_set) {
1770 ngx_del_timer(c->read);
1771 }
1772
1773 #if (NGX_STAT_STUB)
1774 (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
1775 #endif
1776
1777 c->destroyed = 1;
1778
1779 pool = c->pool;
1780
1781 ngx_close_connection(c);
1782
1783 ngx_destroy_pool(pool);
1784 }
1785
1786
1787 static ngx_int_t
1788 ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc)
1789 {
1790 ngx_uint_t i;
1791 ngx_queue_t *q;
1792 ngx_quic_send_ctx_t *ctx;
1793 ngx_quic_server_id_t *sid;
1794 ngx_quic_connection_t *qc;
1795
1796 qc = ngx_quic_get_connection(c);
1797
1798 if (!qc->closing) {
1799
1800 /* drop packets from retransmit queues, no ack is expected */
1801 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
1802 ngx_quic_free_frames(c, &qc->send_ctx[i].sent);
1803 }
1804
1805 if (rc == NGX_DONE) {
1806
1807 /*
1808 * 10.2. Idle Timeout
1809 *
1810 * If the idle timeout is enabled by either peer, a connection is
1811 * silently closed and its state is discarded when it remains idle
1812 */
1813
1814 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1815 "quic closing %s connection",
1816 qc->draining ? "drained" : "idle");
1817
1818 } else {
1819
1820 /*
1821 * 10.3. Immediate Close
1822 *
1823 * An endpoint sends a CONNECTION_CLOSE frame (Section 19.19)
1824 * to terminate the connection immediately.
1825 */
1826
1827 qc->error_level = c->ssl ? SSL_quic_read_level(c->ssl->connection)
1828 : ssl_encryption_initial;
1829
1830 if (rc == NGX_OK) {
1831 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1832 "quic immediate close drain:%d",
1833 qc->draining);
1834
1835 qc->close.log = c->log;
1836 qc->close.data = c;
1837 qc->close.handler = ngx_quic_close_timer_handler;
1838 qc->close.cancelable = 1;
1839
1840 ctx = ngx_quic_get_send_ctx(qc, qc->error_level);
1841
1842 ngx_add_timer(&qc->close, 3 * ngx_quic_pto(c, ctx));
1843
1844 qc->error = NGX_QUIC_ERR_NO_ERROR;
1845
1846 } else {
1847 if (qc->error == 0 && !qc->error_app) {
1848 qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
1849 }
1850
1851 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1852 "quic immediate close due to %s error: %ui %s",
1853 qc->error_app ? "app " : "", qc->error,
1854 qc->error_reason ? qc->error_reason : "");
1855 }
1856
1857 (void) ngx_quic_send_cc(c);
1858
1859 if (qc->error_level == ssl_encryption_handshake) {
1860 /* for clients that might not have handshake keys */
1861 qc->error_level = ssl_encryption_initial;
1862 (void) ngx_quic_send_cc(c);
1863 }
1864 }
1865
1866 qc->closing = 1;
1867 }
1868
1869 if (rc == NGX_ERROR && qc->close.timer_set) {
1870 /* do not wait for timer in case of fatal error */
1871 ngx_del_timer(&qc->close);
1872 }
1873
1874 if (ngx_quic_close_streams(c, qc) == NGX_AGAIN) {
1875 return NGX_AGAIN;
1876 }
1877
1878 if (qc->push.timer_set) {
1879 ngx_del_timer(&qc->push);
1880 }
1881
1882 if (qc->pto.timer_set) {
1883 ngx_del_timer(&qc->pto);
1884 }
1885
1886 if (qc->push.posted) {
1887 ngx_delete_posted_event(&qc->push);
1888 }
1889
1890 while (!ngx_queue_empty(&qc->server_ids)) {
1891 q = ngx_queue_head(&qc->server_ids);
1892 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
1893
1894 ngx_queue_remove(q);
1895 ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node);
1896 qc->nserver_ids--;
1897 }
1898
1899 if (qc->close.timer_set) {
1900 return NGX_AGAIN;
1901 }
1902
1903 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
1904 "quic part of connection is terminated");
1905
1906 /* may be tested from SSL callback during SSL shutdown */
1907 c->udp = NULL;
1908
1909 return NGX_OK;
1910 }
1911
1912
1913 void
1914 ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err,
1915 const char *reason)
1916 {
1917 ngx_quic_connection_t *qc;
1918
1919 qc = ngx_quic_get_connection(c);
1920 qc->error = err;
1921 qc->error_reason = reason;
1922 qc->error_app = 1;
1923 qc->error_ftype = 0;
1924
1925 ngx_quic_close_connection(c, NGX_ERROR);
1926 }
1927
1928
1929 static void
1930 ngx_quic_close_timer_handler(ngx_event_t *ev)
1931 {
1932 ngx_connection_t *c;
1933
1934 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "quic close timer");
1935
1936 c = ev->data;
1937 ngx_quic_close_connection(c, NGX_DONE);
1938 }
1939
1940
1941 static ngx_int_t
1942 ngx_quic_close_streams(ngx_connection_t *c, ngx_quic_connection_t *qc)
1943 {
1944 ngx_event_t *rev, *wev;
1945 ngx_rbtree_t *tree;
1946 ngx_rbtree_node_t *node;
1947 ngx_quic_stream_t *qs;
1948
1949 #if (NGX_DEBUG)
1950 ngx_uint_t ns;
1951 #endif
1952
1953 tree = &qc->streams.tree;
1954
1955 if (tree->root == tree->sentinel) {
1956 return NGX_OK;
1957 }
1958
1959 #if (NGX_DEBUG)
1960 ns = 0;
1961 #endif
1962
1963 for (node = ngx_rbtree_min(tree->root, tree->sentinel);
1964 node;
1965 node = ngx_rbtree_next(tree, node))
1966 {
1967 qs = (ngx_quic_stream_t *) node;
1968
1969 rev = qs->c->read;
1970 rev->error = 1;
1971 rev->ready = 1;
1972
1973 wev = qs->c->write;
1974 wev->error = 1;
1975 wev->ready = 1;
1976
1977 ngx_post_event(rev, &ngx_posted_events);
1978
1979 if (rev->timer_set) {
1980 ngx_del_timer(rev);
1981 }
1982
1983 #if (NGX_DEBUG)
1984 ns++;
1985 #endif
1986 }
1987
1988 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1989 "quic connection has %ui active streams", ns);
1990
1991 return NGX_AGAIN;
1992 }
1993
1994
1995 static ngx_int_t
1996 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf)
1997 {
1998 u_char *p;
1999 ngx_int_t rc;
2000 ngx_uint_t good;
2001 ngx_quic_header_t pkt;
2002 ngx_quic_connection_t *qc;
2003
2004 good = 0;
2005
2006 p = b->pos;
2007
2008 while (p < b->last) {
2009
2010 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
2011 pkt.raw = b;
2012 pkt.data = p;
2013 pkt.len = b->last - p;
2014 pkt.log = c->log;
2015 pkt.flags = p[0];
2016 pkt.raw->pos++;
2017
2018 qc = ngx_quic_get_connection(c);
2019 if (qc) {
2020 qc->error = 0;
2021 qc->error_reason = 0;
2022 }
2023
2024 rc = ngx_quic_process_packet(c, conf, &pkt);
2025
2026 #if (NGX_DEBUG)
2027 if (pkt.parsed) {
2028 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
2029 "quic packet %s done decr:%d pn:%L perr:%ui rc:%i",
2030 ngx_quic_level_name(pkt.level), pkt.decrypted,
2031 pkt.pn, pkt.error, rc);
2032 } else {
2033 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
2034 "quic packet done parse failed rc:%i", rc);
2035 }
2036 #endif
2037
2038 if (rc == NGX_ERROR) {
2039 return NGX_ERROR;
2040 }
2041
2042 if (rc == NGX_OK) {
2043 good = 1;
2044 }
2045
2046 /* NGX_OK || NGX_DECLINED */
2047
2048 /*
2049 * we get NGX_DECLINED when there are no keys [yet] available
2050 * to decrypt packet.
2051 * Instead of queueing it, we ignore it and rely on the sender's
2052 * retransmission:
2053 *
2054 * 12.2. Coalescing Packets:
2055 *
2056 * For example, if decryption fails (because the keys are
2057 * not available or any other reason), the receiver MAY either
2058 * discard or buffer the packet for later processing and MUST
2059 * attempt to process the remaining packets.
2060 *
2061 * We also skip packets that don't match connection state
2062 * or cannot be parsed properly.
2063 */
2064
2065 /* b->pos is at header end, adjust by actual packet length */
2066 b->pos = pkt.data + pkt.len;
2067
2068 /* firefox workaround: skip zero padding at the end of quic packet */
2069 while (b->pos < b->last && *(b->pos) == 0) {
2070 b->pos++;
2071 }
2072
2073 p = b->pos;
2074 }
2075
2076 return good ? NGX_OK : NGX_DECLINED;
2077 }
2078
2079
2080 static ngx_int_t
2081 ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
2082 ngx_quic_header_t *pkt)
2083 {
2084 ngx_int_t rc;
2085 ngx_quic_send_ctx_t *ctx;
2086 ngx_quic_connection_t *qc;
2087
2088 static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
2089
2090 c->log->action = "parsing quic packet";
2091
2092 rc = ngx_quic_parse_packet(pkt);
2093
2094 if (rc == NGX_DECLINED || rc == NGX_ERROR) {
2095 return rc;
2096 }
2097
2098 pkt->parsed = 1;
2099
2100 c->log->action = "processing quic packet";
2101
2102 qc = ngx_quic_get_connection(c);
2103
2104 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
2105 "quic packet rx dcid len:%uz %xV",
2106 pkt->dcid.len, &pkt->dcid);
2107
2108 #if (NGX_DEBUG)
2109 if (pkt->level != ssl_encryption_application) {
2110 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
2111 "quic packet rx scid len:%uz %xV",
2112 pkt->scid.len, &pkt->scid);
2113 }
2114
2115 if (pkt->level == ssl_encryption_initial) {
2116 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
2117 "quic token len:%uz %xV",
2118 pkt->token.len, &pkt->token);
2119 }
2120 #endif
2121
2122 if (qc) {
2123
2124 if (rc == NGX_ABORT) {
2125 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2126 "quic unsupported version: 0x%xD", pkt->version);
2127 return NGX_DECLINED;
2128 }
2129
2130 if (pkt->level != ssl_encryption_application) {
2131 if (pkt->version != qc->version) {
2132 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2133 "quic version mismatch: 0x%xD", pkt->version);
2134 return NGX_DECLINED;
2135 }
2136 }
2137
2138 if (ngx_quic_check_peer(qc, pkt) != NGX_OK) {
2139
2140 if (pkt->level == ssl_encryption_application) {
2141 if (ngx_quic_process_stateless_reset(c, pkt) == NGX_OK) {
2142 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2143 "quic stateless reset packet detected");
2144
2145 qc->draining = 1;
2146 ngx_quic_close_connection(c, NGX_OK);
2147
2148 return NGX_OK;
2149 }
2150
2151 return ngx_quic_send_stateless_reset(c, qc->conf, pkt);
2152 }
2153
2154 return NGX_DECLINED;
2155 }
2156
2157 if (qc->in_retry) {
2158
2159 c->log->action = "retrying quic connection";
2160
2161 if (pkt->level != ssl_encryption_initial) {
2162 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2163 "quic discard late retry packet");
2164 return NGX_DECLINED;
2165 }
2166
2167 if (!pkt->token.len) {
2168 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2169 "quic discard retry packet without token");
2170 return NGX_DECLINED;
2171 }
2172
2173 qc->odcid.len = pkt->dcid.len;
2174 qc->odcid.data = ngx_pstrdup(c->pool, &pkt->dcid);
2175 if (qc->odcid.data == NULL) {
2176 return NGX_ERROR;
2177 }
2178
2179 ngx_quic_clear_temp_server_ids(c);
2180
2181 qc->dcid.len = NGX_QUIC_SERVER_CID_LEN;
2182 qc->dcid.data = ngx_pnalloc(c->pool, qc->dcid.len);
2183 if (qc->dcid.data == NULL) {
2184 return NGX_ERROR;
2185 }
2186
2187 if (ngx_quic_create_server_id(c, qc->dcid.data) != NGX_OK) {
2188 return NGX_ERROR;
2189 }
2190
2191 qc->server_seqnum = 0;
2192
2193 if (ngx_quic_insert_server_id(c, &qc->dcid) == NULL) {
2194 return NGX_ERROR;
2195 }
2196
2197 qc->tp.initial_scid = qc->dcid;
2198 qc->in_retry = 0;
2199
2200 if (ngx_quic_init_secrets(c) != NGX_OK) {
2201 return NGX_ERROR;
2202 }
2203
2204 if (ngx_quic_validate_token(c, pkt) != NGX_OK) {
2205 return NGX_ERROR;
2206 }
2207
2208 qc->validated = 1;
2209 }
2210
2211 } else {
2212
2213 if (rc == NGX_ABORT) {
2214 return ngx_quic_negotiate_version(c, pkt);
2215 }
2216
2217 if (pkt->level == ssl_encryption_initial) {
2218
2219 c->log->action = "creating quic connection";
2220
2221 if (pkt->dcid.len < NGX_QUIC_CID_LEN_MIN) {
2222 /* 7.2. Negotiating Connection IDs */
2223 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2224 "quic too short dcid in initial"
2225 " packet: len:%i", pkt->dcid.len);
2226 return NGX_ERROR;
2227 }
2228
2229 qc = ngx_quic_new_connection(c, conf, pkt);
2230 if (qc == NULL) {
2231 return NGX_ERROR;
2232 }
2233
2234 c->udp = &qc->udp;
2235
2236 if (ngx_terminate || ngx_exiting) {
2237 qc->error = NGX_QUIC_ERR_CONNECTION_REFUSED;
2238 return NGX_ERROR;
2239 }
2240
2241 if (pkt->token.len) {
2242 rc = ngx_quic_validate_token(c, pkt);
2243
2244 if (rc == NGX_OK) {
2245 qc->validated = 1;
2246
2247 } else if (rc == NGX_ERROR) {
2248 return NGX_ERROR;
2249
2250 } else {
2251 /* NGX_DECLINED */
2252 if (conf->retry) {
2253 return ngx_quic_send_retry(c);
2254 }
2255 }
2256
2257 } else if (conf->retry) {
2258 return ngx_quic_send_retry(c);
2259 }
2260
2261 if (ngx_quic_init_secrets(c) != NGX_OK) {
2262 return NGX_ERROR;
2263 }
2264
2265 if (ngx_quic_insert_server_id(c, &qc->odcid) == NULL) {
2266 return NGX_ERROR;
2267 }
2268
2269 qc->server_seqnum = 0;
2270
2271 if (ngx_quic_insert_server_id(c, &qc->dcid) == NULL) {
2272 return NGX_ERROR;
2273 }
2274
2275 } else if (pkt->level == ssl_encryption_application) {
2276 return ngx_quic_send_stateless_reset(c, conf, pkt);
2277
2278 } else {
2279 return NGX_ERROR;
2280 }
2281 }
2282
2283 c->log->action = "decrypting packet";
2284
2285 if (!ngx_quic_keys_available(qc->keys, pkt->level)) {
2286 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2287 "quic no level %d keys yet, ignoring packet", pkt->level);
2288 return NGX_DECLINED;
2289 }
2290
2291 pkt->keys = qc->keys;
2292 pkt->key_phase = qc->key_phase;
2293 pkt->plaintext = buf;
2294
2295 ctx = ngx_quic_get_send_ctx(qc, pkt->level);
2296
2297 rc = ngx_quic_decrypt(pkt, &ctx->largest_pn);
2298 if (rc != NGX_OK) {
2299 qc->error = pkt->error;
2300 qc->error_reason = "failed to decrypt packet";
2301 return rc;
2302 }
2303
2304 pkt->decrypted = 1;
2305
2306 if (c->ssl == NULL) {
2307 if (ngx_quic_init_connection(c) != NGX_OK) {
2308 return NGX_ERROR;
2309 }
2310 }
2311
2312 if (pkt->level == ssl_encryption_handshake) {
2313 /*
2314 * 4.10.1. The successful use of Handshake packets indicates
2315 * that no more Initial packets need to be exchanged
2316 */
2317 ngx_quic_discard_ctx(c, ssl_encryption_initial);
2318
2319 if (qc->validated == 0) {
2320 qc->validated = 1;
2321 ngx_post_event(&qc->push, &ngx_posted_events);
2322 }
2323 }
2324
2325 pkt->received = ngx_current_msec;
2326
2327 c->log->action = "handling payload";
2328
2329 if (pkt->level != ssl_encryption_application) {
2330 return ngx_quic_payload_handler(c, pkt);
2331 }
2332
2333 if (!pkt->key_update) {
2334 return ngx_quic_payload_handler(c, pkt);
2335 }
2336
2337 /* switch keys and generate next on Key Phase change */
2338
2339 qc->key_phase ^= 1;
2340 ngx_quic_keys_switch(c, qc->keys);
2341
2342 rc = ngx_quic_payload_handler(c, pkt);
2343 if (rc != NGX_OK) {
2344 return rc;
2345 }
2346
2347 return ngx_quic_keys_update(c, qc->keys);
2348 }
2349
2350
2351 static ngx_int_t
2352 ngx_quic_init_secrets(ngx_connection_t *c)
2353 {
2354 ngx_quic_connection_t *qc;
2355
2356 qc = ngx_quic_get_connection(c);
2357
2358 if (ngx_quic_keys_set_initial_secret(c->pool, qc->keys, &qc->odcid)
2359 != NGX_OK)
2360 {
2361 return NGX_ERROR;
2362 }
2363
2364 qc->initialized = 1;
2365
2366 return NGX_OK;
2367 }
2368
2369
2370 static void
2371 ngx_quic_discard_ctx(ngx_connection_t *c, enum ssl_encryption_level_t level)
2372 {
2373 ngx_queue_t *q;
2374 ngx_quic_frame_t *f;
2375 ngx_quic_send_ctx_t *ctx;
2376 ngx_quic_connection_t *qc;
2377
2378 qc = ngx_quic_get_connection(c);
2379
2380 if (!ngx_quic_keys_available(qc->keys, level)) {
2381 return;
2382 }
2383
2384 ngx_quic_keys_discard(qc->keys, level);
2385
2386 qc->pto_count = 0;
2387
2388 ctx = ngx_quic_get_send_ctx(qc, level);
2389
2390 while (!ngx_queue_empty(&ctx->sent)) {
2391 q = ngx_queue_head(&ctx->sent);
2392 ngx_queue_remove(q);
2393
2394 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
2395 ngx_quic_congestion_ack(c, f);
2396 ngx_quic_free_frame(c, f);
2397 }
2398
2399 while (!ngx_queue_empty(&ctx->frames)) {
2400 q = ngx_queue_head(&ctx->frames);
2401 ngx_queue_remove(q);
2402
2403 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
2404 ngx_quic_congestion_ack(c, f);
2405 ngx_quic_free_frame(c, f);
2406 }
2407
2408 if (level == ssl_encryption_initial) {
2409 ngx_quic_clear_temp_server_ids(c);
2410 }
2411
2412 ctx->send_ack = 0;
2413 }
2414
2415
2416 static ngx_int_t
2417 ngx_quic_check_peer(ngx_quic_connection_t *qc, ngx_quic_header_t *pkt)
2418 {
2419 ngx_queue_t *q;
2420 ngx_quic_client_id_t *cid;
2421
2422 if (pkt->level == ssl_encryption_application) {
2423 return NGX_OK;
2424 }
2425
2426 for (q = ngx_queue_head(&qc->client_ids);
2427 q != ngx_queue_sentinel(&qc->client_ids);
2428 q = ngx_queue_next(q))
2429 {
2430 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
2431
2432 if (pkt->scid.len == cid->len
2433 && ngx_memcmp(pkt->scid.data, cid->id, cid->len) == 0)
2434 {
2435 return NGX_OK;
2436 }
2437 }
2438
2439 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic unexpected quic scid");
2440 return NGX_ERROR;
2441 }
2442
2443
2444 static ngx_int_t
2445 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
2446 {
2447 u_char *end, *p;
2448 ssize_t len;
2449 ngx_buf_t buf;
2450 ngx_uint_t do_close;
2451 ngx_chain_t chain;
2452 ngx_quic_frame_t frame;
2453 ngx_quic_connection_t *qc;
2454
2455 qc = ngx_quic_get_connection(c);
2456
2457 if (qc->closing) {
2458 /*
2459 * 10.1 Closing and Draining Connection States
2460 * ... delayed or reordered packets are properly discarded.
2461 *
2462 * An endpoint retains only enough information to generate
2463 * a packet containing a CONNECTION_CLOSE frame and to identify
2464 * packets as belonging to the connection.
2465 */
2466
2467 qc->error_level = pkt->level;
2468 qc->error = NGX_QUIC_ERR_NO_ERROR;
2469 qc->error_reason = "connection is closing, packet discarded";
2470 qc->error_ftype = 0;
2471 qc->error_app = 0;
2472
2473 return ngx_quic_send_cc(c);
2474 }
2475
2476 p = pkt->payload.data;
2477 end = p + pkt->payload.len;
2478
2479 do_close = 0;
2480
2481 while (p < end) {
2482
2483 c->log->action = "parsing frames";
2484
2485 ngx_memzero(&buf, sizeof(ngx_buf_t));
2486 buf.temporary = 1;
2487
2488 chain.buf = &buf;
2489 chain.next = NULL;
2490 frame.data = &chain;
2491
2492 len = ngx_quic_parse_frame(pkt, p, end, &frame);
2493
2494 if (len < 0) {
2495 qc->error = pkt->error;
2496 return NGX_ERROR;
2497 }
2498
2499 ngx_quic_log_frame(c->log, &frame, 0);
2500
2501 c->log->action = "handling frames";
2502
2503 p += len;
2504
2505 switch (frame.type) {
2506
2507 case NGX_QUIC_FT_ACK:
2508 if (ngx_quic_handle_ack_frame(c, pkt, &frame) != NGX_OK) {
2509 return NGX_ERROR;
2510 }
2511
2512 continue;
2513
2514 case NGX_QUIC_FT_PADDING:
2515 /* no action required */
2516 continue;
2517
2518 case NGX_QUIC_FT_CONNECTION_CLOSE:
2519 case NGX_QUIC_FT_CONNECTION_CLOSE_APP:
2520 do_close = 1;
2521 continue;
2522 }
2523
2524 /* got there with ack-eliciting packet */
2525 pkt->need_ack = 1;
2526
2527 switch (frame.type) {
2528
2529 case NGX_QUIC_FT_CRYPTO:
2530
2531 if (ngx_quic_handle_crypto_frame(c, pkt, &frame) != NGX_OK) {
2532 return NGX_ERROR;
2533 }
2534
2535 break;
2536
2537 case NGX_QUIC_FT_PING:
2538 break;
2539
2540 case NGX_QUIC_FT_STREAM0:
2541 case NGX_QUIC_FT_STREAM1:
2542 case NGX_QUIC_FT_STREAM2:
2543 case NGX_QUIC_FT_STREAM3:
2544 case NGX_QUIC_FT_STREAM4:
2545 case NGX_QUIC_FT_STREAM5:
2546 case NGX_QUIC_FT_STREAM6:
2547 case NGX_QUIC_FT_STREAM7:
2548
2549 if (ngx_quic_handle_stream_frame(c, pkt, &frame) != NGX_OK) {
2550 return NGX_ERROR;
2551 }
2552
2553 break;
2554
2555 case NGX_QUIC_FT_MAX_DATA:
2556
2557 if (ngx_quic_handle_max_data_frame(c, &frame.u.max_data) != NGX_OK)
2558 {
2559 return NGX_ERROR;
2560 }
2561
2562 break;
2563
2564 case NGX_QUIC_FT_STREAMS_BLOCKED:
2565 case NGX_QUIC_FT_STREAMS_BLOCKED2:
2566
2567 if (ngx_quic_handle_streams_blocked_frame(c, pkt,
2568 &frame.u.streams_blocked)
2569 != NGX_OK)
2570 {
2571 return NGX_ERROR;
2572 }
2573
2574 break;
2575
2576 case NGX_QUIC_FT_STREAM_DATA_BLOCKED:
2577
2578 if (ngx_quic_handle_stream_data_blocked_frame(c, pkt,
2579 &frame.u.stream_data_blocked)
2580 != NGX_OK)
2581 {
2582 return NGX_ERROR;
2583 }
2584
2585 break;
2586
2587 case NGX_QUIC_FT_MAX_STREAM_DATA:
2588
2589 if (ngx_quic_handle_max_stream_data_frame(c, pkt,
2590 &frame.u.max_stream_data)
2591 != NGX_OK)
2592 {
2593 return NGX_ERROR;
2594 }
2595
2596 break;
2597
2598 case NGX_QUIC_FT_RESET_STREAM:
2599
2600 if (ngx_quic_handle_reset_stream_frame(c, pkt,
2601 &frame.u.reset_stream)
2602 != NGX_OK)
2603 {
2604 return NGX_ERROR;
2605 }
2606
2607 break;
2608
2609 case NGX_QUIC_FT_STOP_SENDING:
2610
2611 if (ngx_quic_handle_stop_sending_frame(c, pkt,
2612 &frame.u.stop_sending)
2613 != NGX_OK)
2614 {
2615 return NGX_ERROR;
2616 }
2617
2618 break;
2619
2620 case NGX_QUIC_FT_MAX_STREAMS:
2621 case NGX_QUIC_FT_MAX_STREAMS2:
2622
2623 if (ngx_quic_handle_max_streams_frame(c, pkt, &frame.u.max_streams)
2624 != NGX_OK)
2625 {
2626 return NGX_ERROR;
2627 }
2628
2629 break;
2630
2631 case NGX_QUIC_FT_PATH_CHALLENGE:
2632
2633 if (ngx_quic_handle_path_challenge_frame(c, pkt,
2634 &frame.u.path_challenge)
2635 != NGX_OK)
2636 {
2637 return NGX_ERROR;
2638 }
2639
2640 break;
2641
2642 case NGX_QUIC_FT_NEW_CONNECTION_ID:
2643
2644 if (ngx_quic_handle_new_connection_id_frame(c, pkt, &frame.u.ncid)
2645 != NGX_OK)
2646 {
2647 return NGX_ERROR;
2648 }
2649
2650 break;
2651
2652 case NGX_QUIC_FT_RETIRE_CONNECTION_ID:
2653
2654 if (ngx_quic_handle_retire_connection_id_frame(c, pkt,
2655 &frame.u.retire_cid)
2656 != NGX_OK)
2657 {
2658 return NGX_ERROR;
2659 }
2660
2661 break;
2662
2663 case NGX_QUIC_FT_PATH_RESPONSE:
2664
2665 /* TODO: handle */
2666 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
2667 "quic frame handler not implemented");
2668 break;
2669
2670 default:
2671 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
2672 "quic missing frame handler");
2673 return NGX_ERROR;
2674 }
2675 }
2676
2677 if (p != end) {
2678 ngx_log_error(NGX_LOG_INFO, c->log, 0,
2679 "quic trailing garbage in payload:%ui bytes", end - p);
2680
2681 qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
2682 return NGX_ERROR;
2683 }
2684
2685 if (do_close) {
2686 qc->draining = 1;
2687 ngx_quic_close_connection(c, NGX_OK);
2688 }
2689
2690 if (ngx_quic_ack_packet(c, pkt) != NGX_OK) {
2691 return NGX_ERROR;
2692 }
2693
2694 return NGX_OK;
2695 }
2696
2697
2698 static ngx_int_t
2699 ngx_quic_ack_packet(ngx_connection_t *c, ngx_quic_header_t *pkt)
2700 {
2701 uint64_t base, largest, smallest, gs, ge, gap, range, pn;
2702 uint64_t prev_pending;
2703 ngx_uint_t i, nr;
2704 ngx_quic_send_ctx_t *ctx;
2705 ngx_quic_ack_range_t *r;
2706 ngx_quic_connection_t *qc;
2707
2708 c->log->action = "preparing ack";
2709
2710 qc = ngx_quic_get_connection(c);
2711
2712 ctx = ngx_quic_get_send_ctx(qc, pkt->level);
2713
2714 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
2715 "quic ngx_quic_ack_packet pn:%uL largest %L fr:%uL"
2716 " nranges:%ui", pkt->pn, (int64_t) ctx->largest_range,
2717 ctx->first_range, ctx->nranges);
2718
2719 prev_pending = ctx->pending_ack;
2720
2721 if (pkt->need_ack) {
2722
2723 ngx_post_event(&qc->push, &ngx_posted_events);
2724
2725 if (ctx->send_ack == 0) {
2726 ctx->ack_delay_start = ngx_current_msec;
2727 }
2728
2729 ctx->send_ack++;
2730
2731 if (ctx->pending_ack == NGX_QUIC_UNSET_PN
2732 || ctx->pending_ack < pkt->pn)
2733 {
2734 ctx->pending_ack = pkt->pn;
2735 }
2736 }
2737
2738 base = ctx->largest_range;
2739 pn = pkt->pn;
2740
2741 if (base == NGX_QUIC_UNSET_PN) {
2742 ctx->largest_range = pn;
2743 ctx->largest_received = pkt->received;
2744 return NGX_OK;
2745 }
2746
2747 if (base == pn) {
2748 return NGX_OK;
2749 }
2750
2751 largest = base;
2752 smallest = largest - ctx->first_range;
2753
2754 if (pn > base) {
2755
2756 if (pn - base == 1) {
2757 ctx->first_range++;
2758 ctx->largest_range = pn;
2759 ctx->largest_received = pkt->received;
2760
2761 return NGX_OK;
2762
2763 } else {
2764 /* new gap in front of current largest */
2765
2766 /* no place for new range, send current range as is */
2767 if (ctx->nranges == NGX_QUIC_MAX_RANGES) {
2768
2769 if (prev_pending != NGX_QUIC_UNSET_PN) {
2770 if (ngx_quic_send_ack(c, ctx) != NGX_OK) {
2771 return NGX_ERROR;
2772 }
2773 }
2774
2775 if (prev_pending == ctx->pending_ack || !pkt->need_ack) {
2776 ctx->pending_ack = NGX_QUIC_UNSET_PN;
2777 }
2778 }
2779
2780 gap = pn - base - 2;
2781 range = ctx->first_range;
2782
2783 ctx->first_range = 0;
2784 ctx->largest_range = pn;
2785 ctx->largest_received = pkt->received;
2786
2787 /* packet is out of order, force send */
2788 if (pkt->need_ack) {
2789 ctx->send_ack = NGX_QUIC_MAX_ACK_GAP;
2790 }
2791
2792 i = 0;
2793
2794 goto insert;
2795 }
2796 }
2797
2798 /* pn < base, perform lookup in existing ranges */
2799
2800 /* packet is out of order */
2801 if (pkt->need_ack) {
2802 ctx->send_ack = NGX_QUIC_MAX_ACK_GAP;
2803 }
2804
2805 if (pn >= smallest && pn <= largest) {
2806 return NGX_OK;
2807 }
2808
2809 #if (NGX_SUPPRESS_WARN)
2810 r = NULL;
2811 #endif
2812
2813 for (i = 0; i < ctx->nranges; i++) {
2814 r = &ctx->ranges[i];
2815
2816 ge = smallest - 1;
2817 gs = ge - r->gap;
2818
2819 if (pn >= gs && pn <= ge) {
2820
2821 if (gs == ge) {
2822 /* gap size is exactly one packet, now filled */
2823
2824 /* data moves to previous range, current is removed */
2825
2826 if (i == 0) {
2827 ctx->first_range += r->range + 2;
2828
2829 } else {
2830 ctx->ranges[i - 1].range += r->range + 2;
2831 }
2832
2833 nr = ctx->nranges - i - 1;
2834 if (nr) {
2835 ngx_memmove(&ctx->ranges[i], &ctx->ranges[i + 1],
2836 sizeof(ngx_quic_ack_range_t) * nr);
2837 }
2838
2839 ctx->nranges--;
2840
2841 } else if (pn == gs) {
2842 /* current gap shrinks from tail (current range grows) */
2843 r->gap--;
2844 r->range++;
2845
2846 } else if (pn == ge) {
2847 /* current gap shrinks from head (previous range grows) */
2848 r->gap--;
2849
2850 if (i == 0) {
2851 ctx->first_range++;
2852
2853 } else {
2854 ctx->ranges[i - 1].range++;
2855 }
2856
2857 } else {
2858 /* current gap is split into two parts */
2859
2860 gap = ge - pn - 1;
2861 range = 0;
2862
2863 if (ctx->nranges == NGX_QUIC_MAX_RANGES) {
2864 if (prev_pending != NGX_QUIC_UNSET_PN) {
2865 if (ngx_quic_send_ack(c, ctx) != NGX_OK) {
2866 return NGX_ERROR;
2867 }
2868 }
2869
2870 if (prev_pending == ctx->pending_ack || !pkt->need_ack) {
2871 ctx->pending_ack = NGX_QUIC_UNSET_PN;
2872 }
2873 }
2874
2875 r->gap = pn - gs - 1;
2876 goto insert;
2877 }
2878
2879 return NGX_OK;
2880 }
2881
2882 largest = smallest - r->gap - 2;
2883 smallest = largest - r->range;
2884
2885 if (pn >= smallest && pn <= largest) {
2886 /* this packet number is already known */
2887 return NGX_OK;
2888 }
2889
2890 }
2891
2892 if (pn == smallest - 1) {
2893 /* extend first or last range */
2894
2895 if (i == 0) {
2896 ctx->first_range++;
2897
2898 } else {
2899 r->range++;
2900 }
2901
2902 return NGX_OK;
2903 }
2904
2905 /* nothing found, add new range at the tail */
2906
2907 if (ctx->nranges == NGX_QUIC_MAX_RANGES) {
2908 /* packet is too old to keep it */
2909
2910 if (pkt->need_ack) {
2911 return ngx_quic_send_ack_range(c, ctx, pn, pn);
2912 }
2913
2914 return NGX_OK;
2915 }
2916
2917 gap = smallest - 2 - pn;
2918 range = 0;
2919
2920 insert:
2921
2922 if (ctx->nranges < NGX_QUIC_MAX_RANGES) {
2923 ctx->nranges++;
2924 }
2925
2926 ngx_memmove(&ctx->ranges[i + 1], &ctx->ranges[i],
2927 sizeof(ngx_quic_ack_range_t) * (ctx->nranges - i - 1));
2928
2929 ctx->ranges[i].gap = gap;
2930 ctx->ranges[i].range = range;
2931
2932 return NGX_OK;
2933 }
2934
2935
2936 static ngx_int_t
2937 ngx_quic_send_ack_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
2938 uint64_t smallest, uint64_t largest)
2939 {
2940 ngx_quic_frame_t *frame;
2941
2942 frame = ngx_quic_alloc_frame(c);
2943 if (frame == NULL) {
2944 return NGX_ERROR;
2945 }
2946
2947 frame->level = ctx->level;
2948 frame->type = NGX_QUIC_FT_ACK;
2949 frame->u.ack.largest = largest;
2950 frame->u.ack.delay = 0;
2951 frame->u.ack.range_count = 0;
2952 frame->u.ack.first_range = largest - smallest;
2953
2954 return NGX_OK;
2955 }
2956
2957
2958 static void
2959 ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
2960 uint64_t pn)
2961 {
2962 uint64_t base;
2963 ngx_uint_t i, smallest, largest;
2964 ngx_quic_ack_range_t *r;
2965
2966 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
2967 "quic ngx_quic_drop_ack_ranges pn:%uL largest:%uL"
2968 " fr:%uL nranges:%ui", pn, ctx->largest_range,
2969 ctx->first_range, ctx->nranges);
2970
2971 base = ctx->largest_range;
2972
2973 if (base == NGX_QUIC_UNSET_PN) {
2974 return;
2975 }
2976
2977 if (ctx->pending_ack != NGX_QUIC_UNSET_PN && pn >= ctx->pending_ack) {
2978 ctx->pending_ack = NGX_QUIC_UNSET_PN;
2979 }
2980
2981 largest = base;
2982 smallest = largest - ctx->first_range;
2983
2984 if (pn >= largest) {
2985 ctx->largest_range = NGX_QUIC_UNSET_PN;
2986 ctx->first_range = 0;
2987 ctx->nranges = 0;
2988 return;
2989 }
2990
2991 if (pn >= smallest) {
2992 ctx->first_range = largest - pn - 1;
2993 ctx->nranges = 0;
2994 return;
2995 }
2996
2997 for (i = 0; i < ctx->nranges; i++) {
2998 r = &ctx->ranges[i];
2999
3000 largest = smallest - r->gap - 2;
3001 smallest = largest - r->range;
3002
3003 if (pn >= largest) {
3004 ctx->nranges = i;
3005 return;
3006 }
3007 if (pn >= smallest) {
3008 r->range = largest - pn - 1;
3009 ctx->nranges = i + 1;
3010 return;
3011 }
3012 }
3013 }
3014
3015
3016 static ngx_int_t
3017 ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
3018 {
3019 size_t len, left;
3020 uint64_t ack_delay;
3021 ngx_buf_t *b;
3022 ngx_uint_t i;
3023 ngx_chain_t *cl, **ll;
3024 ngx_quic_frame_t *frame;
3025 ngx_quic_connection_t *qc;
3026
3027 qc = ngx_quic_get_connection(c);
3028
3029 ack_delay = ngx_current_msec - ctx->largest_received;
3030 ack_delay *= 1000;
3031 ack_delay >>= qc->ctp.ack_delay_exponent;
3032
3033 frame = ngx_quic_alloc_frame(c);
3034 if (frame == NULL) {
3035 return NGX_ERROR;
3036 }
3037
3038 ll = &frame->data;
3039 b = NULL;
3040
3041 for (i = 0; i < ctx->nranges; i++) {
3042 len = ngx_quic_create_ack_range(NULL, ctx->ranges[i].gap,
3043 ctx->ranges[i].range);
3044
3045 left = b ? b->end - b->last : 0;
3046
3047 if (left < len) {
3048 cl = ngx_quic_alloc_buf(c);
3049 if (cl == NULL) {
3050 return NGX_ERROR;
3051 }
3052
3053 *ll = cl;
3054 ll = &cl->next;
3055
3056 b = cl->buf;
3057 left = b->end - b->last;
3058
3059 if (left < len) {
3060 return NGX_ERROR;
3061 }
3062 }
3063
3064 b->last += ngx_quic_create_ack_range(b->last, ctx->ranges[i].gap,
3065 ctx->ranges[i].range);
3066
3067 frame->u.ack.ranges_length += len;
3068 }
3069
3070 *ll = NULL;
3071
3072 frame->level = ctx->level;
3073 frame->type = NGX_QUIC_FT_ACK;
3074 frame->u.ack.largest = ctx->largest_range;
3075 frame->u.ack.delay = ack_delay;
3076 frame->u.ack.range_count = ctx->nranges;
3077 frame->u.ack.first_range = ctx->first_range;
3078
3079 ngx_quic_queue_frame(qc, frame);
3080
3081 return NGX_OK;
3082 }
3083
3084
3085 static ngx_int_t
3086 ngx_quic_send_cc(ngx_connection_t *c)
3087 {
3088 ngx_quic_frame_t *frame;
3089 ngx_quic_connection_t *qc;
3090
3091 qc = ngx_quic_get_connection(c);
3092
3093 if (qc->draining) {
3094 return NGX_OK;
3095 }
3096
3097 if (!qc->initialized) {
3098 /* try to initialize secrets to send an early error */
3099 if (ngx_quic_init_secrets(c) != NGX_OK) {
3100 return NGX_OK;
3101 }
3102 }
3103
3104 if (qc->closing
3105 && ngx_current_msec - qc->last_cc < NGX_QUIC_CC_MIN_INTERVAL)
3106 {
3107 /* dot not send CC too often */
3108 return NGX_OK;
3109 }
3110
3111 frame = ngx_quic_alloc_frame(c);
3112 if (frame == NULL) {
3113 return NGX_ERROR;
3114 }
3115
3116 frame->level = qc->error_level;
3117 frame->type = NGX_QUIC_FT_CONNECTION_CLOSE;
3118 frame->u.close.error_code = qc->error;
3119 frame->u.close.frame_type = qc->error_ftype;
3120 frame->u.close.app = qc->error_app;
3121
3122 if (qc->error_reason) {
3123 frame->u.close.reason.len = ngx_strlen(qc->error_reason);
3124 frame->u.close.reason.data = (u_char *) qc->error_reason;
3125 }
3126
3127 ngx_quic_queue_frame(qc, frame);
3128
3129 qc->last_cc = ngx_current_msec;
3130
3131 return ngx_quic_output(c);
3132 }
3133
3134
3135 static ngx_int_t
3136 ngx_quic_send_new_token(ngx_connection_t *c)
3137 {
3138 ngx_str_t token;
3139 ngx_quic_frame_t *frame;
3140 ngx_quic_connection_t *qc;
3141
3142 qc = ngx_quic_get_connection(c);
3143
3144 if (!qc->conf->retry) {
3145 return NGX_OK;
3146 }
3147
3148 if (ngx_quic_new_token(c, &token) != NGX_OK) {
3149 return NGX_ERROR;
3150 }
3151
3152 frame = ngx_quic_alloc_frame(c);
3153 if (frame == NULL) {
3154 return NGX_ERROR;
3155 }
3156
3157 frame->level = ssl_encryption_application;
3158 frame->type = NGX_QUIC_FT_NEW_TOKEN;
3159 frame->u.token.length = token.len;
3160 frame->u.token.data = token.data;
3161
3162 ngx_quic_queue_frame(qc, frame);
3163
3164 return NGX_OK;
3165 }
3166
3167
3168 static ngx_int_t
3169 ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
3170 ngx_quic_frame_t *f)
3171 {
3172 ssize_t n;
3173 u_char *pos, *end;
3174 uint64_t min, max, gap, range;
3175 ngx_msec_t send_time;
3176 ngx_uint_t i;
3177 ngx_quic_send_ctx_t *ctx;
3178 ngx_quic_ack_frame_t *ack;
3179 ngx_quic_connection_t *qc;
3180
3181 qc = ngx_quic_get_connection(c);
3182
3183 ctx = ngx_quic_get_send_ctx(qc, pkt->level);
3184
3185 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3186 "quic ngx_quic_handle_ack_frame level:%d", pkt->level);
3187
3188 ack = &f->u.ack;
3189
3190 /*
3191 * If any computed packet number is negative, an endpoint MUST
3192 * generate a connection error of type FRAME_ENCODING_ERROR.
3193 * (19.3.1)
3194 */
3195
3196 if (ack->first_range > ack->largest) {
3197 qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
3198 ngx_log_error(NGX_LOG_INFO, c->log, 0,
3199 "quic invalid first range in ack frame");
3200 return NGX_ERROR;
3201 }
3202
3203 min = ack->largest - ack->first_range;
3204 max = ack->largest;
3205
3206 if (ngx_quic_handle_ack_frame_range(c, ctx, min, max, &send_time)
3207 != NGX_OK)
3208 {
3209 return NGX_ERROR;
3210 }
3211
3212 /* 13.2.3. Receiver Tracking of ACK Frames */
3213 if (ctx->largest_ack < max || ctx->largest_ack == NGX_QUIC_UNSET_PN) {
3214 ctx->largest_ack = max;
3215 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3216 "quic updated largest received ack:%uL", max);
3217
3218 /*
3219 * An endpoint generates an RTT sample on receiving an
3220 * ACK frame that meets the following two conditions:
3221 *
3222 * - the largest acknowledged packet number is newly acknowledged
3223 * - at least one of the newly acknowledged packets was ack-eliciting.
3224 */
3225
3226 if (send_time != NGX_TIMER_INFINITE) {
3227 ngx_quic_rtt_sample(c, ack, pkt->level, send_time);
3228 }
3229 }
3230
3231 if (f->data) {
3232 pos = f->data->buf->pos;
3233 end = f->data->buf->last;
3234
3235 } else {
3236 pos = NULL;
3237 end = NULL;
3238 }
3239
3240 for (i = 0; i < ack->range_count; i++) {
3241
3242 n = ngx_quic_parse_ack_range(pkt->log, pos, end, &gap, &range);
3243 if (n == NGX_ERROR) {
3244 return NGX_ERROR;
3245 }
3246 pos += n;
3247
3248 if (gap + 2 > min) {
3249 qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
3250 ngx_log_error(NGX_LOG_INFO, c->log, 0,
3251 "quic invalid range:%ui in ack frame", i);
3252 return NGX_ERROR;
3253 }
3254
3255 max = min - gap - 2;
3256
3257 if (range > max) {
3258 qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
3259 ngx_log_error(NGX_LOG_INFO, c->log, 0,
3260 "quic invalid range:%ui in ack frame", i);
3261 return NGX_ERROR;
3262 }
3263
3264 min = max - range;
3265
3266 if (ngx_quic_handle_ack_frame_range(c, ctx, min, max, &send_time)
3267 != NGX_OK)
3268 {
3269 return NGX_ERROR;
3270 }
3271 }
3272
3273 return ngx_quic_detect_lost(c);
3274 }
3275
3276
3277 static ngx_int_t
3278 ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
3279 uint64_t min, uint64_t max, ngx_msec_t *send_time)
3280 {
3281 ngx_uint_t found;
3282 ngx_queue_t *q;
3283 ngx_quic_frame_t *f;
3284 ngx_quic_connection_t *qc;
3285
3286 qc = ngx_quic_get_connection(c);
3287
3288 *send_time = NGX_TIMER_INFINITE;
3289 found = 0;
3290
3291 q = ngx_queue_last(&ctx->sent);
3292
3293 while (q != ngx_queue_sentinel(&ctx->sent)) {
3294
3295 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
3296 q = ngx_queue_prev(q);
3297
3298 if (f->pnum >= min && f->pnum <= max) {
3299 ngx_quic_congestion_ack(c, f);
3300
3301 switch (f->type) {
3302 case NGX_QUIC_FT_ACK:
3303 case NGX_QUIC_FT_ACK_ECN:
3304 ngx_quic_drop_ack_ranges(c, ctx, f->u.ack.largest);
3305 break;
3306
3307 case NGX_QUIC_FT_STREAM0:
3308 case NGX_QUIC_FT_STREAM1:
3309 case NGX_QUIC_FT_STREAM2:
3310 case NGX_QUIC_FT_STREAM3:
3311 case NGX_QUIC_FT_STREAM4:
3312 case NGX_QUIC_FT_STREAM5:
3313 case NGX_QUIC_FT_STREAM6:
3314 case NGX_QUIC_FT_STREAM7:
3315 ngx_quic_handle_stream_ack(c, f);
3316 break;
3317 }
3318
3319 if (f->pnum == max) {
3320 *send_time = f->last;
3321 }
3322
3323 ngx_queue_remove(&f->queue);
3324 ngx_quic_free_frame(c, f);
3325 found = 1;
3326 }
3327 }
3328
3329 if (!found) {
3330
3331 if (max < ctx->pnum) {
3332 /* duplicate ACK or ACK for non-ack-eliciting frame */
3333 return NGX_OK;
3334 }
3335
3336 ngx_log_error(NGX_LOG_INFO, c->log, 0,
3337 "quic ACK for the packet not sent");
3338
3339 qc->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
3340 qc->error_ftype = NGX_QUIC_FT_ACK;
3341 qc->error_reason = "unknown packet number";
3342
3343 return NGX_ERROR;
3344 }
3345
3346 if (!qc->push.timer_set) {
3347 ngx_post_event(&qc->push, &ngx_posted_events);
3348 }
3349
3350 qc->pto_count = 0;
3351
3352 return NGX_OK;
3353 }
3354
3355
3356 static void
3357 ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack,
3358 enum ssl_encryption_level_t level, ngx_msec_t send_time)
3359 {
3360 ngx_msec_t latest_rtt, ack_delay, adjusted_rtt, rttvar_sample;
3361 ngx_quic_connection_t *qc;
3362
3363 qc = ngx_quic_get_connection(c);
3364
3365 latest_rtt = ngx_current_msec - send_time;
3366 qc->latest_rtt = latest_rtt;
3367
3368 if (qc->min_rtt == NGX_TIMER_INFINITE) {
3369 qc->min_rtt = latest_rtt;
3370 qc->avg_rtt = latest_rtt;
3371 qc->rttvar = latest_rtt / 2;
3372
3373 } else {
3374 qc->min_rtt = ngx_min(qc->min_rtt, latest_rtt);
3375
3376 ack_delay = ack->delay * (1 << qc->ctp.ack_delay_exponent) / 1000;
3377
3378 if (c->ssl->handshaked) {
3379 ack_delay = ngx_min(ack_delay, qc->ctp.max_ack_delay);
3380 }
3381
3382 adjusted_rtt = latest_rtt;
3383
3384 if (qc->min_rtt + ack_delay < latest_rtt) {
3385 adjusted_rtt -= ack_delay;
3386 }
3387
3388 qc->avg_rtt = 0.875 * qc->avg_rtt + 0.125 * adjusted_rtt;
3389 rttvar_sample = ngx_abs((ngx_msec_int_t) (qc->avg_rtt - adjusted_rtt));
3390 qc->rttvar = 0.75 * qc->rttvar + 0.25 * rttvar_sample;
3391 }
3392
3393 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
3394 "quic rtt sample latest:%M min:%M avg:%M var:%M",
3395 latest_rtt, qc->min_rtt, qc->avg_rtt, qc->rttvar);
3396 }
3397
3398
3399 static ngx_inline ngx_msec_t
3400 ngx_quic_pto(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
3401 {
3402 ngx_msec_t duration;
3403 ngx_quic_connection_t *qc;
3404
3405 qc = ngx_quic_get_connection(c);
3406
3407 /* PTO calculation: quic-recovery, Appendix 8 */
3408 duration = qc->avg_rtt;
3409
3410 duration += ngx_max(4 * qc->rttvar, NGX_QUIC_TIME_GRANULARITY);
3411 duration <<= qc->pto_count;
3412
3413 if (qc->congestion.in_flight == 0) { /* no in-flight packets */
3414 return duration;
3415 }
3416
3417 if (ctx->level == ssl_encryption_application && c->ssl->handshaked) {
3418 duration += qc->ctp.max_ack_delay << qc->pto_count;
3419 }
3420
3421 return duration;
3422 }
3423
3424
3425 static void
3426 ngx_quic_handle_stream_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
3427 {
3428 uint64_t sent, unacked;
3429 ngx_event_t *wev;
3430 ngx_quic_stream_t *sn;
3431 ngx_quic_connection_t *qc;
3432
3433 qc = ngx_quic_get_connection(c);
3434
3435 sn = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id);
3436 if (sn == NULL) {
3437 return;
3438 }
3439
3440 wev = sn->c->write;
3441 sent = sn->c->sent;
3442 unacked = sent - sn->acked;
3443
3444 if (unacked >= NGX_QUIC_STREAM_BUFSIZE && wev->active) {
3445 wev->ready = 1;
3446 ngx_post_event(wev, &ngx_posted_events);
3447 }
3448
3449 sn->acked += f->u.stream.length;
3450
3451 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, sn->c->log, 0,
3452 "quic stream ack len:%uL acked:%uL unacked:%uL",
3453 f->u.stream.length, sn->acked, sent - sn->acked);
3454 }
3455
3456
3457 static ngx_int_t
3458 ngx_quic_handle_ordered_frame(ngx_connection_t *c, ngx_quic_frames_stream_t *fs,
3459 ngx_quic_frame_t *frame, ngx_quic_frame_handler_pt handler, void *data)
3460 {
3461 size_t full_len;
3462 ngx_int_t rc;
3463 ngx_queue_t *q;
3464 ngx_quic_ordered_frame_t *f;
3465
3466 f = &frame->u.ord;
3467
3468 if (f->offset > fs->received) {
3469 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
3470 "quic out-of-order frame: expecting:%uL got:%uL",
3471 fs->received, f->offset);
3472
3473 return ngx_quic_buffer_frame(c, fs, frame);
3474 }
3475
3476 if (f->offset < fs->received) {
3477
3478 if (ngx_quic_adjust_frame_offset(c, frame, fs->received)
3479 == NGX_DONE)
3480 {
3481 /* old/duplicate data range */
3482 return handler == ngx_quic_crypto_input ? NGX_DECLINED : NGX_OK;
3483 }
3484
3485 /* intersecting data range, frame modified */
3486 }
3487
3488 /* f->offset == fs->received */
3489
3490 rc = handler(c, frame, data);
3491 if (rc == NGX_ERROR) {
3492 return NGX_ERROR;
3493
3494 } else if (rc == NGX_DONE) {
3495 /* handler destroyed stream, queue no longer exists */
3496 return NGX_OK;
3497 }
3498
3499 /* rc == NGX_OK */
3500
3501 fs->received += f->length;
3502
3503 /* now check the queue if we can continue with buffered frames */
3504
3505 do {
3506 q = ngx_queue_head(&fs->frames);
3507 if (q == ngx_queue_sentinel(&fs->frames)) {
3508 break;
3509 }
3510
3511 frame = ngx_queue_data(q, ngx_quic_frame_t, queue);
3512 f = &frame->u.ord;
3513
3514 if (f->offset > fs->received) {
3515 /* gap found, nothing more to do */
3516 break;
3517 }
3518
3519 full_len = f->length;
3520
3521 if (f->offset < fs->received) {
3522
3523 if (ngx_quic_adjust_frame_offset(c, frame, fs->received)
3524 == NGX_DONE)
3525 {
3526 /* old/duplicate data range */
3527 ngx_queue_remove(q);
3528 fs->total -= f->length;
3529
3530 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3531 "quic skipped buffered frame, total:%ui",
3532 fs->total);
3533 ngx_quic_free_frame(c, frame);
3534 continue;
3535 }
3536
3537 /* frame was adjusted, proceed to input */
3538 }
3539
3540 /* f->offset == fs->received */
3541
3542 rc = handler(c, frame, data);
3543
3544 if (rc == NGX_ERROR) {
3545 return NGX_ERROR;
3546
3547 } else if (rc == NGX_DONE) {
3548 /* handler destroyed stream, queue no longer exists */
3549 return NGX_OK;
3550 }
3551
3552 fs->received += f->length;
3553 fs->total -= full_len;
3554
3555 ngx_queue_remove(q);
3556
3557 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3558 "quic consumed buffered frame, total:%ui", fs->total);
3559
3560 ngx_quic_free_frame(c, frame);
3561
3562 } while (1);
3563
3564 return NGX_OK;
3565 }
3566
3567
3568 static ngx_int_t
3569 ngx_quic_adjust_frame_offset(ngx_connection_t *c, ngx_quic_frame_t *frame,
3570 uint64_t offset_in)
3571 {
3572 size_t tail, n;
3573 ngx_buf_t *b;
3574 ngx_chain_t *cl;
3575 ngx_quic_ordered_frame_t *f;
3576
3577 f = &frame->u.ord;
3578
3579 tail = offset_in - f->offset;
3580
3581 if (tail >= f->length) {
3582 /* range preceeding already received data or duplicate, ignore */
3583
3584 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3585 "quic old or duplicate data in ordered frame, ignored");
3586 return NGX_DONE;
3587 }
3588
3589 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3590 "quic adjusted ordered frame data start to expected offset");
3591
3592 /* intersecting range: adjust data size */
3593
3594 f->offset += tail;
3595 f->length -= tail;
3596
3597 for (cl = frame->data; cl; cl = cl->next) {
3598 b = cl->buf;
3599 n = ngx_buf_size(b);
3600
3601 if (n >= tail) {
3602 b->pos += tail;
3603 break;
3604 }
3605
3606 cl->buf->pos = cl->buf->last;
3607 tail -= n;
3608 }
3609
3610 return NGX_OK;
3611 }
3612
3613
3614 static ngx_int_t
3615 ngx_quic_buffer_frame(ngx_connection_t *c, ngx_quic_frames_stream_t *fs,
3616 ngx_quic_frame_t *frame)
3617 {
3618 ngx_queue_t *q;
3619 ngx_quic_frame_t *dst, *item;
3620 ngx_quic_ordered_frame_t *f, *df;
3621
3622 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3623 "quic ngx_quic_buffer_frame");
3624
3625 f = &frame->u.ord;
3626
3627 /* frame start offset is in the future, buffer it */
3628
3629 dst = ngx_quic_alloc_frame(c);
3630 if (dst == NULL) {
3631 return NGX_ERROR;
3632 }
3633
3634 ngx_memcpy(dst, frame, sizeof(ngx_quic_frame_t));
3635
3636 dst->data = ngx_quic_copy_chain(c, frame->data, 0);
3637 if (dst->data == NGX_CHAIN_ERROR) {
3638 return NGX_ERROR;
3639 }
3640
3641 df = &dst->u.ord;
3642
3643 fs->total += f->length;
3644
3645 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3646 "quic ordered frame with unexpected offset:"
3647 " buffered total:%ui", fs->total);
3648
3649 if (ngx_queue_empty(&fs->frames)) {
3650 ngx_queue_insert_after(&fs->frames, &dst->queue);
3651 return NGX_OK;
3652 }
3653
3654 for (q = ngx_queue_last(&fs->frames);
3655 q != ngx_queue_sentinel(&fs->frames);
3656 q = ngx_queue_prev(q))
3657 {
3658 item = ngx_queue_data(q, ngx_quic_frame_t, queue);
3659 f = &item->u.ord;
3660
3661 if (f->offset < df->offset) {
3662 ngx_queue_insert_after(q, &dst->queue);
3663 return NGX_OK;
3664 }
3665 }
3666
3667 ngx_queue_insert_after(&fs->frames, &dst->queue);
3668
3669 return NGX_OK;
3670 }
3671
3672
3673 static ngx_int_t
3674 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
3675 ngx_quic_frame_t *frame)
3676 {
3677 uint64_t last;
3678 ngx_int_t rc;
3679 ngx_quic_send_ctx_t *ctx;
3680 ngx_quic_connection_t *qc;
3681 ngx_quic_crypto_frame_t *f;
3682 ngx_quic_frames_stream_t *fs;
3683
3684 qc = ngx_quic_get_connection(c);
3685 fs = &qc->crypto[pkt->level];
3686 f = &frame->u.crypto;
3687
3688 /* no overflow since both values are 62-bit */
3689 last = f->offset + f->length;
3690
3691 if (last > fs->received && last - fs->received > NGX_QUIC_MAX_BUFFERED) {
3692 qc->error = NGX_QUIC_ERR_CRYPTO_BUFFER_EXCEEDED;
3693 return NGX_ERROR;
3694 }
3695
3696 rc = ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_crypto_input,
3697 NULL);
3698 if (rc != NGX_DECLINED) {
3699 return rc;
3700 }
3701
3702 /* speeding up handshake completion */
3703
3704 if (pkt->level == ssl_encryption_initial) {
3705 ctx = ngx_quic_get_send_ctx(qc, pkt->level);
3706
3707 if (!ngx_queue_empty(&ctx->sent)) {
3708 ngx_quic_resend_frames(c, ctx);
3709
3710 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake);
3711 while (!ngx_queue_empty(&ctx->sent)) {
3712 ngx_quic_resend_frames(c, ctx);
3713 }
3714 }
3715 }
3716
3717 return NGX_OK;
3718 }
3719
3720
3721 static ngx_int_t
3722 ngx_quic_crypto_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data)
3723 {
3724 int n, sslerr;
3725 ngx_buf_t *b;
3726 ngx_chain_t *cl;
3727 ngx_ssl_conn_t *ssl_conn;
3728 ngx_quic_connection_t *qc;
3729
3730 qc = ngx_quic_get_connection(c);
3731
3732 ssl_conn = c->ssl->connection;
3733
3734 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
3735 "quic SSL_quic_read_level:%d SSL_quic_write_level:%d",
3736 (int) SSL_quic_read_level(ssl_conn),
3737 (int) SSL_quic_write_level(ssl_conn));
3738
3739 for (cl = frame->data; cl; cl = cl->next) {
3740 b = cl->buf;
3741
3742 if (!SSL_provide_quic_data(ssl_conn, SSL_quic_read_level(ssl_conn),
3743 b->pos, b->last - b->pos))
3744 {
3745 ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
3746 "SSL_provide_quic_data() failed");
3747 return NGX_ERROR;
3748 }
3749 }
3750
3751 n = SSL_do_handshake(ssl_conn);
3752
3753 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
3754 "quic SSL_quic_read_level:%d SSL_quic_write_level:%d",
3755 (int) SSL_quic_read_level(ssl_conn),
3756 (int) SSL_quic_write_level(ssl_conn));
3757
3758 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
3759
3760 if (n <= 0) {
3761 sslerr = SSL_get_error(ssl_conn, n);
3762
3763 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d",
3764 sslerr);
3765
3766 if (sslerr != SSL_ERROR_WANT_READ) {
3767 ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_do_handshake() failed");
3768 return NGX_ERROR;
3769 }
3770
3771 return NGX_OK;
3772 }
3773
3774 if (SSL_in_init(ssl_conn)) {
3775 return NGX_OK;
3776 }
3777
3778 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3779 "quic ssl cipher:%s", SSL_get_cipher(ssl_conn));
3780
3781 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3782 "quic handshake completed successfully");
3783
3784 c->ssl->handshaked = 1;
3785
3786 frame = ngx_quic_alloc_frame(c);
3787 if (frame == NULL) {
3788 return NGX_ERROR;
3789 }
3790
3791 /* 12.4 Frames and frame types, figure 8 */
3792 frame->level = ssl_encryption_application;
3793 frame->type = NGX_QUIC_FT_HANDSHAKE_DONE;
3794 ngx_quic_queue_frame(qc, frame);
3795
3796 if (ngx_quic_send_new_token(c) != NGX_OK) {
3797 return NGX_ERROR;
3798 }
3799
3800 /*
3801 * Generating next keys before a key update is received.
3802 * See quic-tls 9.4 Header Protection Timing Side-Channels.
3803 */
3804
3805 if (ngx_quic_keys_update(c, qc->keys) != NGX_OK) {
3806 return NGX_ERROR;
3807 }
3808
3809 /*
3810 * 4.10.2 An endpoint MUST discard its handshake keys
3811 * when the TLS handshake is confirmed
3812 */
3813 ngx_quic_discard_ctx(c, ssl_encryption_handshake);
3814
3815 if (ngx_quic_issue_server_ids(c) != NGX_OK) {
3816 return NGX_ERROR;
3817 }
3818
3819 return NGX_OK;
3820 }
3821
3822
3823 static ngx_int_t
3824 ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
3825 ngx_quic_frame_t *frame)
3826 {
3827 size_t window;
3828 uint64_t last;
3829 ngx_buf_t *b;
3830 ngx_pool_t *pool;
3831 ngx_connection_t *sc;
3832 ngx_quic_stream_t *sn;
3833 ngx_quic_connection_t *qc;
3834 ngx_quic_stream_frame_t *f;
3835 ngx_quic_frames_stream_t *fs;
3836
3837 qc = ngx_quic_get_connection(c);
3838 f = &frame->u.stream;
3839
3840 if ((f->stream_id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
3841 && (f->stream_id & NGX_QUIC_STREAM_SERVER_INITIATED))
3842 {
3843 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
3844 return NGX_ERROR;
3845 }
3846
3847 /* no overflow since both values are 62-bit */
3848 last = f->offset + f->length;
3849
3850 sn = ngx_quic_find_stream(&qc->streams.tree, f->stream_id);
3851
3852 if (sn == NULL) {
3853 sn = ngx_quic_create_client_stream(c, f->stream_id);
3854
3855 if (sn == NULL) {
3856 return NGX_ERROR;
3857 }
3858
3859 if (sn == NGX_QUIC_STREAM_GONE) {
3860 return NGX_OK;
3861 }
3862
3863 sc = sn->c;
3864 fs = &sn->fs;
3865 b = sn->b;
3866 window = b->end - b->last;
3867
3868 if (last > window) {
3869 qc->error = NGX_QUIC_ERR_FLOW_CONTROL_ERROR;
3870 goto cleanup;
3871 }
3872
3873 if (ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_stream_input,
3874 sn)
3875 != NGX_OK)
3876 {
3877 goto cleanup;
3878 }
3879
3880 sc->listening->handler(sc);
3881
3882 return NGX_OK;
3883 }
3884
3885 fs = &sn->fs;
3886 b = sn->b;
3887 window = (b->pos - b->start) + (b->end - b->last);
3888
3889 if (last > fs->received && last - fs->received > window) {
3890 qc->error = NGX_QUIC_ERR_FLOW_CONTROL_ERROR;
3891 return NGX_ERROR;
3892 }
3893
3894 return ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_stream_input,
3895 sn);
3896
3897 cleanup:
3898
3899 pool = sc->pool;
3900
3901 ngx_close_connection(sc);
3902 ngx_destroy_pool(pool);
3903
3904 return NGX_ERROR;
3905 }
3906
3907
3908 static ngx_int_t
3909 ngx_quic_stream_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data)
3910 {
3911 uint64_t id;
3912 ngx_buf_t *b;
3913 ngx_event_t *rev;
3914 ngx_chain_t *cl;
3915 ngx_quic_stream_t *sn;
3916 ngx_quic_connection_t *qc;
3917 ngx_quic_stream_frame_t *f;
3918
3919 qc = ngx_quic_get_connection(c);
3920 sn = data;
3921
3922 f = &frame->u.stream;
3923 id = f->stream_id;
3924
3925 b = sn->b;
3926
3927 if ((size_t) ((b->pos - b->start) + (b->end - b->last)) < f->length) {
3928 ngx_log_error(NGX_LOG_INFO, c->log, 0,
3929 "quic no space in stream buffer");
3930 return NGX_ERROR;
3931 }
3932
3933 if ((size_t) (b->end - b->last) < f->length) {
3934 b->last = ngx_movemem(b->start, b->pos, b->last - b->pos);
3935 b->pos = b->start;
3936 }
3937
3938 for (cl = frame->data; cl; cl = cl->next) {
3939 b->last = ngx_cpymem(b->last, cl->buf->pos,
3940 cl->buf->last - cl->buf->pos);
3941 }
3942
3943 rev = sn->c->read;
3944 rev->ready = 1;
3945
3946 if (f->fin) {
3947 rev->pending_eof = 1;
3948 }
3949
3950 if (rev->active) {
3951 rev->handler(rev);
3952 }
3953
3954 /* check if stream was destroyed by handler */
3955 if (ngx_quic_find_stream(&qc->streams.tree, id) == NULL) {
3956 return NGX_DONE;
3957 }
3958
3959 return NGX_OK;
3960 }
3961
3962
3963 static ngx_int_t
3964 ngx_quic_handle_max_data_frame(ngx_connection_t *c,
3965 ngx_quic_max_data_frame_t *f)
3966 {
3967 ngx_event_t *wev;
3968 ngx_rbtree_t *tree;
3969 ngx_rbtree_node_t *node;
3970 ngx_quic_stream_t *qs;
3971 ngx_quic_connection_t *qc;
3972
3973 qc = ngx_quic_get_connection(c);
3974 tree = &qc->streams.tree;
3975
3976 if (f->max_data <= qc->streams.send_max_data) {
3977 return NGX_OK;
3978 }
3979
3980 if (qc->streams.sent >= qc->streams.send_max_data) {
3981
3982 for (node = ngx_rbtree_min(tree->root, tree->sentinel);
3983 node;
3984 node = ngx_rbtree_next(tree, node))
3985 {
3986 qs = (ngx_quic_stream_t *) node;
3987 wev = qs->c->write;
3988
3989 if (wev->active) {
3990 wev->ready = 1;
3991 ngx_post_event(wev, &ngx_posted_events);
3992 }
3993 }
3994 }
3995
3996 qc->streams.send_max_data = f->max_data;
3997
3998 return NGX_OK;
3999 }
4000
4001
4002 static ngx_int_t
4003 ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c,
4004 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f)
4005 {
4006 return NGX_OK;
4007 }
4008
4009
4010 static ngx_int_t
4011 ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c,
4012 ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f)
4013 {
4014 size_t n;
4015 ngx_buf_t *b;
4016 ngx_quic_frame_t *frame;
4017 ngx_quic_stream_t *sn;
4018 ngx_quic_connection_t *qc;
4019
4020 qc = ngx_quic_get_connection(c);
4021
4022 if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
4023 && (f->id & NGX_QUIC_STREAM_SERVER_INITIATED))
4024 {
4025 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
4026 return NGX_ERROR;
4027 }
4028
4029 sn = ngx_quic_find_stream(&qc->streams.tree, f->id);
4030
4031 if (sn == NULL) {
4032 sn = ngx_quic_create_client_stream(c, f->id);
4033
4034 if (sn == NULL) {
4035 return NGX_ERROR;
4036 }
4037
4038 if (sn == NGX_QUIC_STREAM_GONE) {
4039 return NGX_OK;
4040 }
4041
4042 b = sn->b;
4043 n = b->end - b->last;
4044
4045 sn->c->listening->handler(sn->c);
4046
4047 } else {
4048 b = sn->b;
4049 n = sn->fs.received + (b->pos - b->start) + (b->end - b->last);
4050 }
4051
4052 frame = ngx_quic_alloc_frame(c);
4053 if (frame == NULL) {
4054 return NGX_ERROR;
4055 }
4056
4057 frame->level = pkt->level;
4058 frame->type = NGX_QUIC_FT_MAX_STREAM_DATA;
4059 frame->u.max_stream_data.id = f->id;
4060 frame->u.max_stream_data.limit = n;
4061
4062 ngx_quic_queue_frame(qc, frame);
4063
4064 return NGX_OK;
4065 }
4066
4067
4068 static ngx_int_t
4069 ngx_quic_handle_max_stream_data_frame(ngx_connection_t *c,
4070 ngx_quic_header_t *pkt, ngx_quic_max_stream_data_frame_t *f)
4071 {
4072 uint64_t sent;
4073 ngx_event_t *wev;
4074 ngx_quic_stream_t *sn;
4075 ngx_quic_connection_t *qc;
4076
4077 qc = ngx_quic_get_connection(c);
4078
4079 if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
4080 && (f->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0)
4081 {
4082 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
4083 return NGX_ERROR;
4084 }
4085
4086 sn = ngx_quic_find_stream(&qc->streams.tree, f->id);
4087
4088 if (sn == NULL) {
4089 sn = ngx_quic_create_client_stream(c, f->id);
4090
4091 if (sn == NULL) {
4092 return NGX_ERROR;
4093 }
4094
4095 if (sn == NGX_QUIC_STREAM_GONE) {
4096 return NGX_OK;
4097 }
4098
4099 if (f->limit > sn->send_max_data) {
4100 sn->send_max_data = f->limit;
4101 }
4102
4103 sn->c->listening->handler(sn->c);
4104
4105 return NGX_OK;
4106 }
4107
4108 if (f->limit <= sn->send_max_data) {
4109 return NGX_OK;
4110 }
4111
4112 sent = sn->c->sent;
4113
4114 if (sent >= sn->send_max_data) {
4115 wev = sn->c->write;
4116
4117 if (wev->active) {
4118 wev->ready = 1;
4119 ngx_post_event(wev, &ngx_posted_events);
4120 }
4121 }
4122
4123 sn->send_max_data = f->limit;
4124
4125 return NGX_OK;
4126 }
4127
4128
4129 static ngx_int_t
4130 ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
4131 ngx_quic_header_t *pkt, ngx_quic_reset_stream_frame_t *f)
4132 {
4133 ngx_event_t *rev;
4134 ngx_connection_t *sc;
4135 ngx_quic_stream_t *sn;
4136 ngx_quic_connection_t *qc;
4137
4138 qc = ngx_quic_get_connection(c);
4139
4140 if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
4141 && (f->id & NGX_QUIC_STREAM_SERVER_INITIATED))
4142 {
4143 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
4144 return NGX_ERROR;
4145 }
4146
4147 sn = ngx_quic_find_stream(&qc->streams.tree, f->id);
4148
4149 if (sn == NULL) {
4150 sn = ngx_quic_create_client_stream(c, f->id);
4151
4152 if (sn == NULL) {
4153 return NGX_ERROR;
4154 }
4155
4156 if (sn == NGX_QUIC_STREAM_GONE) {
4157 return NGX_OK;
4158 }
4159
4160 sc = sn->c;
4161
4162 rev = sc->read;
4163 rev->error = 1;
4164 rev->ready = 1;
4165
4166 sc->listening->handler(sc);
4167
4168 return NGX_OK;
4169 }
4170
4171 rev = sn->c->read;
4172 rev->error = 1;
4173 rev->ready = 1;
4174
4175 if (rev->active) {
4176 rev->handler(rev);
4177 }
4178
4179 return NGX_OK;
4180 }
4181
4182
4183 static ngx_int_t
4184 ngx_quic_handle_stop_sending_frame(ngx_connection_t *c,
4185 ngx_quic_header_t *pkt, ngx_quic_stop_sending_frame_t *f)
4186 {
4187 ngx_event_t *wev;
4188 ngx_connection_t *sc;
4189 ngx_quic_stream_t *sn;
4190 ngx_quic_connection_t *qc;
4191
4192 qc = ngx_quic_get_connection(c);
4193
4194 if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
4195 && (f->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0)
4196 {
4197 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
4198 return NGX_ERROR;
4199 }
4200
4201 sn = ngx_quic_find_stream(&qc->streams.tree, f->id);
4202
4203 if (sn == NULL) {
4204 sn = ngx_quic_create_client_stream(c, f->id);
4205
4206 if (sn == NULL) {
4207 return NGX_ERROR;
4208 }
4209
4210 if (sn == NGX_QUIC_STREAM_GONE) {
4211 return NGX_OK;
4212 }
4213
4214 sc = sn->c;
4215
4216 wev = sc->write;
4217 wev->error = 1;
4218 wev->ready = 1;
4219
4220 sc->listening->handler(sc);
4221
4222 return NGX_OK;
4223 }
4224
4225 wev = sn->c->write;
4226 wev->error = 1;
4227 wev->ready = 1;
4228
4229 if (wev->active) {
4230 wev->handler(wev);
4231 }
4232
4233 return NGX_OK;
4234 }
4235
4236
4237 static ngx_int_t
4238 ngx_quic_handle_max_streams_frame(ngx_connection_t *c,
4239 ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f)
4240 {
4241 ngx_quic_connection_t *qc;
4242
4243 qc = ngx_quic_get_connection(c);
4244
4245 if (f->bidi) {
4246 if (qc->streams.server_max_streams_bidi < f->limit) {
4247 qc->streams.server_max_streams_bidi = f->limit;
4248
4249 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
4250 "quic max_streams_bidi:%uL", f->limit);
4251 }
4252
4253 } else {
4254 if (qc->streams.server_max_streams_uni < f->limit) {
4255 qc->streams.server_max_streams_uni = f->limit;
4256
4257 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
4258 "quic max_streams_uni:%uL", f->limit);
4259 }
4260 }
4261
4262 return NGX_OK;
4263 }
4264
4265
4266 static ngx_int_t
4267 ngx_quic_handle_path_challenge_frame(ngx_connection_t *c,
4268 ngx_quic_header_t *pkt, ngx_quic_path_challenge_frame_t *f)
4269 {
4270 ngx_quic_frame_t *frame;
4271 ngx_quic_connection_t *qc;
4272
4273 qc = ngx_quic_get_connection(c);
4274
4275 frame = ngx_quic_alloc_frame(c);
4276 if (frame == NULL) {
4277 return NGX_ERROR;
4278 }
4279
4280 frame->level = pkt->level;
4281 frame->type = NGX_QUIC_FT_PATH_RESPONSE;
4282 frame->u.path_response = *f;
4283
4284 ngx_quic_queue_frame(qc, frame);
4285
4286 return NGX_OK;
4287 }
4288
4289
4290 static ngx_int_t
4291 ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c,
4292 ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f)
4293 {
4294 ngx_queue_t *q;
4295 ngx_quic_client_id_t *cid, *item;
4296 ngx_quic_connection_t *qc;
4297
4298 qc = ngx_quic_get_connection(c);
4299
4300 if (f->seqnum < qc->max_retired_seqnum) {
4301 /*
4302 * An endpoint that receives a NEW_CONNECTION_ID frame with
4303 * a sequence number smaller than the Retire Prior To field
4304 * of a previously received NEW_CONNECTION_ID frame MUST send
4305 * a corresponding RETIRE_CONNECTION_ID frame that retires
4306 * the newly received connection ID, unless it has already
4307 * done so for that sequence number.
4308 */
4309
4310 if (ngx_quic_retire_connection_id(c, pkt->level, f->seqnum) != NGX_OK) {
4311 return NGX_ERROR;
4312 }
4313
4314 goto retire;
4315 }
4316
4317 cid = NULL;
4318
4319 for (q = ngx_queue_head(&qc->client_ids);
4320 q != ngx_queue_sentinel(&qc->client_ids);
4321 q = ngx_queue_next(q))
4322 {
4323 item = ngx_queue_data(q, ngx_quic_client_id_t, queue);
4324
4325 if (item->seqnum == f->seqnum) {
4326 cid = item;
4327 break;
4328 }
4329 }
4330
4331 if (cid) {
4332 /*
4333 * Transmission errors, timeouts and retransmissions might cause the
4334 * same NEW_CONNECTION_ID frame to be received multiple times
4335 */
4336
4337 if (cid->len != f->len
4338 || ngx_strncmp(cid->id, f->cid, f->len) != 0
4339 || ngx_strncmp(cid->sr_token, f->srt, NGX_QUIC_SR_TOKEN_LEN) != 0)
4340 {
4341 /*
4342 * ..a sequence number is used for different connection IDs,
4343 * the endpoint MAY treat that receipt as a connection error
4344 * of type PROTOCOL_VIOLATION.
4345 */
4346 qc->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
4347 qc->error_reason = "seqnum refers to different connection id/token";
4348 return NGX_ERROR;
4349 }
4350
4351 } else {
4352
4353 cid = ngx_quic_alloc_client_id(c, qc);
4354 if (cid == NULL) {
4355 return NGX_ERROR;
4356 }
4357
4358 cid->seqnum = f->seqnum;
4359 cid->len = f->len;
4360 ngx_memcpy(cid->id, f->cid, f->len);
4361
4362 ngx_memcpy(cid->sr_token, f->srt, NGX_QUIC_SR_TOKEN_LEN);
4363
4364 ngx_queue_insert_tail(&qc->client_ids, &cid->queue);
4365 qc->nclient_ids++;
4366
4367 /* always use latest available connection id */
4368 if (f->seqnum > qc->client_seqnum) {
4369 qc->scid.len = cid->len;
4370 qc->scid.data = cid->id;
4371 qc->client_seqnum = f->seqnum;
4372 }
4373 }
4374
4375 retire:
4376
4377 if (qc->max_retired_seqnum && f->retire <= qc->max_retired_seqnum) {
4378 /*
4379 * Once a sender indicates a Retire Prior To value, smaller values sent
4380 * in subsequent NEW_CONNECTION_ID frames have no effect. A receiver
4381 * MUST ignore any Retire Prior To fields that do not increase the
4382 * largest received Retire Prior To value.
4383 */
4384 goto done;
4385 }
4386
4387 qc->max_retired_seqnum = f->retire;
4388
4389 q = ngx_queue_head(&qc->client_ids);
4390
4391 while (q != ngx_queue_sentinel(&qc->client_ids)) {
4392
4393 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
4394 q = ngx_queue_next(q);
4395
4396 if (cid->seqnum >= f->retire) {
4397 continue;
4398 }
4399
4400 /* this connection id must be retired */
4401
4402 if (ngx_quic_retire_connection_id(c, pkt->level, cid->seqnum)
4403 != NGX_OK)
4404 {
4405 return NGX_ERROR;
4406 }
4407
4408 ngx_queue_remove(&cid->queue);
4409 ngx_queue_insert_head(&qc->free_client_ids, &cid->queue);
4410 qc->nclient_ids--;
4411 }
4412
4413 done:
4414
4415 if (qc->nclient_ids > qc->tp.active_connection_id_limit) {
4416 /*
4417 * After processing a NEW_CONNECTION_ID frame and
4418 * adding and retiring active connection IDs, if the number of active
4419 * connection IDs exceeds the value advertised in its
4420 * active_connection_id_limit transport parameter, an endpoint MUST
4421 * close the connection with an error of type CONNECTION_ID_LIMIT_ERROR.
4422 */
4423 qc->error = NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR;
4424 qc->error_reason = "too many connection ids received";
4425 return NGX_ERROR;
4426 }
4427
4428 return NGX_OK;
4429 }
4430
4431
4432 static ngx_int_t
4433 ngx_quic_retire_connection_id(ngx_connection_t *c,
4434 enum ssl_encryption_level_t level, uint64_t seqnum)
4435 {
4436 ngx_quic_frame_t *frame;
4437 ngx_quic_connection_t *qc;
4438
4439 qc = ngx_quic_get_connection(c);
4440
4441 frame = ngx_quic_alloc_frame(c);
4442 if (frame == NULL) {
4443 return NGX_ERROR;
4444 }
4445
4446 frame->level = level;
4447 frame->type = NGX_QUIC_FT_RETIRE_CONNECTION_ID;
4448 frame->u.retire_cid.sequence_number = seqnum;
4449
4450 ngx_quic_queue_frame(qc, frame);
4451
4452 return NGX_OK;
4453 }
4454
4455
4456 static ngx_int_t
4457 ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c,
4458 ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f)
4459 {
4460 ngx_queue_t *q;
4461 ngx_quic_server_id_t *sid;
4462 ngx_quic_connection_t *qc;
4463
4464 qc = ngx_quic_get_connection(c);
4465
4466 for (q = ngx_queue_head(&qc->server_ids);
4467 q != ngx_queue_sentinel(&qc->server_ids);
4468 q = ngx_queue_next(q))
4469 {
4470 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
4471
4472 if (sid->seqnum == f->sequence_number) {
4473 ngx_queue_remove(q);
4474 ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue);
4475 ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node);
4476 qc->nserver_ids--;
4477 break;
4478 }
4479 }
4480
4481 return ngx_quic_issue_server_ids(c);
4482 }
4483
4484
4485 static ngx_int_t
4486 ngx_quic_issue_server_ids(ngx_connection_t *c)
4487 {
4488 ngx_str_t dcid;
4489 ngx_uint_t n;
4490 ngx_quic_frame_t *frame;
4491 ngx_quic_server_id_t *sid;
4492 ngx_quic_connection_t *qc;
4493 u_char id[NGX_QUIC_SERVER_CID_LEN];
4494
4495 qc = ngx_quic_get_connection(c);
4496
4497 n = ngx_min(NGX_QUIC_MAX_SERVER_IDS, qc->ctp.active_connection_id_limit);
4498
4499 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
4500 "quic issue server ids has:%ui max:%ui", qc->nserver_ids, n);
4501
4502 while (qc->nserver_ids < n) {
4503 if (ngx_quic_create_server_id(c, id) != NGX_OK) {
4504 return NGX_ERROR;
4505 }
4506
4507 dcid.len = NGX_QUIC_SERVER_CID_LEN;
4508 dcid.data = id;
4509
4510 sid = ngx_quic_insert_server_id(c, &dcid);
4511 if (sid == NULL) {
4512 return NGX_ERROR;
4513 }
4514
4515 frame = ngx_quic_alloc_frame(c);
4516 if (frame == NULL) {
4517 return NGX_ERROR;
4518 }
4519
4520 frame->level = ssl_encryption_application;
4521 frame->type = NGX_QUIC_FT_NEW_CONNECTION_ID;
4522 frame->u.ncid.seqnum = sid->seqnum;
4523 frame->u.ncid.retire = 0;
4524 frame->u.ncid.len = NGX_QUIC_SERVER_CID_LEN;
4525 ngx_memcpy(frame->u.ncid.cid, id, NGX_QUIC_SERVER_CID_LEN);
4526
4527 if (ngx_quic_new_sr_token(c, &dcid, &qc->conf->sr_token_key,
4528 frame->u.ncid.srt)
4529 != NGX_OK)
4530 {
4531 return NGX_ERROR;
4532 }
4533
4534 ngx_quic_queue_frame(qc, frame);
4535 }
4536
4537 return NGX_OK;
4538 }
4539
4540
4541 static void
4542 ngx_quic_clear_temp_server_ids(ngx_connection_t *c)
4543 {
4544 ngx_queue_t *q, *next;
4545 ngx_quic_server_id_t *sid;
4546 ngx_quic_connection_t *qc;
4547
4548 qc = ngx_quic_get_connection(c);
4549
4550 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
4551 "quic clear temp server ids");
4552
4553 for (q = ngx_queue_head(&qc->server_ids);
4554 q != ngx_queue_sentinel(&qc->server_ids);
4555 q = next)
4556 {
4557 next = ngx_queue_next(q);
4558 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
4559
4560 if (sid->seqnum != NGX_QUIC_UNSET_PN) {
4561 continue;
4562 }
4563
4564 ngx_queue_remove(q);
4565 ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue);
4566 ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node);
4567 qc->nserver_ids--;
4568 }
4569 }
4570
4571
4572 static ngx_quic_server_id_t *
4573 ngx_quic_insert_server_id(ngx_connection_t *c, ngx_str_t *id)
4574 {
4575 ngx_str_t dcid;
4576 ngx_quic_server_id_t *sid;
4577 ngx_quic_connection_t *qc;
4578
4579 qc = ngx_quic_get_connection(c);
4580
4581 sid = ngx_quic_alloc_server_id(c, qc);
4582 if (sid == NULL) {
4583 return NULL;
4584 }
4585
4586 sid->seqnum = qc->server_seqnum;
4587
4588 if (qc->server_seqnum != NGX_QUIC_UNSET_PN) {
4589 qc->server_seqnum++;
4590 }
4591
4592 sid->len = id->len;
4593 ngx_memcpy(sid->id, id->data, id->len);
4594
4595 ngx_queue_insert_tail(&qc->server_ids, &sid->queue);
4596 qc->nserver_ids++;
4597
4598 dcid.data = sid->id;
4599 dcid.len = sid->len;
4600
4601 ngx_insert_udp_connection(c, &sid->udp, &dcid);
4602
4603 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4604 "quic insert server id seqnum:%uL id len:%uz %xV",
4605 sid->seqnum, id->len, id);
4606
4607 return sid;
4608 }
4609
4610
4611 static ngx_quic_client_id_t *
4612 ngx_quic_alloc_client_id(ngx_connection_t *c, ngx_quic_connection_t *qc)
4613 {
4614 ngx_queue_t *q;
4615 ngx_quic_client_id_t *cid;
4616
4617 if (!ngx_queue_empty(&qc->free_client_ids)) {
4618
4619 q = ngx_queue_head(&qc->free_client_ids);
4620 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
4621
4622 ngx_queue_remove(&cid->queue);
4623
4624 ngx_memzero(cid, sizeof(ngx_quic_client_id_t));
4625
4626 } else {
4627
4628 cid = ngx_pcalloc(c->pool, sizeof(ngx_quic_client_id_t));
4629 if (cid == NULL) {
4630 return NULL;
4631 }
4632 }
4633
4634 return cid;
4635 }
4636
4637
4638 static ngx_quic_server_id_t *
4639 ngx_quic_alloc_server_id(ngx_connection_t *c, ngx_quic_connection_t *qc)
4640 {
4641 ngx_queue_t *q;
4642 ngx_quic_server_id_t *sid;
4643
4644 if (!ngx_queue_empty(&qc->free_server_ids)) {
4645
4646 q = ngx_queue_head(&qc->free_server_ids);
4647 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
4648
4649 ngx_queue_remove(&sid->queue);
4650
4651 ngx_memzero(sid, sizeof(ngx_quic_server_id_t));
4652
4653 } else {
4654
4655 sid = ngx_pcalloc(c->pool, sizeof(ngx_quic_server_id_t));
4656 if (sid == NULL) {
4657 return NULL;
4658 }
4659 }
4660
4661 return sid;
4662 }
4663
4664
4665 static void
4666 ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame)
4667 {
4668 ngx_quic_send_ctx_t *ctx;
4669
4670 ctx = ngx_quic_get_send_ctx(qc, frame->level);
4671
4672 ngx_queue_insert_tail(&ctx->frames, &frame->queue);
4673
4674 frame->len = ngx_quic_create_frame(NULL, frame);
4675 /* always succeeds */
4676
4677 if (qc->closing) {
4678 return;
4679 }
4680
4681 ngx_post_event(&qc->push, &ngx_posted_events);
4682 }
4683
4684
4685 static ngx_int_t
4686 ngx_quic_output(ngx_connection_t *c)
4687 {
4688 off_t max;
4689 size_t len, min;
4690 ssize_t n;
4691 u_char *p;
4692 ngx_uint_t i, pad;
4693 ngx_quic_send_ctx_t *ctx;
4694 ngx_quic_connection_t *qc;
4695 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
4696
4697 c->log->action = "sending frames";
4698
4699 qc = ngx_quic_get_connection(c);
4700
4701 for ( ;; ) {
4702 p = dst;
4703
4704 len = ngx_min(qc->ctp.max_udp_payload_size,
4705 NGX_QUIC_MAX_UDP_PAYLOAD_SIZE);
4706
4707 if (!qc->validated) {
4708 max = qc->received * 3;
4709 max = (c->sent >= max) ? 0 : max - c->sent;
4710 len = ngx_min(len, (size_t) max);
4711 }
4712
4713 pad = ngx_quic_get_padding_level(c);
4714
4715 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
4716
4717 ctx = &qc->send_ctx[i];
4718
4719 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) {
4720 return NGX_ERROR;
4721 }
4722
4723 min = (i == pad && p - dst < NGX_QUIC_MIN_INITIAL_SIZE)
4724 ? NGX_QUIC_MIN_INITIAL_SIZE - (p - dst) : 0;
4725
4726 n = ngx_quic_output_packet(c, ctx, p, len, min);
4727 if (n == NGX_ERROR) {
4728 return NGX_ERROR;
4729 }
4730
4731 p += n;
4732 len -= n;
4733 }
4734
4735 len = p - dst;
4736 if (len == 0) {
4737 break;
4738 }
4739
4740 n = ngx_quic_send(c, dst, len);
4741 if (n == NGX_ERROR) {
4742 return NGX_ERROR;
4743 }
4744
4745 if (!qc->send_timer_set && !qc->closing) {
4746 qc->send_timer_set = 1;
4747 ngx_add_timer(c->read, qc->tp.max_idle_timeout);
4748 }
4749 }
4750
4751 return NGX_OK;
4752 }
4753
4754
4755 static ngx_uint_t
4756 ngx_quic_get_padding_level(ngx_connection_t *c)
4757 {
4758 ngx_queue_t *q;
4759 ngx_quic_frame_t *f;
4760 ngx_quic_send_ctx_t *ctx;
4761 ngx_quic_connection_t *qc;
4762
4763 /*
4764 * 14.1. Initial Datagram Size
4765 *
4766 * Similarly, a server MUST expand the payload of all UDP datagrams
4767 * carrying ack-eliciting Initial packets to at least the smallest
4768 * allowed maximum datagram size of 1200 bytes
4769 */
4770
4771 qc = ngx_quic_get_connection(c);
4772 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial);
4773
4774 for (q = ngx_queue_head(&ctx->frames);
4775 q != ngx_queue_sentinel(&ctx->frames);
4776 q = ngx_queue_next(q))
4777 {
4778 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
4779
4780 if (f->need_ack) {
4781 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake);
4782
4783 if (ngx_queue_empty(&ctx->frames)) {
4784 return 0;
4785 }
4786
4787 return 1;
4788 }
4789 }
4790
4791 return NGX_QUIC_SEND_CTX_LAST;
4792 }
4793
4794
4795 static ngx_int_t
4796 ngx_quic_generate_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
4797 {
4798 ngx_msec_t delay;
4799 ngx_quic_connection_t *qc;
4800
4801 if (!ctx->send_ack) {
4802 return NGX_OK;
4803 }
4804
4805 if (ctx->level == ssl_encryption_application) {
4806
4807 delay = ngx_current_msec - ctx->ack_delay_start;
4808 qc = ngx_quic_get_connection(c);
4809
4810 if (ctx->send_ack < NGX_QUIC_MAX_ACK_GAP
4811 && delay < qc->tp.max_ack_delay)
4812 {
4813 if (!qc->push.timer_set && !qc->closing) {
4814 ngx_add_timer(&qc->push,
4815 qc->tp.max_ack_delay - delay);
4816 }
4817
4818 return NGX_OK;
4819 }
4820 }
4821
4822 if (ngx_quic_send_ack(c, ctx) != NGX_OK) {
4823 return NGX_ERROR;
4824 }
4825
4826 ctx->send_ack = 0;
4827
4828 return NGX_OK;
4829 }
4830
4831
4832 static ssize_t
4833 ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
4834 u_char *data, size_t max, size_t min)
4835 {
4836 size_t len, hlen, pad_len;
4837 u_char *p;
4838 ssize_t flen;
4839 ngx_str_t out, res;
4840 ngx_int_t rc;
4841 ngx_uint_t nframes;
4842 ngx_msec_t now;
4843 ngx_queue_t *q;
4844 ngx_quic_frame_t *f;
4845 ngx_quic_header_t pkt;
4846 ngx_quic_congestion_t *cg;
4847 ngx_quic_connection_t *qc;
4848 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
4849
4850 if (ngx_queue_empty(&ctx->frames)) {
4851 return 0;
4852 }
4853
4854 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
4855 "quic output %s packet max:%uz min:%uz",
4856 ngx_quic_level_name(ctx->level), max, min);
4857
4858 qc = ngx_quic_get_connection(c);
4859 cg = &qc->congestion;
4860
4861 hlen = (ctx->level == ssl_encryption_application)
4862 ? NGX_QUIC_MAX_SHORT_HEADER
4863 : NGX_QUIC_MAX_LONG_HEADER;
4864
4865 hlen += EVP_GCM_TLS_TAG_LEN;
4866 hlen -= NGX_QUIC_MAX_CID_LEN - qc->scid.len;
4867
4868 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
4869
4870 now = ngx_current_msec;
4871 nframes = 0;
4872 p = src;
4873 len = 0;
4874
4875 for (q = ngx_queue_head(&ctx->frames);
4876 q != ngx_queue_sentinel(&ctx->frames);
4877 q = ngx_queue_next(q))
4878 {
4879 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
4880
4881 if (!pkt.need_ack && f->need_ack && max > cg->window) {
4882 max = cg->window;
4883 }
4884
4885 if (hlen + len >= max) {
4886 break;
4887 }
4888
4889 if (hlen + len + f->len > max) {
4890 rc = ngx_quic_split_frame(c, f, max - hlen - len);
4891
4892 if (rc == NGX_ERROR) {
4893 return NGX_ERROR;
4894 }
4895
4896 if (rc == NGX_DECLINED) {
4897 break;
4898 }
4899 }
4900
4901 if (f->need_ack) {
4902 pkt.need_ack = 1;
4903 }
4904
4905 ngx_quic_log_frame(c->log, f, 1);
4906
4907 flen = ngx_quic_create_frame(p, f);
4908 if (flen == -1) {
4909 return NGX_ERROR;
4910 }
4911
4912 len += flen;
4913 p += flen;
4914
4915 f->pnum = ctx->pnum;
4916 f->first = now;
4917 f->last = now;
4918 f->plen = 0;
4919
4920 nframes++;
4921 }
4922
4923 if (nframes == 0) {
4924 return 0;
4925 }
4926
4927 out.data = src;
4928 out.len = len;
4929
4930 pkt.keys = qc->keys;
4931 pkt.flags = NGX_QUIC_PKT_FIXED_BIT;
4932
4933 if (ctx->level == ssl_encryption_initial) {
4934 pkt.flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_INITIAL;
4935
4936 } else if (ctx->level == ssl_encryption_handshake) {
4937 pkt.flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_HANDSHAKE;
4938
4939 } else {
4940 if (qc->key_phase) {
4941 pkt.flags |= NGX_QUIC_PKT_KPHASE;
4942 }
4943 }
4944
4945 ngx_quic_set_packet_number(&pkt, ctx);
4946
4947 pkt.version = qc->version;
4948 pkt.log = c->log;
4949 pkt.level = ctx->level;
4950 pkt.dcid = qc->scid;
4951 pkt.scid = qc->dcid;
4952
4953 pad_len = 4;
4954
4955 if (min) {
4956 hlen = EVP_GCM_TLS_TAG_LEN
4957 + ngx_quic_create_header(&pkt, NULL, out.len, NULL);
4958
4959 if (min > hlen + pad_len) {
4960 pad_len = min - hlen;
4961 }
4962 }
4963
4964 if (out.len < pad_len) {
4965 ngx_memset(p, NGX_QUIC_FT_PADDING, pad_len - out.len);
4966 out.len = pad_len;
4967 }
4968
4969 pkt.payload = out;
4970
4971 res.data = data;
4972
4973 ngx_log_debug6(NGX_LOG_DEBUG_EVENT, c->log, 0,
4974 "quic packet tx %s bytes:%ui"
4975 " need_ack:%d number:%L encoded nl:%d trunc:0x%xD",
4976 ngx_quic_level_name(ctx->level), out.len, pkt.need_ack,
4977 pkt.number, pkt.num_len, pkt.trunc);
4978
4979 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
4980 return NGX_ERROR;
4981 }
4982
4983 ctx->pnum++;
4984
4985 if (pkt.need_ack) {
4986 /* move frames into the sent queue to wait for ack */
4987
4988 if (!qc->closing) {
4989 q = ngx_queue_head(&ctx->frames);
4990 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
4991 f->plen = res.len;
4992
4993 do {
4994 q = ngx_queue_head(&ctx->frames);
4995 ngx_queue_remove(q);
4996 ngx_queue_insert_tail(&ctx->sent, q);
4997 } while (--nframes);
4998
4999 if (qc->pto.timer_set) {
5000 ngx_del_timer(&qc->pto);
5001 }
5002
5003 ngx_add_timer(&qc->pto, ngx_quic_pto(c, ctx));
5004 }
5005
5006 cg->in_flight += res.len;
5007
5008 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5009 "quic congestion send if:%uz", cg->in_flight);
5010 }
5011
5012 while (nframes--) {
5013 q = ngx_queue_head(&ctx->frames);
5014 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
5015
5016 ngx_queue_remove(q);
5017 ngx_quic_free_frame(c, f);
5018 }
5019
5020 return res.len;
5021 }
5022
5023
5024 static ngx_int_t
5025 ngx_quic_split_frame(ngx_connection_t *c, ngx_quic_frame_t *f, size_t len)
5026 {
5027 size_t shrink;
5028 ngx_quic_frame_t *nf;
5029 ngx_quic_ordered_frame_t *of, *onf;
5030
5031 switch (f->type) {
5032 case NGX_QUIC_FT_CRYPTO:
5033 case NGX_QUIC_FT_STREAM0:
5034 case NGX_QUIC_FT_STREAM1:
5035 case NGX_QUIC_FT_STREAM2:
5036 case NGX_QUIC_FT_STREAM3:
5037 case NGX_QUIC_FT_STREAM4:
5038 case NGX_QUIC_FT_STREAM5:
5039 case NGX_QUIC_FT_STREAM6:
5040 case NGX_QUIC_FT_STREAM7:
5041 break;
5042
5043 default:
5044 return NGX_DECLINED;
5045 }
5046
5047 if ((size_t) f->len <= len) {
5048 return NGX_OK;
5049 }
5050
5051 shrink = f->len - len;
5052
5053 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
5054 "quic split frame now:%uz need:%uz shrink:%uz",
5055 f->len, len, shrink);
5056
5057 of = &f->u.ord;
5058
5059 if (of->length <= shrink) {
5060 return NGX_DECLINED;
5061 }
5062
5063 of->length -= shrink;
5064 f->len = ngx_quic_create_frame(NULL, f);
5065
5066 if ((size_t) f->len > len) {
5067 ngx_log_error(NGX_LOG_ERR, c->log, 0, "could not split QUIC frame");
5068 return NGX_ERROR;
5069 }
5070
5071 nf = ngx_quic_alloc_frame(c);
5072 if (nf == NULL) {
5073 return NGX_ERROR;
5074 }
5075
5076 *nf = *f;
5077 onf = &nf->u.ord;
5078 onf->offset += of->length;
5079 onf->length = shrink;
5080 nf->len = ngx_quic_create_frame(NULL, nf);
5081
5082 nf->data = ngx_quic_split_bufs(c, f->data, of->length);
5083 if (nf->data == NGX_CHAIN_ERROR) {
5084 return NGX_ERROR;
5085 }
5086
5087 ngx_queue_insert_after(&f->queue, &nf->queue);
5088
5089 return NGX_OK;
5090 }
5091
5092
5093 static void
5094 ngx_quic_free_frames(ngx_connection_t *c, ngx_queue_t *frames)
5095 {
5096 ngx_queue_t *q;
5097 ngx_quic_frame_t *f;
5098
5099 do {
5100 q = ngx_queue_head(frames);
5101
5102 if (q == ngx_queue_sentinel(frames)) {
5103 break;
5104 }
5105
5106 ngx_queue_remove(q);
5107
5108 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
5109
5110 ngx_quic_free_frame(c, f);
5111 } while (1);
5112 }
5113
5114
5115 static ssize_t
5116 ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len)
5117 {
5118 ngx_buf_t b;
5119 ngx_chain_t cl, *res;
5120
5121 ngx_memzero(&b, sizeof(ngx_buf_t));
5122
5123 b.pos = b.start = buf;
5124 b.last = b.end = buf + len;
5125 b.last_buf = 1;
5126 b.temporary = 1;
5127
5128 cl.buf = &b;
5129 cl.next= NULL;
5130
5131 res = c->send_chain(c, &cl, 0);
5132 if (res == NGX_CHAIN_ERROR) {
5133 return NGX_ERROR;
5134 }
5135
5136 return len;
5137 }
5138
5139
5140 static void
5141 ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_send_ctx_t *ctx)
5142 {
5143 uint64_t delta;
5144
5145 delta = ctx->pnum - ctx->largest_ack;
5146 pkt->number = ctx->pnum;
5147
5148 if (delta <= 0x7F) {
5149 pkt->num_len = 1;
5150 pkt->trunc = ctx->pnum & 0xff;
5151
5152 } else if (delta <= 0x7FFF) {
5153 pkt->num_len = 2;
5154 pkt->flags |= 0x1;
5155 pkt->trunc = ctx->pnum & 0xffff;
5156
5157 } else if (delta <= 0x7FFFFF) {
5158 pkt->num_len = 3;
5159 pkt->flags |= 0x2;
5160 pkt->trunc = ctx->pnum & 0xffffff;
5161
5162 } else {
5163 pkt->num_len = 4;
5164 pkt->flags |= 0x3;
5165 pkt->trunc = ctx->pnum & 0xffffffff;
5166 }
5167 }
5168
5169
5170 static void
5171 ngx_quic_pto_handler(ngx_event_t *ev)
5172 {
5173 ngx_uint_t i;
5174 ngx_queue_t *q;
5175 ngx_connection_t *c;
5176 ngx_quic_frame_t *start;
5177 ngx_quic_send_ctx_t *ctx;
5178 ngx_quic_connection_t *qc;
5179
5180 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "quic pto timer");
5181
5182 c = ev->data;
5183 qc = ngx_quic_get_connection(c);
5184
5185 qc->pto_count++;
5186
5187 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
5188
5189 ctx = &qc->send_ctx[i];
5190
5191 if (ngx_queue_empty(&ctx->sent)) {
5192 continue;
5193 }
5194
5195 q = ngx_queue_head(&ctx->sent);
5196 start = ngx_queue_data(q, ngx_quic_frame_t, queue);
5197
5198 if (start->pnum <= ctx->largest_ack
5199 && ctx->largest_ack != NGX_QUIC_UNSET_PN)
5200 {
5201 continue;
5202 }
5203
5204 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
5205 "quic pto pnum:%uL pto_count:%ui level:%d",
5206 start->pnum, qc->pto_count, start->level);
5207
5208 ngx_quic_resend_frames(c, ctx);
5209 }
5210
5211 ngx_quic_connstate_dbg(c);
5212 }
5213
5214
5215 static void
5216 ngx_quic_push_handler(ngx_event_t *ev)
5217 {
5218 ngx_connection_t *c;
5219
5220 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "quic push timer");
5221
5222 c = ev->data;
5223
5224 if (ngx_quic_output(c) != NGX_OK) {
5225 ngx_quic_close_connection(c, NGX_ERROR);
5226 return;
5227 }
5228
5229 ngx_quic_connstate_dbg(c);
5230 }
5231
5232
5233 static
5234 void ngx_quic_lost_handler(ngx_event_t *ev)
5235 {
5236 ngx_connection_t *c;
5237
5238 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "quic lost timer");
5239
5240 c = ev->data;
5241
5242 if (ngx_quic_detect_lost(c) != NGX_OK) {
5243 ngx_quic_close_connection(c, NGX_ERROR);
5244 }
5245
5246 ngx_quic_connstate_dbg(c);
5247 }
5248
5249
5250 static ngx_int_t
5251 ngx_quic_detect_lost(ngx_connection_t *c)
5252 {
5253 ngx_uint_t i;
5254 ngx_msec_t now, wait, min_wait, thr;
5255 ngx_queue_t *q;
5256 ngx_quic_frame_t *start;
5257 ngx_quic_send_ctx_t *ctx;
5258 ngx_quic_connection_t *qc;
5259
5260 qc = ngx_quic_get_connection(c);
5261 now = ngx_current_msec;
5262
5263 min_wait = 0;
5264
5265 thr = NGX_QUIC_TIME_THR * ngx_max(qc->latest_rtt, qc->avg_rtt);
5266 thr = ngx_max(thr, NGX_QUIC_TIME_GRANULARITY);
5267
5268 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
5269
5270 ctx = &qc->send_ctx[i];
5271
5272 if (ctx->largest_ack == NGX_QUIC_UNSET_PN) {
5273 continue;
5274 }
5275
5276 while (!ngx_queue_empty(&ctx->sent)) {
5277
5278 q = ngx_queue_head(&ctx->sent);
5279 start = ngx_queue_data(q, ngx_quic_frame_t, queue);
5280
5281 if (start->pnum > ctx->largest_ack) {
5282 break;
5283 }
5284
5285 wait = start->last + thr - now;
5286
5287 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
5288 "quic detect_lost pnum:%uL thr:%M wait:%i level:%d",
5289 start->pnum, thr, (ngx_int_t) wait, start->level);
5290
5291 if ((ngx_msec_int_t) wait > 0
5292 && ctx->largest_ack - start->pnum < NGX_QUIC_PKT_THR)
5293 {
5294
5295 if (min_wait == 0 || wait < min_wait) {
5296 min_wait = wait;
5297 }
5298
5299 break;
5300 }
5301
5302 ngx_quic_resend_frames(c, ctx);
5303 }
5304 }
5305
5306 /* no more preceeding packets */
5307
5308 if (min_wait == 0) {
5309 qc->pto.handler = ngx_quic_pto_handler;
5310 return NGX_OK;
5311 }
5312
5313 qc->pto.handler = ngx_quic_lost_handler;
5314
5315 if (qc->pto.timer_set) {
5316 ngx_del_timer(&qc->pto);
5317 }
5318
5319 ngx_add_timer(&qc->pto, min_wait);
5320
5321 return NGX_OK;
5322 }
5323
5324
5325 static void
5326 ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
5327 {
5328 size_t n;
5329 ngx_buf_t *b;
5330 ngx_queue_t *q;
5331 ngx_quic_frame_t *f, *start;
5332 ngx_quic_stream_t *sn;
5333 ngx_quic_connection_t *qc;
5334
5335 qc = ngx_quic_get_connection(c);
5336 q = ngx_queue_head(&ctx->sent);
5337 start = ngx_queue_data(q, ngx_quic_frame_t, queue);
5338
5339 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5340 "quic resend packet pnum:%uL", start->pnum);
5341
5342 ngx_quic_congestion_lost(c, start);
5343
5344 do {
5345 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
5346
5347 if (f->pnum != start->pnum) {
5348 break;
5349 }
5350
5351 q = ngx_queue_next(q);
5352
5353 ngx_queue_remove(&f->queue);
5354
5355 switch (f->type) {
5356 case NGX_QUIC_FT_ACK:
5357 case NGX_QUIC_FT_ACK_ECN:
5358 /* force generation of most recent acknowledgment */
5359 ctx->send_ack = NGX_QUIC_MAX_ACK_GAP;
5360 ngx_quic_free_frame(c, f);
5361 break;
5362
5363 case NGX_QUIC_FT_PING:
5364 case NGX_QUIC_FT_PATH_RESPONSE:
5365 case NGX_QUIC_FT_CONNECTION_CLOSE:
5366 ngx_quic_free_frame(c, f);
5367 break;
5368
5369 case NGX_QUIC_FT_MAX_DATA:
5370 f->u.max_data.max_data = qc->streams.recv_max_data;
5371 ngx_quic_queue_frame(qc, f);
5372 break;
5373
5374 case NGX_QUIC_FT_MAX_STREAMS:
5375 case NGX_QUIC_FT_MAX_STREAMS2:
5376 f->u.max_streams.limit = f->u.max_streams.bidi
5377 ? qc->streams.client_max_streams_bidi
5378 : qc->streams.client_max_streams_uni;
5379 ngx_quic_queue_frame(qc, f);
5380 break;
5381
5382 case NGX_QUIC_FT_MAX_STREAM_DATA:
5383 sn = ngx_quic_find_stream(&qc->streams.tree,
5384 f->u.max_stream_data.id);
5385 if (sn == NULL) {
5386 ngx_quic_free_frame(c, f);
5387 break;
5388 }
5389
5390 b = sn->b;
5391 n = sn->fs.received + (b->pos - b->start) + (b->end - b->last);
5392
5393 if (f->u.max_stream_data.limit < n) {
5394 f->u.max_stream_data.limit = n;
5395 }
5396
5397 ngx_quic_queue_frame(qc, f);
5398 break;
5399
5400 case NGX_QUIC_FT_STREAM0:
5401 case NGX_QUIC_FT_STREAM1:
5402 case NGX_QUIC_FT_STREAM2:
5403 case NGX_QUIC_FT_STREAM3:
5404 case NGX_QUIC_FT_STREAM4:
5405 case NGX_QUIC_FT_STREAM5:
5406 case NGX_QUIC_FT_STREAM6:
5407 case NGX_QUIC_FT_STREAM7:
5408 sn = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id);
5409
5410 if (sn && sn->c->write->error) {
5411 /* RESET_STREAM was sent */
5412 ngx_quic_free_frame(c, f);
5413 break;
5414 }
5415
5416 /* fall through */
5417
5418 default:
5419 ngx_queue_insert_tail(&ctx->frames, &f->queue);
5420 }
5421
5422 } while (q != ngx_queue_sentinel(&ctx->sent));
5423
5424 if (qc->closing) {
5425 return;
5426 }
5427
5428 ngx_post_event(&qc->push, &ngx_posted_events);
5429 }
5430
5431
5432 ngx_connection_t *
5433 ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi)
5434 {
5435 size_t rcvbuf_size;
5436 uint64_t id;
5437 ngx_quic_stream_t *qs, *sn;
5438 ngx_quic_connection_t *qc;
5439
5440 qs = c->quic;
5441 qc = ngx_quic_get_connection(qs->parent);
5442
5443 if (bidi) {
5444 if (qc->streams.server_streams_bidi
5445 >= qc->streams.server_max_streams_bidi)
5446 {
5447 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5448 "quic too many server bidi streams:%uL",
5449 qc->streams.server_streams_bidi);
5450 return NULL;
5451 }
5452
5453 id = (qc->streams.server_streams_bidi << 2)
5454 | NGX_QUIC_STREAM_SERVER_INITIATED;
5455
5456 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
5457 "quic creating server bidi stream"
5458 " streams:%uL max:%uL id:0x%xL",
5459 qc->streams.server_streams_bidi,
5460 qc->streams.server_max_streams_bidi, id);
5461
5462 qc->streams.server_streams_bidi++;
5463 rcvbuf_size = qc->tp.initial_max_stream_data_bidi_local;
5464
5465 } else {
5466 if (qc->streams.server_streams_uni
5467 >= qc->streams.server_max_streams_uni)
5468 {
5469 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5470 "quic too many server uni streams:%uL",
5471 qc->streams.server_streams_uni);
5472 return NULL;
5473 }
5474
5475 id = (qc->streams.server_streams_uni << 2)
5476 | NGX_QUIC_STREAM_SERVER_INITIATED
5477 | NGX_QUIC_STREAM_UNIDIRECTIONAL;
5478
5479 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
5480 "quic creating server uni stream"
5481 " streams:%uL max:%uL id:0x%xL",
5482 qc->streams.server_streams_uni,
5483 qc->streams.server_max_streams_uni, id);
5484
5485 qc->streams.server_streams_uni++;
5486 rcvbuf_size = 0;
5487 }
5488
5489 sn = ngx_quic_create_stream(qs->parent, id, rcvbuf_size);
5490 if (sn == NULL) {
5491 return NULL;
5492 }
5493
5494 return sn->c;
5495 }
5496
5497
5498 static void
5499 ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp,
5500 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
5501 {
5502 ngx_rbtree_node_t **p;
5503 ngx_quic_stream_t *qn, *qnt;
5504
5505 for ( ;; ) {
5506 qn = (ngx_quic_stream_t *) node;
5507 qnt = (ngx_quic_stream_t *) temp;
5508
5509 p = (qn->id < qnt->id) ? &temp->left : &temp->right;
5510
5511 if (*p == sentinel) {
5512 break;
5513 }
5514
5515 temp = *p;
5516 }
5517
5518 *p = node;
5519 node->parent = temp;
5520 node->left = sentinel;
5521 node->right = sentinel;
5522 ngx_rbt_red(node);
5523 }
5524
5525
5526 static ngx_quic_stream_t *
5527 ngx_quic_find_stream(ngx_rbtree_t *rbtree, uint64_t id)
5528 {
5529 ngx_rbtree_node_t *node, *sentinel;
5530 ngx_quic_stream_t *qn;
5531
5532 node = rbtree->root;
5533 sentinel = rbtree->sentinel;
5534
5535 while (node != sentinel) {
5536 qn = (ngx_quic_stream_t *) node;
5537
5538 if (id == qn->id) {
5539 return qn;
5540 }
5541
5542 node = (id < qn->id) ? node->left : node->right;
5543 }
5544
5545 return NULL;
5546 }
5547
5548
5549 static ngx_quic_stream_t *
5550 ngx_quic_create_client_stream(ngx_connection_t *c, uint64_t id)
5551 {
5552 size_t n;
5553 uint64_t min_id;
5554 ngx_quic_stream_t *sn;
5555 ngx_quic_connection_t *qc;
5556
5557 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5558 "quic stream id:0x%xL is new", id);
5559
5560 qc = ngx_quic_get_connection(c);
5561
5562 if (id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
5563
5564 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) {
5565 if ((id >> 2) < qc->streams.server_streams_uni) {
5566 return NGX_QUIC_STREAM_GONE;
5567 }
5568
5569 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
5570 return NULL;
5571 }
5572
5573 if ((id >> 2) < qc->streams.client_streams_uni) {
5574 return NGX_QUIC_STREAM_GONE;
5575 }
5576
5577 if ((id >> 2) >= qc->streams.client_max_streams_uni) {
5578 qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR;
5579 return NULL;
5580 }
5581
5582 min_id = (qc->streams.client_streams_uni << 2)
5583 | NGX_QUIC_STREAM_UNIDIRECTIONAL;
5584 qc->streams.client_streams_uni = (id >> 2) + 1;
5585 n = qc->tp.initial_max_stream_data_uni;
5586
5587 } else {
5588
5589 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) {
5590 if ((id >> 2) < qc->streams.server_streams_bidi) {
5591 return NGX_QUIC_STREAM_GONE;
5592 }
5593
5594 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
5595 return NULL;
5596 }
5597
5598 if ((id >> 2) < qc->streams.client_streams_bidi) {
5599 return NGX_QUIC_STREAM_GONE;
5600 }
5601
5602 if ((id >> 2) >= qc->streams.client_max_streams_bidi) {
5603 qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR;
5604 return NULL;
5605 }
5606
5607 min_id = (qc->streams.client_streams_bidi << 2);
5608 qc->streams.client_streams_bidi = (id >> 2) + 1;
5609 n = qc->tp.initial_max_stream_data_bidi_remote;
5610 }
5611
5612 if (n < NGX_QUIC_STREAM_BUFSIZE) {
5613 n = NGX_QUIC_STREAM_BUFSIZE;
5614 }
5615
5616 /*
5617 * 2.1. Stream Types and Identifiers
5618 *
5619 * Within each type, streams are created with numerically increasing
5620 * stream IDs. A stream ID that is used out of order results in all
5621 * streams of that type with lower-numbered stream IDs also being
5622 * opened.
5623 */
5624
5625 for ( /* void */ ; min_id < id; min_id += 0x04) {
5626
5627 sn = ngx_quic_create_stream(c, min_id, n);
5628 if (sn == NULL) {
5629 return NULL;
5630 }
5631
5632 sn->c->listening->handler(sn->c);
5633 }
5634
5635 return ngx_quic_create_stream(c, id, n);
5636 }
5637
5638
5639 static ngx_quic_stream_t *
5640 ngx_quic_create_stream(ngx_connection_t *c, uint64_t id, size_t rcvbuf_size)
5641 {
5642 ngx_log_t *log;
5643 ngx_pool_t *pool;
5644 ngx_quic_stream_t *sn;
5645 ngx_pool_cleanup_t *cln;
5646 ngx_quic_connection_t *qc;
5647
5648 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5649 "quic stream id:0x%xL create", id);
5650
5651 qc = ngx_quic_get_connection(c);
5652
5653 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log);
5654 if (pool == NULL) {
5655 return NULL;
5656 }
5657
5658 sn = ngx_pcalloc(pool, sizeof(ngx_quic_stream_t));
5659 if (sn == NULL) {
5660 ngx_destroy_pool(pool);
5661 return NULL;
5662 }
5663
5664 sn->node.key = id;
5665 sn->parent = c;
5666 sn->id = id;
5667
5668 sn->b = ngx_create_temp_buf(pool, rcvbuf_size);
5669 if (sn->b == NULL) {
5670 ngx_destroy_pool(pool);
5671 return NULL;
5672 }
5673
5674 ngx_queue_init(&sn->fs.frames);
5675
5676 log = ngx_palloc(pool, sizeof(ngx_log_t));
5677 if (log == NULL) {
5678 ngx_destroy_pool(pool);
5679 return NULL;
5680 }
5681
5682 *log = *c->log;
5683 pool->log = log;
5684
5685 sn->c = ngx_get_connection(-1, log);
5686 if (sn->c == NULL) {
5687 ngx_destroy_pool(pool);
5688 return NULL;
5689 }
5690
5691 sn->c->quic = sn;
5692 sn->c->type = SOCK_STREAM;
5693 sn->c->pool = pool;
5694 sn->c->ssl = c->ssl;
5695 sn->c->sockaddr = c->sockaddr;
5696 sn->c->listening = c->listening;
5697 sn->c->addr_text = c->addr_text;
5698 sn->c->local_sockaddr = c->local_sockaddr;
5699 sn->c->local_socklen = c->local_socklen;
5700 sn->c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
5701
5702 sn->c->recv = ngx_quic_stream_recv;
5703 sn->c->send = ngx_quic_stream_send;
5704 sn->c->send_chain = ngx_quic_stream_send_chain;
5705
5706 sn->c->read->log = log;
5707 sn->c->write->log = log;
5708
5709 log->connection = sn->c->number;
5710
5711 if ((id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0
5712 || (id & NGX_QUIC_STREAM_SERVER_INITIATED))
5713 {
5714 sn->c->write->ready = 1;
5715 }
5716
5717 if (id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
5718 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) {
5719 sn->send_max_data = qc->ctp.initial_max_stream_data_uni;
5720 }
5721
5722 } else {
5723 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) {
5724 sn->send_max_data = qc->ctp.initial_max_stream_data_bidi_remote;
5725 } else {
5726 sn->send_max_data = qc->ctp.initial_max_stream_data_bidi_local;
5727 }
5728 }
5729
5730 cln = ngx_pool_cleanup_add(pool, 0);
5731 if (cln == NULL) {
5732 ngx_close_connection(sn->c);
5733 ngx_destroy_pool(pool);
5734 return NULL;
5735 }
5736
5737 cln->handler = ngx_quic_stream_cleanup_handler;
5738 cln->data = sn->c;
5739
5740 ngx_rbtree_insert(&qc->streams.tree, &sn->node);
5741
5742 return sn;
5743 }
5744
5745
5746 static ssize_t
5747 ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size)
5748 {
5749 ssize_t len;
5750 ngx_buf_t *b;
5751 ngx_event_t *rev;
5752 ngx_connection_t *pc;
5753 ngx_quic_frame_t *frame;
5754 ngx_quic_stream_t *qs;
5755 ngx_quic_connection_t *qc;
5756
5757 qs = c->quic;
5758 b = qs->b;
5759 pc = qs->parent;
5760 qc = ngx_quic_get_connection(pc);
5761 rev = c->read;
5762
5763 if (rev->error) {
5764 return NGX_ERROR;
5765 }
5766
5767 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
5768 "quic stream recv id:0x%xL eof:%d avail:%z",
5769 qs->id, rev->pending_eof, b->last - b->pos);
5770
5771 if (b->pos == b->last) {
5772 rev->ready = 0;
5773
5774 if (rev->pending_eof) {
5775 rev->eof = 1;
5776 return 0;
5777 }
5778
5779 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5780 "quic stream id:0x%xL recv() not ready", qs->id);
5781 return NGX_AGAIN;
5782 }
5783
5784 len = ngx_min(b->last - b->pos, (ssize_t) size);
5785
5786 ngx_memcpy(buf, b->pos, len);
5787
5788 b->pos += len;
5789 qc->streams.received += len;
5790
5791 if (b->pos == b->last) {
5792 b->pos = b->start;
5793 b->last = b->start;
5794 rev->ready = rev->pending_eof;
5795 }
5796
5797 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
5798 "quic stream id:0x%xL recv len:%z of size:%uz",
5799 qs->id, len, size);
5800
5801 if (!rev->pending_eof) {
5802 frame = ngx_quic_alloc_frame(pc);
5803 if (frame == NULL) {
5804 return NGX_ERROR;
5805 }
5806
5807 frame->level = ssl_encryption_application;
5808 frame->type = NGX_QUIC_FT_MAX_STREAM_DATA;
5809 frame->u.max_stream_data.id = qs->id;
5810 frame->u.max_stream_data.limit = qs->fs.received + (b->pos - b->start)
5811 + (b->end - b->last);
5812
5813 ngx_quic_queue_frame(qc, frame);
5814 }
5815
5816 if ((qc->streams.recv_max_data / 2) < qc->streams.received) {
5817
5818 frame = ngx_quic_alloc_frame(pc);
5819
5820 if (frame == NULL) {
5821 return NGX_ERROR;
5822 }
5823
5824 qc->streams.recv_max_data *= 2;
5825
5826 frame->level = ssl_encryption_application;
5827 frame->type = NGX_QUIC_FT_MAX_DATA;
5828 frame->u.max_data.max_data = qc->streams.recv_max_data;
5829
5830 ngx_quic_queue_frame(qc, frame);
5831
5832 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
5833 "quic stream id:0x%xL recv: increased max_data:%uL",
5834 qs->id, qc->streams.recv_max_data);
5835 }
5836
5837 return len;
5838 }
5839
5840
5841 static ssize_t
5842 ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, size_t size)
5843 {
5844 ngx_buf_t b;
5845 ngx_chain_t cl;
5846
5847 ngx_memzero(&b, sizeof(ngx_buf_t));
5848
5849 b.memory = 1;
5850 b.pos = buf;
5851 b.last = buf + size;
5852
5853 cl.buf = &b;
5854 cl.next = NULL;
5855
5856 if (ngx_quic_stream_send_chain(c, &cl, 0) == NGX_CHAIN_ERROR) {
5857 return NGX_ERROR;
5858 }
5859
5860 if (b.pos == buf) {
5861 return NGX_AGAIN;
5862 }
5863
5864 return b.pos - buf;
5865 }
5866
5867
5868 static ngx_chain_t *
5869 ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
5870 {
5871 size_t n, flow;
5872 ngx_event_t *wev;
5873 ngx_chain_t *cl;
5874 ngx_connection_t *pc;
5875 ngx_quic_frame_t *frame;
5876 ngx_quic_stream_t *qs;
5877 ngx_quic_connection_t *qc;
5878
5879 qs = c->quic;
5880 pc = qs->parent;
5881 qc = ngx_quic_get_connection(pc);
5882 wev = c->write;
5883
5884 if (wev->error) {
5885 return NGX_CHAIN_ERROR;
5886 }
5887
5888 flow = ngx_quic_max_stream_flow(c);
5889 if (flow == 0) {
5890 wev->ready = 0;
5891 return in;
5892 }
5893
5894 n = (limit && (size_t) limit < flow) ? (size_t) limit : flow;
5895
5896 frame = ngx_quic_alloc_frame(pc);
5897 if (frame == NULL) {
5898 return NGX_CHAIN_ERROR;
5899 }
5900
5901 frame->data = ngx_quic_copy_chain(pc, in, n);
5902 if (frame->data == NGX_CHAIN_ERROR) {
5903 return NGX_CHAIN_ERROR;
5904 }
5905
5906 for (n = 0, cl = frame->data; cl; cl = cl->next) {
5907 n += ngx_buf_size(cl->buf);
5908 }
5909
5910 while (in && ngx_buf_size(in->buf) == 0) {
5911 in = in->next;
5912 }
5913
5914 frame->level = ssl_encryption_application;
5915 frame->type = NGX_QUIC_FT_STREAM6; /* OFF=1 LEN=1 FIN=0 */
5916 frame->u.stream.off = 1;
5917 frame->u.stream.len = 1;
5918 frame->u.stream.fin = 0;
5919
5920 frame->u.stream.type = frame->type;
5921 frame->u.stream.stream_id = qs->id;
5922 frame->u.stream.offset = c->sent;
5923 frame->u.stream.length = n;
5924
5925 c->sent += n;
5926 qc->streams.sent += n;
5927
5928 ngx_quic_queue_frame(qc, frame);
5929
5930 wev->ready = (n < flow) ? 1 : 0;
5931
5932 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5933 "quic send_chain sent:%uz", n);
5934
5935 return in;
5936 }
5937
5938
5939 static size_t
5940 ngx_quic_max_stream_flow(ngx_connection_t *c)
5941 {
5942 size_t size;
5943 uint64_t sent, unacked;
5944 ngx_quic_stream_t *qs;
5945 ngx_quic_connection_t *qc;
5946
5947 qs = c->quic;
5948 qc = ngx_quic_get_connection(qs->parent);
5949
5950 size = NGX_QUIC_STREAM_BUFSIZE;
5951 sent = c->sent;
5952 unacked = sent - qs->acked;
5953
5954 if (qc->streams.send_max_data == 0) {
5955 qc->streams.send_max_data = qc->ctp.initial_max_data;
5956 }
5957
5958 if (unacked >= NGX_QUIC_STREAM_BUFSIZE) {
5959 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
5960 "quic send flow hit buffer size");
5961 return 0;
5962 }
5963
5964 if (unacked + size > NGX_QUIC_STREAM_BUFSIZE) {
5965 size = NGX_QUIC_STREAM_BUFSIZE - unacked;
5966 }
5967
5968 if (qc->streams.sent >= qc->streams.send_max_data) {
5969 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
5970 "quic send flow hit MAX_DATA");
5971 return 0;
5972 }
5973
5974 if (qc->streams.sent + size > qc->streams.send_max_data) {
5975 size = qc->streams.send_max_data - qc->streams.sent;
5976 }
5977
5978 if (sent >= qs->send_max_data) {
5979 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
5980 "quic send flow hit MAX_STREAM_DATA");
5981 return 0;
5982 }
5983
5984 if (sent + size > qs->send_max_data) {
5985 size = qs->send_max_data - sent;
5986 }
5987
5988 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5989 "quic send flow:%uz", size);
5990
5991 return size;
5992 }
5993
5994
5995 static void
5996 ngx_quic_stream_cleanup_handler(void *data)
5997 {
5998 ngx_connection_t *c = data;
5999
6000 ngx_connection_t *pc;
6001 ngx_quic_frame_t *frame;
6002 ngx_quic_stream_t *qs;
6003 ngx_quic_connection_t *qc;
6004
6005 qs = c->quic;
6006 pc = qs->parent;
6007 qc = ngx_quic_get_connection(pc);
6008
6009 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6010 "quic stream id:0x%xL cleanup", qs->id);
6011
6012 ngx_rbtree_delete(&qc->streams.tree, &qs->node);
6013 ngx_quic_free_frames(pc, &qs->fs.frames);
6014
6015 if (qc->closing) {
6016 /* schedule handler call to continue ngx_quic_close_connection() */
6017 ngx_post_event(pc->read, &ngx_posted_events);
6018 return;
6019 }
6020
6021 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0
6022 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0)
6023 {
6024 if (!c->read->pending_eof && !c->read->error) {
6025 frame = ngx_quic_alloc_frame(pc);
6026 if (frame == NULL) {
6027 return;
6028 }
6029
6030 frame->level = ssl_encryption_application;
6031 frame->type = NGX_QUIC_FT_STOP_SENDING;
6032 frame->u.stop_sending.id = qs->id;
6033 frame->u.stop_sending.error_code = 0x100; /* HTTP/3 no error */
6034
6035 ngx_quic_queue_frame(qc, frame);
6036 }
6037 }
6038
6039 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) {
6040 frame = ngx_quic_alloc_frame(pc);
6041 if (frame == NULL) {
6042 return;
6043 }
6044
6045 frame->level = ssl_encryption_application;
6046 frame->type = NGX_QUIC_FT_MAX_STREAMS;
6047
6048 if (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
6049 frame->u.max_streams.limit = ++qc->streams.client_max_streams_uni;
6050 frame->u.max_streams.bidi = 0;
6051
6052 } else {
6053 frame->u.max_streams.limit = ++qc->streams.client_max_streams_bidi;
6054 frame->u.max_streams.bidi = 1;
6055 }
6056
6057 ngx_quic_queue_frame(qc, frame);
6058
6059 if (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
6060 /* do not send fin for client unidirectional streams */
6061 return;
6062 }
6063 }
6064
6065 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6066 "quic stream id:0x%xL send fin", qs->id);
6067
6068 frame = ngx_quic_alloc_frame(pc);
6069 if (frame == NULL) {
6070 return;
6071 }
6072
6073 frame->level = ssl_encryption_application;
6074 frame->type = NGX_QUIC_FT_STREAM7; /* OFF=1 LEN=1 FIN=1 */
6075 frame->u.stream.off = 1;
6076 frame->u.stream.len = 1;
6077 frame->u.stream.fin = 1;
6078
6079 frame->u.stream.type = frame->type;
6080 frame->u.stream.stream_id = qs->id;
6081 frame->u.stream.offset = c->sent;
6082 frame->u.stream.length = 0;
6083
6084 ngx_quic_queue_frame(qc, frame);
6085
6086 (void) ngx_quic_output(pc);
6087 }
6088
6089
6090 static ngx_quic_frame_t *
6091 ngx_quic_alloc_frame(ngx_connection_t *c)
6092 {
6093 ngx_queue_t *q;
6094 ngx_quic_frame_t *frame;
6095 ngx_quic_connection_t *qc;
6096
6097 qc = ngx_quic_get_connection(c);
6098
6099 if (!ngx_queue_empty(&qc->free_frames)) {
6100
6101 q = ngx_queue_head(&qc->free_frames);
6102 frame = ngx_queue_data(q, ngx_quic_frame_t, queue);
6103
6104 ngx_queue_remove(&frame->queue);
6105
6106 #ifdef NGX_QUIC_DEBUG_ALLOC
6107 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6108 "quic reuse frame n:%ui", qc->nframes);
6109 #endif
6110
6111 } else {
6112 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t));
6113 if (frame == NULL) {
6114 return NULL;
6115 }
6116
6117 #ifdef NGX_QUIC_DEBUG_ALLOC
6118 ++qc->nframes;
6119
6120 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6121 "quic alloc frame n:%ui", qc->nframes);
6122 #endif
6123 }
6124
6125 ngx_memzero(frame, sizeof(ngx_quic_frame_t));
6126
6127 return frame;
6128 }
6129
6130
6131 static void
6132 ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
6133 {
6134 ngx_msec_t timer;
6135 ngx_quic_congestion_t *cg;
6136 ngx_quic_connection_t *qc;
6137
6138 if (f->plen == 0) {
6139 return;
6140 }
6141
6142 qc = ngx_quic_get_connection(c);
6143 cg = &qc->congestion;
6144
6145 cg->in_flight -= f->plen;
6146
6147 timer = f->last - cg->recovery_start;
6148
6149 if ((ngx_msec_int_t) timer <= 0) {
6150 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
6151 "quic congestion ack recovery win:%uz ss:%z if:%uz",
6152 cg->window, cg->ssthresh, cg->in_flight);
6153
6154 return;
6155 }
6156
6157 if (cg->window < cg->ssthresh) {
6158 cg->window += f->plen;
6159
6160 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
6161 "quic congestion slow start win:%uz ss:%z if:%uz",
6162 cg->window, cg->ssthresh, cg->in_flight);
6163
6164 } else {
6165 cg->window += qc->tp.max_udp_payload_size * f->plen / cg->window;
6166
6167 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
6168 "quic congestion avoidance win:%uz ss:%z if:%uz",
6169 cg->window, cg->ssthresh, cg->in_flight);
6170 }
6171
6172 /* prevent recovery_start from wrapping */
6173
6174 timer = cg->recovery_start - ngx_current_msec + qc->tp.max_idle_timeout * 2;
6175
6176 if ((ngx_msec_int_t) timer < 0) {
6177 cg->recovery_start = ngx_current_msec - qc->tp.max_idle_timeout * 2;
6178 }
6179 }
6180
6181
6182 static void
6183 ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
6184 {
6185 ngx_msec_t timer;
6186 ngx_quic_congestion_t *cg;
6187 ngx_quic_connection_t *qc;
6188
6189 if (f->plen == 0) {
6190 return;
6191 }
6192
6193 qc = ngx_quic_get_connection(c);
6194 cg = &qc->congestion;
6195
6196 cg->in_flight -= f->plen;
6197 f->plen = 0;
6198
6199 timer = f->last - cg->recovery_start;
6200
6201 if ((ngx_msec_int_t) timer <= 0) {
6202 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
6203 "quic congestion lost recovery win:%uz ss:%z if:%uz",
6204 cg->window, cg->ssthresh, cg->in_flight);
6205
6206 return;
6207 }
6208
6209 cg->recovery_start = ngx_current_msec;
6210 cg->window /= 2;
6211
6212 if (cg->window < qc->tp.max_udp_payload_size * 2) {
6213 cg->window = qc->tp.max_udp_payload_size * 2;
6214 }
6215
6216 cg->ssthresh = cg->window;
6217
6218 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
6219 "quic congestion lost win:%uz ss:%z if:%uz",
6220 cg->window, cg->ssthresh, cg->in_flight);
6221 }
6222
6223
6224 static void
6225 ngx_quic_free_frame(ngx_connection_t *c, ngx_quic_frame_t *frame)
6226 {
6227 ngx_quic_connection_t *qc;
6228
6229 qc = ngx_quic_get_connection(c);
6230
6231 if (frame->data) {
6232 ngx_quic_free_bufs(c, frame->data);
6233 }
6234
6235 ngx_queue_insert_head(&qc->free_frames, &frame->queue);
6236
6237 #ifdef NGX_QUIC_DEBUG_ALLOC
6238 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6239 "quic free frame n:%ui", qc->nframes);
6240 #endif
6241 }
6242
6243
6244 uint32_t
6245 ngx_quic_version(ngx_connection_t *c)
6246 {
6247 uint32_t version;
6248 ngx_quic_connection_t *qc;
6249
6250 qc = ngx_quic_get_connection(c);
6251
6252 version = qc->version;
6253
6254 return (version & 0xff000000) == 0xff000000 ? version & 0xff : version;
6255 }
6256
6257
6258 static ngx_chain_t *
6259 ngx_quic_alloc_buf(ngx_connection_t *c)
6260 {
6261 ngx_buf_t *b;
6262 ngx_chain_t *cl;
6263 ngx_quic_connection_t *qc;
6264
6265 qc = ngx_quic_get_connection(c);
6266
6267 if (qc->free_bufs) {
6268 cl = qc->free_bufs;
6269 qc->free_bufs = cl->next;
6270
6271 b = cl->buf;
6272 b->pos = b->start;
6273 b->last = b->start;
6274
6275 #ifdef NGX_QUIC_DEBUG_ALLOC
6276 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6277 "quic reuse buffer n:%ui", qc->nbufs);
6278 #endif
6279
6280 return cl;
6281 }
6282
6283 cl = ngx_alloc_chain_link(c->pool);
6284 if (cl == NULL) {
6285 return NULL;
6286 }
6287
6288 b = ngx_create_temp_buf(c->pool, NGX_QUIC_BUFFER_SIZE);
6289 if (b == NULL) {
6290 return NULL;
6291 }
6292
6293 b->tag = (ngx_buf_tag_t) &ngx_quic_alloc_buf;
6294
6295 cl->buf = b;
6296
6297 #ifdef NGX_QUIC_DEBUG_ALLOC
6298 ++qc->nbufs;
6299
6300 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6301 "quic alloc buffer n:%ui", qc->nbufs);
6302 #endif
6303
6304 return cl;
6305 }
6306
6307
6308 static void
6309 ngx_quic_free_bufs(ngx_connection_t *c, ngx_chain_t *in)
6310 {
6311 ngx_buf_t *b, *shadow;
6312 ngx_chain_t *cl;
6313 ngx_quic_connection_t *qc;
6314
6315 qc = ngx_quic_get_connection(c);
6316
6317 while (in) {
6318 #ifdef NGX_QUIC_DEBUG_ALLOC
6319 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6320 "quic free buffer n:%ui", qc->nbufs);
6321 #endif
6322
6323 cl = in;
6324 in = in->next;
6325 b = cl->buf;
6326
6327 if (b->shadow) {
6328 if (!b->last_shadow) {
6329 b->recycled = 1;
6330 ngx_free_chain(c->pool, cl);
6331 continue;
6332 }
6333
6334 do {
6335 shadow = b->shadow;
6336 b->shadow = qc->free_shadow_bufs;
6337 qc->free_shadow_bufs = b;
6338 b = shadow;
6339 } while (b->recycled);
6340
6341 if (b->shadow) {
6342 b->last_shadow = 1;
6343 ngx_free_chain(c->pool, cl);
6344 continue;
6345 }
6346
6347 cl->buf = b;
6348 }
6349
6350 cl->next = qc->free_bufs;
6351 qc->free_bufs = cl;
6352 }
6353 }
6354
6355
6356 static ngx_chain_t *
6357 ngx_quic_copy_buf(ngx_connection_t *c, u_char *data, size_t len)
6358 {
6359 size_t n;
6360 ngx_buf_t *b;
6361 ngx_chain_t *cl, *out, **ll;
6362
6363 out = NULL;
6364 ll = &out;
6365
6366 while (len) {
6367 cl = ngx_quic_alloc_buf(c);
6368 if (cl == NULL) {
6369 return NGX_CHAIN_ERROR;
6370 }
6371
6372 b = cl->buf;
6373 n = ngx_min((size_t) (b->end - b->last), len);
6374
6375 b->last = ngx_cpymem(b->last, data, n);
6376
6377 data += n;
6378 len -= n;
6379
6380 *ll = cl;
6381 ll = &cl->next;
6382 }
6383
6384 *ll = NULL;
6385
6386 return out;
6387 }
6388
6389
6390 static ngx_chain_t *
6391 ngx_quic_copy_chain(ngx_connection_t *c, ngx_chain_t *in, size_t limit)
6392 {
6393 size_t n;
6394 ngx_buf_t *b;
6395 ngx_chain_t *cl, *out, **ll;
6396
6397 out = NULL;
6398 ll = &out;
6399
6400 while (in) {
6401 if (!ngx_buf_in_memory(in->buf) || ngx_buf_size(in->buf) == 0) {
6402 in = in->next;
6403 continue;
6404 }
6405
6406 cl = ngx_quic_alloc_buf(c);
6407 if (cl == NULL) {
6408 return NGX_CHAIN_ERROR;
6409 }
6410
6411 *ll = cl;
6412 ll = &cl->next;
6413
6414 b = cl->buf;
6415
6416 while (in && b->last != b->end) {
6417
6418 n = ngx_min(in->buf->last - in->buf->pos, b->end - b->last);
6419
6420 if (limit > 0 && n > limit) {
6421 n = limit;
6422 }
6423
6424 b->last = ngx_cpymem(b->last, in->buf->pos, n);
6425
6426 in->buf->pos += n;
6427 if (in->buf->pos == in->buf->last) {
6428 in = in->next;
6429 }
6430
6431 if (limit > 0) {
6432 if (limit == n) {
6433 goto done;
6434 }
6435
6436 limit -= n;
6437 }
6438 }
6439
6440 }
6441
6442 done:
6443
6444 *ll = NULL;
6445
6446 return out;
6447 }
6448
6449
6450 static ngx_chain_t *
6451 ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in, size_t len)
6452 {
6453 size_t n;
6454 ngx_buf_t *b;
6455 ngx_chain_t *out;
6456 ngx_quic_connection_t *qc;
6457
6458 qc = ngx_quic_get_connection(c);
6459
6460 while (in) {
6461 n = ngx_buf_size(in->buf);
6462
6463 if (n == len) {
6464 out = in->next;
6465 in->next = NULL;
6466 return out;
6467 }
6468
6469 if (n > len) {
6470 break;
6471 }
6472
6473 len -= n;
6474 in = in->next;
6475 }
6476
6477 if (in == NULL) {
6478 return NULL;
6479 }
6480
6481 /* split in->buf by creating shadow bufs which reference it */
6482
6483 if (in->buf->shadow == NULL) {
6484 if (qc->free_shadow_bufs) {
6485 b = qc->free_shadow_bufs;
6486 qc->free_shadow_bufs = b->shadow;
6487
6488 } else {
6489 b = ngx_alloc_buf(c->pool);
6490 if (b == NULL) {
6491 return NGX_CHAIN_ERROR;
6492 }
6493 }
6494
6495 *b = *in->buf;
6496 b->shadow = in->buf;
6497 b->last_shadow = 1;
6498 in->buf = b;
6499 }
6500
6501 out = ngx_alloc_chain_link(c->pool);
6502 if (out == NULL) {
6503 return NGX_CHAIN_ERROR;
6504 }
6505
6506 if (qc->free_shadow_bufs) {
6507 b = qc->free_shadow_bufs;
6508 qc->free_shadow_bufs = b->shadow;
6509
6510 } else {
6511 b = ngx_alloc_buf(c->pool);
6512 if (b == NULL) {
6513 ngx_free_chain(c->pool, out);
6514 return NGX_CHAIN_ERROR;
6515 }
6516 }
6517
6518 out->buf = b;
6519 out->next = in->next;
6520 in->next = NULL;
6521
6522 *b = *in->buf;
6523 b->last_shadow = 0;
6524 b->pos = b->pos + len;
6525
6526 in->buf->shadow = b;
6527 in->buf->last = in->buf->pos + len;
6528
6529 return out;
6530 }