Mercurial > hg > nginx-quic
changeset 7705: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)