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) {
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);
p += n;
in->buf->pos += n;
offset += n;
+ limit -= n;
if (in->buf->pos == in->buf->last) {
in = in->next;
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);
}
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);
}
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;
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) {
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;
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() */
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)
{