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;
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;
}
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;
}
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;
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;
}