[PATCH 2 of 3] HTTP/3: proper uni stream closure detection

Vladimir Homutov vl at nginx.com
Mon Jan 31 10:40:36 UTC 2022


On Mon, Jan 31, 2022 at 10:34:07AM +0300, Roman Arutyunyan wrote:
> # HG changeset patch
> # User Roman Arutyunyan <arut at nginx.com>
> # Date 1643611590 -10800
> #      Mon Jan 31 09:46:30 2022 +0300
> # Branch quic
> # Node ID d3c6dea9454c48ded14b8c087dffc4dea46f78ef
> # Parent  8dcb9908989401d750b14fe5dccf444a5485c23d
> HTTP/3: proper uni stream closure detection.
>
> Previously, closure detection for server-initiated uni streams was not properly
> implemented.  Instead, HTTP/3 code relied on QUIC code posting the read event
> and setting rev->error when it needed to close the stream.  Then, regular
> uni stream read handler called c->recv() and received error, which closed the
> stream.  This was an ad-hoc solution.  If, for whatever reason, the read
> handler was called earlier, c->recv() would return 0, which would also close
> the stream.
>
> Now server-initiated uni streams have a separate read event handler for
> tracking stream closure.  The handler calls c->recv(), which normally returns
> 0, but may return error in case of closure.
>
> diff --git a/src/http/v3/ngx_http_v3_uni.c b/src/http/v3/ngx_http_v3_uni.c
> --- a/src/http/v3/ngx_http_v3_uni.c
> +++ b/src/http/v3/ngx_http_v3_uni.c
> @@ -26,6 +26,7 @@ typedef struct {
>
>  static void ngx_http_v3_close_uni_stream(ngx_connection_t *c);
>  static void ngx_http_v3_uni_read_handler(ngx_event_t *rev);
> +static void ngx_http_v3_dummy_read_handler(ngx_event_t *wev);
>  static void ngx_http_v3_dummy_write_handler(ngx_event_t *wev);
>  static void ngx_http_v3_push_cleanup(void *data);
>  static ngx_connection_t *ngx_http_v3_get_uni_stream(ngx_connection_t *c,
> @@ -252,6 +253,32 @@ failed:
>
>
>  static void
> +ngx_http_v3_dummy_read_handler(ngx_event_t *rev)

should it be ngx_http_v3_uni_dummy_read_handler?

> +{
> +    u_char             ch;
> +    ngx_connection_t  *c;
> +
> +    c = rev->data;
> +
> +    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 dummy read handler");
> +
> +    if (rev->ready) {
> +        if (c->recv(c, &ch, 1) != 0) {
> +            ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR, NULL);
> +            ngx_http_v3_close_uni_stream(c);
> +            return;
> +        }
> +    }
> +
> +    if (ngx_handle_read_event(rev, 0) != NGX_OK) {
> +        ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
> +                                        NULL);
> +        ngx_http_v3_close_uni_stream(c);
> +    }
> +}
> +
> +
> +static void
>  ngx_http_v3_dummy_write_handler(ngx_event_t *wev)
>  {
>      ngx_connection_t  *c;
> @@ -393,7 +420,7 @@ ngx_http_v3_get_uni_stream(ngx_connectio
>
>      sc->data = us;
>
> -    sc->read->handler = ngx_http_v3_uni_read_handler;
> +    sc->read->handler = ngx_http_v3_dummy_read_handler;
>      sc->write->handler = ngx_http_v3_dummy_write_handler;
>
>      if (index >= 0) {
> @@ -409,6 +436,8 @@ ngx_http_v3_get_uni_stream(ngx_connectio
>          goto failed;
>      }
>
> +    ngx_post_event(sc->read, &ngx_posted_events);
> +
>      return sc;
>
>  failed:

Looks ok



More information about the nginx-devel mailing list