# HG changeset patch # User Roman Arutyunyan # Date 1585127664 -10800 # Node ID dadbc66e9fca309d17c2218ba79f6ca25e64f749 # Parent 4cf00c14f11a4e02257339efc0e41bf2aa3b1210 Simplifed handling HTTP/3 streams. diff --git a/src/http/v3/ngx_http_v3.h b/src/http/v3/ngx_http_v3.h --- a/src/http/v3/ngx_http_v3.h +++ b/src/http/v3/ngx_http_v3.h @@ -15,8 +15,6 @@ #include -#define NGX_HTTP_V3_STREAM 0x48335354 /* "H3ST" */ - #define NGX_HTTP_V3_ALPN(s) NGX_HTTP_V3_ALPN_DRAFT(s) #define NGX_HTTP_V3_ALPN_DRAFT(s) "\x05h3-" #s #define NGX_HTTP_V3_ALPN_ADVERTISE NGX_HTTP_V3_ALPN(NGX_QUIC_DRAFT_VERSION) @@ -41,6 +39,14 @@ #define NGX_HTTP_V3_PARAM_MAX_HEADER_LIST_SIZE 0x06 #define NGX_HTTP_V3_PARAM_BLOCKED_STREAMS 0x07 +#define NGX_HTTP_V3_STREAM_CLIENT_CONTROL 0 +#define NGX_HTTP_V3_STREAM_SERVER_CONTROL 1 +#define NGX_HTTP_V3_STREAM_CLIENT_ENCODER 2 +#define NGX_HTTP_V3_STREAM_SERVER_ENCODER 3 +#define NGX_HTTP_V3_STREAM_CLIENT_DECODER 4 +#define NGX_HTTP_V3_STREAM_SERVER_DECODER 5 +#define NGX_HTTP_V3_MAX_KNOWN_STREAM 6 + typedef struct { ngx_quic_tp_t quic; @@ -51,14 +57,7 @@ typedef struct { ngx_http_connection_t hc; ngx_array_t *dynamic; - - ngx_connection_t *client_encoder; - ngx_connection_t *client_decoder; - ngx_connection_t *client_control; - - ngx_connection_t *server_encoder; - ngx_connection_t *server_decoder; - ngx_connection_t *server_control; + ngx_connection_t *known_streams[NGX_HTTP_V3_MAX_KNOWN_STREAM]; } ngx_http_v3_connection_t; diff --git a/src/http/v3/ngx_http_v3_streams.c b/src/http/v3/ngx_http_v3_streams.c --- a/src/http/v3/ngx_http_v3_streams.c +++ b/src/http/v3/ngx_http_v3_streams.c @@ -15,40 +15,30 @@ typedef ngx_int_t (*ngx_http_v3_handler_ typedef struct { - uint32_t signature; /* QSTR */ - ngx_http_v3_handler_pt handler; void *data; - - ngx_uint_t type; - ngx_uint_t client; /* unsigned client:1; */ + ngx_int_t index; } ngx_http_v3_uni_stream_t; static void ngx_http_v3_close_uni_stream(ngx_connection_t *c); -static void ngx_http_v3_uni_stream_cleanup(void *data); 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 ngx_connection_t *ngx_http_v3_create_uni_stream(ngx_connection_t *c, +static ngx_connection_t *ngx_http_v3_get_uni_stream(ngx_connection_t *c, ngx_uint_t type); -static ngx_connection_t *ngx_http_v3_get_control(ngx_connection_t *c); -static ngx_connection_t *ngx_http_v3_get_encoder(ngx_connection_t *c); -static ngx_connection_t *ngx_http_v3_get_decoder(ngx_connection_t *c); void ngx_http_v3_handle_client_uni_stream(ngx_connection_t *c) { - ngx_pool_cleanup_t *cln; ngx_http_v3_uni_stream_t *us; c->log->connection = c->number; - /* XXX */ - (void) ngx_http_v3_get_control(c); - (void) ngx_http_v3_get_encoder(c); - (void) ngx_http_v3_get_decoder(c); + ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL); + ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); + ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 new uni stream id:0x%uxL", c->qs->id); @@ -59,21 +49,10 @@ ngx_http_v3_handle_client_uni_stream(ngx return; } - us->signature = NGX_HTTP_V3_STREAM; - us->client = 1; - us->type = (ngx_uint_t) -1; + us->index = -1; c->data = us; - cln = ngx_pool_cleanup_add(c->pool, 0); - if (cln == NULL) { - ngx_http_v3_close_uni_stream(c); - return; - } - - cln->handler = ngx_http_v3_uni_stream_cleanup; - cln->data = c; - c->read->handler = ngx_http_v3_read_uni_stream_type; c->write->handler = ngx_http_v3_dummy_write_handler; @@ -84,7 +63,18 @@ ngx_http_v3_handle_client_uni_stream(ngx static void ngx_http_v3_close_uni_stream(ngx_connection_t *c) { - ngx_pool_t *pool; + ngx_pool_t *pool; + ngx_http_v3_connection_t *h3c; + ngx_http_v3_uni_stream_t *us; + + us = c->data; + h3c = c->qs->parent->data; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream"); + + if (us->index >= 0) { + h3c->known_streams[us->index] = NULL; + } c->destroyed = 1; @@ -97,64 +87,17 @@ ngx_http_v3_close_uni_stream(ngx_connect static void -ngx_http_v3_uni_stream_cleanup(void *data) -{ - ngx_connection_t *c = data; - - ngx_http_v3_connection_t *h3c; - ngx_http_v3_uni_stream_t *us; - - us = c->data; - h3c = c->qs->parent->data; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream"); - - switch (us->type) { - - case NGX_HTTP_V3_STREAM_ENCODER: - - if (us->client) { - h3c->client_encoder = NULL; - } else { - h3c->server_encoder = NULL; - } - - break; - - case NGX_HTTP_V3_STREAM_DECODER: - - if (us->client) { - h3c->client_decoder = NULL; - } else { - h3c->server_decoder = NULL; - } - - break; - - case NGX_HTTP_V3_STREAM_CONTROL: - - if (us->client) { - h3c->client_control = NULL; - } else { - h3c->server_control = NULL; - } - - break; - } -} - - -static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev) { u_char ch; ssize_t n; + ngx_int_t index; ngx_connection_t *c; ngx_http_v3_connection_t *h3c; - ngx_http_v3_uni_stream_t *st; + ngx_http_v3_uni_stream_t *us; c = rev->data; - st = c->data; + us = c->data; h3c = c->qs->parent->data; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read stream type"); @@ -171,21 +114,15 @@ ngx_http_v3_read_uni_stream_type(ngx_eve break; } - st->type = ch; - - switch (st->type) { + switch (ch) { case NGX_HTTP_V3_STREAM_ENCODER: ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 encoder stream"); - if (h3c->client_encoder) { - goto failed; - } - - h3c->client_encoder = c; - st->handler = ngx_http_v3_parse_encoder; + index = NGX_HTTP_V3_STREAM_CLIENT_ENCODER; + us->handler = ngx_http_v3_parse_encoder; n = sizeof(ngx_http_v3_parse_encoder_t); break; @@ -195,12 +132,8 @@ ngx_http_v3_read_uni_stream_type(ngx_eve ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 decoder stream"); - if (h3c->client_decoder) { - goto failed; - } - - h3c->client_decoder = c; - st->handler = ngx_http_v3_parse_decoder; + index = NGX_HTTP_V3_STREAM_CLIENT_DECODER; + us->handler = ngx_http_v3_parse_decoder; n = sizeof(ngx_http_v3_parse_decoder_t); break; @@ -210,12 +143,8 @@ ngx_http_v3_read_uni_stream_type(ngx_eve ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 control stream"); - if (h3c->client_control) { - goto failed; - } - - h3c->client_control = c; - st->handler = ngx_http_v3_parse_control; + index = NGX_HTTP_V3_STREAM_CLIENT_CONTROL; + us->handler = ngx_http_v3_parse_control; n = sizeof(ngx_http_v3_parse_control_t); break; @@ -223,13 +152,24 @@ ngx_http_v3_read_uni_stream_type(ngx_eve default: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http3 stream 0x%02xi", st->type); + "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"); + goto failed; + } + + us->index = index; + h3c->known_streams[index] = c; + } + if (n) { - st->data = ngx_pcalloc(c->pool, n); - if (st->data == NULL) { + us->data = ngx_pcalloc(c->pool, n); + if (us->data == NULL) { goto failed; } } @@ -258,10 +198,10 @@ ngx_http_v3_uni_read_handler(ngx_event_t ssize_t n; ngx_int_t rc, i; ngx_connection_t *c; - ngx_http_v3_uni_stream_t *st; + ngx_http_v3_uni_stream_t *us; c = rev->data; - st = c->data; + us = c->data; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read handler"); @@ -277,13 +217,13 @@ ngx_http_v3_uni_read_handler(ngx_event_t break; } - if (st->handler == NULL) { + if (us->handler == NULL) { continue; } for (i = 0; i < n; i++) { - rc = st->handler(c, st->data, buf[i]); + rc = us->handler(c, us->data, buf[i]); if (rc == NGX_ERROR) { goto failed; @@ -331,14 +271,37 @@ ngx_http_v3_dummy_write_handler(ngx_even /* XXX async & buffered stream writes */ static ngx_connection_t * -ngx_http_v3_create_uni_stream(ngx_connection_t *c, ngx_uint_t type) +ngx_http_v3_get_uni_stream(ngx_connection_t *c, ngx_uint_t type) { u_char buf[NGX_HTTP_V3_VARLEN_INT_LEN]; size_t n; + ngx_int_t index; ngx_connection_t *sc; - ngx_pool_cleanup_t *cln; + ngx_http_v3_connection_t *h3c; ngx_http_v3_uni_stream_t *us; + switch (type) { + case NGX_HTTP_V3_STREAM_ENCODER: + index = NGX_HTTP_V3_STREAM_SERVER_ENCODER; + break; + case NGX_HTTP_V3_STREAM_DECODER: + index = NGX_HTTP_V3_STREAM_SERVER_DECODER; + break; + case NGX_HTTP_V3_STREAM_CONTROL: + index = NGX_HTTP_V3_STREAM_SERVER_CONTROL; + break; + default: + index = -1; + } + + h3c = c->qs->parent->data; + + if (index >= 0) { + if (h3c->known_streams[index]) { + return h3c->known_streams[index]; + } + } + sc = ngx_quic_create_uni_stream(c); if (sc == NULL) { return NULL; @@ -352,20 +315,14 @@ ngx_http_v3_create_uni_stream(ngx_connec goto failed; } - us->signature = NGX_HTTP_V3_STREAM; - us->type = type; + us->index = index; + sc->data = us; sc->read->handler = ngx_http_v3_uni_read_handler; sc->write->handler = ngx_http_v3_dummy_write_handler; - cln = ngx_pool_cleanup_add(sc->pool, 0); - if (cln == NULL) { - goto failed; - } - - cln->handler = ngx_http_v3_uni_stream_cleanup; - cln->data = sc; + h3c->known_streams[index] = sc; n = (u_char *) ngx_http_v3_encode_varlen_int(buf, type) - buf; @@ -383,54 +340,6 @@ failed: } -static ngx_connection_t * -ngx_http_v3_get_control(ngx_connection_t *c) -{ - ngx_http_v3_connection_t *h3c; - - h3c = c->qs->parent->data; - - if (h3c->server_control == NULL) { - h3c->server_control = ngx_http_v3_create_uni_stream(c, - NGX_HTTP_V3_STREAM_CONTROL); - } - - return h3c->server_encoder; -} - - -static ngx_connection_t * -ngx_http_v3_get_encoder(ngx_connection_t *c) -{ - ngx_http_v3_connection_t *h3c; - - h3c = c->qs->parent->data; - - if (h3c->server_encoder == NULL) { - h3c->server_encoder = ngx_http_v3_create_uni_stream(c, - NGX_HTTP_V3_STREAM_ENCODER); - } - - return h3c->server_encoder; -} - - -static ngx_connection_t * -ngx_http_v3_get_decoder(ngx_connection_t *c) -{ - ngx_http_v3_connection_t *h3c; - - h3c = c->qs->parent->data; - - if (h3c->server_decoder == NULL) { - h3c->server_decoder = ngx_http_v3_create_uni_stream(c, - NGX_HTTP_V3_STREAM_DECODER); - } - - return h3c->server_encoder; -} - - ngx_int_t ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, ngx_uint_t index, ngx_str_t *value) @@ -443,7 +352,7 @@ ngx_http_v3_client_ref_insert(ngx_connec "http3 client ref insert, %s[%ui] \"%V\"", dynamic ? "dynamic" : "static", index, value); - ec = ngx_http_v3_get_encoder(c); + ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); if (ec == NULL) { return NGX_ERROR; } @@ -488,7 +397,7 @@ ngx_http_v3_client_insert(ngx_connection ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client insert \"%V\":\"%V\"", name, value); - ec = ngx_http_v3_get_encoder(c); + ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); if (ec == NULL) { return NGX_ERROR; } @@ -537,7 +446,7 @@ ngx_http_v3_client_set_capacity(ngx_conn ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client set capacity %ui", capacity); - ec = ngx_http_v3_get_encoder(c); + ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); if (ec == NULL) { return NGX_ERROR; } @@ -564,7 +473,7 @@ ngx_http_v3_client_duplicate(ngx_connect ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client duplicate %ui", index); - ec = ngx_http_v3_get_encoder(c); + ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER); if (ec == NULL) { return NGX_ERROR; } @@ -591,7 +500,7 @@ ngx_http_v3_client_ack_header(ngx_connec ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client ack header %ui", stream_id); - dc = ngx_http_v3_get_decoder(c); + dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); if (dc == NULL) { return NGX_ERROR; } @@ -618,7 +527,7 @@ ngx_http_v3_client_cancel_stream(ngx_con ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client cancel stream %ui", stream_id); - dc = ngx_http_v3_get_decoder(c); + dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); if (dc == NULL) { return NGX_ERROR; } @@ -645,7 +554,7 @@ ngx_http_v3_client_inc_insert_count(ngx_ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client increment insert count %ui", inc); - dc = ngx_http_v3_get_decoder(c); + dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); if (dc == NULL) { return NGX_ERROR; }