Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic_output.c @ 8971:1e2f4e9c8195 quic
QUIC: reworked migration handling.
The quic connection now holds active, backup and probe paths instead
of sockets. The number of migration paths is now limited and cannot
be inflated by a bad client or an attacker.
The client id is now associated with path rather than socket. This allows
to simplify processing of output and connection ids handling.
New migration abandons any previously started migrations. This allows to
free consumed client ids and request new for use in future migrations and
make progress in case when connection id limit is hit during migration.
A path now can be revalidated without losing its state.
The patch also fixes various issues with NAT rebinding case handling:
- paths are now validated (previously, there was no validation
and paths were left in limited state)
- attempt to reuse id on different path is now again verified
(this was broken in 40445fc7c403)
- former path is now validated in case of apparent migration
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Wed, 19 Jan 2022 22:39:24 +0300 |
parents | 19e063e955bf |
children | e5509ff0dfd2 |
comparison
equal
deleted
inserted
replaced
8970:7106a918a277 | 8971:1e2f4e9c8195 |
---|---|
49 size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment); | 49 size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment); |
50 #endif | 50 #endif |
51 static ssize_t ngx_quic_output_packet(ngx_connection_t *c, | 51 static ssize_t ngx_quic_output_packet(ngx_connection_t *c, |
52 ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min); | 52 ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min); |
53 static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, | 53 static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, |
54 ngx_quic_header_t *pkt); | 54 ngx_quic_header_t *pkt, ngx_quic_path_t *path); |
55 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); | 55 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); |
56 static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len, | 56 static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len, |
57 struct sockaddr *sockaddr, socklen_t socklen); | 57 struct sockaddr *sockaddr, socklen_t socklen); |
58 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt, | 58 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt, |
59 ngx_quic_send_ctx_t *ctx); | 59 ngx_quic_send_ctx_t *ctx); |
129 ngx_quic_connection_t *qc; | 129 ngx_quic_connection_t *qc; |
130 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | 130 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; |
131 | 131 |
132 qc = ngx_quic_get_connection(c); | 132 qc = ngx_quic_get_connection(c); |
133 cg = &qc->congestion; | 133 cg = &qc->congestion; |
134 path = qc->socket->path; | 134 path = qc->path; |
135 | 135 |
136 while (cg->in_flight < cg->window) { | 136 while (cg->in_flight < cg->window) { |
137 | 137 |
138 p = dst; | 138 p = dst; |
139 | 139 |
267 | 267 |
268 if (!qc->conf->gso_enabled) { | 268 if (!qc->conf->gso_enabled) { |
269 return 0; | 269 return 0; |
270 } | 270 } |
271 | 271 |
272 if (qc->socket->path->limited) { | 272 if (qc->path->limited) { |
273 /* don't even try to be faster on non-validated paths */ | 273 /* don't even try to be faster on non-validated paths */ |
274 return 0; | 274 return 0; |
275 } | 275 } |
276 | 276 |
277 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial); | 277 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial); |
323 ngx_quic_connection_t *qc; | 323 ngx_quic_connection_t *qc; |
324 static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF]; | 324 static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF]; |
325 | 325 |
326 qc = ngx_quic_get_connection(c); | 326 qc = ngx_quic_get_connection(c); |
327 cg = &qc->congestion; | 327 cg = &qc->congestion; |
328 path = qc->socket->path; | 328 path = qc->path; |
329 | 329 |
330 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); | 330 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); |
331 | 331 |
332 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) { | 332 if (ngx_quic_generate_ack(c, ctx) != NGX_OK) { |
333 return NGX_ERROR; | 333 return NGX_ERROR; |
503 | 503 |
504 static ssize_t | 504 static ssize_t |
505 ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, | 505 ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, |
506 u_char *data, size_t max, size_t min) | 506 u_char *data, size_t max, size_t min) |
507 { | 507 { |
508 size_t len, pad, min_payload, max_payload; | 508 size_t len, pad, min_payload, max_payload; |
509 u_char *p; | 509 u_char *p; |
510 ssize_t flen; | 510 ssize_t flen; |
511 ngx_str_t res; | 511 ngx_str_t res; |
512 ngx_int_t rc; | 512 ngx_int_t rc; |
513 ngx_uint_t nframes, expand; | 513 ngx_uint_t nframes, expand; |
514 ngx_msec_t now; | 514 ngx_msec_t now; |
515 ngx_queue_t *q; | 515 ngx_queue_t *q; |
516 ngx_quic_frame_t *f; | 516 ngx_quic_frame_t *f; |
517 ngx_quic_header_t pkt; | 517 ngx_quic_header_t pkt; |
518 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | 518 ngx_quic_connection_t *qc; |
519 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | |
519 | 520 |
520 if (ngx_queue_empty(&ctx->frames)) { | 521 if (ngx_queue_empty(&ctx->frames)) { |
521 return 0; | 522 return 0; |
522 } | 523 } |
523 | 524 |
524 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | 525 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, |
525 "quic output %s packet max:%uz min:%uz", | 526 "quic output %s packet max:%uz min:%uz", |
526 ngx_quic_level_name(ctx->level), max, min); | 527 ngx_quic_level_name(ctx->level), max, min); |
527 | 528 |
528 ngx_quic_init_packet(c, ctx, &pkt); | 529 qc = ngx_quic_get_connection(c); |
530 | |
531 ngx_quic_init_packet(c, ctx, &pkt, qc->path); | |
529 | 532 |
530 min_payload = ngx_quic_payload_size(&pkt, min); | 533 min_payload = ngx_quic_payload_size(&pkt, min); |
531 max_payload = ngx_quic_payload_size(&pkt, max); | 534 max_payload = ngx_quic_payload_size(&pkt, max); |
532 | 535 |
533 /* RFC 9001, 5.4.2. Header Protection Sample */ | 536 /* RFC 9001, 5.4.2. Header Protection Sample */ |
666 } | 669 } |
667 | 670 |
668 | 671 |
669 static void | 672 static void |
670 ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, | 673 ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, |
671 ngx_quic_header_t *pkt) | 674 ngx_quic_header_t *pkt, ngx_quic_path_t *path) |
672 { | 675 { |
673 ngx_quic_socket_t *qsock; | 676 ngx_quic_socket_t *qsock; |
674 ngx_quic_connection_t *qc; | 677 ngx_quic_connection_t *qc; |
675 | 678 |
676 qc = ngx_quic_get_connection(c); | 679 qc = ngx_quic_get_connection(c); |
677 | 680 |
678 qsock = qc->socket; | 681 qsock = ngx_quic_get_socket(c); |
679 | 682 |
680 ngx_memzero(pkt, sizeof(ngx_quic_header_t)); | 683 ngx_memzero(pkt, sizeof(ngx_quic_header_t)); |
681 | 684 |
682 pkt->flags = NGX_QUIC_PKT_FIXED_BIT; | 685 pkt->flags = NGX_QUIC_PKT_FIXED_BIT; |
683 | 686 |
691 if (qc->key_phase) { | 694 if (qc->key_phase) { |
692 pkt->flags |= NGX_QUIC_PKT_KPHASE; | 695 pkt->flags |= NGX_QUIC_PKT_KPHASE; |
693 } | 696 } |
694 } | 697 } |
695 | 698 |
696 pkt->dcid.data = qsock->cid->id; | 699 pkt->dcid.data = path->cid->id; |
697 pkt->dcid.len = qsock->cid->len; | 700 pkt->dcid.len = path->cid->len; |
698 | 701 |
699 pkt->scid.data = qsock->sid.id; | 702 pkt->scid.data = qsock->sid.id; |
700 pkt->scid.len = qsock->sid.len; | 703 pkt->scid.len = qsock->sid.len; |
701 | 704 |
702 pkt->version = qc->version; | 705 pkt->version = qc->version; |
1200 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | 1203 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; |
1201 | 1204 |
1202 qc = ngx_quic_get_connection(c); | 1205 qc = ngx_quic_get_connection(c); |
1203 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); | 1206 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); |
1204 | 1207 |
1205 ngx_quic_init_packet(c, ctx, &pkt); | 1208 ngx_quic_init_packet(c, ctx, &pkt, path); |
1206 | 1209 |
1207 min = ngx_quic_path_limit(c, path, min); | 1210 min = ngx_quic_path_limit(c, path, min); |
1208 | 1211 |
1209 min_payload = min ? ngx_quic_payload_size(&pkt, min) : 0; | 1212 min_payload = min ? ngx_quic_payload_size(&pkt, min) : 0; |
1210 | 1213 |