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

Roman Arutyunyan arut at nginx.com
Mon Jan 31 15:21:05 UTC 2022


# 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 3436b441239b494e6f63db3b8d26a71682b4f106
# Parent  b42a041d23a2226ec6def395bd0b084889b85473
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,7 +26,8 @@ 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_write_handler(ngx_event_t *wev);
+static void ngx_http_v3_uni_dummy_read_handler(ngx_event_t *wev);
+static void ngx_http_v3_uni_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,
     ngx_uint_t type);
@@ -68,7 +69,7 @@ ngx_http_v3_init_uni_stream(ngx_connecti
     c->data = us;
 
     c->read->handler = ngx_http_v3_uni_read_handler;
-    c->write->handler = ngx_http_v3_dummy_write_handler;
+    c->write->handler = ngx_http_v3_uni_dummy_write_handler;
 
     ngx_http_v3_uni_read_handler(c->read);
 }
@@ -252,7 +253,33 @@ failed:
 
 
 static void
-ngx_http_v3_dummy_write_handler(ngx_event_t *wev)
+ngx_http_v3_uni_dummy_read_handler(ngx_event_t *rev)
+{
+    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_uni_dummy_write_handler(ngx_event_t *wev)
 {
     ngx_connection_t  *c;
 
@@ -393,8 +420,8 @@ ngx_http_v3_get_uni_stream(ngx_connectio
 
     sc->data = us;
 
-    sc->read->handler = ngx_http_v3_uni_read_handler;
-    sc->write->handler = ngx_http_v3_dummy_write_handler;
+    sc->read->handler = ngx_http_v3_uni_dummy_read_handler;
+    sc->write->handler = ngx_http_v3_uni_dummy_write_handler;
 
     if (index >= 0) {
         h3c->known_streams[index] = sc;
@@ -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:



More information about the nginx-devel mailing list