aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2022-01-31 09:46:30 +0300
committerRoman Arutyunyan <arut@nginx.com>2022-01-31 09:46:30 +0300
commit77efe512fa18580bef6f8d795bc1c1cfff5d0097 (patch)
tree299b8fb15007f9f566bd8dae6c3c65af35eb1262 /src
parent5e31cdbb98466055ce27d4596b5e5a1406fc83d4 (diff)
downloadnginx-77efe512fa18580bef6f8d795bc1c1cfff5d0097.tar.gz
nginx-77efe512fa18580bef6f8d795bc1c1cfff5d0097.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/http/v3/ngx_http_v3_uni.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/src/http/v3/ngx_http_v3_uni.c b/src/http/v3/ngx_http_v3_uni.c
index f0a599655..bd7eb278b 100644
--- 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_connection_t *c)
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_connection_t *c, ngx_uint_t type)
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_connection_t *c, ngx_uint_t type)
goto failed;
}
+ ngx_post_event(sc->read, &ngx_posted_events);
+
return sc;
failed: