# HG changeset patch # User Roman Arutyunyan # Date 1585130181 -10800 # Node ID 4cf00c14f11a4e02257339efc0e41bf2aa3b1210 # Parent 618a65de08b30748f2567ff9b824661dbc5894ee Safe QUIC stream creation. diff -r 618a65de08b3 -r 4cf00c14f11a src/event/ngx_event_quic.c --- a/src/event/ngx_event_quic.c Tue Mar 24 18:05:45 2020 +0300 +++ b/src/event/ngx_event_quic.c Wed Mar 25 12:56:21 2020 +0300 @@ -16,9 +16,6 @@ } ngx_quic_state_t; -#define NGX_QUIC_STREAM_BUFSIZE 16384 - - typedef struct { ngx_rbtree_t tree; ngx_rbtree_node_t sentinel; @@ -122,7 +119,7 @@ static ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree, ngx_uint_t key); static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c, - ngx_uint_t id); + uint64_t id, size_t rcvbuf_size); 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, @@ -1096,6 +1093,7 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, ngx_quic_stream_frame_t *f) { + size_t n; ngx_buf_t *b; ngx_event_t *rev; ngx_quic_stream_t *sn; @@ -1137,15 +1135,28 @@ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "stream is new"); - sn = ngx_quic_create_stream(c, f->stream_id); + n = (f->stream_id & NGX_QUIC_STREAM_UNIDIRECTIONAL) + ? qc->tp.initial_max_stream_data_uni + : qc->tp.initial_max_stream_data_bidi_remote; + + if (n < NGX_QUIC_STREAM_BUFSIZE) { + n = NGX_QUIC_STREAM_BUFSIZE; + } + + if (n < f->length) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, "no space in stream buffer"); + return NGX_ERROR; + } + + sn = ngx_quic_create_stream(c, f->stream_id, n); if (sn == NULL) { return NGX_ERROR; } b = sn->b; + b->last = ngx_cpymem(b->last, f->data, f->length); - ngx_memcpy(b->start, f->data, f->length); - b->last = b->start + f->length; + sn->c->read->ready = 1; qc->streams.handler(sn->c); @@ -1419,7 +1430,7 @@ qc->streams.id_counter++; - sn = ngx_quic_create_stream(qs->parent, id); + sn = ngx_quic_create_stream(qs->parent, id, 0); if (sn == NULL) { return NULL; } @@ -1494,82 +1505,65 @@ static ngx_quic_stream_t * -ngx_quic_create_stream(ngx_connection_t *c, ngx_uint_t id) +ngx_quic_create_stream(ngx_connection_t *c, uint64_t id, size_t rcvbuf_size) { - size_t n; - ngx_log_t *log; - ngx_pool_t *pool; - ngx_event_t *rev, *wev; - ngx_quic_stream_t *sn; - ngx_pool_cleanup_t *cln; - ngx_quic_connection_t *qc; + ngx_log_t *log; + ngx_pool_t *pool; + ngx_quic_stream_t *sn; + ngx_pool_cleanup_t *cln; - qc = c->quic; - - sn = ngx_pcalloc(c->pool, sizeof(ngx_quic_stream_t)); - if (sn == NULL) { + pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log); + if (pool == NULL) { return NULL; } - sn->c = ngx_get_connection(-1, c->log); // TODO: free on connection termination - if (sn->c == NULL) { + sn = ngx_pcalloc(pool, sizeof(ngx_quic_stream_t)); + if (sn == NULL) { + ngx_destroy_pool(pool); return NULL; } - pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log); - if (pool == NULL) { - /* XXX free connection */ - // TODO: add pool cleanup handdler + sn->node.key = id; + sn->parent = c; + sn->id = id; + + sn->b = ngx_create_temp_buf(pool, rcvbuf_size); + if (sn->b == NULL) { + ngx_destroy_pool(pool); return NULL; } log = ngx_palloc(pool, sizeof(ngx_log_t)); if (log == NULL) { - /* XXX free pool and connection */ + ngx_destroy_pool(pool); return NULL; } *log = *c->log; pool->log = log; - sn->c->log = log; - sn->c->pool = pool; - - sn->c->listening = c->listening; - sn->c->sockaddr = c->sockaddr; - sn->c->local_sockaddr = c->local_sockaddr; - sn->c->addr_text = c->addr_text; - sn->c->ssl = c->ssl; - - rev = sn->c->read; - wev = sn->c->write; - - rev->ready = 1; - - rev->log = c->log; - wev->log = c->log; - - sn->c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); - - n = ngx_max(NGX_QUIC_STREAM_BUFSIZE, - qc->tp.initial_max_stream_data_bidi_remote); - - sn->node.key =id; - sn->b = ngx_create_temp_buf(pool, n); - if (sn->b == NULL) { + sn->c = ngx_get_connection(-1, log); + if (sn->c == NULL) { + ngx_destroy_pool(pool); return NULL; } - ngx_rbtree_insert(&qc->streams.tree, &sn->node); - - sn->id = id; - sn->parent = c; sn->c->qs = sn; + sn->c->pool = pool; + sn->c->ssl = c->ssl; + sn->c->sockaddr = c->sockaddr; + sn->c->listening = c->listening; + sn->c->addr_text = c->addr_text; + sn->c->local_sockaddr = c->local_sockaddr; + sn->c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); sn->c->recv = ngx_quic_stream_recv; sn->c->send = ngx_quic_stream_send; sn->c->send_chain = ngx_quic_stream_send_chain; + sn->c->read->log = c->log; + sn->c->write->log = c->log; + cln = ngx_pool_cleanup_add(pool, 0); if (cln == NULL) { ngx_close_connection(sn->c); @@ -1580,6 +1574,8 @@ cln->handler = ngx_quic_stream_cleanup_handler; cln->data = sn->c; + ngx_rbtree_insert(&c->quic->streams.tree, &sn->node); + return sn; } diff -r 618a65de08b3 -r 4cf00c14f11a src/event/ngx_event_quic.h --- a/src/event/ngx_event_quic.h Tue Mar 24 18:05:45 2020 +0300 +++ b/src/event/ngx_event_quic.h Wed Mar 25 12:56:21 2020 +0300 @@ -24,6 +24,8 @@ #define NGX_QUIC_STREAM_SERVER_INITIATED 0x01 #define NGX_QUIC_STREAM_UNIDIRECTIONAL 0x02 +#define NGX_QUIC_STREAM_BUFSIZE 16384 + typedef struct { /* configurable */