summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/event/ngx_event_quic.c111
-rw-r--r--src/event/ngx_event_quic.h7
2 files changed, 82 insertions, 36 deletions
diff --git a/src/event/ngx_event_quic.c b/src/event/ngx_event_quic.c
index 990c1ec14..2dd415f99 100644
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -320,7 +320,7 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t level, const uint8_t *data, size_t len)
{
u_char *p, *end;
- size_t client_params_len;
+ size_t client_params_len, fsize, limit;
const uint8_t *client_params;
ngx_quic_frame_t *frame;
ngx_connection_t *c;
@@ -359,30 +359,55 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
qc->tp.max_idle_timeout = qc->ctp.max_idle_timeout;
}
+ if (qc->ctp.max_packet_size < NGX_QUIC_MIN_INITIAL_SIZE
+ || qc->ctp.max_packet_size > NGX_QUIC_DEFAULT_MAX_PACKET_SIZE)
+ {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "maximum packet size is invalid");
+ return NGX_ERROR;
+ }
+
qc->client_tp_done = 1;
}
}
+ /*
+ * we need to fit at least 1 frame into a packet, thus account head/tail;
+ * 17 = 1 + 8x2 is max header for CRYPTO frame, with 1 byte for frame type
+ */
+ limit = qc->ctp.max_packet_size - NGX_QUIC_MAX_LONG_HEADER - 17
+ - EVP_GCM_TLS_TAG_LEN;
+
fs = &qc->crypto[level];
- frame = ngx_quic_alloc_frame(c, len);
- if (frame == NULL) {
- return 0;
- }
+ p = (u_char *) data;
+ end = (u_char *) data + len;
- ngx_memcpy(frame->data, data, len);
+ while (p < end) {
- frame->level = level;
- frame->type = NGX_QUIC_FT_CRYPTO;
- frame->u.crypto.offset += fs->sent;
- frame->u.crypto.length = len;
- frame->u.crypto.data = frame->data;
+ fsize = ngx_min(limit, (size_t) (end - p));
- fs->sent += len;
+ frame = ngx_quic_alloc_frame(c, fsize);
+ if (frame == NULL) {
+ return 0;
+ }
- ngx_sprintf(frame->info, "crypto, generated by SSL len=%ui level=%d", len, level);
+ ngx_memcpy(frame->data, p, fsize);
- ngx_quic_queue_frame(qc, frame);
+ frame->level = level;
+ frame->type = NGX_QUIC_FT_CRYPTO;
+ frame->u.crypto.offset = fs->sent;
+ frame->u.crypto.length = fsize;
+ frame->u.crypto.data = frame->data;
+
+ fs->sent += fsize;
+ p += fsize;
+
+ ngx_sprintf(frame->info, "crypto, generated by SSL len=%ui level=%d",
+ fsize, level);
+
+ ngx_quic_queue_frame(qc, frame);
+ }
return 1;
}
@@ -478,7 +503,7 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_quic_tp_t *tp,
ngx_quic_connection_t *qc;
static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE];
- if (ngx_buf_size(pkt->raw) < 1200) {
+ if (ngx_buf_size(pkt->raw) < NGX_QUIC_MIN_INITIAL_SIZE) {
ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram");
return NGX_ERROR;
}
@@ -2671,6 +2696,8 @@ 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, size_t size)
{
+ u_char *p, *end;
+ size_t fsize, limit;
ngx_connection_t *pc;
ngx_quic_frame_t *frame;
ngx_quic_stream_t *qs;
@@ -2686,31 +2713,47 @@ ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, size_t size)
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send: %uz", size);
- frame = ngx_quic_alloc_frame(pc, size);
- if (frame == NULL) {
- return 0;
- }
+ /*
+ * we need to fit at least 1 frame into a packet, thus account head/tail;
+ * 25 = 1 + 8x3 is max header for STREAM frame, with 1 byte for frame type
+ */
+ limit = qc->ctp.max_packet_size - NGX_QUIC_MAX_SHORT_HEADER - 25
+ - EVP_GCM_TLS_TAG_LEN;
- ngx_memcpy(frame->data, buf, size);
+ p = (u_char *) buf;
+ end = (u_char *) buf + size;
- frame->level = ssl_encryption_application;
- frame->type = NGX_QUIC_FT_STREAM6; /* OFF=1 LEN=1 FIN=0 */
- frame->u.stream.off = 1;
- frame->u.stream.len = 1;
- frame->u.stream.fin = 0;
+ while (p < end) {
- frame->u.stream.type = frame->type;
- frame->u.stream.stream_id = qs->id;
- frame->u.stream.offset = c->sent;
- frame->u.stream.length = size;
- frame->u.stream.data = frame->data;
+ fsize = ngx_min(limit, (size_t) (end - p));
- c->sent += size;
+ frame = ngx_quic_alloc_frame(pc, fsize);
+ if (frame == NULL) {
+ return 0;
+ }
- ngx_sprintf(frame->info, "stream %xi len=%ui level=%d",
- qs->id, size, frame->level);
+ ngx_memcpy(frame->data, p, fsize);
- ngx_quic_queue_frame(qc, frame);
+ frame->level = ssl_encryption_application;
+ frame->type = NGX_QUIC_FT_STREAM6; /* OFF=1 LEN=1 FIN=0 */
+ frame->u.stream.off = 1;
+ frame->u.stream.len = 1;
+ frame->u.stream.fin = 0;
+
+ frame->u.stream.type = frame->type;
+ frame->u.stream.stream_id = qs->id;
+ frame->u.stream.offset = c->sent;
+ frame->u.stream.length = fsize;
+ frame->u.stream.data = frame->data;
+
+ c->sent += fsize;
+ p += fsize;
+
+ ngx_sprintf(frame->info, "stream %xi len=%ui level=%d",
+ qs->id, fsize, frame->level);
+
+ ngx_quic_queue_frame(qc, frame);
+ }
return size;
}
diff --git a/src/event/ngx_event_quic.h b/src/event/ngx_event_quic.h
index c843fbabe..0dfc9b2e7 100644
--- a/src/event/ngx_event_quic.h
+++ b/src/event/ngx_event_quic.h
@@ -14,13 +14,16 @@
#define NGX_QUIC_DRAFT_VERSION 27
#define NGX_QUIC_VERSION (0xff000000 + NGX_QUIC_DRAFT_VERSION)
-#define NGX_QUIC_MAX_SHORT_HEADER 25
-#define NGX_QUIC_MAX_LONG_HEADER 346
+#define NGX_QUIC_MAX_SHORT_HEADER 25 /* 1 flags + 20 dcid + 4 pn */
+#define NGX_QUIC_MAX_LONG_HEADER 56
+ /* 1 flags + 4 version + 2 x (1 + 20) s/dcid + 4 pn + 4 len + token len */
#define NGX_QUIC_DEFAULT_MAX_PACKET_SIZE 65527
#define NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT 3
#define NGX_QUIC_DEFAULT_MAX_ACK_DELAY 25
+#define NGX_QUIC_MIN_INITIAL_SIZE 1200
+
#define NGX_QUIC_STREAM_SERVER_INITIATED 0x01
#define NGX_QUIC_STREAM_UNIDIRECTIONAL 0x02