aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2020-03-19 15:34:35 +0300
committerRoman Arutyunyan <arut@nginx.com>2020-03-19 15:34:35 +0300
commit4cbfc073942d6fd2ef4ef69d252687b12fe5687c (patch)
treedc4a684f58515af7d9a803669468197ee239e7f0
parent8ad2707d4f5c007ec308262ea03481d95eee7e02 (diff)
downloadnginx-4cbfc073942d6fd2ef4ef69d252687b12fe5687c.tar.gz
nginx-4cbfc073942d6fd2ef4ef69d252687b12fe5687c.zip
Send a FIN frame when QUIC stream is closed.
-rw-r--r--src/event/ngx_event_quic.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/event/ngx_event_quic.c b/src/event/ngx_event_quic.c
index a58a0aaba..991aa499c 100644
--- 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_connection_t *c, u_char *buf,
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 *c, ngx_uint_t id)
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 *c, ngx_uint_t id)
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, u_char *buf, size_t size)
}
+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)