changeset 8890:b4c7853b0488 quic

QUIC: added shutdown support in stream proxy.
author Vladimir Homutov <vl@nginx.com>
date Thu, 23 Sep 2021 16:25:49 +0300
parents 61d0fa67b55e
children c5155a0cb12f
files src/event/quic/ngx_event_quic.h src/event/quic/ngx_event_quic_streams.c src/stream/ngx_stream_proxy_module.c
diffstat 3 files changed, 66 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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_co
 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);
--- 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 *
 }
 
 
+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)
 {
--- 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_sess
         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");