]> git.kaiwu.me - nginx.git/commitdiff
QUIC: relaxed client id requirements.
authorVladimir Homutov <vl@nginx.com>
Wed, 5 May 2021 15:11:55 +0000 (18:11 +0300)
committerVladimir Homutov <vl@nginx.com>
Wed, 5 May 2021 15:11:55 +0000 (18:11 +0300)
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.

src/event/quic/ngx_event_quic_connid.c
src/event/quic/ngx_event_quic_connid.h
src/event/quic/ngx_event_quic_migration.c

index a30e7ef358e2a325739e954436352e29a563605b..4dbb2bbd6582d811c7267b2822583318cf8a84a3 100644 (file)
@@ -325,6 +325,35 @@ 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)
+{
+    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)
index fc7850a9c97764eabf5dd706f88a12ef982ae6e4..a0552e9dd419c9d37875688c8d73d8ba3a7722b8 100644 (file)
@@ -23,6 +23,8 @@ ngx_int_t ngx_quic_create_server_id(ngx_connection_t *c, u_char *id);
 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_ */
index f1c923f83cd533350602d13948f387e19d4b4cf5..74dc0113b10ee7fbf6792d7bf556798265ef88c8 100644 (file)
@@ -348,16 +348,23 @@ ngx_quic_update_paths(ngx_connection_t *c, ngx_quic_header_t *pkt)
         }
     }
 
+    /* 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";
 
-        ngx_log_error(NGX_LOG_ERR, c->log, 0,
-                      "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) {
 
-        return NGX_ERROR;
+            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";
+
+            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);