[PATCH 1 of 2] HTTP/3: use parent QUIC connection as argument when possible

Sergey Kandaurov pluknet at nginx.com
Tue Dec 7 08:05:39 UTC 2021


> On 18 Nov 2021, at 12:52, Roman Arutyunyan <arut at nginx.com> wrote:
> 
> # HG changeset patch
> # User Roman Arutyunyan <arut at nginx.com>
> # Date 1637160358 -10800
> #      Wed Nov 17 17:45:58 2021 +0300
> # Branch quic
> # Node ID b844c77ff22218a4863d1d926bcaaa0b043c8af5
> # Parent  41caf541011045612975b7bb8423a18fd424df77
> HTTP/3: use parent QUIC connection as argument when possible.
> 
> Functions in ngx_http_v3.c, ngx_http_v3_streams.c and ngx_http_v3_tables.c
> now receive parent QUIC connection as the first argument instead of QUIC stream
> connection.  It makes sense since they are not related to a QUIC stream and
> operate connection-wise.
> 
> Also, ngx_quic_open_stream() now receives parent QUIC connection instead of
> QUIC stream connection for the same reason.
> 
> Also, ngx_http_v3_finalize_connection() and ngx_http_v3_shutdown_connection()
> macros are eliminated.  Instead, ngx_quic_finalize_connection() and
> ngx_quic_shutdown_connection() are called directly with the parent QUIC
> connection.
> 
> diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c
> --- a/src/event/quic/ngx_event_quic_streams.c
> +++ b/src/event/quic/ngx_event_quic_streams.c
> @@ -37,11 +37,10 @@ ngx_connection_t *
> ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi)
> {
>     uint64_t                id;
> -    ngx_quic_stream_t      *qs, *nqs;
> +    ngx_quic_stream_t      *qs;
>     ngx_quic_connection_t  *qc;
> 
> -    qs = c->quic;
> -    qc = ngx_quic_get_connection(qs->parent);
> +    qc = ngx_quic_get_connection(c);
> 
>     if (bidi) {
>         if (qc->streams.server_streams_bidi
> @@ -87,12 +86,12 @@ ngx_quic_open_stream(ngx_connection_t *c
>         qc->streams.server_streams_uni++;
>     }
> 
> -    nqs = ngx_quic_create_stream(qs->parent, id);
> -    if (nqs == NULL) {
> +    qs = ngx_quic_create_stream(c, id);
> +    if (qs == NULL) {
>         return NULL;
>     }
> 
> -    return nqs->connection;
> +    return qs->connection;
> }
> 
> 
> diff --git a/src/http/modules/ngx_http_quic_module.h b/src/http/modules/ngx_http_quic_module.h
> --- a/src/http/modules/ngx_http_quic_module.h
> +++ b/src/http/modules/ngx_http_quic_module.h
> @@ -19,7 +19,8 @@
> 
> 
> #define ngx_http_quic_get_connection(c)                                       \
> -    ((ngx_http_connection_t *) (c)->quic->parent->data)
> +    ((ngx_http_connection_t *) ((c)->quic ? (c)->quic->parent->data           \
> +                                          : (c)->data))
> 
> 
> ngx_int_t ngx_http_quic_init(ngx_connection_t *c);
> diff --git a/src/http/v3/ngx_http_v3.c b/src/http/v3/ngx_http_v3.c
> --- a/src/http/v3/ngx_http_v3.c
> +++ b/src/http/v3/ngx_http_v3.c
> @@ -17,13 +17,11 @@ static void ngx_http_v3_cleanup_session(
> ngx_int_t
> ngx_http_v3_init_session(ngx_connection_t *c)
> {
> -    ngx_connection_t       *pc;
>     ngx_pool_cleanup_t     *cln;
>     ngx_http_connection_t  *hc;
>     ngx_http_v3_session_t  *h3c;
> 
> -    pc = c->quic->parent;
> -    hc = pc->data;
> +    hc = c->data;
> 
>     if (hc->v3_session) {
>         return NGX_OK;
> @@ -31,7 +29,7 @@ ngx_http_v3_init_session(ngx_connection_
> 
>     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 init session");
> 
> -    h3c = ngx_pcalloc(pc->pool, sizeof(ngx_http_v3_session_t));
> +    h3c = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_session_t));
>     if (h3c == NULL) {
>         goto failed;
>     }
> @@ -42,12 +40,12 @@ ngx_http_v3_init_session(ngx_connection_
>     ngx_queue_init(&h3c->blocked);
>     ngx_queue_init(&h3c->pushing);
> 
> -    h3c->keepalive.log = pc->log;
> -    h3c->keepalive.data = pc;
> +    h3c->keepalive.log = c->log;
> +    h3c->keepalive.data = c;
>     h3c->keepalive.handler = ngx_http_v3_keepalive_handler;
>     h3c->keepalive.cancelable = 1;
> 
> -    cln = ngx_pool_cleanup_add(pc->pool, 0);
> +    cln = ngx_pool_cleanup_add(c->pool, 0);
>     if (cln == NULL) {
>         goto failed;
>     }
> @@ -63,8 +61,8 @@ failed:
> 
>     ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to create http3 session");
> 
> -    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
> -                                    "failed to create http3 session");
> +    ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
> +                                 "failed to create http3 session");
>     return NGX_ERROR;
> }
> 
> @@ -106,8 +104,8 @@ ngx_http_v3_check_flood(ngx_connection_t
>     if (h3c->total_bytes / 8 > h3c->payload_bytes + 1048576) {
>         ngx_log_error(NGX_LOG_INFO, c->log, 0, "http3 flood detected");
> 
> -        ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR,
> -                                        "HTTP/3 flood detected");
> +        ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR,
> +                                     "HTTP/3 flood detected");
>         return NGX_ERROR;
>     }
> 
> 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
> @@ -84,12 +84,6 @@
>     ngx_http_get_module_srv_conf(ngx_http_quic_get_connection(c)->conf_ctx,     \
>                                  module)
> 
> -#define ngx_http_v3_finalize_connection(c, code, reason)                      \
> -    ngx_quic_finalize_connection(c->quic->parent, code, reason)
> -
> -#define ngx_http_v3_shutdown_connection(c, code, reason)                      \
> -    ngx_quic_shutdown_connection(c->quic->parent, code, reason)
> -
> #define ngx_http_v3_connection(c)                                             \
>     ((c)->quic ? ngx_http_quic_get_connection(c)->addr_conf->http3 : 0)
> 
> diff --git a/src/http/v3/ngx_http_v3_filter_module.c b/src/http/v3/ngx_http_v3_filter_module.c
> --- a/src/http/v3/ngx_http_v3_filter_module.c
> +++ b/src/http/v3/ngx_http_v3_filter_module.c
> @@ -907,7 +907,7 @@ ngx_http_v3_create_push_request(ngx_http
>     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
>                    "http3 create push request id:%uL", push_id);
> 
> -    c = ngx_http_v3_create_push_stream(pc, push_id);
> +    c = ngx_http_v3_create_push_stream(pc->quic->parent, push_id);
>     if (c == NULL) {
>         return NGX_ABORT;
>     }
> 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
> @@ -353,7 +353,8 @@ ngx_http_v3_parse_headers(ngx_connection
> 
>         case sw_verify:
> 
> -            rc = ngx_http_v3_check_insert_count(c, st->prefix.insert_count);
> +            rc = ngx_http_v3_check_insert_count(c->quic->parent,
> +                                                st->prefix.insert_count);

For the record, as previously reported in
http://mailman.nginx.org/pipermail/nginx-devel/2021-December/014607.html
and discussed privately, this needs to be a stream connection, as otherwise,
when inserting a new dynamic entry that unblocks a stream, an event will be
mis-posted on the main connection, instead.  Reverting this part helps.

>             if (rc != NGX_OK) {
>                 return rc;
>             }
> @@ -392,7 +393,9 @@ done:
>     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers done");
> 
>     if (st->prefix.insert_count > 0) {
> -        if (ngx_http_v3_send_ack_section(c, c->quic->id) != NGX_OK) {
> +        if (ngx_http_v3_send_ack_section(c->quic->parent, c->quic->id)
> +            != NGX_OK)
> +        {

Similarly, I doubt if this kind of changes is really necessary
throughout ngx_http_v3_parse.c.  In general, c->quic->parent is
used to finalize a connection, so I'd consider pushing this down
to ngx_quic_finalize_connection().

>             return NGX_ERROR;
>         }
>     }
> @@ -466,7 +469,7 @@ ngx_http_v3_parse_field_section_prefix(n
> 
> done:
> 
> -    rc = ngx_http_v3_decode_insert_count(c, &st->insert_count);
> +    rc = ngx_http_v3_decode_insert_count(c->quic->parent, &st->insert_count);
>     if (rc != NGX_OK) {
>         return rc;
>     }
> @@ -1102,14 +1105,16 @@ ngx_http_v3_parse_lookup(ngx_connection_
>     u_char  *p;
> 
>     if (!dynamic) {
> -        if (ngx_http_v3_lookup_static(c, index, name, value) != NGX_OK) {
> +        if (ngx_http_v3_lookup_static(c->quic->parent, index, name, value)
> +            != NGX_OK)
> +        {
>             return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED;
>         }
> 
>         return NGX_OK;
>     }
> 
> -    if (ngx_http_v3_lookup(c, index, name, value) != NGX_OK) {
> +    if (ngx_http_v3_lookup(c->quic->parent, index, name, value) != NGX_OK) {
>         return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED;
>     }
> 
> @@ -1264,7 +1269,7 @@ ngx_http_v3_parse_control(ngx_connection
>                 return rc;
>             }
> 
> -            rc = ngx_http_v3_cancel_push(c, st->vlint.value);
> +            rc = ngx_http_v3_cancel_push(c->quic->parent, st->vlint.value);
>             if (rc != NGX_OK) {
>                 return rc;
>             }
> @@ -1310,7 +1315,7 @@ ngx_http_v3_parse_control(ngx_connection
>                 return rc;
>             }
> 
> -            rc = ngx_http_v3_set_max_push_id(c, st->vlint.value);
> +            rc = ngx_http_v3_set_max_push_id(c->quic->parent, st->vlint.value);
>             if (rc != NGX_OK) {
>                 return rc;
>             }
> @@ -1334,7 +1339,7 @@ ngx_http_v3_parse_control(ngx_connection
>                 return rc;
>             }
> 
> -            rc = ngx_http_v3_goaway(c, st->vlint.value);
> +            rc = ngx_http_v3_goaway(c->quic->parent, st->vlint.value);
>             if (rc != NGX_OK) {
>                 return rc;
>             }
> @@ -1398,7 +1403,9 @@ ngx_http_v3_parse_settings(ngx_connectio
>                 return rc;
>             }
> 
> -            if (ngx_http_v3_set_param(c, st->id, st->vlint.value) != NGX_OK) {
> +            if (ngx_http_v3_set_param(c->quic->parent, st->id, st->vlint.value)
> +                != NGX_OK)
> +            {
>                 return NGX_HTTP_V3_ERR_SETTINGS_ERROR;
>             }
> 
> @@ -1493,7 +1500,7 @@ ngx_http_v3_parse_encoder(ngx_connection
>                 return rc;
>             }
> 
> -            rc = ngx_http_v3_set_capacity(c, st->pint.value);
> +            rc = ngx_http_v3_set_capacity(c->quic->parent, st->pint.value);
>             if (rc != NGX_OK) {
>                 return rc;
>             }
> @@ -1508,7 +1515,7 @@ ngx_http_v3_parse_encoder(ngx_connection
>                 return rc;
>             }
> 
> -            rc = ngx_http_v3_duplicate(c, st->pint.value);
> +            rc = ngx_http_v3_duplicate(c->quic->parent, st->pint.value);
>             if (rc != NGX_OK) {
>                 return rc;
>             }
> @@ -1613,7 +1620,8 @@ done:
>                    st->dynamic ? "dynamic" : "static",
>                    st->index, &st->value);
> 
> -    rc = ngx_http_v3_ref_insert(c, st->dynamic, st->index, &st->value);
> +    rc = ngx_http_v3_ref_insert(c->quic->parent, st->dynamic, st->index,
> +                                &st->value);
>     if (rc != NGX_OK) {
>         return rc;
>     }
> @@ -1731,7 +1739,7 @@ done:
>                    "http3 parse field iln done \"%V\":\"%V\"",
>                    &st->name, &st->value);
> 
> -    rc = ngx_http_v3_insert(c, &st->name, &st->value);
> +    rc = ngx_http_v3_insert(c->quic->parent, &st->name, &st->value);
>     if (rc != NGX_OK) {
>         return rc;
>     }
> @@ -1793,7 +1801,7 @@ ngx_http_v3_parse_decoder(ngx_connection
>                 return rc;
>             }
> 
> -            rc = ngx_http_v3_ack_section(c, st->pint.value);
> +            rc = ngx_http_v3_ack_section(c->quic->parent, st->pint.value);
>             if (rc != NGX_OK) {
>                 return rc;
>             }
> @@ -1808,7 +1816,7 @@ ngx_http_v3_parse_decoder(ngx_connection
>                 return rc;
>             }
> 
> -            rc = ngx_http_v3_cancel_stream(c, st->pint.value);
> +            rc = ngx_http_v3_cancel_stream(c->quic->parent, st->pint.value);
>             if (rc != NGX_OK) {
>                 return rc;
>             }
> @@ -1823,7 +1831,7 @@ ngx_http_v3_parse_decoder(ngx_connection
>                 return rc;
>             }
> 
> -            rc = ngx_http_v3_inc_insert_count(c, st->pint.value);
> +            rc = ngx_http_v3_inc_insert_count(c->quic->parent, st->pint.value);
>             if (rc != NGX_OK) {
>                 return rc;
>             }

[..]

-- 
Sergey Kandaurov



More information about the nginx-devel mailing list