From c4f5b50c47a867dfb72f80a5c3dd0e87508e0502 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Thu, 29 Apr 2021 15:35:02 +0300 Subject: QUIC: connection migration. The patch adds proper transitions between multiple networking addresses that can be used by a single quic connection. New networking paths are validated using PATH_CHALLENGE/PATH_RESPONSE frames. --- src/event/quic/ngx_event_quic_socket.c | 355 +++++++++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) create mode 100644 src/event/quic/ngx_event_quic_socket.c (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c new file mode 100644 index 000000000..968ad6a73 --- /dev/null +++ b/src/event/quic/ngx_event_quic_socket.c @@ -0,0 +1,355 @@ + +/* + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include + + +static ngx_int_t ngx_quic_create_temp_socket(ngx_connection_t *c, + ngx_quic_connection_t *qc, ngx_str_t *dcid, ngx_quic_path_t *path, + ngx_quic_client_id_t *cid); + +static void ngx_quic_unref_path(ngx_connection_t *c, ngx_quic_path_t *path); + + +ngx_int_t +ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, + ngx_quic_header_t *pkt) +{ + ngx_quic_path_t *path; + ngx_quic_socket_t *qsock; + ngx_quic_client_id_t *cid; + + /* + * qc->nclient_ids = 0 + * qc->nsockets = 0 + * qc->max_retired_seqnum = 0 + * qc->client_seqnum = 0 + */ + + ngx_queue_init(&qc->sockets); + ngx_queue_init(&qc->free_sockets); + + ngx_queue_init(&qc->paths); + ngx_queue_init(&qc->free_paths); + + ngx_queue_init(&qc->client_ids); + ngx_queue_init(&qc->free_client_ids); + + qc->tp.original_dcid.len = pkt->odcid.len; + qc->tp.original_dcid.data = ngx_pstrdup(c->pool, &pkt->odcid); + if (qc->tp.original_dcid.data == NULL) { + return NGX_ERROR; + } + + /* socket to use for further processing */ + qsock = ngx_quic_alloc_socket(c, qc); + if (qsock == NULL) { + return NGX_ERROR; + } + + /* socket is listening at new server id (autogenerated) */ + if (ngx_quic_listen(c, qc, qsock) != NGX_OK) { + return NGX_ERROR; + } + + qc->tp.initial_scid.len = qsock->sid.len; + qc->tp.initial_scid.data = ngx_pnalloc(c->pool, qsock->sid.len); + if (qc->tp.initial_scid.data == NULL) { + goto failed; + } + ngx_memcpy(qc->tp.initial_scid.data, qsock->sid.id, qsock->sid.len); + + /* for all packets except first, this is set at udp layer */ + c->udp = &qsock->udp; + + /* ngx_quic_get_connection(c) macro is now usable */ + + /* we have a client identified by scid */ + cid = ngx_quic_create_client_id(c, &pkt->scid, 0, NULL); + if (cid == NULL) { + goto failed; + } + + /* the client arrived from this path */ + path = ngx_quic_add_path(c, c->sockaddr, c->socklen); + if (path == NULL) { + goto failed; + } + + if (pkt->validated) { + path->state = NGX_QUIC_PATH_VALIDATED; + path->validated_at = ngx_time(); + } + + /* now bind socket to client and path */ + ngx_quic_connect(c, qsock, path, cid); + + if (ngx_quic_create_temp_socket(c, qc, &pkt->odcid, path, cid) != NGX_OK) { + goto failed; + } + + /* use this socket as default destination */ + qc->socket = qsock; + + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic active socket is #%uL:%uL:%uL (%s)", + qsock->sid.seqnum, qsock->cid->seqnum, qsock->path->seqnum, + ngx_quic_path_state_str(qsock->path)); + + return NGX_OK; + +failed: + + ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node); + c->udp = NULL; + + return NGX_ERROR; +} + + +static ngx_int_t +ngx_quic_create_temp_socket(ngx_connection_t *c, ngx_quic_connection_t *qc, + ngx_str_t *dcid, ngx_quic_path_t *path, ngx_quic_client_id_t *cid) +{ + ngx_str_t id; + ngx_quic_socket_t *qsock; + ngx_quic_server_id_t *sid; + + qsock = ngx_quic_alloc_socket(c, qc); + if (qsock == NULL) { + return NGX_ERROR; + } + + sid = &qsock->sid; + + sid->seqnum = NGX_QUIC_UNSET_PN; /* mark socket as temporary */ + + sid->len = dcid->len; + ngx_memcpy(sid->id, dcid->data, dcid->len); + + id.len = sid->len; + id.data = sid->id; + + ngx_insert_udp_connection(c, &qsock->udp, &id); + + ngx_queue_insert_tail(&qc->sockets, &qsock->queue); + + qc->nsockets++; + qsock->quic = qc; + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic socket #%L listening at sid:%xV nsock:%ui", + (int64_t) sid->seqnum, &id, qc->nsockets); + + ngx_quic_connect(c, qsock, path, cid); + + return NGX_OK; +} + + +ngx_quic_socket_t * +ngx_quic_alloc_socket(ngx_connection_t *c, ngx_quic_connection_t *qc) +{ + ngx_queue_t *q; + ngx_quic_socket_t *sock; + + if (!ngx_queue_empty(&qc->free_sockets)) { + + q = ngx_queue_head(&qc->free_sockets); + sock = ngx_queue_data(q, ngx_quic_socket_t, queue); + + ngx_queue_remove(&sock->queue); + + ngx_memzero(sock, sizeof(ngx_quic_socket_t)); + + } else { + + sock = ngx_pcalloc(c->pool, sizeof(ngx_quic_socket_t)); + if (sock == NULL) { + return NULL; + } + } + + return sock; +} + + +void +ngx_quic_close_socket(ngx_connection_t *c, ngx_quic_socket_t *qsock) +{ + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + + ngx_queue_remove(&qsock->queue); + ngx_queue_insert_head(&qc->free_sockets, &qsock->queue); + + ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node); + qc->nsockets--; + + if (qsock->path) { + ngx_quic_unref_path(c, qsock->path); + } + + if (qsock->cid) { + ngx_quic_unref_client_id(c, qsock->cid); + } + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic socket #%L closed nsock:%ui", + (int64_t) qsock->sid.seqnum, qc->nsockets); +} + + +static void +ngx_quic_unref_path(ngx_connection_t *c, ngx_quic_path_t *path) +{ + ngx_quic_connection_t *qc; + + path->refcnt--; + + if (path->refcnt) { + return; + } + + qc = ngx_quic_get_connection(c); + + ngx_queue_remove(&path->queue); + ngx_queue_insert_head(&qc->free_paths, &path->queue); + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic path #%uL addr:%V removed", + path->seqnum, &path->addr_text); +} + + +ngx_int_t +ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc, + ngx_quic_socket_t *qsock) +{ + ngx_str_t id; + ngx_quic_server_id_t *sid; + + sid = &qsock->sid; + + sid->len = NGX_QUIC_SERVER_CID_LEN; + + if (ngx_quic_create_server_id(c, sid->id) != NGX_OK) { + return NGX_ERROR; + } + + sid->seqnum = qc->server_seqnum++; + + id.data = sid->id; + id.len = sid->len; + + ngx_insert_udp_connection(c, &qsock->udp, &id); + + ngx_queue_insert_tail(&qc->sockets, &qsock->queue); + + qc->nsockets++; + qsock->quic = qc; + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic socket #%uL listening at sid:%xV nsock:%ui", + sid->seqnum, &id, qc->nsockets); + + return NGX_OK; +} + + +void +ngx_quic_connect(ngx_connection_t *c, ngx_quic_socket_t *sock, + ngx_quic_path_t *path, ngx_quic_client_id_t *cid) +{ + sock->path = path; + path->refcnt++; + + sock->cid = cid; + cid->refcnt++; + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic socket #%L connected to cid #%uL path:%uL", + (int64_t) sock->sid.seqnum, + sock->cid->seqnum, path->seqnum); +} + + +void +ngx_quic_close_sockets(ngx_connection_t *c) +{ + ngx_queue_t *q; + ngx_quic_socket_t *qsock; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + + ngx_quic_close_socket(c, qc->socket); + + if (qc->backup) { + ngx_quic_close_socket(c, qc->backup); + } + + while (!ngx_queue_empty(&qc->sockets)) { + q = ngx_queue_head(&qc->sockets); + qsock = ngx_queue_data(q, ngx_quic_socket_t, queue); + + ngx_quic_close_socket(c, qsock); + } +} + + +ngx_quic_socket_t * +ngx_quic_find_socket(ngx_connection_t *c, uint64_t seqnum) +{ + ngx_queue_t *q; + ngx_quic_socket_t *qsock; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + + for (q = ngx_queue_head(&qc->sockets); + q != ngx_queue_sentinel(&qc->sockets); + q = ngx_queue_next(q)) + { + qsock = ngx_queue_data(q, ngx_quic_socket_t, queue); + + if (qsock->sid.seqnum == seqnum) { + return qsock; + } + } + + return NULL; +} + + +ngx_quic_socket_t * +ngx_quic_get_unconnected_socket(ngx_connection_t *c) +{ + ngx_queue_t *q; + ngx_quic_socket_t *sock; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + + for (q = ngx_queue_head(&qc->sockets); + q != ngx_queue_sentinel(&qc->sockets); + q = ngx_queue_next(q)) + { + sock = ngx_queue_data(q, ngx_quic_socket_t, queue); + + if (sock->cid == NULL) { + return sock; + } + } + + return NULL; + } + + -- cgit From 8f8cb92e9229d75ea5816f35c6b4bfdfb253a486 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Tue, 26 Oct 2021 18:05:57 +0300 Subject: QUIC: style. --- src/event/quic/ngx_event_quic_socket.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index 968ad6a73..ddde68f09 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -350,6 +350,4 @@ ngx_quic_get_unconnected_socket(ngx_connection_t *c) } return NULL; - } - - +} -- cgit From e165526e43d60b9249690faccbb380be20e88af3 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Thu, 18 Nov 2021 14:19:36 +0300 Subject: QUIC: fixed handling of RETIRE_CONNECTION_ID frame. Previously, the retired socket was not closed if it didn't match active or backup. New sockets could not be created (due to count limit), since retired socket was not closed before calling ngx_quic_create_sockets(). When replacing retired socket, new socket is only requested after closing old one, to avoid hitting the limit on the number of active connection ids. Together with added restrictions, this fixes an issue when a current socket could be closed during migration, recreated and erroneously reused leading to null pointer dereference. --- src/event/quic/ngx_event_quic_socket.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index ddde68f09..3b507fca8 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -14,8 +14,6 @@ static ngx_int_t ngx_quic_create_temp_socket(ngx_connection_t *c, ngx_quic_connection_t *qc, ngx_str_t *dcid, ngx_quic_path_t *path, ngx_quic_client_id_t *cid); -static void ngx_quic_unref_path(ngx_connection_t *c, ngx_quic_path_t *path); - ngx_int_t ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, @@ -207,7 +205,7 @@ ngx_quic_close_socket(ngx_connection_t *c, ngx_quic_socket_t *qsock) } -static void +void ngx_quic_unref_path(ngx_connection_t *c, ngx_quic_path_t *path) { ngx_quic_connection_t *qc; -- cgit From 0de6a1ebb48c13e658b0e94be1a3045a725c4624 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Thu, 18 Nov 2021 14:33:21 +0300 Subject: QUIC: removed unnecessary closing of active/backup sockets. All open sockets are stored in a queue. There is no need to close some of them separately. If it happens that active and backup point to same socket, double close may happen (leading to possible segfault). --- src/event/quic/ngx_event_quic_socket.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index 3b507fca8..4a9fb232d 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -288,12 +288,6 @@ ngx_quic_close_sockets(ngx_connection_t *c) qc = ngx_quic_get_connection(c); - ngx_quic_close_socket(c, qc->socket); - - if (qc->backup) { - ngx_quic_close_socket(c, qc->backup); - } - while (!ngx_queue_empty(&qc->sockets)) { q = ngx_queue_head(&qc->sockets); qsock = ngx_queue_data(q, ngx_quic_socket_t, queue); -- cgit From a31745499bcf35fac236bdc5f3d0d0a6d679b4e0 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Mon, 13 Dec 2021 17:27:29 +0300 Subject: QUIC: improved path validation. Previously, path was considered valid during arbitrary selected 10m timeout since validation. This is quite not what RFC 9000 says; the relevant part is: An endpoint MAY skip validation of a peer address if that address has been seen recently. The patch considers a path to be 'recently seen' if packets were received during idle timeout. If a packet is received from the path that was seen not so recently, such path is considered new, and anti-amplification restrictions apply. --- src/event/quic/ngx_event_quic_socket.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index 4a9fb232d..2b9b0fed3 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -82,7 +82,6 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, if (pkt->validated) { path->state = NGX_QUIC_PATH_VALIDATED; - path->validated_at = ngx_time(); } /* now bind socket to client and path */ -- cgit From 10fd8be86d657839fbc6218891bfe9046ab5b592 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Mon, 13 Dec 2021 09:48:33 +0300 Subject: QUIC: decoupled path state and limitation status. The path validation status and anti-amplification limit status is actually two different variables. It is possible that validating path should not be limited (for example, when re-validating former path). --- src/event/quic/ngx_event_quic_socket.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index 2b9b0fed3..a04ad6202 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -82,6 +82,7 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, if (pkt->validated) { path->state = NGX_QUIC_PATH_VALIDATED; + path->limited = 0; } /* now bind socket to client and path */ -- cgit From fa21bf0cc7ba2d94f66a061d644163547d79e6a2 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Mon, 27 Dec 2021 13:49:56 +0300 Subject: QUIC: got rid of ngx_quic_create_temp_socket(). It was mostly copy of the ngx_quic_listen(). Now ngx_quic_listen() no longer generates server id and increments seqnum. Instead, the server id is generated when the socket is created. The ngx_quic_alloc_socket() function is renamed to ngx_quic_create_socket(). --- src/event/quic/ngx_event_quic_socket.c | 88 +++++++++++----------------------- 1 file changed, 27 insertions(+), 61 deletions(-) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index a04ad6202..426e1ebae 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -10,17 +10,12 @@ #include -static ngx_int_t ngx_quic_create_temp_socket(ngx_connection_t *c, - ngx_quic_connection_t *qc, ngx_str_t *dcid, ngx_quic_path_t *path, - ngx_quic_client_id_t *cid); - - ngx_int_t ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, ngx_quic_header_t *pkt) { ngx_quic_path_t *path; - ngx_quic_socket_t *qsock; + ngx_quic_socket_t *qsock, *tmp; ngx_quic_client_id_t *cid; /* @@ -45,13 +40,13 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, return NGX_ERROR; } - /* socket to use for further processing */ - qsock = ngx_quic_alloc_socket(c, qc); + /* socket to use for further processing (id auto-generated) */ + qsock = ngx_quic_create_socket(c, qc); if (qsock == NULL) { return NGX_ERROR; } - /* socket is listening at new server id (autogenerated) */ + /* socket is listening at new server id */ if (ngx_quic_listen(c, qc, qsock) != NGX_OK) { return NGX_ERROR; } @@ -88,10 +83,22 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, /* now bind socket to client and path */ ngx_quic_connect(c, qsock, path, cid); - if (ngx_quic_create_temp_socket(c, qc, &pkt->odcid, path, cid) != NGX_OK) { + tmp = ngx_pcalloc(c->pool, sizeof(ngx_quic_socket_t)); + if (tmp == NULL) { + goto failed; + } + + tmp->sid.seqnum = NGX_QUIC_UNSET_PN; /* temporary socket */ + + ngx_memcpy(tmp->sid.id, pkt->odcid.data, pkt->odcid.len); + tmp->sid.len = pkt->odcid.len; + + if (ngx_quic_listen(c, qc, tmp) != NGX_OK) { goto failed; } + ngx_quic_connect(c, tmp, path, cid); + /* use this socket as default destination */ qc->socket = qsock; @@ -111,48 +118,8 @@ failed: } -static ngx_int_t -ngx_quic_create_temp_socket(ngx_connection_t *c, ngx_quic_connection_t *qc, - ngx_str_t *dcid, ngx_quic_path_t *path, ngx_quic_client_id_t *cid) -{ - ngx_str_t id; - ngx_quic_socket_t *qsock; - ngx_quic_server_id_t *sid; - - qsock = ngx_quic_alloc_socket(c, qc); - if (qsock == NULL) { - return NGX_ERROR; - } - - sid = &qsock->sid; - - sid->seqnum = NGX_QUIC_UNSET_PN; /* mark socket as temporary */ - - sid->len = dcid->len; - ngx_memcpy(sid->id, dcid->data, dcid->len); - - id.len = sid->len; - id.data = sid->id; - - ngx_insert_udp_connection(c, &qsock->udp, &id); - - ngx_queue_insert_tail(&qc->sockets, &qsock->queue); - - qc->nsockets++; - qsock->quic = qc; - - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic socket #%L listening at sid:%xV nsock:%ui", - (int64_t) sid->seqnum, &id, qc->nsockets); - - ngx_quic_connect(c, qsock, path, cid); - - return NGX_OK; -} - - ngx_quic_socket_t * -ngx_quic_alloc_socket(ngx_connection_t *c, ngx_quic_connection_t *qc) +ngx_quic_create_socket(ngx_connection_t *c, ngx_quic_connection_t *qc) { ngx_queue_t *q; ngx_quic_socket_t *sock; @@ -174,6 +141,13 @@ ngx_quic_alloc_socket(ngx_connection_t *c, ngx_quic_connection_t *qc) } } + sock->sid.len = NGX_QUIC_SERVER_CID_LEN; + if (ngx_quic_create_server_id(c, sock->sid.id) != NGX_OK) { + return NULL; + } + + sock->sid.seqnum = qc->server_seqnum++; + return sock; } @@ -236,14 +210,6 @@ ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc, sid = &qsock->sid; - sid->len = NGX_QUIC_SERVER_CID_LEN; - - if (ngx_quic_create_server_id(c, sid->id) != NGX_OK) { - return NGX_ERROR; - } - - sid->seqnum = qc->server_seqnum++; - id.data = sid->id; id.len = sid->len; @@ -255,8 +221,8 @@ ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc, qsock->quic = qc; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic socket #%uL listening at sid:%xV nsock:%ui", - sid->seqnum, &id, qc->nsockets); + "quic socket #%L listening at sid:%xV nsock:%ui", + (int64_t) sid->seqnum, &id, qc->nsockets); return NGX_OK; } -- cgit From 8a4a267d74fa31e4693691a1a8788b0773329481 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Wed, 19 Jan 2022 22:39:24 +0300 Subject: 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 --- src/event/quic/ngx_event_quic_socket.c | 101 ++++----------------------------- 1 file changed, 12 insertions(+), 89 deletions(-) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index 426e1ebae..b5d168a7a 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -14,11 +14,12 @@ ngx_int_t ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, ngx_quic_header_t *pkt) { - ngx_quic_path_t *path; ngx_quic_socket_t *qsock, *tmp; ngx_quic_client_id_t *cid; /* + * qc->path = NULL + * * qc->nclient_ids = 0 * qc->nsockets = 0 * qc->max_retired_seqnum = 0 @@ -51,6 +52,8 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, return NGX_ERROR; } + qsock->used = 1; + qc->tp.initial_scid.len = qsock->sid.len; qc->tp.initial_scid.data = ngx_pnalloc(c->pool, qsock->sid.len); if (qc->tp.initial_scid.data == NULL) { @@ -69,19 +72,20 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, goto failed; } - /* the client arrived from this path */ - path = ngx_quic_add_path(c, c->sockaddr, c->socklen); - if (path == NULL) { + /* path of the first packet is our initial active path */ + qc->path = ngx_quic_new_path(c, c->sockaddr, c->socklen, cid); + if (qc->path == NULL) { goto failed; } + qc->path->tag = NGX_QUIC_PATH_ACTIVE; + if (pkt->validated) { - path->state = NGX_QUIC_PATH_VALIDATED; - path->limited = 0; + qc->path->validated = 1; + qc->path->limited = 0; } - /* now bind socket to client and path */ - ngx_quic_connect(c, qsock, path, cid); + ngx_quic_path_dbg(c, "set active", qc->path); tmp = ngx_pcalloc(c->pool, sizeof(ngx_quic_socket_t)); if (tmp == NULL) { @@ -97,16 +101,6 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, goto failed; } - ngx_quic_connect(c, tmp, path, cid); - - /* use this socket as default destination */ - qc->socket = qsock; - - ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic active socket is #%uL:%uL:%uL (%s)", - qsock->sid.seqnum, qsock->cid->seqnum, qsock->path->seqnum, - ngx_quic_path_state_str(qsock->path)); - return NGX_OK; failed: @@ -165,42 +159,12 @@ ngx_quic_close_socket(ngx_connection_t *c, ngx_quic_socket_t *qsock) ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node); qc->nsockets--; - if (qsock->path) { - ngx_quic_unref_path(c, qsock->path); - } - - if (qsock->cid) { - ngx_quic_unref_client_id(c, qsock->cid); - } - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic socket #%L closed nsock:%ui", (int64_t) qsock->sid.seqnum, qc->nsockets); } -void -ngx_quic_unref_path(ngx_connection_t *c, ngx_quic_path_t *path) -{ - ngx_quic_connection_t *qc; - - path->refcnt--; - - if (path->refcnt) { - return; - } - - qc = ngx_quic_get_connection(c); - - ngx_queue_remove(&path->queue); - ngx_queue_insert_head(&qc->free_paths, &path->queue); - - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic path #%uL addr:%V removed", - path->seqnum, &path->addr_text); -} - - ngx_int_t ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc, ngx_quic_socket_t *qsock) @@ -228,23 +192,6 @@ ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc, } -void -ngx_quic_connect(ngx_connection_t *c, ngx_quic_socket_t *sock, - ngx_quic_path_t *path, ngx_quic_client_id_t *cid) -{ - sock->path = path; - path->refcnt++; - - sock->cid = cid; - cid->refcnt++; - - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic socket #%L connected to cid #%uL path:%uL", - (int64_t) sock->sid.seqnum, - sock->cid->seqnum, path->seqnum); -} - - void ngx_quic_close_sockets(ngx_connection_t *c) { @@ -285,27 +232,3 @@ ngx_quic_find_socket(ngx_connection_t *c, uint64_t seqnum) return NULL; } - - -ngx_quic_socket_t * -ngx_quic_get_unconnected_socket(ngx_connection_t *c) -{ - ngx_queue_t *q; - ngx_quic_socket_t *sock; - ngx_quic_connection_t *qc; - - qc = ngx_quic_get_connection(c); - - for (q = ngx_queue_head(&qc->sockets); - q != ngx_queue_sentinel(&qc->sockets); - q = ngx_queue_next(q)) - { - sock = ngx_queue_data(q, ngx_quic_socket_t, queue); - - if (sock->cid == NULL) { - return sock; - } - } - - return NULL; -} -- cgit From 26bc237677f1baad3ab565b70cc951f8a3b6ad90 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Fri, 28 Jan 2022 14:57:33 +0300 Subject: QUIC: got rid of hash symbol in backup and logging. Now all objectes with sequence number (i.e. sockets, connection ids and paths) are logged as "foo seq:N". --- src/event/quic/ngx_event_quic_socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index b5d168a7a..44387fd3c 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -160,7 +160,7 @@ ngx_quic_close_socket(ngx_connection_t *c, ngx_quic_socket_t *qsock) qc->nsockets--; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic socket #%L closed nsock:%ui", + "quic socket seq:%L closed nsock:%ui", (int64_t) qsock->sid.seqnum, qc->nsockets); } @@ -185,7 +185,7 @@ ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc, qsock->quic = qc; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic socket #%L listening at sid:%xV nsock:%ui", + "quic socket seq:%L listening at sid:%xV nsock:%ui", (int64_t) sid->seqnum, &id, qc->nsockets); return NGX_OK; -- cgit From 2526632f7172d46d54dbf9738b497d91b9543f50 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Wed, 16 Feb 2022 15:45:47 +0300 Subject: QUIC: fixed indentation. --- src/event/quic/ngx_event_quic_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index 44387fd3c..c9e1b603c 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -38,7 +38,7 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc, qc->tp.original_dcid.len = pkt->odcid.len; qc->tp.original_dcid.data = ngx_pstrdup(c->pool, &pkt->odcid); if (qc->tp.original_dcid.data == NULL) { - return NGX_ERROR; + return NGX_ERROR; } /* socket to use for further processing (id auto-generated) */ -- cgit From 9d81ef744cdaacf1e52bcaec4224d375af5ba59b Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 20 Apr 2022 16:01:17 +0400 Subject: QUIC: separate UDP framework for QUIC. Previously, QUIC used the existing UDP framework, which was created for UDP in Stream. However the way QUIC connections are created and looked up is different from the way UDP connections in Stream are created and looked up. Now these two implementations are decoupled. --- src/event/quic/ngx_event_quic_socket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index c9e1b603c..6813fcd0a 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -177,7 +177,10 @@ ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc, id.data = sid->id; id.len = sid->len; - ngx_insert_udp_connection(c, &qsock->udp, &id); + qsock->udp.connection = c; + qsock->udp.node.key = ngx_crc32_long(id.data, id.len); + + ngx_rbtree_insert(&c->listening->rbtree, &qsock->udp.node); ngx_queue_insert_tail(&qc->sockets, &qsock->queue); -- cgit From 0a3c79614521d7612b63eff4e09c25ed219fb65b Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Sun, 14 May 2023 12:30:11 +0400 Subject: Common tree insert function for QUIC and UDP connections. Previously, ngx_udp_rbtree_insert_value() was used for plain UDP and ngx_quic_rbtree_insert_value() was used for QUIC. Because of this it was impossible to initialize connection tree in ngx_create_listening() since this function is not aware what kind of listening it creates. Now ngx_udp_rbtree_insert_value() is used for both QUIC and UDP. To make is possible, a generic key field is added to ngx_udp_connection_t. It keeps client address for UDP and connection ID for QUIC. --- src/event/quic/ngx_event_quic_socket.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/event/quic/ngx_event_quic_socket.c') diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c index 6813fcd0a..6652523b7 100644 --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -179,6 +179,7 @@ ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc, qsock->udp.connection = c; qsock->udp.node.key = ngx_crc32_long(id.data, id.len); + qsock->udp.key = id; ngx_rbtree_insert(&c->listening->rbtree, &qsock->udp.node); -- cgit