QUIC: ngx_quic_buffer_t object.
The object is used instead of ngx_chain_t pointer for buffer operations like ngx_quic_write_chain() and ngx_quic_read_chain(). These functions are renamed to ngx_quic_write_buffer() and ngx_quic_read_buffer().
This commit is contained in:
parent
28919d3e59
commit
8363d84edd
7 changed files with 129 additions and 103 deletions
|
@ -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);
|
||||
|
|
|
@ -48,6 +48,13 @@ typedef enum {
|
|||
} ngx_quic_stream_recv_state_e;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint64_t size;
|
||||
uint64_t offset;
|
||||
ngx_chain_t *chain;
|
||||
} ngx_quic_buffer_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_ssl_t *ssl;
|
||||
|
||||
|
@ -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; */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
if (f->offset == ctx->crypto.offset) {
|
||||
if (ngx_quic_crypto_input(c, frame->data) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_quic_skip_buffer(c, &ctx->crypto, last);
|
||||
|
||||
} else {
|
||||
if (ngx_quic_write_buffer(c, &ctx->crypto, frame->data, f->length,
|
||||
f->offset)
|
||||
== NGX_CHAIN_ERROR)
|
||||
{
|
||||
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_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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue