aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVladimir Homutov <vl@nginx.com>2021-09-23 16:25:49 +0300
committerVladimir Homutov <vl@nginx.com>2021-09-23 16:25:49 +0300
commitf5d0c6db674b9c40f995559051e8847157229b57 (patch)
tree8e9e64fc894b90a83c31ed5c9125a940ee04a486 /src
parentbbd05ae252bce1907173d13c6e48d1bed71cd9ea (diff)
downloadnginx-f5d0c6db674b9c40f995559051e8847157229b57.tar.gz
nginx-f5d0c6db674b9c40f995559051e8847157229b57.zip
QUIC: added shutdown support in stream proxy.
Diffstat (limited to 'src')
-rw-r--r--src/event/quic/ngx_event_quic.h1
-rw-r--r--src/event/quic/ngx_event_quic_streams.c50
-rw-r--r--src/stream/ngx_stream_proxy_module.c15
3 files changed, 66 insertions, 0 deletions
diff --git a/src/event/quic/ngx_event_quic.h b/src/event/quic/ngx_event_quic.h
index dda1e385e..47359fe85 100644
--- a/src/event/quic/ngx_event_quic.h
+++ b/src/event/quic/ngx_event_quic.h
@@ -92,6 +92,7 @@ void ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err,
void ngx_quic_shutdown_connection(ngx_connection_t *c, ngx_uint_t err,
const char *reason);
ngx_int_t ngx_quic_reset_stream(ngx_connection_t *c, ngx_uint_t err);
+ngx_int_t ngx_quic_shutdown_stream(ngx_connection_t *c, int how);
uint32_t ngx_quic_version(ngx_connection_t *c);
ngx_int_t ngx_quic_handle_read_event(ngx_event_t *rev, ngx_uint_t flags);
ngx_int_t ngx_quic_handle_write_event(ngx_event_t *wev, size_t lowat);
diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c
index 2ba5ade97..e1c131590 100644
--- a/src/event/quic/ngx_event_quic_streams.c
+++ b/src/event/quic/ngx_event_quic_streams.c
@@ -252,6 +252,56 @@ ngx_quic_reset_stream(ngx_connection_t *c, ngx_uint_t err)
}
+ngx_int_t
+ngx_quic_shutdown_stream(ngx_connection_t *c, int how)
+{
+ ngx_event_t *wev;
+ ngx_connection_t *pc;
+ ngx_quic_frame_t *frame;
+ ngx_quic_stream_t *qs;
+ ngx_quic_connection_t *qc;
+
+ if (how != NGX_WRITE_SHUTDOWN) {
+ return NGX_OK;
+ }
+
+ wev = c->write;
+
+ if (wev->error) {
+ return NGX_OK;
+ }
+
+ qs = c->quic;
+ pc = qs->parent;
+ qc = ngx_quic_get_connection(pc);
+
+ frame = ngx_quic_alloc_frame(pc);
+ if (frame == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "quic stream id:0x%xL shutdown", qs->id);
+
+ frame->level = ssl_encryption_application;
+ frame->type = NGX_QUIC_FT_STREAM;
+ frame->u.stream.off = 1;
+ frame->u.stream.len = 1;
+ frame->u.stream.fin = 1;
+
+ frame->u.stream.stream_id = qs->id;
+ frame->u.stream.offset = c->sent;
+ frame->u.stream.length = 0;
+
+ ngx_quic_queue_frame(qc, frame);
+
+ wev->ready = 1;
+ wev->error = 1;
+
+ return NGX_OK;
+}
+
+
static ngx_quic_stream_t *
ngx_quic_create_client_stream(ngx_connection_t *c, uint64_t id)
{
diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c
index 934e7d8f2..8a7f3b665 100644
--- a/src/stream/ngx_stream_proxy_module.c
+++ b/src/stream/ngx_stream_proxy_module.c
@@ -1767,6 +1767,21 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream,
if (dst->type == SOCK_STREAM && pscf->half_close
&& src->read->eof && !u->half_closed && !dst->buffered)
{
+
+#if (NGX_STREAM_QUIC)
+ if (dst->quic) {
+
+ if (ngx_quic_shutdown_stream(dst, NGX_WRITE_SHUTDOWN)
+ != NGX_OK)
+ {
+ ngx_stream_proxy_finalize(s,
+ NGX_STREAM_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ } else
+#endif
+
if (ngx_shutdown_socket(dst->fd, NGX_WRITE_SHUTDOWN) == -1) {
ngx_connection_error(c, ngx_socket_errno,
ngx_shutdown_socket_n " failed");