aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/event/quic/ngx_event_quic.c2
-rw-r--r--src/event/quic/ngx_event_quic.h14
-rw-r--r--src/event/quic/ngx_event_quic_connection.h3
-rw-r--r--src/event/quic/ngx_event_quic_frames.c98
-rw-r--r--src/event/quic/ngx_event_quic_frames.h12
-rw-r--r--src/event/quic/ngx_event_quic_ssl.c50
-rw-r--r--src/event/quic/ngx_event_quic_streams.c51
7 files changed, 128 insertions, 102 deletions
diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c
index c98f586b7..8ef559dae 100644
--- a/src/event/quic/ngx_event_quic.c
+++ b/src/event/quic/ngx_event_quic.c
@@ -1077,7 +1077,7 @@ 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_chain(c, ctx->crypto);
+ ngx_quic_free_buffer(c, &ctx->crypto);
while (!ngx_queue_empty(&ctx->sent)) {
q = ngx_queue_head(&ctx->sent);
diff --git a/src/event/quic/ngx_event_quic.h b/src/event/quic/ngx_event_quic.h
index c2295816a..8f6dd7e78 100644
--- a/src/event/quic/ngx_event_quic.h
+++ b/src/event/quic/ngx_event_quic.h
@@ -49,6 +49,13 @@ typedef enum {
typedef struct {
+ uint64_t size;
+ uint64_t offset;
+ ngx_chain_t *chain;
+} ngx_quic_buffer_t;
+
+
+typedef struct {
ngx_ssl_t *ssl;
ngx_flag_t retry;
@@ -84,13 +91,12 @@ struct ngx_quic_stream_s {
uint64_t recv_offset;
uint64_t recv_window;
uint64_t recv_last;
- uint64_t recv_size;
uint64_t recv_final_size;
- ngx_chain_t *in;
- ngx_chain_t *out;
- ngx_uint_t cancelable; /* unsigned cancelable:1; */
+ ngx_quic_buffer_t send;
+ ngx_quic_buffer_t recv;
ngx_quic_stream_send_state_e send_state;
ngx_quic_stream_recv_state_e recv_state;
+ 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 2b29284af..377b26bd6 100644
--- a/src/event/quic/ngx_event_quic_connection.h
+++ b/src/event/quic/ngx_event_quic_connection.h
@@ -160,8 +160,7 @@ typedef struct {
struct ngx_quic_send_ctx_s {
enum ssl_encryption_level_t level;
- ngx_chain_t *crypto;
- uint64_t crypto_received;
+ ngx_quic_buffer_t crypto;
uint64_t crypto_sent;
uint64_t pnum; /* to be sent */
diff --git a/src/event/quic/ngx_event_quic_frames.c b/src/event/quic/ngx_event_quic_frames.c
index 188235d9e..b89072ea2 100644
--- a/src/event/quic/ngx_event_quic_frames.c
+++ b/src/event/quic/ngx_event_quic_frames.c
@@ -340,6 +340,7 @@ ngx_quic_split_frame(ngx_connection_t *c, ngx_quic_frame_t *f, size_t len)
{
size_t shrink;
ngx_quic_frame_t *nf;
+ ngx_quic_buffer_t qb;
ngx_quic_ordered_frame_t *of, *onf;
switch (f->type) {
@@ -375,6 +376,14 @@ ngx_quic_split_frame(ngx_connection_t *c, ngx_quic_frame_t *f, size_t len)
return NGX_ERROR;
}
+ ngx_memzero(&qb, sizeof(ngx_quic_buffer_t));
+ qb.chain = f->data;
+
+ f->data = ngx_quic_read_buffer(c, &qb, of->length);
+ if (f->data == NGX_CHAIN_ERROR) {
+ return NGX_ERROR;
+ }
+
nf = ngx_quic_alloc_frame(c);
if (nf == NULL) {
return NGX_ERROR;
@@ -385,11 +394,7 @@ ngx_quic_split_frame(ngx_connection_t *c, ngx_quic_frame_t *f, size_t len)
onf->offset += of->length;
onf->length = shrink;
nf->len = ngx_quic_create_frame(NULL, nf);
-
- f->data = ngx_quic_read_chain(c, &nf->data, of->length);
- if (f->data == NGX_CHAIN_ERROR) {
- return NGX_ERROR;
- }
+ nf->data = qb.chain;
if (f->type == NGX_QUIC_FT_STREAM) {
f->u.stream.fin = 0;
@@ -402,13 +407,13 @@ ngx_quic_split_frame(ngx_connection_t *c, ngx_quic_frame_t *f, size_t len)
ngx_chain_t *
-ngx_quic_read_chain(ngx_connection_t *c, ngx_chain_t **chain, off_t limit)
+ngx_quic_read_buffer(ngx_connection_t *c, ngx_quic_buffer_t *qb, uint64_t limit)
{
- off_t n;
+ uint64_t n;
ngx_buf_t *b;
ngx_chain_t *out, **ll;
- out = *chain;
+ out = qb->chain;
for (ll = &out; *ll; ll = &(*ll)->next) {
b = (*ll)->buf;
@@ -433,15 +438,53 @@ ngx_quic_read_chain(ngx_connection_t *c, ngx_chain_t **chain, off_t limit)
}
limit -= n;
+ qb->offset += n;
}
- *chain = *ll;
+ qb->chain = *ll;
*ll = NULL;
return out;
}
+void
+ngx_quic_skip_buffer(ngx_connection_t *c, ngx_quic_buffer_t *qb,
+ uint64_t offset)
+{
+ size_t n;
+ ngx_buf_t *b;
+ ngx_chain_t *cl;
+
+ while (qb->chain) {
+ if (qb->offset >= offset) {
+ break;
+ }
+
+ cl = qb->chain;
+ b = cl->buf;
+ n = b->last - b->pos;
+
+ if (qb->offset + n > offset) {
+ n = offset - qb->offset;
+ b->pos += n;
+ qb->offset += n;
+ break;
+ }
+
+ qb->offset += n;
+ qb->chain = cl->next;
+
+ cl->next = NULL;
+ ngx_quic_free_chain(c, cl);
+ }
+
+ if (qb->chain == NULL) {
+ qb->offset = offset;
+ }
+}
+
+
ngx_chain_t *
ngx_quic_alloc_chain(ngx_connection_t *c)
{
@@ -496,17 +539,16 @@ ngx_quic_copy_buf(ngx_connection_t *c, u_char *data, size_t len)
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, size_t *size)
+ngx_quic_write_buffer(ngx_connection_t *c, ngx_quic_buffer_t *qb,
+ ngx_chain_t *in, uint64_t limit, uint64_t offset)
{
- off_t n;
u_char *p;
+ uint64_t n, base;
ngx_buf_t *b;
- ngx_chain_t *cl;
+ ngx_chain_t *cl, **chain;
- if (size) {
- *size = 0;
- }
+ base = qb->offset;
+ chain = &qb->chain;
while (in && limit) {
cl = *chain;
@@ -526,21 +568,21 @@ ngx_quic_write_chain(ngx_connection_t *c, ngx_chain_t **chain, ngx_chain_t *in,
b = cl->buf;
n = b->last - b->pos;
- if (n <= offset) {
- offset -= n;
+ if (base + n <= offset) {
+ base += n;
chain = &cl->next;
continue;
}
- if (b->sync && offset > 0) {
- if (ngx_quic_split_chain(c, cl, offset) != NGX_OK) {
+ if (b->sync && offset > base) {
+ if (ngx_quic_split_chain(c, cl, offset - base) != NGX_OK) {
return NGX_CHAIN_ERROR;
}
continue;
}
- p = b->pos + offset;
+ p = b->pos + (offset - base);
while (in) {
@@ -558,10 +600,7 @@ ngx_quic_write_chain(ngx_connection_t *c, ngx_chain_t **chain, ngx_chain_t *in,
if (b->sync) {
ngx_memcpy(p, in->buf->pos, n);
-
- if (size) {
- *size += n;
- }
+ qb->size += n;
}
p += n;
@@ -588,6 +627,15 @@ ngx_quic_write_chain(ngx_connection_t *c, ngx_chain_t **chain, ngx_chain_t *in,
}
+void
+ngx_quic_free_buffer(ngx_connection_t *c, ngx_quic_buffer_t *qb)
+{
+ ngx_quic_free_chain(c, qb->chain);
+
+ qb->chain = NULL;
+}
+
+
#if (NGX_DEBUG)
void
diff --git a/src/event/quic/ngx_event_quic_frames.h b/src/event/quic/ngx_event_quic_frames.h
index b06575d4e..853e36ca1 100644
--- a/src/event/quic/ngx_event_quic_frames.h
+++ b/src/event/quic/ngx_event_quic_frames.h
@@ -28,10 +28,14 @@ ngx_chain_t *ngx_quic_copy_buf(ngx_connection_t *c, u_char *data,
size_t len);
void ngx_quic_trim_chain(ngx_chain_t *in, size_t size);
void ngx_quic_free_chain(ngx_connection_t *c, ngx_chain_t *in);
-ngx_chain_t *ngx_quic_read_chain(ngx_connection_t *c, ngx_chain_t **chain,
- off_t limit);
-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, size_t *size);
+
+ngx_chain_t *ngx_quic_read_buffer(ngx_connection_t *c, ngx_quic_buffer_t *qb,
+ uint64_t limit);
+ngx_chain_t *ngx_quic_write_buffer(ngx_connection_t *c, ngx_quic_buffer_t *qb,
+ ngx_chain_t *in, uint64_t limit, uint64_t offset);
+void ngx_quic_skip_buffer(ngx_connection_t *c, ngx_quic_buffer_t *qb,
+ uint64_t offset);
+void ngx_quic_free_buffer(ngx_connection_t *c, ngx_quic_buffer_t *qb);
#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 126758253..8e01a8742 100644
--- a/src/event/quic/ngx_event_quic_ssl.c
+++ b/src/event/quic/ngx_event_quic_ssl.c
@@ -331,10 +331,8 @@ ngx_int_t
ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
ngx_quic_frame_t *frame)
{
- size_t len;
uint64_t last;
- ngx_buf_t *b;
- ngx_chain_t *cl, **ll;
+ ngx_chain_t *cl;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
ngx_quic_crypto_frame_t *f;
@@ -346,12 +344,12 @@ ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
/* no overflow since both values are 62-bit */
last = f->offset + f->length;
- if (last > ctx->crypto_received + NGX_QUIC_MAX_BUFFERED) {
+ if (last > ctx->crypto.offset + NGX_QUIC_MAX_BUFFERED) {
qc->error = NGX_QUIC_ERR_CRYPTO_BUFFER_EXCEEDED;
return NGX_ERROR;
}
- if (last <= ctx->crypto_received) {
+ if (last <= ctx->crypto.offset) {
if (pkt->level == ssl_encryption_initial) {
/* speeding up handshake completion */
@@ -368,45 +366,23 @@ ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
return NGX_OK;
}
- if (f->offset > ctx->crypto_received) {
- if (ngx_quic_write_chain(c, &ctx->crypto, frame->data, f->length,
- f->offset - ctx->crypto_received, NULL)
- == NGX_CHAIN_ERROR)
- {
+ if (f->offset == ctx->crypto.offset) {
+ if (ngx_quic_crypto_input(c, frame->data) != NGX_OK) {
return NGX_ERROR;
}
- return NGX_OK;
- }
-
- ngx_quic_trim_chain(frame->data, ctx->crypto_received - f->offset);
-
- if (ngx_quic_crypto_input(c, frame->data) != NGX_OK) {
- return NGX_ERROR;
- }
+ ngx_quic_skip_buffer(c, &ctx->crypto, last);
- ngx_quic_trim_chain(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;
+ } else {
+ if (ngx_quic_write_buffer(c, &ctx->crypto, frame->data, f->length,
+ f->offset)
+ == NGX_CHAIN_ERROR)
+ {
+ return NGX_ERROR;
}
-
- len += b->last - b->pos;
- ll = &(*ll)->next;
}
- ctx->crypto_received += len;
- ctx->crypto = *ll;
- *ll = NULL;
+ cl = ngx_quic_read_buffer(c, &ctx->crypto, (uint64_t) -1);
if (cl) {
if (ngx_quic_crypto_input(c, cl) != NGX_OK) {
diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c
index 54ed051ca..1906bc695 100644
--- a/src/event/quic/ngx_event_quic_streams.c
+++ b/src/event/quic/ngx_event_quic_streams.c
@@ -261,8 +261,7 @@ ngx_quic_do_reset_stream(ngx_quic_stream_t *qs, ngx_uint_t err)
ngx_quic_queue_frame(qc, frame);
- ngx_quic_free_chain(pc, qs->out);
- qs->out = NULL;
+ ngx_quic_free_buffer(pc, &qs->send);
return NGX_OK;
}
@@ -760,7 +759,7 @@ ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size)
return 0;
}
- in = ngx_quic_read_chain(pc, &qs->in, size);
+ in = ngx_quic_read_buffer(pc, &qs->recv, size);
if (in == NGX_CHAIN_ERROR) {
return NGX_ERROR;
}
@@ -835,8 +834,7 @@ ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, size_t size)
static ngx_chain_t *
ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
- off_t flow;
- size_t n;
+ uint64_t n, flow;
ngx_event_t *wev;
ngx_connection_t *pc;
ngx_quic_stream_t *qs;
@@ -863,25 +861,27 @@ ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
return in;
}
- if (limit == 0 || limit > flow) {
+ if (limit == 0 || limit > (off_t) flow) {
limit = flow;
}
- in = ngx_quic_write_chain(pc, &qs->out, in, limit,
- c->sent - qs->send_offset, &n);
+ n = qs->send.size;
+
+ in = ngx_quic_write_buffer(pc, &qs->send, in, limit, c->sent);
if (in == NGX_CHAIN_ERROR) {
return NGX_CHAIN_ERROR;
}
+ n = qs->send.size - n;
c->sent += n;
qc->streams.sent += n;
- if (flow == (off_t) n) {
+ if (flow == n) {
wev->ready = 0;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
- "quic send_chain sent:%uz", n);
+ "quic send_chain sent:%uL", n);
if (ngx_quic_stream_flush(qs) != NGX_OK) {
return NGX_CHAIN_ERROR;
@@ -894,10 +894,9 @@ ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
static ngx_int_t
ngx_quic_stream_flush(ngx_quic_stream_t *qs)
{
- off_t limit;
- size_t len;
+ off_t limit, len;
ngx_uint_t last;
- ngx_chain_t *out, *cl;
+ ngx_chain_t *out;
ngx_quic_frame_t *frame;
ngx_connection_t *pc;
ngx_quic_connection_t *qc;
@@ -919,20 +918,18 @@ ngx_quic_stream_flush(ngx_quic_stream_t *qs)
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pc->log, 0,
"quic stream id:0x%xL flush limit:%O", qs->id, limit);
- out = ngx_quic_read_chain(pc, &qs->out, limit);
+ len = qs->send.offset;
+
+ out = ngx_quic_read_buffer(pc, &qs->send, limit);
if (out == NGX_CHAIN_ERROR) {
return NGX_ERROR;
}
- len = 0;
+ len = qs->send.offset - len;
last = 0;
- for (cl = out; cl; cl = cl->next) {
- len += cl->buf->last - cl->buf->pos;
- }
-
if (qs->send_final_size != (uint64_t) -1
- && qs->send_final_size == qs->send_offset + len)
+ && qs->send_final_size == qs->send.offset)
{
qs->send_state = NGX_QUIC_STREAM_SEND_DATA_SENT;
last = 1;
@@ -965,7 +962,7 @@ ngx_quic_stream_flush(ngx_quic_stream_t *qs)
qc->streams.send_offset += len;
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pc->log, 0,
- "quic stream id:0x%xL flush len:%uz last:%ui",
+ "quic stream id:0x%xL flush len:%O last:%ui",
qs->id, len, last);
if (qs->connection == NULL) {
@@ -1026,8 +1023,8 @@ ngx_quic_close_stream(ngx_quic_stream_t *qs)
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, 0,
"quic stream id:0x%xL close", qs->id);
- ngx_quic_free_chain(pc, qs->in);
- ngx_quic_free_chain(pc, qs->out);
+ ngx_quic_free_buffer(pc, &qs->send);
+ ngx_quic_free_buffer(pc, &qs->recv);
ngx_rbtree_delete(&qc->streams.tree, &qs->node);
ngx_queue_insert_tail(&qc->streams.free, &qs->queue);
@@ -1071,7 +1068,6 @@ ngx_int_t
ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
ngx_quic_frame_t *frame)
{
- size_t size;
uint64_t last;
ngx_quic_stream_t *qs;
ngx_quic_connection_t *qc;
@@ -1140,17 +1136,14 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
qs->recv_state = NGX_QUIC_STREAM_RECV_SIZE_KNOWN;
}
- if (ngx_quic_write_chain(c, &qs->in, frame->data, f->length,
- f->offset - qs->recv_offset, &size)
+ if (ngx_quic_write_buffer(c, &qs->recv, frame->data, f->length, f->offset)
== NGX_CHAIN_ERROR)
{
return NGX_ERROR;
}
- qs->recv_size += size;
-
if (qs->recv_state == NGX_QUIC_STREAM_RECV_SIZE_KNOWN
- && qs->recv_size == qs->recv_final_size)
+ && qs->recv.size == qs->recv_final_size)
{
qs->recv_state = NGX_QUIC_STREAM_RECV_DATA_RECVD;
}