# HG changeset patch # User Vladimir Homutov # Date 1585750151 -10800 # Node ID 7ea2c68735f90ef6b245e0f4c5c036bf4ff64579 # Parent e10b4c61420f79b227b7769d5a264a4ab4da7ea7 Output buffering. Currently, the output is called periodically, each 200 ms to invoke ngx_quic_output() that will push all pending frames into packets. TODO: implement flags a-là Nagle & co (NO_DELAY/NO_PUSH...) diff --git a/src/event/ngx_event_quic.c b/src/event/ngx_event_quic.c --- a/src/event/ngx_event_quic.c +++ b/src/event/ngx_event_quic.c @@ -69,6 +69,7 @@ struct ngx_quic_connection_s { ngx_ssl_t *ssl; + ngx_event_t push; ngx_event_t retry; ngx_queue_t free_frames; @@ -145,6 +146,7 @@ static ngx_int_t ngx_quic_send_frames(ng static void ngx_quic_retransmit_handler(ngx_event_t *ev); static ngx_int_t ngx_quic_retransmit_ns(ngx_connection_t *c, ngx_quic_namespace_t *ns, ngx_msec_t *waitp); +static void ngx_quic_push_handler(ngx_event_t *ev); static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); @@ -464,6 +466,11 @@ ngx_quic_new_connection(ngx_connection_t qc->retry.handler = ngx_quic_retransmit_handler; qc->retry.cancelable = 1; + qc->push.log = c->log; + qc->push.data = c; + qc->push.handler = ngx_quic_push_handler; + qc->push.cancelable = 1; + c->quic = qc; qc->ssl = ssl; qc->tp = *tp; @@ -713,6 +720,10 @@ ngx_quic_close_connection(ngx_connection return; } + if (qc->push.timer_set) { + ngx_del_timer(&qc->push); + } + if (qc->retry.timer_set) { ngx_del_timer(&qc->retry); } @@ -1163,7 +1174,8 @@ ngx_quic_payload_handler(ngx_connection_ ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler level=%d", pkt->pn, ack_frame->level); ngx_quic_queue_frame(qc, ack_frame); - return ngx_quic_output(c); + // TODO: call output() after processing some special frames? + return NGX_OK; } @@ -1471,6 +1483,12 @@ ngx_quic_queue_frame(ngx_quic_connection ns = &qc->ns[ngx_quic_ns(frame->level)]; ngx_queue_insert_tail(&ns->frames, &frame->queue); + + /* TODO: check PUSH flag on stream and call output */ + + if (!qc->push.timer_set && !qc->closing) { + ngx_add_timer(&qc->push, qc->tp.max_ack_delay); + } } @@ -1742,6 +1760,26 @@ ngx_quic_retransmit_handler(ngx_event_t } +static void +ngx_quic_push_handler(ngx_event_t *ev) +{ + ngx_connection_t *c; + ngx_quic_connection_t *qc; + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "push timer"); + + c = ev->data; + qc = c->quic; + + if (ngx_quic_output(c) != NGX_OK) { + ngx_quic_close_connection(c); + return; + } + + ngx_add_timer(&qc->push, qc->tp.max_ack_delay); +} + + static ngx_int_t ngx_quic_retransmit_ns(ngx_connection_t *c, ngx_quic_namespace_t *ns, ngx_msec_t *waitp) @@ -2060,8 +2098,6 @@ ngx_quic_stream_send(ngx_connection_t *c ngx_quic_queue_frame(qc, frame); - ngx_quic_output(pc); - return size; }