# HG changeset patch # User Roman Arutyunyan # Date 1620216017 -10800 # Node ID 345370fdd32df26973de918b27704bb6c6dec7e0 # Parent 0981329169ea7821383e86c742e3bdc57a347258 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. 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 @@ -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); diff --git a/src/http/v3/ngx_http_v3_parse.c b/src/http/v3/ngx_http_v3_parse.c --- 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; +} diff --git a/src/http/v3/ngx_http_v3_parse.h b/src/http/v3/ngx_http_v3_parse.h --- 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_ */ 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 @@ -10,13 +10,8 @@ #include -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,