diff options
| -rw-r--r-- | src/event/ngx_event_quic.c | 111 | ||||
| -rw-r--r-- | src/event/ngx_event_quic.h | 7 |
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 |
