changeset 8772:345370fdd32d quic

HTTP/3: moved parsing uni stream type to ngx_http_v3_parse.c. Previously it was parsed in ngx_http_v3_streams.c, while the streams were parsed in ngx_http_v3_parse.c. Now all parsing is done in one file. This simplifies parsing API and cleans up ngx_http_v3_streams.c.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 05 May 2021 15:00:17 +0300
parents 0981329169ea
children b43e50f47b2e
files src/http/v3/ngx_http_v3.h src/http/v3/ngx_http_v3_parse.c src/http/v3/ngx_http_v3_parse.h src/http/v3/ngx_http_v3_streams.c
diffstat 4 files changed, 164 insertions(+), 130 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/v3/ngx_http_v3.h
+++ b/src/http/v3/ngx_http_v3.h
@@ -169,6 +169,7 @@ uintptr_t ngx_http_v3_encode_header_lpbi
 
 ngx_int_t ngx_http_v3_init_session(ngx_connection_t *c);
 void ngx_http_v3_init_uni_stream(ngx_connection_t *c);
+ngx_int_t ngx_http_v3_register_uni_stream(ngx_connection_t *c, uint64_t type);
 ngx_connection_t *ngx_http_v3_create_push_stream(ngx_connection_t *c,
     uint64_t push_id);
 ngx_int_t ngx_http_v3_send_goaway(ngx_connection_t *c, uint64_t id);
--- a/src/http/v3/ngx_http_v3_parse.c
+++ b/src/http/v3/ngx_http_v3_parse.c
@@ -14,9 +14,6 @@
     ((type) == 0x02 || (type) == 0x06 || (type) == 0x08 || (type) == 0x09)
 
 
