changeset 8777:d5f93733c17d quic

QUIC: relaxed client id requirements. Client IDs cannot be reused on different paths. This change allows to reuse client id previosly seen on the same path (but with different dcid) in case when no unused client IDs are available.
author Vladimir Homutov <vl@nginx.com>
date Wed, 05 May 2021 18:11:55 +0300
parents 901126931bd5
children 5186ee5a94b9
files src/event/quic/ngx_event_quic_connid.c src/event/quic/ngx_event_quic_connid.h src/event/quic/ngx_event_quic_migration.c
diffstat 3 files changed, 44 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/quic/ngx_event_quic_connid.c	Thu May 06 12:36:14 2021 +0300
+++ b/src/event/quic/ngx_event_quic_connid.c	Wed May 05 18:11:55 2021 +0300
@@ -325,6 +325,35 @@
 }
 
 
+ngx_quic_client_id_t *
+ngx_quic_used_client_id(ngx_connection_t *c, ngx_quic_path_t *path)
+{
+    ngx_queue_t            *q;
+    ngx_quic_socket_t      *qsock;
+    ngx_quic_connection_t  *qc;
+
+    qc = ngx_quic_get_connection(c);
+
+    /* best guess: cid used by active path is good for us */
+    if (qc->socket->path == path) {
+        return qc->socket->cid;
+    }
+
+    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->path && qsock->path == path) {
+            return qsock->cid;
+        }
+    }
+
+    return NULL;
+}
+
+
 ngx_int_t
 ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c,
     ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f)
--- a/src/event/quic/ngx_event_quic_connid.h	Thu May 06 12:36:14 2021 +0300
+++ b/src/event/quic/ngx_event_quic_connid.h	Wed May 05 18:11:55 2021 +0300
@@ -23,6 +23,8 @@
 ngx_quic_client_id_t *ngx_quic_create_client_id(ngx_connection_t *c,
     ngx_str_t *id, uint64_t seqnum, u_char *token);
 ngx_quic_client_id_t *ngx_quic_next_client_id(ngx_connection_t *c);
+ngx_quic_client_id_t *ngx_quic_used_client_id(ngx_connection_t *c,
+    ngx_quic_path_t *path);
 void ngx_quic_unref_client_id(ngx_connection_t *c, ngx_quic_client_id_t *cid);
 
 #endif /* _NGX_EVENT_QUIC_CONNID_H_INCLUDED_ */
--- a/src/event/quic/ngx_event_quic_migration.c	Thu May 06 12:36:14 2021 +0300
+++ b/src/event/quic/ngx_event_quic_migration.c	Wed May 05 18:11:55 2021 +0300
@@ -348,16 +348,23 @@
         }
     }
 
+    /* prefer unused client IDs if available */
     cid = ngx_quic_next_client_id(c);
     if (cid == NULL) {
-        qc = ngx_quic_get_connection(c);
-        qc->error = NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR;
-        qc->error_reason = "no available client ids for new path";
+
+        /* try to reuse connection ID used on the same path */
+        cid = ngx_quic_used_client_id(c, path);
+        if (cid == NULL) {
 
-        ngx_log_error(NGX_LOG_ERR, c->log, 0,
-                      "no available client ids for new path");
+            qc = ngx_quic_get_connection(c);
+            qc->error = NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR;
+            qc->error_reason = "no available client ids for new path";
 
-        return NGX_ERROR;
+            ngx_log_error(NGX_LOG_ERR, c->log, 0,
+                          "no available client ids for new path");
+
+            return NGX_ERROR;
+        }
     }
 
     ngx_quic_connect(c, qsock, path, cid);