aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/event/quic/ngx_event_quic.c6
-rw-r--r--src/event/quic/ngx_event_quic.h5
-rw-r--r--src/event/quic/ngx_event_quic_connection.h14
-rw-r--r--src/event/quic/ngx_event_quic_frames.c261
-rw-r--r--src/event/quic/ngx_event_quic_frames.h7
-rw-r--r--src/event/quic/ngx_event_quic_ssl.c111
-rw-r--r--src/event/quic/ngx_event_quic_ssl.h3
-rw-r--r--src/event/quic/ngx_event_quic_streams.c162
-rw-r--r--src/event/quic/ngx_event_quic_streams.h2
9 files changed, 220 insertions, 351 deletions
diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c
index b1aa758ee..cc83df0ce 100644
--- a/src/event/quic/ngx_event_quic.c
+++ b/src/event/quic/ngx_event_quic.c
@@ -266,10 +266,6 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf,
qc->send_ctx[1].level = ssl_encryption_handshake;
qc->send_ctx[2].level = ssl_encryption_application;
- for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) {
- ngx_queue_init(&qc->crypto[i].frames);
- }
-
ngx_queue_init(&qc->free_frames);
qc->avg_rtt = NGX_QUIC_INITIAL_RTT;
@@ -1022,6 +1018,8 @@ ngx_quic_discard_ctx(ngx_connection_t *c, enum ssl_encryption_level_t level)
ctx = ngx_quic_get_send_ctx(qc, level);
+ ngx_quic_free_bufs(c, ctx->crypto);
+
while (!ngx_queue_empty(&ctx->sent)) {
q = ngx_queue_head(&ctx->sent);
ngx_queue_remove(q);
diff --git a/src/event/quic/ngx_event_quic.h b/src/event/quic/ngx_event_quic.h
index a18f2954e..83e72a6f3 100644
--- a/src/event/quic/ngx_event_quic.h
+++ b/src/event/quic/ngx_event_quic.h
@@ -70,8 +70,6 @@ typedef struct {
} ngx_quic_conf_t;
-typedef struct ngx_quic_frames_stream_s ngx_quic_frames_stream_t;
-
struct ngx_quic_stream_s {
ngx_rbtree_node_t node;
ngx_connection_t *parent;
@@ -80,8 +78,9 @@ struct ngx_quic_stream_s {
uint64_t acked;
uint64_t send_max_data;
uint64_t recv_max_data;
+ uint64_t recv_offset;
+ uint64_t final_size;
ngx_chain_t *in;
- ngx_quic_frames_stream_t *fs;
ngx_uint_t cancelable; /* unsigned cancelable:1; */
};
diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h
index 2e1206129..784378647 100644
--- a/src/event/quic/ngx_event_quic_connection.h
+++ b/src/event/quic/ngx_event_quic_connection.h
@@ -140,14 +140,6 @@ typedef struct {
} ngx_quic_congestion_t;
-struct ngx_quic_frames_stream_s {
- uint64_t sent;
- uint64_t received;
- ngx_queue_t frames; /* reorder queue */
- size_t total; /* size of buffered data */
-};
-
-
/*
* 12.3. Packet Numbers
*
@@ -159,6 +151,10 @@ struct ngx_quic_frames_stream_s {
struct ngx_quic_send_ctx_s {
enum ssl_encryption_level_t level;
+ ngx_chain_t *crypto;
+ uint64_t crypto_received;
+ uint64_t crypto_sent;
+
uint64_t pnum; /* to be sent */
uint64_t largest_ack; /* received from peer */
uint64_t largest_pn; /* received from peer */
@@ -203,8 +199,6 @@ struct ngx_quic_connection_s {
ngx_quic_send_ctx_t send_ctx[NGX_QUIC_SEND_CTX_LAST];
- ngx_quic_frames_stream_t crypto[NGX_QUIC_ENCRYPTION_LAST];
-
ngx_quic_keys_t *keys;
ngx_quic_conf_t *conf;
diff --git a/src/event/quic/ngx_event_quic_frames.c b/src/event/quic/ngx_event_quic_frames.c
index aaa7166c7..3177fa992 100644
--- a/src/event/quic/ngx_event_quic_frames.c
+++ b/src/event/quic/ngx_event_quic_frames.c
@@ -16,11 +16,6 @@
static ngx_chain_t *ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in,
size_t len);
-static ngx_int_t ngx_quic_buffer_frame(ngx_connection_t *c,
- ngx_quic_frames_stream_t *stream, ngx_quic_frame_t *f);
-static ngx_int_t ngx_quic_adjust_frame_offset(ngx_connection_t *c,
- ngx_quic_frame_t *f, uint64_t offset_in);
-
ngx_quic_frame_t *
ngx_quic_alloc_frame(ngx_connection_t *c)
@@ -84,6 +79,26 @@ ngx_quic_free_frame(ngx_connection_t *c, ngx_quic_frame_t *frame)
void
+ngx_quic_trim_bufs(ngx_chain_t *in, size_t size)
+{
+ size_t n;
+ ngx_buf_t *b;
+
+ while (in && size > 0) {
+ b = in->buf;
+ n = ngx_min((size_t) (b->last - b->pos), size);
+
+ b->pos += n;
+ size -= n;
+
+ if (b->pos == b->last) {
+ in = in->next;
+ }
+ }
+}
+
+
+void
ngx_quic_free_bufs(ngx_connection_t *c, ngx_chain_t *in)
{
ngx_buf_t *b, *shadow;
@@ -469,217 +484,75 @@ done:
ngx_int_t
-ngx_quic_handle_ordered_frame(ngx_connection_t *c, ngx_quic_frames_stream_t *fs,
- ngx_quic_frame_t *frame, ngx_quic_frame_handler_pt handler, void *data)
+ngx_quic_order_bufs(ngx_connection_t *c, ngx_chain_t **out, ngx_chain_t *in,
+ size_t offset)
{
- size_t full_len;
- ngx_int_t rc;
- ngx_queue_t *q;
- ngx_quic_ordered_frame_t *f;
-
- f = &frame->u.ord;
-
- if (f->offset > fs->received) {
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic out-of-order frame: expecting:%uL got:%uL",
- fs->received, f->offset);
-
- return ngx_quic_buffer_frame(c, fs, frame);
- }
-
- if (f->offset < fs->received) {
-
- if (ngx_quic_adjust_frame_offset(c, frame, fs->received)
- == NGX_DONE)
- {
- /* old/duplicate data range */
- return handler == ngx_quic_crypto_input ? NGX_DECLINED : NGX_OK;
- }
-
- /* intersecting data range, frame modified */
- }
-
- /* f->offset == fs->received */
-
- rc = handler(c, frame, data);
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
-
- } else if (rc == NGX_DONE) {
- /* handler destroyed stream, queue no longer exists */
- return NGX_OK;
- }
-
- /* rc == NGX_OK */
+ u_char *p;
+ size_t n;
+ ngx_buf_t *b;
+ ngx_chain_t *cl, *sl;
- fs->received += f->length;
+ while (in) {
+ cl = *out;
- /* now check the queue if we can continue with buffered frames */
+ if (cl == NULL) {
+ cl = ngx_quic_alloc_buf(c);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
- do {
- q = ngx_queue_head(&fs->frames);
- if (q == ngx_queue_sentinel(&fs->frames)) {
- break;
+ cl->buf->last = cl->buf->end;
+ cl->buf->sync = 1; /* hole */
+ cl->next = NULL;
+ *out = cl;
}
- frame = ngx_queue_data(q, ngx_quic_frame_t, queue);
- f = &frame->u.ord;
+ b = cl->buf;
+ n = b->last - b->pos;
- if (f->offset > fs->received) {
- /* gap found, nothing more to do */
- break;
+ if (n <= offset) {
+ offset -= n;
+ out = &cl->next;
+ continue;
}
- full_len = f->length;
-
- if (f->offset < fs->received) {
-
- if (ngx_quic_adjust_frame_offset(c, frame, fs->received)
- == NGX_DONE)
- {
- /* old/duplicate data range */
- ngx_queue_remove(q);
- fs->total -= f->length;
-
- ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic skipped buffered frame, total:%ui",
- fs->total);
- ngx_quic_free_frame(c, frame);
- continue;
+ if (b->sync && offset > 0) {
+ sl = ngx_quic_split_bufs(c, cl, offset);
+ if (sl == NGX_CHAIN_ERROR) {
+ return NGX_ERROR;
}
- /* frame was adjusted, proceed to input */
- }
-
- /* f->offset == fs->received */
-
- rc = handler(c, frame, data);
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
-
- } else if (rc == NGX_DONE) {
- /* handler destroyed stream, queue no longer exists */
- return NGX_OK;
+ cl->next = sl;
+ continue;
}
- fs->received += f->length;
- fs->total -= full_len;
-
- ngx_queue_remove(q);
-
- ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic consumed buffered frame, total:%ui", fs->total);
-
- ngx_quic_free_frame(c, frame);
-
- } while (1);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_quic_adjust_frame_offset(ngx_connection_t *c, ngx_quic_frame_t *frame,
- uint64_t offset_in)
-{
- size_t tail, n;
- ngx_buf_t *b;
- ngx_chain_t *cl;
- ngx_quic_ordered_frame_t *f;
-
- f = &frame->u.ord;
-
- tail = offset_in - f->offset;
+ for (p = b->pos + offset; p != b->last && in; /* void */ ) {
+ n = ngx_min(b->last - p, in->buf->last - in->buf->pos);
- if (tail >= f->length) {
- /* range preceeding already received data or duplicate, ignore */
-
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic old or duplicate data in ordered frame, ignored");
- return NGX_DONE;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic adjusted ordered frame data start to expected offset");
-
- /* intersecting range: adjust data size */
-
- f->offset += tail;
- f->length -= tail;
+ if (b->sync) {
+ ngx_memcpy(p, in->buf->pos, n);
+ }
- for (cl = frame->data; cl; cl = cl->next) {
- b = cl->buf;
- n = ngx_buf_size(b);
+ p += n;
+ in->buf->pos += n;
+ offset += n;
- if (n >= tail) {
- b->pos += tail;
- break;
+ if (in->buf->pos == in->buf->last) {
+ in = in->next;
+ }
}
- cl->buf->pos = cl->buf->last;
- tail -= n;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_quic_buffer_frame(ngx_connection_t *c, ngx_quic_frames_stream_t *fs,
- ngx_quic_frame_t *frame)
-{
- ngx_queue_t *q;
- ngx_quic_frame_t *dst, *item;
- ngx_quic_ordered_frame_t *f, *df;
-
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic ngx_quic_buffer_frame");
-
- f = &frame->u.ord;
-
- /* frame start offset is in the future, buffer it */
-
- dst = ngx_quic_alloc_frame(c);
- if (dst == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(dst, frame, sizeof(ngx_quic_frame_t));
-
- dst->data = ngx_quic_copy_chain(c, frame->data, 0);
- if (dst->data == NGX_CHAIN_ERROR) {
- return NGX_ERROR;
- }
-
- df = &dst->u.ord;
-
- fs->total += f->length;
-
- ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic ordered frame with unexpected offset:"
- " buffered total:%ui", fs->total);
-
- if (ngx_queue_empty(&fs->frames)) {
- ngx_queue_insert_after(&fs->frames, &dst->queue);
- return NGX_OK;
- }
-
- for (q = ngx_queue_last(&fs->frames);
- q != ngx_queue_sentinel(&fs->frames);
- q = ngx_queue_prev(q))
- {
- item = ngx_queue_data(q, ngx_quic_frame_t, queue);
- f = &item->u.ord;
+ if (b->sync && p != b->pos) {
+ sl = ngx_quic_split_bufs(c, cl, p - b->pos);
+ if (sl == NGX_CHAIN_ERROR) {
+ return NGX_ERROR;
+ }
- if (f->offset < df->offset) {
- ngx_queue_insert_after(q, &dst->queue);
- return NGX_OK;
+ cl->next = sl;
+ cl->buf->sync = 0;
}
}
- ngx_queue_insert_after(&fs->frames, &dst->queue);
-
return NGX_OK;
}
diff --git a/src/event/quic/ngx_event_quic_frames.h b/src/event/quic/ngx_event_quic_frames.h
index c7d08cb5d..f4c147682 100644
--- a/src/event/quic/ngx_event_quic_frames.h
+++ b/src/event/quic/ngx_event_quic_frames.h
@@ -28,11 +28,10 @@ ngx_chain_t *ngx_quic_copy_buf(ngx_connection_t *c, u_char *data,
size_t len);
ngx_chain_t *ngx_quic_copy_chain(ngx_connection_t *c, ngx_chain_t *in,
size_t limit);
+void ngx_quic_trim_bufs(ngx_chain_t *in, size_t size);
void ngx_quic_free_bufs(ngx_connection_t *c, ngx_chain_t *in);
-
-ngx_int_t ngx_quic_handle_ordered_frame(ngx_connection_t *c,
- ngx_quic_frames_stream_t *fs, ngx_quic_frame_t *frame,
- ngx_quic_frame_handler_pt handler, void *data);
+ngx_int_t ngx_quic_order_bufs(ngx_connection_t *c, ngx_chain_t **out,
+ ngx_chain_t *in, size_t offset);
#if (NGX_DEBUG)
void ngx_quic_log_frame(ngx_log_t *log, ngx_quic_frame_t *f, ngx_uint_t tx);
diff --git a/src/event/quic/ngx_event_quic_ssl.c b/src/event/quic/ngx_event_quic_ssl.c
index a4e96d204..3ade0b5ac 100644
--- a/src/event/quic/ngx_event_quic_ssl.c
+++ b/src/event/quic/ngx_event_quic_ssl.c
@@ -33,6 +33,7 @@ static int ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
static int ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t level, const uint8_t *data, size_t len);
static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn);
+static ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data);
static SSL_QUIC_METHOD quic_method = {
@@ -149,14 +150,14 @@ static int
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;
- const uint8_t *client_params;
- ngx_quic_tp_t ctp;
- ngx_quic_frame_t *frame;
- ngx_connection_t *c;
- ngx_quic_connection_t *qc;
- ngx_quic_frames_stream_t *fs;
+ 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_send_ctx_t *ctx;
+ ngx_quic_connection_t *qc;
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
qc = ngx_quic_get_connection(c);
@@ -228,7 +229,7 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
qc->client_tp_done = 1;
}
- fs = &qc->crypto[level];
+ ctx = ngx_quic_get_send_ctx(qc, level);
frame = ngx_quic_alloc_frame(c);
if (frame == NULL) {
@@ -242,10 +243,10 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
frame->level = level;
frame->type = NGX_QUIC_FT_CRYPTO;
- frame->u.crypto.offset = fs->sent;
+ frame->u.crypto.offset = ctx->crypto_sent;
frame->u.crypto.length = len;
- fs->sent += len;
+ ctx->crypto_sent += len;
ngx_quic_queue_frame(qc, frame);
@@ -272,57 +273,97 @@ ngx_int_t
ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
ngx_quic_frame_t *frame)
{
- uint64_t last;
- ngx_int_t rc;
- ngx_quic_send_ctx_t *ctx;
- ngx_quic_connection_t *qc;
- ngx_quic_crypto_frame_t *f;
- ngx_quic_frames_stream_t *fs;
+ size_t len;
+ uint64_t last;
+ ngx_buf_t *b;
+ ngx_chain_t *cl, **ll;
+ ngx_quic_send_ctx_t *ctx;
+ ngx_quic_connection_t *qc;
+ ngx_quic_crypto_frame_t *f;
qc = ngx_quic_get_connection(c);
- fs = &qc->crypto[pkt->level];
+ ctx = ngx_quic_get_send_ctx(qc, pkt->level);
f = &frame->u.crypto;
/* no overflow since both values are 62-bit */
last = f->offset + f->length;
- if (last > fs->received && last - fs->received > NGX_QUIC_MAX_BUFFERED) {
+ if (last > ctx->crypto_received + NGX_QUIC_MAX_BUFFERED) {
qc->error = NGX_QUIC_ERR_CRYPTO_BUFFER_EXCEEDED;
return NGX_ERROR;
}
- rc = ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_crypto_input,
- NULL);
- if (rc != NGX_DECLINED) {
- return rc;
+ if (last <= ctx->crypto_received) {
+ if (pkt->level == ssl_encryption_initial) {
+ /* speeding up handshake completion */
+
+ if (!ngx_queue_empty(&ctx->sent)) {
+ ngx_quic_resend_frames(c, ctx);
+
+ ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake);
+ while (!ngx_queue_empty(&ctx->sent)) {
+ ngx_quic_resend_frames(c, ctx);
+ }
+ }
+ }
+
+ return NGX_OK;
}
- /* speeding up handshake completion */
+ if (f->offset > ctx->crypto_received) {
+ return ngx_quic_order_bufs(c, &ctx->crypto, frame->data,
+ f->offset - ctx->crypto_received);
+ }
- if (pkt->level == ssl_encryption_initial) {
- ctx = ngx_quic_get_send_ctx(qc, pkt->level);
+ ngx_quic_trim_bufs(frame->data, ctx->crypto_received - f->offset);
- if (!ngx_queue_empty(&ctx->sent)) {
- ngx_quic_resend_frames(c, ctx);
+ if (ngx_quic_crypto_input(c, frame->data) != NGX_OK) {
+ return NGX_ERROR;
+ }
- ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake);
- while (!ngx_queue_empty(&ctx->sent)) {
- ngx_quic_resend_frames(c, ctx);
- }
+ ngx_quic_trim_bufs(ctx->crypto, last - ctx->crypto_received);
+ ctx->crypto_received = last;
+
+ cl = ctx->crypto;
+ ll = &cl;
+ len = 0;
+
+ while (*ll) {
+ b = (*ll)->buf;
+
+ if (b->sync && b->pos != b->last) {
+ /* hole */
+ break;
+ }
+
+ len += b->last - b->pos;
+ ll = &(*ll)->next;
+ }
+
+ ctx->crypto_received += len;
+ ctx->crypto = *ll;
+ *ll = NULL;
+
+ if (cl) {
+ if (ngx_quic_crypto_input(c, cl) != NGX_OK) {
+ return NGX_ERROR;
}
+
+ ngx_quic_free_bufs(c, cl);
}
return NGX_OK;
}
-ngx_int_t
-ngx_quic_crypto_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data)
+static ngx_int_t
+ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data)
{
int n, sslerr;
ngx_buf_t *b;
ngx_chain_t *cl;
ngx_ssl_conn_t *ssl_conn;
+ ngx_quic_frame_t *frame;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
@@ -334,7 +375,7 @@ ngx_quic_crypto_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data)
(int) SSL_quic_read_level(ssl_conn),
(int) SSL_quic_write_level(ssl_conn));
- for (cl = frame->data; cl; cl = cl->next) {
+ for (cl = data; cl; cl = cl->next) {
b = cl->buf;
if (!SSL_provide_quic_data(ssl_conn, SSL_quic_read_level(ssl_conn),
diff --git a/src/event/quic/ngx_event_quic_ssl.h b/src/event/quic/ngx_event_quic_ssl.h
index 68656b85c..ee0aa07c9 100644
--- a/src/event/quic/ngx_event_quic_ssl.h
+++ b/src/event/quic/ngx_event_quic_ssl.h
@@ -16,7 +16,4 @@ ngx_int_t ngx_quic_init_connection(ngx_connection_t *c);
ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c,
ngx_quic_header_t *pkt, ngx_quic_frame_t *frame);
-ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c,
- ngx_quic_frame_t *frame, void *data);
-
#endif /* _NGX_EVENT_QUIC_SSL_H_INCLUDED_ */
diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c
index 9a3d28132..816da61d5 100644
--- a/src/event/quic/ngx_event_quic_streams.c
+++ b/src/event/quic/ngx_event_quic_streams.c
@@ -349,14 +349,7 @@ ngx_quic_create_stream(ngx_connection_t *c, uint64_t id)
qs->node.key = id;
qs->parent = c;
qs->id = id;
-
- qs->fs = ngx_pcalloc(pool, sizeof(ngx_quic_frames_stream_t));
- if (qs->fs == NULL) {
- ngx_destroy_pool(pool);
- return NULL;
- }
-
- ngx_queue_init(&qs->fs->frames);
+ qs->final_size = (uint64_t) -1;
log = ngx_palloc(pool, sizeof(ngx_log_t));
if (log == NULL) {
@@ -457,14 +450,14 @@ ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size)
return NGX_ERROR;
}
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic stream recv id:0x%xL eof:%d",
- qs->id, rev->pending_eof);
+ ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "quic stream id:0x%xL recv eof:%d buf:%uz",
+ qs->id, rev->pending_eof, size);
- if (qs->in == NULL) {
+ if (qs->in == NULL || qs->in->buf->sync) {
rev->ready = 0;
- if (rev->pending_eof) {
+ if (qs->recv_offset == qs->final_size) {
rev->eof = 1;
return 0;
}
@@ -480,6 +473,11 @@ ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size)
for (ll = &cl; *ll; ll = &(*ll)->next) {
b = (*ll)->buf;
+ if (b->sync) {
+ /* hole */
+ break;
+ }
+
n = ngx_min(b->last - b->pos, (ssize_t) size);
buf = ngx_cpymem(buf, b->pos, n);
@@ -499,14 +497,14 @@ ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size)
qc->streams.received += len;
qs->recv_max_data += len;
+ qs->recv_offset += len;
if (qs->in == NULL) {
rev->ready = rev->pending_eof;
}
- ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic stream id:0x%xL recv len:%z of size:%uz",
- qs->id, len, size);
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "quic stream id:0x%xL recv len:%z", qs->id, len);
if (!rev->pending_eof) {
frame = ngx_quic_alloc_frame(pc);
@@ -719,7 +717,6 @@ ngx_quic_stream_cleanup_handler(void *data)
"quic stream id:0x%xL cleanup", qs->id);
ngx_rbtree_delete(&qc->streams.tree, &qs->node);
- ngx_quic_free_frames(pc, &qs->fs->frames);
ngx_quic_free_bufs(pc, qs->in);
if (qc->closing) {
@@ -815,13 +812,12 @@ ngx_int_t
ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
ngx_quic_frame_t *frame)
{
- uint64_t last;
- ngx_pool_t *pool;
- ngx_connection_t *sc;
- ngx_quic_stream_t *qs;
- ngx_quic_connection_t *qc;
- ngx_quic_stream_frame_t *f;
- ngx_quic_frames_stream_t *fs;
+ uint64_t last;
+ ngx_pool_t *pool;
+ ngx_connection_t *sc;
+ ngx_quic_stream_t *qs;
+ ngx_quic_connection_t *qc;
+ ngx_quic_stream_frame_t *f;
qc = ngx_quic_get_connection(c);
f = &frame->u.stream;
@@ -850,17 +846,22 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
}
sc = qs->connection;
- fs = qs->fs;
if (last > qs->recv_max_data) {
qc->error = NGX_QUIC_ERR_FLOW_CONTROL_ERROR;
goto cleanup;
}
- if (ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_stream_input,
- qs)
- != NGX_OK)
- {
+ if (f->fin) {
+ sc->read->pending_eof = 1;
+ qs->final_size = last;
+ }
+
+ if (f->offset == 0) {
+ sc->read->ready = 1;
+ }
+
+ if (ngx_quic_order_bufs(c, &qs->in, frame->data, f->offset) != NGX_OK) {
goto cleanup;
}
@@ -869,90 +870,50 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
return NGX_OK;
}
- fs = qs->fs;
-
if (last > qs->recv_max_data) {
qc->error = NGX_QUIC_ERR_FLOW_CONTROL_ERROR;
return NGX_ERROR;
}
- return ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_stream_input,
- qs);
-
-cleanup:
-
- pool = sc->pool;
-
- ngx_close_connection(sc);
- ngx_destroy_pool(pool);
-
- return NGX_ERROR;
-}
-
-
-ngx_int_t
-ngx_quic_stream_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data)
-{
- ssize_t n;
- uint64_t id;
- ngx_buf_t *b;
- ngx_event_t *rev;
- ngx_chain_t *cl, **ll;
- ngx_quic_stream_t *qs;
- ngx_quic_connection_t *qc;
- ngx_quic_stream_frame_t *f;
-
- qc = ngx_quic_get_connection(c);
- qs = data;
-
- f = &frame->u.stream;
- id = f->stream_id;
- cl = frame->data;
-
- for (ll = &qs->in; *ll; ll = &(*ll)->next) {
- if ((*ll)->next) {
- continue;
- }
+ if (qs->final_size != (uint64_t) -1 && last > qs->final_size) {
+ qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
+ return NGX_ERROR;
+ }
- /* append to last buffer */
+ if (last <= qs->recv_offset) {
+ return NGX_OK;
+ }
- b = (*ll)->buf;
+ if (f->offset < qs->recv_offset) {
+ ngx_quic_trim_bufs(frame->data, qs->recv_offset - f->offset);
+ f->offset = qs->recv_offset;
+ }
- while (cl && b->last != b->end) {
- n = ngx_min(cl->buf->last - cl->buf->pos, b->end - b->last);
- b->last = ngx_cpymem(b->last, cl->buf->pos, n);
- cl->buf->pos += n;
+ if (f->offset == qs->recv_offset) {
+ qs->connection->read->ready = 1;
+ }
- if (cl->buf->pos == cl->buf->last) {
- cl = cl->next;
- }
+ if (f->fin) {
+ if (qs->final_size != (uint64_t) -1 && qs->final_size != last) {
+ qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
+ return NGX_ERROR;
}
- }
- cl = ngx_quic_copy_chain(c, cl, 0);
- if (cl == NGX_CHAIN_ERROR) {
- return NGX_ERROR;
+ qs->connection->read->pending_eof = 1;
+ qs->final_size = last;
}
- *ll = cl;
-
- rev = qs->connection->read;
- rev->ready = 1;
+ return ngx_quic_order_bufs(c, &qs->in, frame->data,
+ f->offset - qs->recv_offset);
- if (f->fin) {
- rev->pending_eof = 1;
- }
+cleanup:
- if (rev->active) {
- rev->handler(rev);
- }
+ pool = sc->pool;
- /* check if stream was destroyed by handler */
- if (ngx_quic_find_stream(&qc->streams.tree, id) == NULL) {
- return NGX_DONE;
- }
+ ngx_close_connection(sc);
+ ngx_destroy_pool(pool);
- return NGX_OK;
+ return NGX_ERROR;
}
@@ -1150,6 +1111,8 @@ ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
return NGX_OK;
}
+ qs->final_size = f->final_size;
+
sc = qs->connection;
rev = sc->read;
@@ -1161,6 +1124,13 @@ ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
return NGX_OK;
}
+ if (qs->final_size != (uint64_t) -1 && qs->final_size != f->final_size) {
+ qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
+ return NGX_ERROR;
+ }
+
+ qs->final_size = f->final_size;
+
rev = qs->connection->read;
rev->error = 1;
rev->ready = 1;
diff --git a/src/event/quic/ngx_event_quic_streams.h b/src/event/quic/ngx_event_quic_streams.h
index 1a755e91e..0ee9c37f2 100644
--- a/src/event/quic/ngx_event_quic_streams.h
+++ b/src/event/quic/ngx_event_quic_streams.h
@@ -14,8 +14,6 @@
ngx_int_t ngx_quic_handle_stream_frame(ngx_connection_t *c,
ngx_quic_header_t *pkt, ngx_quic_frame_t *frame);
-ngx_int_t ngx_quic_stream_input(ngx_connection_t *c,
- ngx_quic_frame_t *frame, void *data);
void ngx_quic_handle_stream_ack(ngx_connection_t *c,
ngx_quic_frame_t *f);
ngx_int_t ngx_quic_handle_max_data_frame(ngx_connection_t *c,