-static ngx_int_t ngx_http_v3_parse_settings(ngx_connection_t *c,
-    ngx_http_v3_parse_settings_t *st, u_char ch);
-
 static ngx_int_t ngx_http_v3_parse_varlen_int(ngx_connection_t *c,
     ngx_http_v3_parse_varlen_int_t *st, u_char ch);
 static ngx_int_t ngx_http_v3_parse_prefix_int(ngx_connection_t *c,
@@ -39,11 +36,21 @@ static ngx_int_t ngx_http_v3_parse_heade
 static ngx_int_t ngx_http_v3_parse_header_lpbi(ngx_connection_t *c,
     ngx_http_v3_parse_header_t *st, u_char ch);
 
+static ngx_int_t ngx_http_v3_parse_control(ngx_connection_t *c,
+    ngx_http_v3_parse_control_t *st, u_char ch);
+static ngx_int_t ngx_http_v3_parse_settings(ngx_connection_t *c,
+    ngx_http_v3_parse_settings_t *st, u_char ch);
+
+static ngx_int_t ngx_http_v3_parse_encoder(ngx_connection_t *c,
+    ngx_http_v3_parse_encoder_t *st, u_char ch);
 static ngx_int_t ngx_http_v3_parse_header_inr(ngx_connection_t *c,
     ngx_http_v3_parse_header_t *st, u_char ch);
 static ngx_int_t ngx_http_v3_parse_header_iwnr(ngx_connection_t *c,
     ngx_http_v3_parse_header_t *st, u_char ch);
 
+static ngx_int_t ngx_http_v3_parse_decoder(ngx_connection_t *c,
+    ngx_http_v3_parse_decoder_t *st, u_char ch);
+
 static ngx_int_t ngx_http_v3_parse_lookup(ngx_connection_t *c,
     ngx_uint_t dynamic, ngx_uint_t index, ngx_str_t *name, ngx_str_t *value);
 
@@ -986,11 +993,10 @@ ngx_http_v3_parse_lookup(ngx_connection_
 }
 
 
-ngx_int_t
-ngx_http_v3_parse_control(ngx_connection_t *c, void *data, u_char ch)
+static ngx_int_t
+ngx_http_v3_parse_control(ngx_connection_t *c, ngx_http_v3_parse_control_t *st,
+    u_char ch)
 {
-    ngx_http_v3_parse_control_t *st = data;
-
     ngx_int_t  rc;
     enum {
         sw_start = 0,
@@ -1208,11 +1214,10 @@ done:
 }
 
 
-ngx_int_t
-ngx_http_v3_parse_encoder(ngx_connection_t *c, void *data, u_char ch)
+static ngx_int_t
+ngx_http_v3_parse_encoder(ngx_connection_t *c, ngx_http_v3_parse_encoder_t *st,
+    u_char ch)
 {
-    ngx_http_v3_parse_encoder_t *st = data;
-
     ngx_int_t  rc;
     enum {
         sw_start = 0,
@@ -1500,11 +1505,10 @@ done:
 }
 
 
-ngx_int_t
-ngx_http_v3_parse_decoder(ngx_connection_t *c, void *data, u_char ch)
+static ngx_int_t
+ngx_http_v3_parse_decoder(ngx_connection_t *c, ngx_http_v3_parse_decoder_t *st,
+    u_char ch)
 {
-    ngx_http_v3_parse_decoder_t *st = data;
-
     ngx_int_t  rc;
     enum {
         sw_start = 0,
@@ -1674,3 +1678,92 @@ done:
     st->state = sw_start;
     return NGX_DONE;
 }
+
+
+ngx_int_t
+ngx_http_v3_parse_uni(ngx_connection_t *c, ngx_http_v3_parse_uni_t *st,
+    u_char ch)
+{
+    ngx_int_t  rc;
+    enum {
+        sw_start = 0,
+        sw_type,
+        sw_control,
+        sw_encoder,
+        sw_decoder,
+        sw_unknown
+    };
+
+    switch (st->state) {
+    case sw_start:
+
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse uni");
+
+        st->state = sw_type;
+
+        /* fall through */
+
+    case sw_type:
+
+        rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, ch);
+        if (rc != NGX_DONE) {
+            return rc;
+        }
+
+        rc = ngx_http_v3_register_uni_stream(c, st->vlint.value);
+        if (rc != NGX_OK) {
+            return rc;
+        }
+
+        switch (st->vlint.value) {
+        case NGX_HTTP_V3_STREAM_CONTROL:
+            st->state = sw_control;
+            break;
+
+        case NGX_HTTP_V3_STREAM_ENCODER:
+            st->state = sw_encoder;
+            break;
+
+        case NGX_HTTP_V3_STREAM_DECODER:
+            st->state = sw_decoder;
+            break;
+
+        default:
+            st->state = sw_unknown;
+        }
+
+        break;
+
+    case sw_control:
+
+        rc = ngx_http_v3_parse_control(c, &st->u.control, ch);
+        if (rc != NGX_OK) {
+            return rc;
+        }
+
+        break;
+
+    case sw_encoder:
+
+        rc = ngx_http_v3_parse_encoder(c, &st->u.encoder, ch);
+        if (rc != NGX_OK) {
+            return rc;
+        }
+
+        break;
+
+    case sw_decoder:
+
+        rc = ngx_http_v3_parse_decoder(c, &st->u.decoder, ch);
+        if (rc != NGX_OK) {
+            return rc;
+        }
+
+        break;
+
+    case sw_unknown:
+        break;
+    }
+
+    return NGX_AGAIN;
+}
--- a/src/http/v3/ngx_http_v3_parse.h
+++ b/src/http/v3/ngx_http_v3_parse.h
@@ -108,6 +108,17 @@ typedef struct {
 
 typedef struct {
     ngx_uint_t                      state;
+    ngx_http_v3_parse_varlen_int_t  vlint;
+    union {
+        ngx_http_v3_parse_encoder_t  encoder;
+        ngx_http_v3_parse_decoder_t  decoder;
+        ngx_http_v3_parse_control_t  control;
+    } u;
+} ngx_http_v3_parse_uni_t;
+
+
+typedef struct {
+    ngx_uint_t                      state;
     ngx_uint_t                      type;
     ngx_uint_t                      length;
     ngx_http_v3_parse_varlen_int_t  vlint;
@@ -128,10 +139,8 @@ ngx_int_t ngx_http_v3_parse_headers(ngx_
     ngx_http_v3_parse_headers_t *st, u_char ch);
 ngx_int_t ngx_http_v3_parse_data(ngx_connection_t *c,
     ngx_http_v3_parse_data_t *st, u_char ch);
-
-ngx_int_t ngx_http_v3_parse_control(ngx_connection_t *c, void *data, u_char ch);
-ngx_int_t ngx_http_v3_parse_encoder(ngx_connection_t *c, void *data, u_char ch);
-ngx_int_t ngx_http_v3_parse_decoder(ngx_connection_t *c, void *data, u_char ch);
+ngx_int_t ngx_http_v3_parse_uni(ngx_connection_t *c,
+    ngx_http_v3_parse_uni_t *st, u_char ch);
 
 
 #endif /* _NGX_HTTP_V3_PARSE_H_INCLUDED_ */
--- a/src/http/v3/ngx_http_v3_streams.c
+++ b/src/http/v3/ngx_http_v3_streams.c
@@ -10,13 +10,8 @@
 #include <ngx_http.h>
 
 
-typedef ngx_int_t (*ngx_http_v3_handler_pt)(ngx_connection_t *c, void *data,
-    u_char ch);
-
-
 typedef struct {
-    ngx_http_v3_handler_pt          handler;
-    void                           *data;
+    ngx_http_v3_parse_uni_t         parse;
     ngx_int_t                       index;
 } ngx_http_v3_uni_stream_t;
 
@@ -32,7 +27,6 @@ typedef struct {
 static void ngx_http_v3_keepalive_handler(ngx_event_t *ev);
 static void ngx_http_v3_cleanup_session(void *data);
 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c);
-static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev);
 static void ngx_http_v3_uni_read_handler(ngx_event_t *rev);
 static void ngx_http_v3_dummy_write_handler(ngx_event_t *wev);
 static void ngx_http_v3_push_cleanup(void *data);
@@ -131,10 +125,10 @@ ngx_http_v3_init_uni_stream(ngx_connecti
 
     c->data = us;
 
-    c->read->handler = ngx_http_v3_read_uni_stream_type;
+    c->read->handler = ngx_http_v3_uni_read_handler;
     c->write->handler = ngx_http_v3_dummy_write_handler;
 
-    ngx_http_v3_read_uni_stream_type(c->read);
+    ngx_http_v3_uni_read_handler(c->read);
 }
 
 
@@ -164,118 +158,59 @@ ngx_http_v3_close_uni_stream(ngx_connect
 }
 
 
-static void
-ngx_http_v3_read_uni_stream_type(ngx_event_t *rev)
+ngx_int_t
+ngx_http_v3_register_uni_stream(ngx_connection_t *c, uint64_t type)
 {
-    u_char                     ch;
-    ssize_t                    n;
-    ngx_int_t                  index, rc;
-    ngx_connection_t          *c;
+    ngx_int_t                  index;
     ngx_http_v3_session_t     *h3c;
     ngx_http_v3_uni_stream_t  *us;
 
-    c = rev->data;
-    us = c->data;
-    h3c = ngx_http_v3_get_session(c);
+    switch (type) {
+
+    case NGX_HTTP_V3_STREAM_ENCODER:
+
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                       "http3 encoder stream");
+        index = NGX_HTTP_V3_STREAM_CLIENT_ENCODER;
+        break;
 
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read stream type");
+    case NGX_HTTP_V3_STREAM_DECODER:
 
-    while (rev->ready) {
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                       "http3 decoder stream");
+        index = NGX_HTTP_V3_STREAM_CLIENT_DECODER;
+        break;
 
-        n = c->recv(c, &ch, 1);
+    case NGX_HTTP_V3_STREAM_CONTROL:
 
-        if (n == NGX_AGAIN) {
-            break;
-        }
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                       "http3 control stream");
+        index = NGX_HTTP_V3_STREAM_CLIENT_CONTROL;
+
+        break;
+
+    default:
 
-        if (n == 0) {
-            rc = NGX_HTTP_V3_ERR_GENERAL_PROTOCOL_ERROR;
-            goto failed;
-        }
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                       "http3 stream 0x%02xL", type);
+        index = -1;
+    }
 
-        if (n != 1) {
-            rc = NGX_HTTP_V3_ERR_INTERNAL_ERROR;
-            goto failed;
+    if (index >= 0) {
+        h3c = ngx_http_v3_get_session(c);
+
+        if (h3c->known_streams[index]) {
+            ngx_log_error(NGX_LOG_INFO, c->log, 0, "stream exists");
+            return NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR;
         }
 
-        switch (ch) {
-
-        case NGX_HTTP_V3_STREAM_ENCODER:
-
-            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                           "http3 encoder stream");
-
-            index = NGX_HTTP_V3_STREAM_CLIENT_ENCODER;
-            us->handler = ngx_http_v3_parse_encoder;
-            n = sizeof(ngx_http_v3_parse_encoder_t);
-
-            break;
-
-        case NGX_HTTP_V3_STREAM_DECODER:
-
-            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                           "http3 decoder stream");
-
-            index = NGX_HTTP_V3_STREAM_CLIENT_DECODER;
-            us->handler = ngx_http_v3_parse_decoder;
-            n = sizeof(ngx_http_v3_parse_decoder_t);
-
-            break;
-
-        case NGX_HTTP_V3_STREAM_CONTROL:
-
-            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                           "http3 control stream");
-
-            index = NGX_HTTP_V3_STREAM_CLIENT_CONTROL;
-            us->handler = ngx_http_v3_parse_control;
-            n = sizeof(ngx_http_v3_parse_control_t);
+        h3c->known_streams[index] = c;
 
-            break;
-
-        default:
-
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                           "http3 stream 0x%02xi", (ngx_int_t) ch);
-            index = -1;
-            n = 0;
-        }
-
-        if (index >= 0) {
-            if (h3c->known_streams[index]) {
-                ngx_log_error(NGX_LOG_INFO, c->log, 0, "stream exists");
-                rc = NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR;
-                goto failed;
-            }
-
-            us->index = index;
-            h3c->known_streams[index] = c;
-        }
-
-        if (n) {
-            us->data = ngx_pcalloc(c->pool, n);
-            if (us->data == NULL) {
-                rc = NGX_HTTP_V3_ERR_INTERNAL_ERROR;
-                goto failed;
-            }
-        }
-
-        rev->handler = ngx_http_v3_uni_read_handler;
-        ngx_http_v3_uni_read_handler(rev);
-        return;
+        us = c->data;
+        us->index = index;
     }
 
-    if (ngx_handle_read_event(rev, 0) != NGX_OK) {
-        rc = NGX_HTTP_V3_ERR_INTERNAL_ERROR;
-        goto failed;
-    }
-
-    return;
-
-failed:
-
-    ngx_http_v3_finalize_connection(c, rc, "could not read stream type");
-    ngx_http_v3_close_uni_stream(c);
+    return NGX_OK;
 }
 
 
@@ -317,13 +252,9 @@ ngx_http_v3_uni_read_handler(ngx_event_t
             break;
         }
 
-        if (us->handler == NULL) {
-            continue;
-        }
-
         for (i = 0; i < n; i++) {
 
-            rc = us->handler(c, us->data, buf[i]);
+            rc = ngx_http_v3_parse_uni(c, &us->parse, buf[i]);
 
             if (rc == NGX_DONE) {
                 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,