changeset 8265:d45325e90221 quic

Limit output QUIC packets with client max_packet_size. Additionally, receive larger packets than 512 bytes.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 23 Mar 2020 18:47:17 +0300
parents c58bbe31e87d
children f92e583fc256
files src/event/ngx_event_quic.c src/event/ngx_event_quic.h src/event/ngx_event_quic_protection.c src/http/v3/ngx_http_v3_module.c
diffstat 4 files changed, 37 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -41,6 +41,7 @@ struct ngx_quic_connection_s {
 
     ngx_uint_t                        client_tp_done;
     ngx_quic_tp_t                     tp;
+    ngx_quic_tp_t                     ctp;
 
     ngx_quic_state_t                  state;
 
@@ -219,7 +220,6 @@ ngx_quic_add_handshake_data(ngx_ssl_conn
     u_char                 *p, *end;
     size_t                  client_params_len;
     const uint8_t          *client_params;
-    ngx_quic_tp_t           ctp;
     ngx_quic_frame_t       *frame;
     ngx_connection_t       *c;
     ngx_quic_connection_t  *qc;
@@ -244,15 +244,12 @@ ngx_quic_add_handshake_data(ngx_ssl_conn
             p = (u_char *) client_params;
             end = p + client_params_len;
 
-            ngx_memzero(&ctp, sizeof(ngx_quic_tp_t));
-
-            if (ngx_quic_parse_transport_params(p, end, &ctp, c->log) != NGX_OK)
+            if (ngx_quic_parse_transport_params(p, end, &qc->ctp, c->log)
+                != NGX_OK)
             {
                 return NGX_ERROR;
             }
 
-            /* TODO: save/use obtained client parameters: merge with ours? */
-
             qc->client_tp_done = 1;
         }
     }
@@ -371,6 +368,7 @@ static ngx_int_t
 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_quic_tp_t *tp,
     ngx_quic_header_t *pkt)
 {
+    ngx_quic_tp_t          *ctp;
     ngx_quic_connection_t  *qc;
 
     if (ngx_buf_size(pkt->raw) < 1200) {
@@ -406,6 +404,11 @@ ngx_quic_new_connection(ngx_connection_t
     qc->ssl = ssl;
     qc->tp = *tp;
 
+    ctp = &qc->ctp;
+    ctp->max_packet_size = NGX_QUIC_DEFAULT_MAX_PACKET_SIZE;
+    ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT;
+    ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY;
+
     qc->dcid.len = pkt->dcid.len;
     qc->dcid.data = ngx_pnalloc(c->pool, pkt->dcid.len);
     if (qc->dcid.data == NULL) {
@@ -520,10 +523,10 @@ ngx_quic_input_handler(ngx_event_t *rev)
     ngx_buf_t          b;
     ngx_connection_t  *c;
 
-    u_char             buf[512];
+    static u_char      buf[65535];
 
     b.start = buf;
-    b.end = buf + 512;
+    b.end = buf + sizeof(buf);
     b.pos = b.last = b.start;
 
     c = rev->data;
@@ -1092,7 +1095,7 @@ ngx_quic_queue_frame(ngx_quic_connection
 static ngx_int_t
 ngx_quic_output(ngx_connection_t *c)
 {
-    size_t                  len;
+    size_t                  len, hlen, n;
     ngx_uint_t              lvl;
     ngx_quic_frame_t       *f, *start;
     ngx_quic_connection_t  *qc;
@@ -1110,10 +1113,19 @@ ngx_quic_output(ngx_connection_t *c)
     do {
         len = 0;
 
+        hlen = (lvl == ssl_encryption_application) ? NGX_QUIC_MAX_SHORT_HEADER
+                                                   : NGX_QUIC_MAX_LONG_HEADER;
+
         do {
             /* process same-level group of frames */
 
-            len += ngx_quic_create_frame(NULL, NULL, f);// TODO: handle overflow, max size
+            n = ngx_quic_create_frame(NULL, NULL, f);
+
+            if (len && hlen + len + n > qc->ctp.max_packet_size) {
+                break;
+            }
+
+            len += n;
 
             f = f->next;
         } while (f && f->level == lvl);
--- a/src/event/ngx_event_quic.h
+++ b/src/event/ngx_event_quic.h
@@ -14,6 +14,13 @@
 #define quic_version        0xff000018  /* draft-24 (ngtcp2) */
 //#define quic_version      0xff00001b  /* draft-27 (FFN 76) */
 
+#define NGX_QUIC_MAX_SHORT_HEADER            25
+#define NGX_QUIC_MAX_LONG_HEADER             346
+
+#define NGX_QUIC_DEFAULT_MAX_PACKET_SIZE     65527
+#define NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT  3
+#define NGX_QUIC_DEFAULT_MAX_ACK_DELAY       25
+
 
 typedef struct {
     /* configurable */
--- a/src/event/ngx_event_quic_protection.c
+++ b/src/event/ngx_event_quic_protection.c
@@ -697,7 +697,7 @@ ngx_quic_create_long_packet(ngx_pool_t *
 
     out.len = payload->len + EVP_GCM_TLS_TAG_LEN;
 
-    ad.data = ngx_alloc(346 /*max header*/, log);
+    ad.data = ngx_alloc(NGX_QUIC_MAX_LONG_HEADER, log);
     if (ad.data == 0) {
         return NGX_ERROR;
     }
@@ -766,7 +766,7 @@ ngx_quic_create_short_packet(ngx_pool_t 
 
     out.len = payload->len + EVP_GCM_TLS_TAG_LEN;
 
-    ad.data = ngx_alloc(25 /*max header*/, log);
+    ad.data = ngx_alloc(NGX_QUIC_MAX_SHORT_HEADER, log);
     if (ad.data == 0) {
         return NGX_ERROR;
     }
--- a/src/http/v3/ngx_http_v3_module.c
+++ b/src/http/v3/ngx_http_v3_module.c
@@ -233,11 +233,13 @@ ngx_http_v3_merge_srv_conf(ngx_conf_t *c
 
     // > 2 ^ 14 is invalid
     ngx_conf_merge_msec_value(conf->quic.max_ack_delay,
-                              prev->quic.max_ack_delay, 25);
+                              prev->quic.max_ack_delay,
+                              NGX_QUIC_DEFAULT_MAX_ACK_DELAY);
 
     // < 1200 is invalid
     ngx_conf_merge_uint_value(conf->quic.max_packet_size,
-                              prev->quic.max_packet_size, 65527);
+                              prev->quic.max_packet_size,
+                              NGX_QUIC_DEFAULT_MAX_PACKET_SIZE);
 
     ngx_conf_merge_uint_value(conf->quic.initial_max_data,
                               prev->quic.initial_max_data, 10000000);
@@ -261,7 +263,8 @@ ngx_http_v3_merge_srv_conf(ngx_conf_t *c
 
     // > 20 is invalid
     ngx_conf_merge_uint_value(conf->quic.ack_delay_exponent,
-                              prev->quic.ack_delay_exponent, 3);
+                              prev->quic.ack_delay_exponent,
+                              NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT);
 
     ngx_conf_merge_uint_value(conf->quic.disable_active_migration,
                               prev->quic.disable_active_migration, 1);