aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/event/quic/ngx_event_quic.h1
-rw-r--r--src/event/quic/ngx_event_quic_frames.c10
-rw-r--r--src/event/quic/ngx_event_quic_frames.h2
-rw-r--r--src/event/quic/ngx_event_quic_ssl.c2
-rw-r--r--src/event/quic/ngx_event_quic_streams.c33
5 files changed, 33 insertions, 15 deletions
diff --git a/src/event/quic/ngx_event_quic.h b/src/event/quic/ngx_event_quic.h
index 8ae7bf643..9481fef62 100644
--- a/src/event/quic/ngx_event_quic.h
+++ b/src/event/quic/ngx_event_quic.h
@@ -63,6 +63,7 @@ struct ngx_quic_stream_s {
uint64_t recv_last;
uint64_t final_size;
ngx_chain_t *in;
+ ngx_chain_t *out;
ngx_uint_t cancelable; /* unsigned cancelable:1; */
};
diff --git a/src/event/quic/ngx_event_quic_frames.c b/src/event/quic/ngx_event_quic_frames.c
index 4a3902f7f..71ed981e6 100644
--- a/src/event/quic/ngx_event_quic_frames.c
+++ b/src/event/quic/ngx_event_quic_frames.c
@@ -482,14 +482,14 @@ done:
ngx_int_t
ngx_quic_order_bufs(ngx_connection_t *c, ngx_chain_t **out, ngx_chain_t *in,
- size_t offset)
+ off_t limit, off_t offset)
{
+ off_t n;
u_char *p;
- size_t n;
ngx_buf_t *b;
ngx_chain_t *cl, *sl;
- while (in) {
+ while (in && limit) {
cl = *out;
if (cl == NULL) {
@@ -523,8 +523,9 @@ ngx_quic_order_bufs(ngx_connection_t *c, ngx_chain_t **out, ngx_chain_t *in,
continue;
}
- for (p = b->pos + offset; p != b->last && in; /* void */ ) {
+ for (p = b->pos + offset; p != b->last && in && limit; /* void */ ) {
n = ngx_min(b->last - p, in->buf->last - in->buf->pos);
+ n = ngx_min(n, limit);
if (b->sync) {
ngx_memcpy(p, in->buf->pos, n);
@@ -533,6 +534,7 @@ ngx_quic_order_bufs(ngx_connection_t *c, ngx_chain_t **out, ngx_chain_t *in,
p += n;
in->buf->pos += n;
offset += n;
+ limit -= n;
if (in->buf->pos == in->buf->last) {
in = in->next;
diff --git a/src/event/quic/ngx_event_quic_frames.h b/src/event/quic/ngx_event_quic_frames.h
index f4c147682..1310f6dfd 100644
--- a/src/event/quic/ngx_event_quic_frames.h
+++ b/src/event/quic/ngx_event_quic_frames.h
@@ -31,7 +31,7 @@ ngx_chain_t *ngx_quic_copy_chain(ngx_connection_t *c, ngx_chain_t *in,
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_order_bufs(ngx_connection_t *c, ngx_chain_t **out,
- ngx_chain_t *in, size_t offset);
+ ngx_chain_t *in, off_t limit, off_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 fb4b1af85..d2f1237a5 100644
--- a/src/event/quic/ngx_event_quic_ssl.c
+++ b/src/event/quic/ngx_event_quic_ssl.c
@@ -369,7 +369,7 @@ ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
}
if (f->offset > ctx->crypto_received) {
- return ngx_quic_order_bufs(c, &ctx->crypto, frame->data,
+ return ngx_quic_order_bufs(c, &ctx->crypto, frame->data, f->length,
f->offset - ctx->crypto_received);
}
diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c
index 295aa54aa..d5facc270 100644
--- a/src/event/quic/ngx_event_quic_streams.c
+++ b/src/event/quic/ngx_event_quic_streams.c
@@ -838,8 +838,9 @@ static ngx_chain_t *
ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
size_t n, flow;
+ ngx_buf_t *b;
ngx_event_t *wev;
- ngx_chain_t *cl;
+ ngx_chain_t *out, **ll;
ngx_connection_t *pc;
ngx_quic_frame_t *frame;
ngx_quic_stream_t *qs;
@@ -862,18 +863,30 @@ ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
n = (limit && (size_t) limit < flow) ? (size_t) limit : flow;
- frame = ngx_quic_alloc_frame(pc);
- if (frame == NULL) {
+ if (ngx_quic_order_bufs(pc, &qs->out, in, n, 0) != NGX_OK) {
return NGX_CHAIN_ERROR;
}
- frame->data = ngx_quic_copy_chain(pc, in, n);
- if (frame->data == NGX_CHAIN_ERROR) {
- return NGX_CHAIN_ERROR;
+ n = 0;
+ out = qs->out;
+
+ for (ll = &out; *ll; ll = &(*ll)->next) {
+ b = (*ll)->buf;
+
+ if (b->sync) {
+ /* hole */
+ break;
+ }
+
+ n += b->last - b->pos;
}
- for (n = 0, cl = frame->data; cl; cl = cl->next) {
- n += ngx_buf_size(cl->buf);
+ qs->out = *ll;
+ *ll = NULL;
+
+ frame = ngx_quic_alloc_frame(pc);
+ if (frame == NULL) {
+ return NGX_CHAIN_ERROR;
}
while (in && ngx_buf_size(in->buf) == 0) {
@@ -882,6 +895,7 @@ ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_STREAM;
+ frame->data = out;
frame->u.stream.off = 1;
frame->u.stream.len = 1;
frame->u.stream.fin = 0;
@@ -977,6 +991,7 @@ ngx_quic_stream_cleanup_handler(void *data)
ngx_rbtree_delete(&qc->streams.tree, &qs->node);
ngx_quic_free_bufs(pc, qs->in);
+ ngx_quic_free_bufs(pc, qs->out);
if (qc->closing) {
/* schedule handler call to continue ngx_quic_close_connection() */
@@ -1098,7 +1113,7 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
qs->final_size = last;
}
- if (ngx_quic_order_bufs(c, &qs->in, frame->data,
+ if (ngx_quic_order_bufs(c, &qs->in, frame->data, f->length,
f->offset - qs->recv_offset)
!= NGX_OK)
{