diff src/event/ngx_event_quic_transport.c @ 8560:d0d3fc0697a0 quic

QUIC: packet processing refactoring. All packet header parsing is now performed by ngx_quic_parse_packet() function, located in the ngx_quic_transport.c file. The packet processing is centralized in the ngx_quic_process_packet() function which decides if the packet should be accepted, ignored or connection should be closed, depending on the connection state. As a result of refactoring, behavior has changed in some places: - minimal size of Initial packet is now always tested - connection IDs are always tested in existing connections - old keys are discarded on encryption level switch
author Vladimir Homutov <vl@nginx.com>
date Wed, 30 Sep 2020 15:14:09 +0300
parents a89a58c642ef
children b31c02454539
line wrap: on
line diff
--- a/src/event/ngx_event_quic_transport.c
+++ b/src/event/ngx_event_quic_transport.c
@@ -67,6 +67,12 @@ static u_char *ngx_quic_read_bytes(u_cha
 static u_char *ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len,
     u_char *dst);
 
+static ngx_int_t ngx_quic_parse_long_header(ngx_quic_header_t *pkt);
+static ngx_int_t ngx_quic_parse_short_header(ngx_quic_header_t *pkt,
+    size_t dcid_len);
+static ngx_int_t ngx_quic_parse_initial_header(ngx_quic_header_t *pkt);
+static ngx_int_t ngx_quic_parse_handshake_header(ngx_quic_header_t *pkt);
+
 static ngx_int_t ngx_quic_frame_allowed(ngx_quic_header_t *pkt,
     ngx_uint_t frame_type);
 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack);
@@ -245,6 +251,52 @@ ngx_quic_error_text(uint64_t error_code)
 
 
 ngx_int_t
+ngx_quic_parse_packet(ngx_quic_header_t *pkt)
+{
+    if (!ngx_quic_long_pkt(pkt->flags)) {
+        pkt->level = ssl_encryption_application;
+
+        return ngx_quic_parse_short_header(pkt, NGX_QUIC_SERVER_CID_LEN);
+    }
+
+    if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
+        return NGX_DECLINED;
+    }
+
+    if (pkt->version != NGX_QUIC_VERSION) {
+        return NGX_ABORT;
+    }
+
+    if (ngx_quic_pkt_in(pkt->flags)) {
+
+        if (pkt->len < NGX_QUIC_MIN_INITIAL_SIZE) {
+            ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
+                          "quic UDP datagram is too small for initial packet");
+            return NGX_DECLINED;
+        }
+
+        pkt->level = ssl_encryption_initial;
+
+        return ngx_quic_parse_initial_header(pkt);
+    }
+
+    if (ngx_quic_pkt_hs(pkt->flags)) {
+        pkt->level = ssl_encryption_handshake;
+
+    } else if (ngx_quic_pkt_zrtt(pkt->flags)) {
+        pkt->level = ssl_encryption_early_data;
+
+    } else {
+         ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
+                       "quic unknown long packet type");
+         return NGX_DECLINED;
+    }
+
+    return ngx_quic_parse_handshake_header(pkt);
+}
+
+
+static ngx_int_t
 ngx_quic_parse_long_header(ngx_quic_header_t *pkt)
 {
     u_char   *p, *end;
@@ -456,8 +508,8 @@ ngx_quic_create_retry_itag(ngx_quic_head
 }
 
 
-ngx_int_t
-ngx_quic_parse_short_header(ngx_quic_header_t *pkt, ngx_str_t *dcid)
+static ngx_int_t
+ngx_quic_parse_short_header(ngx_quic_header_t *pkt, size_t dcid_len)
 {
     u_char  *p, *end;
 
@@ -472,14 +524,9 @@ ngx_quic_parse_short_header(ngx_quic_hea
         return NGX_ERROR;
     }
 
-    if (ngx_memcmp(p, dcid->data, dcid->len) != 0) {
-        ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "unexpected quic dcid");
-        return NGX_ERROR;
-    }
+    pkt->dcid.len = dcid_len;
 
-    pkt->dcid.len = dcid->len;
-
-    p = ngx_quic_read_bytes(p, end, dcid->len, &pkt->dcid.data);
+    p = ngx_quic_read_bytes(p, end, dcid_len, &pkt->dcid.data);
     if (p == NULL) {
         ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
                       "quic packet is too small to read dcid");
@@ -492,7 +539,7 @@ ngx_quic_parse_short_header(ngx_quic_hea
 }
 
 
-ngx_int_t
+static ngx_int_t
 ngx_quic_parse_initial_header(ngx_quic_header_t *pkt)
 {
     u_char    *p, *end;
@@ -548,7 +595,7 @@ ngx_quic_parse_initial_header(ngx_quic_h
 }
 
 
-ngx_int_t
+static ngx_int_t
 ngx_quic_parse_handshake_header(ngx_quic_header_t *pkt)
 {
     u_char    *p, *end;