changeset 8239:5ad7bffd3850 quic

Send a FIN frame when QUIC stream is closed.
author Roman Arutyunyan <arut@nginx.com>
date Thu, 19 Mar 2020 15:34:35 +0300
parents a3257a725b3d
children 1f002206a59b
files src/event/ngx_event_quic.c
diffstat 1 files changed, 64 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -110,6 +110,7 @@ static ssize_t ngx_quic_stream_recv(ngx_
     size_t size);
 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf,
     size_t size);
+static void ngx_quic_stream_cleanup_handler(void *data);
 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c,
     ngx_chain_t *in, off_t limit);
 
@@ -1286,6 +1287,7 @@ ngx_quic_create_stream(ngx_connection_t 
     ngx_log_t               *log;
     ngx_pool_t              *pool;
     ngx_event_t             *rev, *wev;
+    ngx_pool_cleanup_t      *cln;
     ngx_quic_connection_t   *qc;
     ngx_quic_stream_node_t  *sn;
 
@@ -1352,6 +1354,16 @@ ngx_quic_create_stream(ngx_connection_t 
     sn->c->send = ngx_quic_stream_send;
     sn->c->send_chain = ngx_quic_stream_send_chain;
 
+    cln = ngx_pool_cleanup_add(pool, 0);
+    if (cln == NULL) {
+        ngx_close_connection(sn->c);
+        ngx_destroy_pool(pool);
+        return NULL;
+    }
+
+    cln->handler = ngx_quic_stream_cleanup_handler;
+    cln->data = sn->c;
+
     return sn;
 }
 
@@ -1457,6 +1469,58 @@ ngx_quic_stream_send(ngx_connection_t *c
 }
 
 
+static void
+ngx_quic_stream_cleanup_handler(void *data)
+{
+    ngx_connection_t *c = data;
+
+    ngx_connection_t        *pc;
+    ngx_quic_frame_t        *frame;
+    ngx_quic_stream_t       *qs;
+    ngx_quic_connection_t   *qc;
+    ngx_quic_stream_node_t  *sn;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send fin");
+
+    qs = c->qs;
+    pc = qs->parent;
+    qc = pc->quic;
+
+    if ((qs->id & 0x03) == 0x02) {
+        /* do not send fin for client unidirectional streams */
+        return;
+    }
+
+    // XXX: get direct pointer from stream structure?
+    sn = ngx_quic_find_stream(&qc->streams.tree, qs->id);
+
+    if (sn == NULL) {
+        return;
+    }
+
+    frame = ngx_pcalloc(pc->pool, sizeof(ngx_quic_frame_t));
+    if (frame == NULL) {
+        return;
+    }
+
+    frame->level = ssl_encryption_application;
+    frame->type = NGX_QUIC_FT_STREAM7; /* OFF=1 LEN=1 FIN=1 */
+    frame->u.stream.off = 1;
+    frame->u.stream.len = 1;
+    frame->u.stream.fin = 1;
+
+    frame->u.stream.type = frame->type;
+    frame->u.stream.stream_id = qs->id;
+    frame->u.stream.offset = c->sent;
+    frame->u.stream.length = 0;
+    frame->u.stream.data = NULL;
+
+    ngx_sprintf(frame->info, "stream %xi fin=1 level=%d", qs->id, frame->level);
+
+    ngx_quic_queue_frame(qc, frame);
+}
+
+
 static ngx_chain_t *
 ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in,
     off_t limit)