aboutsummaryrefslogtreecommitdiff
path: root/src/event/quic/ngx_event_quic_frames.c
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2021-12-24 18:17:23 +0300
committerRoman Arutyunyan <arut@nginx.com>2021-12-24 18:17:23 +0300
commitbaea97bc543d68ea2cc3a5dc96363777204f99bd (patch)
treea12ae66050d66a98d867bbcadf2853b61fa7c01c /src/event/quic/ngx_event_quic_frames.c
parent97b34a01e268b2d4946375b806b7e6364e765d70 (diff)
downloadnginx-baea97bc543d68ea2cc3a5dc96363777204f99bd.tar.gz
nginx-baea97bc543d68ea2cc3a5dc96363777204f99bd.zip
QUIC: refactored ngx_quic_order_bufs() and ngx_quic_split_bufs().
They are replaced with ngx_quic_write_chain() and ngx_quic_read_chain(). These functions represent the API to data buffering. The first function adds data of given size at given offset to the buffer. Now it returns the unwritten part of the chain similar to c->send_chain(). The second function returns data of given size from the beginning of the buffer. Its second argument and return value are swapped compared to ngx_quic_split_bufs() to better match ngx_quic_write_chain(). Added, returned and stored data are regular ngx_chain_t/ngx_buf_t chains. Missing data is marked with b->sync flag. The functions are now used in both send and recv data chains in QUIC streams.
Diffstat (limited to 'src/event/quic/ngx_event_quic_frames.c')
-rw-r--r--src/event/quic/ngx_event_quic_frames.c116
1 files changed, 72 insertions, 44 deletions
diff --git a/src/event/quic/ngx_event_quic_frames.c b/src/event/quic/ngx_event_quic_frames.c
index 71ed981e6..fe6d98043 100644
--- a/src/event/quic/ngx_event_quic_frames.c
+++ b/src/event/quic/ngx_event_quic_frames.c
@@ -13,10 +13,6 @@
#define NGX_QUIC_BUFFER_SIZE 4096
-static ngx_chain_t *ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in,
- size_t len);
-
-
ngx_quic_frame_t *
ngx_quic_alloc_frame(ngx_connection_t *c)
{
@@ -243,8 +239,8 @@ ngx_quic_split_frame(ngx_connection_t *c, ngx_quic_frame_t *f, size_t len)
onf->length = shrink;
nf->len = ngx_quic_create_frame(NULL, nf);
- nf->data = ngx_quic_split_bufs(c, f->data, of->length);
- if (nf->data == NGX_CHAIN_ERROR) {
+ f->data = ngx_quic_read_chain(c, &nf->data, of->length);
+ if (f->data == NGX_CHAIN_ERROR) {
return NGX_ERROR;
}
@@ -254,37 +250,48 @@ ngx_quic_split_frame(ngx_connection_t *c, ngx_quic_frame_t *f, size_t len)
}
-static ngx_chain_t *
-ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in, size_t len)
+ngx_chain_t *
+ngx_quic_read_chain(ngx_connection_t *c, ngx_chain_t **chain, off_t limit)
{
- size_t n;
+ off_t n;
ngx_buf_t *b;
- ngx_chain_t *out;
+ ngx_chain_t *out, *in, *cl, **ll;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
- while (in) {
- n = ngx_buf_size(in->buf);
+ out = *chain;
+
+ for (ll = &out; *ll; ll = &(*ll)->next) {
+ b = (*ll)->buf;
- if (n == len) {
- out = in->next;
- in->next = NULL;
- return out;
+ if (b->sync) {
+ /* hole */
+ break;
}
- if (n > len) {
+ if (limit == 0) {
break;
}
- len -= n;
- in = in->next;
- }
+ n = b->last - b->pos;
- if (in == NULL) {
- return NULL;
+ if (n > limit) {
+ goto split;
+ }
+
+ limit -= n;
}
+ *chain = *ll;
+ *ll = NULL;
+
+ return out;
+
+split:
+
+ in = *ll;
+
/* split in->buf by creating shadow bufs which reference it */
if (in->buf->shadow == NULL) {
@@ -305,8 +312,8 @@ ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in, size_t len)
in->buf = b;
}
- out = ngx_alloc_chain_link(c->pool);
- if (out == NULL) {
+ cl = ngx_alloc_chain_link(c->pool);
+ if (cl == NULL) {
return NGX_CHAIN_ERROR;
}
@@ -317,21 +324,23 @@ ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in, size_t len)
} else {
b = ngx_alloc_buf(c->pool);
if (b == NULL) {
- ngx_free_chain(c->pool, out);
+ ngx_free_chain(c->pool, cl);
return NGX_CHAIN_ERROR;
}
}
- out->buf = b;
- out->next = in->next;
+ cl->buf = b;
+ cl->next = in->next;
in->next = NULL;
+ *chain = cl;
*b = *in->buf;
b->last_shadow = 0;
- b->pos = b->pos + len;
+ b->pos += limit;
in->buf->shadow = b;
- in->buf->last = in->buf->pos + len;
+ in->buf->last = b->pos;
+ in->buf->last_buf = 0;
return out;
}
@@ -480,8 +489,8 @@ done:
}
-ngx_int_t
-ngx_quic_order_bufs(ngx_connection_t *c, ngx_chain_t **out, ngx_chain_t *in,
+ngx_chain_t *
+ngx_quic_write_chain(ngx_connection_t *c, ngx_chain_t **chain, ngx_chain_t *in,
off_t limit, off_t offset)
{
off_t n;
@@ -490,18 +499,18 @@ ngx_quic_order_bufs(ngx_connection_t *c, ngx_chain_t **out, ngx_chain_t *in,
ngx_chain_t *cl, *sl;
while (in && limit) {
- cl = *out;
+ cl = *chain;
if (cl == NULL) {
cl = ngx_quic_alloc_buf(c);
if (cl == NULL) {
- return NGX_ERROR;
+ return NGX_CHAIN_ERROR;
}
cl->buf->last = cl->buf->end;
cl->buf->sync = 1; /* hole */
cl->next = NULL;
- *out = cl;
+ *chain = cl;
}
b = cl->buf;
@@ -509,17 +518,25 @@ ngx_quic_order_bufs(ngx_connection_t *c, ngx_chain_t **out, ngx_chain_t *in,
if (n <= offset) {
offset -= n;
- out = &cl->next;
+ chain = &cl->next;
continue;
}
if (b->sync && offset > 0) {
- sl = ngx_quic_split_bufs(c, cl, offset);
- if (sl == NGX_CHAIN_ERROR) {
- return NGX_ERROR;
+ /* split hole at offset */
+
+ b->sync = 0;
+
+ sl = ngx_quic_read_chain(c, &cl, offset);
+ if (cl == NGX_CHAIN_ERROR) {
+ return NGX_CHAIN_ERROR;
}
- cl->next = sl;
+ sl->buf->sync = 1;
+ cl->buf->sync = 1;
+
+ *chain = sl;
+ sl->next = cl;
continue;
}
@@ -541,18 +558,29 @@ ngx_quic_order_bufs(ngx_connection_t *c, ngx_chain_t **out, ngx_chain_t *in,
}
}
+ if (b->sync && p == b->last) {
+ b->sync = 0;
+ continue;
+ }
+
if (b->sync && p != b->pos) {
- sl = ngx_quic_split_bufs(c, cl, p - b->pos);
+ /* split hole at p - b->pos */
+
+ b->sync = 0;
+
+ sl = ngx_quic_read_chain(c, &cl, p - b->pos);
if (sl == NGX_CHAIN_ERROR) {
- return NGX_ERROR;
+ return NGX_CHAIN_ERROR;
}
- cl->next = sl;
- cl->buf->sync = 0;
+ cl->buf->sync = 1;
+
+ *chain = sl;
+ sl->next = cl;
}
}
- return NGX_OK;
+ return in;
}