changeset 8309:7ea2c68735f9 quic

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...)
author Vladimir Homutov <vl@nginx.com>
date Wed, 01 Apr 2020 17:09:11 +0300
parents e10b4c61420f
children 7ac890c18f5e
files src/event/ngx_event_quic.c
diffstat 1 files changed, 39 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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;
 }