changeset 8687:1c6343bd7933 quic

QUIC: refactored packet processing. - split ngx_quic_process_packet() in two functions with the second one called ngx_quic_process_payload() in charge of decrypring and handling the payload - renamed ngx_quic_payload_handler() to ngx_quic_handle_frames() - moved error cleanup from ngx_quic_input() to ngx_quic_process_payload() - moved handling closed connection from ngx_quic_handle_frames() to ngx_quic_process_payload() - minor fixes
author Roman Arutyunyan <arut@nginx.com>
date Thu, 28 Jan 2021 12:35:18 +0300
parents dffb66fb783b
children a346905c359f
files src/event/quic/ngx_event_quic.c
diffstat 1 files changed, 127 insertions(+), 116 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/quic/ngx_event_quic.c
+++ b/src/event/quic/ngx_event_quic.c
@@ -255,13 +255,15 @@ static ngx_int_t ngx_quic_input(ngx_conn
     ngx_quic_conf_t *conf);
 static ngx_int_t ngx_quic_process_packet(ngx_connection_t *c,
     ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
+static ngx_int_t ngx_quic_process_payload(ngx_connection_t *c,
+    ngx_quic_header_t *pkt);
 static ngx_int_t ngx_quic_send_early_cc(ngx_connection_t *c,
     ngx_quic_header_t *inpkt, ngx_uint_t err, const char *reason);
 static void ngx_quic_discard_ctx(ngx_connection_t *c,
     enum ssl_encryption_level_t level);
 static ngx_int_t ngx_quic_check_peer(ngx_quic_connection_t *qc,
     ngx_quic_header_t *pkt);
-static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c,
+static ngx_int_t ngx_quic_handle_frames(ngx_connection_t *c,
     ngx_quic_header_t *pkt);
 static ngx_int_t ngx_quic_ack_packet(ngx_connection_t *c,
     ngx_quic_header_t *pkt);
@@ -2120,11 +2122,10 @@ ngx_quic_close_streams(ngx_connection_t 
 static ngx_int_t
 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf)
 {
-    u_char                 *p;
-    ngx_int_t               rc;
-    ngx_uint_t              good;
-    ngx_quic_header_t       pkt;
-    ngx_quic_connection_t  *qc;
+    u_char             *p;
+    ngx_int_t           rc;
+    ngx_uint_t          good;
+    ngx_quic_header_t   pkt;
 
     good = 0;
 
@@ -2140,12 +2141,6 @@ ngx_quic_input(ngx_connection_t *c, ngx_
         pkt.flags = p[0];
         pkt.raw->pos++;
 
-        qc = ngx_quic_get_connection(c);
-        if (qc) {
-            qc->error = 0;
-            qc->error_reason = 0;
-        }
-
         rc = ngx_quic_process_packet(c, conf, &pkt);
 
 #if (NGX_DEBUG)
@@ -2212,11 +2207,8 @@ ngx_quic_process_packet(ngx_connection_t
     ngx_quic_header_t *pkt)
 {
     ngx_int_t               rc;
-    ngx_quic_send_ctx_t    *ctx;
     ngx_quic_connection_t  *qc;
 
-    static u_char           buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
-
     c->log->action = "parsing quic packet";
 
     rc = ngx_quic_parse_packet(pkt);
@@ -2229,8 +2221,6 @@ ngx_quic_process_packet(ngx_connection_t
 
     c->log->action = "processing quic packet";
 
-    qc = ngx_quic_get_connection(c);
-
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    "quic packet rx dcid len:%uz %xV",
                    pkt->dcid.len, &pkt->dcid);
@@ -2249,6 +2239,8 @@ ngx_quic_process_packet(ngx_connection_t
     }
 #endif
 
+    qc = ngx_quic_get_connection(c);
+
     if (qc) {
 
         if (rc == NGX_ABORT) {
@@ -2284,83 +2276,102 @@ ngx_quic_process_packet(ngx_connection_t
             return NGX_DECLINED;
         }
 
-    } else {
-
-        if (rc == NGX_ABORT) {
-            return ngx_quic_negotiate_version(c, pkt);
-        }
-
-        if (pkt->level == ssl_encryption_initial) {
-            c->log->action = "processing initial packet";
-
-            if (pkt->dcid.len < NGX_QUIC_CID_LEN_MIN) {
-                /* 7.2.  Negotiating Connection IDs */
-                ngx_log_error(NGX_LOG_INFO, c->log, 0,
-                              "quic too short dcid in initial"
-                              " packet: len:%i", pkt->dcid.len);
-                return NGX_ERROR;
+        return ngx_quic_process_payload(c, pkt);
+    }
+
+    /* packet does not belong to a connection */
+
+    if (rc == NGX_ABORT) {
+        return ngx_quic_negotiate_version(c, pkt);
+    }
+
+    if (pkt->level == ssl_encryption_application) {
+        return ngx_quic_send_stateless_reset(c, conf, pkt);
+    }
+
+    if (pkt->level != ssl_encryption_initial) {
+        return NGX_ERROR;
+    }
+
+    c->log->action = "processing initial packet";
+
+    if (pkt->dcid.len < NGX_QUIC_CID_LEN_MIN) {
+        /* 7.2.  Negotiating Connection IDs */
+        ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                      "quic too short dcid in initial"
+                      " packet: len:%i", pkt->dcid.len);
+        return NGX_ERROR;
+    }
+
+    /* process retry and initialize connection IDs */
+
+    if (pkt->token.len) {
+
+        rc = ngx_quic_validate_token(c, conf->token_key, pkt);
+
+        if (rc == NGX_ERROR) {
+            /* internal error */
+            return NGX_ERROR;
+
+        } else if (rc == NGX_ABORT) {
+            /* token cannot be decrypted */
+            return ngx_quic_send_early_cc(c, pkt,
+                                          NGX_QUIC_ERR_INVALID_TOKEN,
+                                          "cannot decrypt token");
+        } else if (rc == NGX_DECLINED) {
+            /* token is invalid */
+
+            if (pkt->retried) {
+                /* invalid Retry token */
+                return ngx_quic_send_early_cc(c, pkt,
+                                          NGX_QUIC_ERR_INVALID_TOKEN,
+                                          "invalid token");
+            } else if (conf->retry) {
+                /* invalid NEW_TOKEN */
+                return ngx_quic_send_retry(c, conf, pkt);
             }
-
-            /* process retry and initialize connection IDs */
-
-            if (pkt->token.len) {
-
-                rc = ngx_quic_validate_token(c, conf->token_key, pkt);
-
-                if (rc == NGX_ERROR) {
-                    /* internal error */
-                    return NGX_ERROR;
-
-                } else if (rc == NGX_ABORT) {
-                    /* token cannot be decrypted */
-                    return ngx_quic_send_early_cc(c, pkt,
-                                                  NGX_QUIC_ERR_INVALID_TOKEN,
-                                                  "cannot decrypt token");
-                } else if (rc == NGX_DECLINED) {
-                    /* token is invalid */
-
-                    if (pkt->retried) {
-                        /* invalid Retry token */
-                        return ngx_quic_send_early_cc(c, pkt,
-                                                  NGX_QUIC_ERR_INVALID_TOKEN,
-                                                  "invalid token");
-                    } else if (conf->retry) {
-                        /* invalid NEW_TOKEN */
-                        return ngx_quic_send_retry(c, conf, pkt);
-                    }
-                }
-
-                /* NGX_OK */
-
-            } else if (conf->retry) {
-                return ngx_quic_send_retry(c, conf, pkt);
-
-            } else {
-                pkt->odcid = pkt->dcid;
-            }
-
-            if (ngx_terminate || ngx_exiting) {
-                if (conf->retry) {
-                    return ngx_quic_send_retry(c, conf, pkt);
-                }
-
-                return NGX_ERROR;
-            }
-
-            c->log->action = "creating quic connection";
-
-            qc = ngx_quic_new_connection(c, conf, pkt);
-            if (qc == NULL) {
-                return NGX_ERROR;
-            }
-
-        } else if (pkt->level == ssl_encryption_application) {
-            return ngx_quic_send_stateless_reset(c, conf, pkt);
-
-        } else {
-            return NGX_ERROR;
-        }
-    }
+        }
+
+        /* NGX_OK */
+
+    } else if (conf->retry) {
+        return ngx_quic_send_retry(c, conf, pkt);
+
+    } else {
+        pkt->odcid = pkt->dcid;
+    }
+
+    if (ngx_terminate || ngx_exiting) {
+        if (conf->retry) {
+            return ngx_quic_send_retry(c, conf, pkt);
+        }
+
+        return NGX_ERROR;
+    }
+
+    c->log->action = "creating quic connection";
+
+    qc = ngx_quic_new_connection(c, conf, pkt);
+    if (qc == NULL) {
+        return NGX_ERROR;
+    }
+
+    return ngx_quic_process_payload(c, pkt);
+}
+
+
+static ngx_int_t
+ngx_quic_process_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
+{
+    ngx_int_t               rc;
+    ngx_quic_send_ctx_t    *ctx;
+    ngx_quic_connection_t  *qc;
+    static u_char           buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
+
+    qc = ngx_quic_get_connection(c);
+
+    qc->error = 0;
+    qc->error_reason = 0;
 
     c->log->action = "decrypting packet";
 
@@ -2404,16 +2415,35 @@ ngx_quic_process_packet(ngx_connection_t
         }
     }
 
+    if (qc->closing) {
+        /*
+         * 10.1  Closing and Draining Connection States
+         * ... delayed or reordered packets are properly discarded.
+         *
+         *  An endpoint retains only enough information to generate
+         *  a packet containing a CONNECTION_CLOSE frame and to identify
+         *  packets as belonging to the connection.
+         */
+
+        qc->error_level = pkt->level;
+        qc->error = NGX_QUIC_ERR_NO_ERROR;
+        qc->error_reason = "connection is closing, packet discarded";
+        qc->error_ftype = 0;
+        qc->error_app = 0;
+
+        return ngx_quic_send_cc(c);
+    }
+
     pkt->received = ngx_current_msec;
 
     c->log->action = "handling payload";
 
     if (pkt->level != ssl_encryption_application) {
-        return ngx_quic_payload_handler(c, pkt);
+        return ngx_quic_handle_frames(c, pkt);
     }
 
     if (!pkt->key_update) {
-        return ngx_quic_payload_handler(c, pkt);
+        return ngx_quic_handle_frames(c, pkt);
     }
 
     /* switch keys and generate next on Key Phase change */
@@ -2421,7 +2451,7 @@ ngx_quic_process_packet(ngx_connection_t
     qc->key_phase ^= 1;
     ngx_quic_keys_switch(c, qc->keys);
 
-    rc = ngx_quic_payload_handler(c, pkt);
+    rc = ngx_quic_handle_frames(c, pkt);
     if (rc != NGX_OK) {
         return rc;
     }
@@ -2581,7 +2611,7 @@ ngx_quic_check_peer(ngx_quic_connection_
 
 
 static ngx_int_t
-ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
+ngx_quic_handle_frames(ngx_connection_t *c, ngx_quic_header_t *pkt)
 {
     u_char                 *end, *p;
     ssize_t                 len;
@@ -2593,25 +2623,6 @@ ngx_quic_payload_handler(ngx_connection_
 
     qc = ngx_quic_get_connection(c);
 
-    if (qc->closing) {
-        /*
-         * 10.1  Closing and Draining Connection States
-         * ... delayed or reordered packets are properly discarded.
-         *
-         *  An endpoint retains only enough information to generate
-         *  a packet containing a CONNECTION_CLOSE frame and to identify
-         *  packets as belonging to the connection.
-         */
-
-        qc->error_level = pkt->level;
-        qc->error = NGX_QUIC_ERR_NO_ERROR;
-        qc->error_reason = "connection is closing, packet discarded";
-        qc->error_ftype = 0;
-        qc->error_app = 0;
-
-        return ngx_quic_send_cc(c);
-    }
-
     p = pkt->payload.data;
     end = p + pkt->payload.len;