changeset 8307:dc7ac778aafe quic

Introduced packet namespace in QUIC connection. The structure contains all data that is related to the namespace: packet number and output queue (next patch).
author Vladimir Homutov <vl@nginx.com>
date Wed, 01 Apr 2020 14:31:08 +0300
parents 058a5af7ddfc
children e10b4c61420f
files src/event/ngx_event_quic.c src/event/ngx_event_quic_protection.c src/event/ngx_event_quic_transport.c src/event/ngx_event_quic_transport.h
diffstat 4 files changed, 37 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -9,6 +9,20 @@
 #include <ngx_event.h>
 
 
+/*  0-RTT and 1-RTT data exist in the same packet number space,
+ *  so we have 3 packet number spaces:
+ *
+ *  0 - Initial
+ *  1 - Handshake
+ *  2 - 0-RTT and 1-RTT
+ */
+#define ngx_quic_ns(level)                                                    \
+    ((level) == ssl_encryption_initial) ? 0                                   \
+        : (((level) == ssl_encryption_handshake) ? 1 : 2)
+
+#define NGX_QUIC_NAMESPACE_LAST  (NGX_QUIC_ENCRYPTION_LAST - 1)
+
+
 typedef enum {
     NGX_QUIC_ST_INITIAL,     /* connection just created */
     NGX_QUIC_ST_HANDSHAKE,   /* handshake started */
@@ -26,6 +40,14 @@ typedef struct {
 } ngx_quic_streams_t;
 
 
+typedef struct {
+    ngx_quic_secret_t                 client_secret;
+    ngx_quic_secret_t                 server_secret;
+
+    ngx_uint_t                        pnum;
+} ngx_quic_namespace_t;
+
+
 struct ngx_quic_connection_s {
     ngx_str_t                         scid;
     ngx_str_t                         dcid;
@@ -37,11 +59,7 @@ struct ngx_quic_connection_s {
 
     ngx_quic_state_t                  state;
 
-    /* current packet numbers  for each namespace */
-    ngx_uint_t                        initial_pn;
-    ngx_uint_t                        handshake_pn;
-    ngx_uint_t                        appdata_pn;
-
+    ngx_quic_namespace_t              ns[NGX_QUIC_NAMESPACE_LAST];
     ngx_quic_secrets_t                keys[NGX_QUIC_ENCRYPTION_LAST];
     uint64_t                          crypto_offset[NGX_QUIC_ENCRYPTION_LAST];
 
@@ -1106,11 +1124,14 @@ ngx_quic_payload_handler(ngx_connection_
         return NGX_ERROR;
     }
 
-    ack_frame->level = pkt->level;
+    ack_frame->level = (pkt->level == ssl_encryption_early_data)
+                       ? ssl_encryption_application
+                       : pkt->level;
+
     ack_frame->type = NGX_QUIC_FT_ACK;
     ack_frame->u.ack.pn = pkt->pn;
 
-    ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler level=%d", pkt->pn, pkt->level);
+    ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler level=%d", pkt->pn, ack_frame->level);
     ngx_quic_queue_frame(qc, ack_frame);
 
     return ngx_quic_output(c);
@@ -1454,6 +1475,7 @@ ngx_quic_frames_send(ngx_connection_t *c
     ngx_quic_frame_t       *f;
     ngx_quic_header_t       pkt;
     ngx_quic_secrets_t     *keys;
+    ngx_quic_namespace_t   *ns;
     ngx_quic_connection_t  *qc;
     static ngx_str_t        initial_token = ngx_null_string;
     static u_char           src[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE];
@@ -1493,20 +1515,17 @@ ngx_quic_frames_send(ngx_connection_t *c
     qc = c->quic;
 
     keys = &c->quic->keys[start->level];
+    ns = &c->quic->ns[ngx_quic_ns(start->level)];
 
     pkt.secret = &keys->server;
+    pkt.number = ns->pnum;
 
     if (start->level == ssl_encryption_initial) {
-        pkt.number = &qc->initial_pn;
         pkt.flags = NGX_QUIC_PKT_INITIAL;
         pkt.token = initial_token;
 
     } else if (start->level == ssl_encryption_handshake) {
-        pkt.number = &qc->handshake_pn;
         pkt.flags = NGX_QUIC_PKT_HANDSHAKE;
-
-    } else {
-        pkt.number = &qc->appdata_pn;
     }
 
     pkt.log = c->log;
@@ -1525,7 +1544,7 @@ ngx_quic_frames_send(ngx_connection_t *c
 
     c->send(c, res.data, res.len); // TODO: err handling
 
-    (*pkt.number)++;
+    ns->pnum++;
 
     return NGX_OK;
 }
--- a/src/event/ngx_event_quic_protection.c
+++ b/src/event/ngx_event_quic_protection.c
@@ -673,7 +673,7 @@ ngx_quic_create_long_packet(ngx_quic_hea
     }
 
     ngx_memcpy(nonce, pkt->secret->iv.data, pkt->secret->iv.len);
-    pn = *pkt->number;
+    pn = pkt->number;
     nonce[11] ^= pn;
 
     ngx_quic_hexdump0(pkt->log, "server_iv", pkt->secret->iv.data, 12);
@@ -731,7 +731,7 @@ ngx_quic_create_short_packet(ngx_quic_he
     if (pkt->level == ssl_encryption_handshake
         || pkt->level == ssl_encryption_application)
     {
-        nonce[11] ^= *pkt->number;
+        nonce[11] ^= pkt->number;
     }
 
     ngx_quic_hexdump0(pkt->log, "server_iv", pkt->secret->iv.data, 12);
--- a/src/event/ngx_event_quic_transport.c
+++ b/src/event/ngx_event_quic_transport.c
@@ -366,7 +366,7 @@ ngx_quic_create_long_header(ngx_quic_hea
 
     *pnp = p;
 
-    *p++ = (uint64_t) (*pkt->number);
+    *p++ = pkt->number; // XXX: uint64
 
     return p - start;
 }
@@ -386,7 +386,7 @@ ngx_quic_create_short_header(ngx_quic_he
 
     *pnp = p;
 
-    *p++ = (*pkt->number);
+    *p++ = pkt->number; // XXX: uint64
 
     return p - start;
 }
--- a/src/event/ngx_event_quic_transport.h
+++ b/src/event/ngx_event_quic_transport.h
@@ -232,7 +232,7 @@ typedef struct {
     ngx_log_t                                  *log;
 
     struct ngx_quic_secret_s                   *secret;
-    ngx_uint_t                                 *number;
+    uint64_t                                    number;
     uint8_t                                     flags;
     uint32_t                                    version;
     ngx_str_t                                   token;