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

QUIC: separate files for output and ack related processing.
author Vladimir Homutov <vl@nginx.com>
date Tue, 13 Apr 2021 14:41:20 +0300
parents
children 4117aa7fa38e
comparison
equal deleted inserted replaced
8750:41807e581de9 8751:bc910a5ec737
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_connection.h>
11
12
13 #define NGX_QUIC_MAX_SHORT_HEADER 25 /* 1 flags + 20 dcid + 4 pn */
14 #define NGX_QUIC_MAX_LONG_HEADER 56
15 /* 1 flags + 4 version + 2 x (1 + 20) s/dcid + 4 pn + 4 len + token len */
16
17 #define NGX_QUIC_MAX_UDP_PAYLOAD_OUT 1252
18 #define NGX_QUIC_MAX_UDP_PAYLOAD_OUT6 1232
19
20 #define NGX_QUIC_RETRY_TOKEN_LIFETIME 3 /* seconds */
21 #define NGX_QUIC_NEW_TOKEN_LIFETIME 600 /* seconds */
22 #define NGX_QUIC_RETRY_BUFFER_SIZE 256
23 /* 1 flags + 4 version + 3 x (1 + 20) s/o/dcid + itag + token(64) */
24
25 /*
26 * Endpoints MUST discard packets that are too small to be valid QUIC
27 * packets. With the set of AEAD functions defined in [QUIC-TLS],
28 * packets that are smaller than 21 bytes are never valid.
29 */
30 #define NGX_QUIC_MIN_PKT_LEN 21
31
32 #define NGX_QUIC_MIN_SR_PACKET 43 /* 5 rand + 16 srt + 22 padding */
33 #define NGX_QUIC_MAX_SR_PACKET 1200
34
35 #define NGX_QUIC_CC_MIN_INTERVAL 1000 /* 1s */
36
37
38 static ssize_t ngx_quic_output_packet(ngx_connection_t *c,
39 ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min);
40 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c);
41 static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len);
42 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt,
43 ngx_quic_send_ctx_t *ctx);
44
45
46 size_t
47 ngx_quic_max_udp_payload(ngx_connection_t *c)
48 {
49 /* TODO: path MTU discovery */
50
51 #if (NGX_HAVE_INET6)
52 if (c->sockaddr->sa_family == AF_INET6) {
53 return NGX_QUIC_MAX_UDP_PAYLOAD_OUT6;
54 }
55 #endif
56
57 return NGX_QUIC_MAX_UDP_PAYLOAD_OUT;
58 }
59
60
61 ngx_int_t
62 ngx_quic_output(ngx_connection_t *c)
63 {
64 off_t max;
65 size_t len, min, in_flight;
66 ssize_t n;
67 u_char *p;
68 ngx_uint_t i, pad;
69 ngx_quic_send_ctx_t *ctx;
70 ngx_quic_congestion_t *cg;
71 ngx_quic_connection_t *qc;
72 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
73
74 c->log->action = "sending frames";
75
76 qc = ngx_quic_get_connection(c);
77 cg = &qc->congestion;
78
79 in_flight = cg->in_flight;
80
81 for ( ;; ) {
82 p = dst;
83
84 len = ngx_min(qc->ctp.max_udp_payload_size,
85 NGX_QUIC_MAX_UDP_PAYLOAD_SIZE);
86
87 if (!qc->validated) {
88 max = qc->received * 3;
89 max = (c->sent >= max) ? 0 : max - c->sent;
90 len = ngx_min(len, (size_t) max);
91 }
92
93 pad = ngx_quic_get_padding_level(c);
94
95 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
96
97 ctx = &qc->send_ctx[i];
98
99 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) {
100 return NGX_ERROR;
101 }
102
103 min = (i == pad && p - dst < NGX_QUIC_MIN_INITIAL_SIZE)
104 ? NGX_QUIC_MIN_INITIAL_SIZE - (p - dst) : 0;
105
106 n = ngx_quic_output_packet(c, ctx, p, len, min);
107 if (n == NGX_ERROR) {
108 return NGX_ERROR;
109 }
110
111 p += n;
112 len -= n;
113 }
114
115 len = p - dst;
116 if (len == 0) {
117 break;
118 }
119
120 n = ngx_quic_send(c, dst, len);
121 if (n == NGX_ERROR) {
122 return NGX_ERROR;
123 }
124 }
125
126 if (in_flight != cg->in_flight && !qc->send_timer_set && !qc->closing) {
127 qc->send_timer_set = 1;
128 ngx_add_timer(c->read, qc->tp.max_idle_timeout);
129 }
130
131 ngx_quic_set_lost_timer(c);
132
133 return NGX_OK;
134 }
135
136
137 static ngx_uint_t
138 ngx_quic_get_padding_level(ngx_connection_t *c)
139 {
140 ngx_queue_t *q;
141 ngx_quic_frame_t *f;
142 ngx_quic_send_ctx_t *ctx;
143 ngx_quic_connection_t *qc;
144
145 /*
146 * 14.1. Initial Datagram Size
147 *
148 * Similarly, a server MUST expand the payload of all UDP datagrams
149 * carrying ack-eliciting Initial packets to at least the smallest
150 * allowed maximum datagram size of 1200 bytes
151 */
152
153 qc = ngx_quic_get_connection(c);
154 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial);
155
156 for (q = ngx_queue_head(&ctx->frames);
157 q != ngx_queue_sentinel(&ctx->frames);
158 q = ngx_queue_next(q))
159 {
160 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
161
162 if (f->need_ack) {
163 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake);
164
165 if (ngx_queue_empty(&ctx->frames)) {
166 return 0;
167 }
168
169 return 1;
170 }
171 }
172
173 return NGX_QUIC_SEND_CTX_LAST;
174 }
175
176
177 static ssize_t
178 ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
179 u_char *data, size_t max, size_t min)
180 {
181 size_t len, hlen, pad_len;
182 u_char *p;
183 ssize_t flen;
184 ngx_str_t out, res;
185 ngx_int_t rc;
186 ngx_uint_t nframes;
187 ngx_msec_t now;
188 ngx_queue_t *q;
189 ngx_quic_frame_t *f;
190 ngx_quic_header_t pkt;
191 ngx_quic_congestion_t *cg;
192 ngx_quic_connection_t *qc;
193 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
194
195 if (ngx_queue_empty(&ctx->frames)) {
196 return 0;
197 }
198
199 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
200 "quic output %s packet max:%uz min:%uz",
201 ngx_quic_level_name(ctx->level), max, min);
202
203 qc = ngx_quic_get_connection(c);
204 cg = &qc->congestion;
205
206 hlen = (ctx->level == ssl_encryption_application)
207 ? NGX_QUIC_MAX_SHORT_HEADER
208 : NGX_QUIC_MAX_LONG_HEADER;
209
210 hlen += EVP_GCM_TLS_TAG_LEN;
211 hlen -= NGX_QUIC_MAX_CID_LEN - qc->scid.len;
212
213 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
214
215 now = ngx_current_msec;
216 nframes = 0;
217 p = src;
218 len = 0;
219
220 for (q = ngx_queue_head(&ctx->frames);
221 q != ngx_queue_sentinel(&ctx->frames);
222 q = ngx_queue_next(q))
223 {
224 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
225
226 if (!pkt.need_ack && f->need_ack && max > cg->window) {
227 max = cg->window;
228 }
229
230 if (hlen + len >= max) {
231 break;
232 }
233
234 if (hlen + len + f->len > max) {
235 rc = ngx_quic_split_frame(c, f, max - hlen - len);
236
237 if (rc == NGX_ERROR) {
238 return NGX_ERROR;
239 }
240
241 if (rc == NGX_DECLINED) {
242 break;
243 }
244 }
245
246 if (f->need_ack) {
247 pkt.need_ack = 1;
248 }
249
250 ngx_quic_log_frame(c->log, f, 1);
251
252 flen = ngx_quic_create_frame(p, f);
253 if (flen == -1) {
254 return NGX_ERROR;
255 }
256
257 len += flen;
258 p += flen;
259
260 f->pnum = ctx->pnum;
261 f->first = now;
262 f->last = now;
263 f->plen = 0;
264
265 nframes++;
266
267 if (f->flush) {
268 break;
269 }
270 }
271
272 if (nframes == 0) {
273 return 0;
274 }
275
276 out.data = src;
277 out.len = len;
278
279 pkt.keys = qc->keys;
280 pkt.flags = NGX_QUIC_PKT_FIXED_BIT;
281
282 if (ctx->level == ssl_encryption_initial) {
283 pkt.flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_INITIAL;
284
285 } else if (ctx->level == ssl_encryption_handshake) {
286 pkt.flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_HANDSHAKE;
287
288 } else {
289 if (qc->key_phase) {
290 pkt.flags |= NGX_QUIC_PKT_KPHASE;
291 }
292 }
293
294 ngx_quic_set_packet_number(&pkt, ctx);
295
296 pkt.version = qc->version;
297 pkt.log = c->log;
298 pkt.level = ctx->level;
299 pkt.dcid = qc->scid;
300 pkt.scid = qc->dcid;
301
302 pad_len = 4;
303
304 if (min) {
305 hlen = EVP_GCM_TLS_TAG_LEN
306 + ngx_quic_create_header(&pkt, NULL, out.len, NULL);
307
308 if (min > hlen + pad_len) {
309 pad_len = min - hlen;
310 }
311 }
312
313 if (out.len < pad_len) {
314 ngx_memset(p, NGX_QUIC_FT_PADDING, pad_len - out.len);
315 out.len = pad_len;
316 }
317
318 pkt.payload = out;
319
320 res.data = data;
321
322 ngx_log_debug6(NGX_LOG_DEBUG_EVENT, c->log, 0,
323 "quic packet tx %s bytes:%ui"
324 " need_ack:%d number:%L encoded nl:%d trunc:0x%xD",
325 ngx_quic_level_name(ctx->level), out.len, pkt.need_ack,
326 pkt.number, pkt.num_len, pkt.trunc);
327
328 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
329 return NGX_ERROR;
330 }
331
332 ctx->pnum++;
333
334 if (pkt.need_ack) {
335 /* move frames into the sent queue to wait for ack */
336
337 if (!qc->closing) {
338 q = ngx_queue_head(&ctx->frames);
339 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
340 f->plen = res.len;
341
342 do {
343 q = ngx_queue_head(&ctx->frames);
344 ngx_queue_remove(q);
345 ngx_queue_insert_tail(&ctx->sent, q);
346 } while (--nframes);
347 }
348
349 cg->in_flight += res.len;
350
351 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
352 "quic congestion send if:%uz", cg->in_flight);
353 }
354
355 while (nframes--) {
356 q = ngx_queue_head(&ctx->frames);
357 f = ngx_queue_data(q, ngx_quic_frame_t, queue);
358
359 ngx_queue_remove(q);
360 ngx_quic_free_frame(c, f);
361 }
362
363 return res.len;
364 }
365
366
367 ssize_t
368 ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len)
369 {
370 ngx_buf_t b;
371 ngx_chain_t cl, *res;
372
373 ngx_memzero(&b, sizeof(ngx_buf_t));
374
375 b.pos = b.start = buf;
376 b.last = b.end = buf + len;
377 b.last_buf = 1;
378 b.temporary = 1;
379
380 cl.buf = &b;
381 cl.next= NULL;
382
383 res = c->send_chain(c, &cl, 0);
384 if (res == NGX_CHAIN_ERROR) {
385 return NGX_ERROR;
386 }
387
388 return len;
389 }
390
391
392 static void
393 ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_send_ctx_t *ctx)
394 {
395 uint64_t delta;
396
397 delta = ctx->pnum - ctx->largest_ack;
398 pkt->number = ctx->pnum;
399
400 if (delta <= 0x7F) {
401 pkt->num_len = 1;
402 pkt->trunc = ctx->pnum & 0xff;
403
404 } else if (delta <= 0x7FFF) {
405 pkt->num_len = 2;
406 pkt->flags |= 0x1;
407 pkt->trunc = ctx->pnum & 0xffff;
408
409 } else if (delta <= 0x7FFFFF) {
410 pkt->num_len = 3;
411 pkt->flags |= 0x2;
412 pkt->trunc = ctx->pnum & 0xffffff;
413
414 } else {
415 pkt->num_len = 4;
416 pkt->flags |= 0x3;
417 pkt->trunc = ctx->pnum & 0xffffffff;
418 }
419 }
420
421
422 ngx_int_t
423 ngx_quic_negotiate_version(ngx_connection_t *c, ngx_quic_header_t *inpkt)
424 {
425 size_t len;
426 ngx_quic_header_t pkt;
427 static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
428
429 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
430 "sending version negotiation packet");
431
432 pkt.log = c->log;
433 pkt.flags = NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_FIXED_BIT;
434 pkt.dcid = inpkt->scid;
435 pkt.scid = inpkt->dcid;
436
437 len = ngx_quic_create_version_negotiation(&pkt, buf);
438
439 #ifdef NGX_QUIC_DEBUG_PACKETS
440 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
441 "quic vnego packet to send len:%uz %*xs", len, len, buf);
442 #endif
443
444 (void) ngx_quic_send(c, buf, len);
445
446 return NGX_ERROR;
447 }
448
449
450 int
451 ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
452 uint8_t alert)
453 {
454 ngx_connection_t *c;
455 ngx_quic_connection_t *qc;
456
457 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
458
459 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
460 "quic ngx_quic_send_alert() lvl:%d alert:%d",
461 (int) level, (int) alert);
462
463 qc = ngx_quic_get_connection(c);
464 if (qc == NULL) {
465 return 1;
466 }
467
468 qc->error_level = level;
469 qc->error = NGX_QUIC_ERR_CRYPTO(alert);
470 qc->error_reason = "TLS alert";
471 qc->error_app = 0;
472 qc->error_ftype = 0;
473
474 if (ngx_quic_send_cc(c) != NGX_OK) {
475 return 0;
476 }
477
478 return 1;
479 }
480
481
482 ngx_int_t
483 ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
484 ngx_quic_header_t *pkt)
485 {
486 u_char *token;
487 size_t len, max;
488 uint16_t rndbytes;
489 u_char buf[NGX_QUIC_MAX_SR_PACKET];
490
491 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
492 "quic handle stateless reset output");
493
494 if (pkt->len <= NGX_QUIC_MIN_PKT_LEN) {
495 return NGX_DECLINED;
496 }
497
498 if (pkt->len <= NGX_QUIC_MIN_SR_PACKET) {
499 len = pkt->len - 1;
500
501 } else {
502 max = ngx_min(NGX_QUIC_MAX_SR_PACKET, pkt->len * 3);
503
504 if (RAND_bytes((u_char *) &rndbytes, sizeof(rndbytes)) != 1) {
505 return NGX_ERROR;
506 }
507
508 len = (rndbytes % (max - NGX_QUIC_MIN_SR_PACKET + 1))
509 + NGX_QUIC_MIN_SR_PACKET;
510 }
511
512 if (RAND_bytes(buf, len - NGX_QUIC_SR_TOKEN_LEN) != 1) {
513 return NGX_ERROR;
514 }
515
516 buf[0] &= ~NGX_QUIC_PKT_LONG;
517 buf[0] |= NGX_QUIC_PKT_FIXED_BIT;
518
519 token = &buf[len - NGX_QUIC_SR_TOKEN_LEN];
520
521 if (ngx_quic_new_sr_token(c, &pkt->dcid, conf->sr_token_key, token)
522 != NGX_OK)
523 {
524 return NGX_ERROR;
525 }
526
527 (void) ngx_quic_send(c, buf, len);
528
529 return NGX_DECLINED;
530 }
531
532
533 ngx_int_t
534 ngx_quic_send_cc(ngx_connection_t *c)
535 {
536 ngx_quic_frame_t *frame;
537 ngx_quic_connection_t *qc;
538
539 qc = ngx_quic_get_connection(c);
540
541 if (qc->draining) {
542 return NGX_OK;
543 }
544
545 if (qc->closing
546 && ngx_current_msec - qc->last_cc < NGX_QUIC_CC_MIN_INTERVAL)
547 {
548 /* dot not send CC too often */
549 return NGX_OK;
550 }
551
552 frame = ngx_quic_alloc_frame(c);
553 if (frame == NULL) {
554 return NGX_ERROR;
555 }
556
557 frame->level = qc->error_level;
558 frame->type = qc->error_app ? NGX_QUIC_FT_CONNECTION_CLOSE_APP
559 : NGX_QUIC_FT_CONNECTION_CLOSE;
560 frame->u.close.error_code = qc->error;
561 frame->u.close.frame_type = qc->error_ftype;
562
563 if (qc->error_reason) {
564 frame->u.close.reason.len = ngx_strlen(qc->error_reason);
565 frame->u.close.reason.data = (u_char *) qc->error_reason;
566 }
567
568 ngx_quic_queue_frame(qc, frame);
569
570 qc->last_cc = ngx_current_msec;
571
572 return ngx_quic_output(c);
573 }
574
575
576 ngx_int_t
577 ngx_quic_send_early_cc(ngx_connection_t *c, ngx_quic_header_t *inpkt,
578 ngx_uint_t err, const char *reason)
579 {
580 ssize_t len;
581 ngx_str_t res;
582 ngx_quic_frame_t frame;
583 ngx_quic_header_t pkt;
584
585 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
586 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
587
588 ngx_memzero(&frame, sizeof(ngx_quic_frame_t));
589 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
590
591 frame.level = inpkt->level;
592 frame.type = NGX_QUIC_FT_CONNECTION_CLOSE;
593 frame.u.close.error_code = err;
594
595 frame.u.close.reason.data = (u_char *) reason;
596 frame.u.close.reason.len = ngx_strlen(reason);
597
598 len = ngx_quic_create_frame(NULL, &frame);
599 if (len > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE) {
600 return NGX_ERROR;
601 }
602
603 ngx_quic_log_frame(c->log, &frame, 1);
604
605 len = ngx_quic_create_frame(src, &frame);
606 if (len == -1) {
607 return NGX_ERROR;
608 }
609
610 pkt.keys = ngx_quic_keys_new(c->pool);
611 if (pkt.keys == NULL) {
612 return NGX_ERROR;
613 }
614
615 if (ngx_quic_keys_set_initial_secret(c->pool, pkt.keys, &inpkt->dcid,
616 inpkt->version)
617 != NGX_OK)
618 {
619 return NGX_ERROR;
620 }
621
622 pkt.flags = NGX_QUIC_PKT_FIXED_BIT | NGX_QUIC_PKT_LONG
623 | NGX_QUIC_PKT_INITIAL;
624
625 pkt.num_len = 1;
626 /*
627 * pkt.num = 0;
628 * pkt.trunc = 0;
629 */
630
631 pkt.version = inpkt->version;
632 pkt.log = c->log;
633 pkt.level = inpkt->level;
634 pkt.dcid = inpkt->scid;
635 pkt.scid = inpkt->dcid;
636 pkt.payload.data = src;
637 pkt.payload.len = len;
638
639 res.data = dst;
640
641 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
642 return NGX_ERROR;
643 }
644
645 if (ngx_quic_send(c, res.data, res.len) == NGX_ERROR) {
646 return NGX_ERROR;
647 }
648
649 return NGX_OK;
650 }
651
652
653 ngx_int_t
654 ngx_quic_send_retry(ngx_connection_t *c, ngx_quic_conf_t *conf,
655 ngx_quic_header_t *inpkt)
656 {
657 time_t expires;
658 ssize_t len;
659 ngx_str_t res, token;
660 ngx_quic_header_t pkt;
661
662 u_char buf[NGX_QUIC_RETRY_BUFFER_SIZE];
663 u_char dcid[NGX_QUIC_SERVER_CID_LEN];
664
665 expires = ngx_time() + NGX_QUIC_RETRY_TOKEN_LIFETIME;
666
667 if (ngx_quic_new_token(c, conf->av_token_key, &token, &inpkt->dcid,
668 expires, 1)
669 != NGX_OK)
670 {
671 return NGX_ERROR;
672 }
673
674 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
675 pkt.flags = NGX_QUIC_PKT_FIXED_BIT | NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_RETRY;
676 pkt.version = inpkt->version;
677 pkt.log = c->log;
678
679 pkt.odcid = inpkt->dcid;
680 pkt.dcid = inpkt->scid;
681
682 /* TODO: generate routable dcid */
683 if (RAND_bytes(dcid, NGX_QUIC_SERVER_CID_LEN) != 1) {
684 return NGX_ERROR;
685 }
686
687 pkt.scid.len = NGX_QUIC_SERVER_CID_LEN;
688 pkt.scid.data = dcid;
689
690 pkt.token = token;
691
692 res.data = buf;
693
694 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
695 return NGX_ERROR;
696 }
697
698 #ifdef NGX_QUIC_DEBUG_PACKETS
699 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
700 "quic packet to send len:%uz %xV", res.len, &res);
701 #endif
702
703 len = ngx_quic_send(c, res.data, res.len);
704 if (len == NGX_ERROR) {
705 return NGX_ERROR;
706 }
707
708 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
709 "quic retry packet sent to %xV", &pkt.dcid);
710
711 /*
712 * quic-transport 17.2.5.1: A server MUST NOT send more than one Retry
713 * packet in response to a single UDP datagram.
714 * NGX_DONE will stop quic_input() from processing further
715 */
716 return NGX_DONE;
717 }
718
719
720 ngx_int_t
721 ngx_quic_send_new_token(ngx_connection_t *c)
722 {
723 time_t expires;
724 ngx_str_t token;
725 ngx_quic_frame_t *frame;
726 ngx_quic_connection_t *qc;
727
728 qc = ngx_quic_get_connection(c);
729
730 if (!qc->conf->retry) {
731 return NGX_OK;
732 }
733
734 expires = ngx_time() + NGX_QUIC_NEW_TOKEN_LIFETIME;
735
736 if (ngx_quic_new_token(c, qc->conf->av_token_key, &token, NULL, expires, 0)
737 != NGX_OK)
738 {
739 return NGX_ERROR;
740 }
741
742 frame = ngx_quic_alloc_frame(c);
743 if (frame == NULL) {
744 return NGX_ERROR;
745 }
746
747 frame->level = ssl_encryption_application;
748 frame->type = NGX_QUIC_FT_NEW_TOKEN;
749 frame->u.token.length = token.len;
750 frame->u.token.data = token.data;
751
752 ngx_quic_queue_frame(qc, frame);
753
754 return NGX_OK;
755 }
756
757
758 ngx_int_t
759 ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
760 {
761 size_t len, left;
762 uint64_t ack_delay;
763 ngx_buf_t *b;
764 ngx_uint_t i;
765 ngx_chain_t *cl, **ll;
766 ngx_quic_frame_t *frame;
767 ngx_quic_connection_t *qc;
768
769 qc = ngx_quic_get_connection(c);
770
771 ack_delay = ngx_current_msec - ctx->largest_received;
772 ack_delay *= 1000;
773 ack_delay >>= qc->tp.ack_delay_exponent;
774
775 frame = ngx_quic_alloc_frame(c);
776 if (frame == NULL) {
777 return NGX_ERROR;
778 }
779
780 ll = &frame->data;
781 b = NULL;
782
783 for (i = 0; i < ctx->nranges; i++) {
784 len = ngx_quic_create_ack_range(NULL, ctx->ranges[i].gap,
785 ctx->ranges[i].range);
786
787 left = b ? b->end - b->last : 0;
788
789 if (left < len) {
790 cl = ngx_quic_alloc_buf(c);
791 if (cl == NULL) {
792 return NGX_ERROR;
793 }
794
795 *ll = cl;
796 ll = &cl->next;
797
798 b = cl->buf;
799 left = b->end - b->last;
800
801 if (left < len) {
802 return NGX_ERROR;
803 }
804 }
805
806 b->last += ngx_quic_create_ack_range(b->last, ctx->ranges[i].gap,
807 ctx->ranges[i].range);
808
809 frame->u.ack.ranges_length += len;
810 }
811
812 *ll = NULL;
813
814 frame->level = ctx->level;
815 frame->type = NGX_QUIC_FT_ACK;
816 frame->u.ack.largest = ctx->largest_range;
817 frame->u.ack.delay = ack_delay;
818 frame->u.ack.range_count = ctx->nranges;
819 frame->u.ack.first_range = ctx->first_range;
820
821 ngx_quic_queue_frame(qc, frame);
822
823 return NGX_OK;
824 }
825
826
827 ngx_int_t
828 ngx_quic_send_ack_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
829 uint64_t smallest, uint64_t largest)
830 {
831 ngx_quic_frame_t *frame;
832 ngx_quic_connection_t *qc;
833
834 qc = ngx_quic_get_connection(c);
835
836 frame = ngx_quic_alloc_frame(c);
837 if (frame == NULL) {
838 return NGX_ERROR;
839 }
840
841 frame->level = ctx->level;
842 frame->type = NGX_QUIC_FT_ACK;
843 frame->u.ack.largest = largest;
844 frame->u.ack.delay = 0;
845 frame->u.ack.range_count = 0;
846 frame->u.ack.first_range = largest - smallest;
847
848 ngx_quic_queue_frame(qc, frame);
849
850 return NGX_OK;
851 }