aboutsummaryrefslogtreecommitdiff
path: root/src/event/quic/ngx_event_quic_frames.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/event/quic/ngx_event_quic_frames.c')
-rw-r--r--src/event/quic/ngx_event_quic_frames.c261
1 files changed, 67 insertions, 194 deletions
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;
}