mirror of
https://github.com/nginx/nginx.git
synced 2024-11-21 16:28:40 +00:00
QUIC: defer stream removal until all its data is acked.
Previously, stream was kept alive until all its data is sent. This resulted in disabling retransmission of final part of stream when QUIC connection was closed right after closing stream connection.
This commit is contained in:
parent
dc82bed893
commit
a2a513b93c
@ -85,6 +85,7 @@ struct ngx_quic_stream_s {
|
||||
ngx_connection_t *parent;
|
||||
ngx_connection_t *connection;
|
||||
uint64_t id;
|
||||
uint64_t sent;
|
||||
uint64_t acked;
|
||||
uint64_t send_max_data;
|
||||
uint64_t send_offset;
|
||||
@ -98,7 +99,8 @@ struct ngx_quic_stream_s {
|
||||
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; */
|
||||
unsigned cancelable:1;
|
||||
unsigned fin_acked:1;
|
||||
};
|
||||
|
||||
|
||||
|
@ -253,6 +253,7 @@ ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
|
||||
break;
|
||||
|
||||
case NGX_QUIC_FT_STREAM:
|
||||
case NGX_QUIC_FT_RESET_STREAM:
|
||||
ngx_quic_handle_stream_ack(c, f);
|
||||
break;
|
||||
}
|
||||
|
@ -887,7 +887,7 @@ ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
||||
|
||||
qs->send_state = NGX_QUIC_STREAM_SEND_SEND;
|
||||
|
||||
flow = qs->acked + qc->conf->stream_buffer_size - c->sent;
|
||||
flow = qs->acked + qc->conf->stream_buffer_size - qs->sent;
|
||||
|
||||
if (flow == 0) {
|
||||
wev->ready = 0;
|
||||
@ -900,13 +900,14 @@ ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
||||
|
||||
n = qs->send.size;
|
||||
|
||||
in = ngx_quic_write_buffer(pc, &qs->send, in, limit, c->sent);
|
||||
in = ngx_quic_write_buffer(pc, &qs->send, in, limit, qs->sent);
|
||||
if (in == NGX_CHAIN_ERROR) {
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
|
||||
n = qs->send.size - n;
|
||||
c->sent += n;
|
||||
qs->sent += n;
|
||||
qc->streams.sent += n;
|
||||
|
||||
if (flow == n) {
|
||||
@ -1045,9 +1046,12 @@ ngx_quic_close_stream(ngx_quic_stream_t *qs)
|
||||
if (!qc->closing) {
|
||||
/* make sure everything is sent and final size is received */
|
||||
|
||||
if (qs->recv_state == NGX_QUIC_STREAM_RECV_RECV
|
||||
|| qs->send_state == NGX_QUIC_STREAM_SEND_READY
|
||||
|| qs->send_state == NGX_QUIC_STREAM_SEND_SEND)
|
||||
if (qs->recv_state == NGX_QUIC_STREAM_RECV_RECV) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (qs->send_state != NGX_QUIC_STREAM_SEND_DATA_RECVD
|
||||
&& qs->send_state != NGX_QUIC_STREAM_SEND_RESET_RECVD)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
@ -1488,36 +1492,70 @@ ngx_quic_handle_max_streams_frame(ngx_connection_t *c,
|
||||
void
|
||||
ngx_quic_handle_stream_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
|
||||
{
|
||||
uint64_t sent, unacked;
|
||||
uint64_t acked;
|
||||
ngx_quic_stream_t *qs;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
qs = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id);
|
||||
if (qs == NULL) {
|
||||
switch (f->type) {
|
||||
|
||||
case NGX_QUIC_FT_RESET_STREAM:
|
||||
|
||||
qs = ngx_quic_find_stream(&qc->streams.tree, f->u.reset_stream.id);
|
||||
if (qs == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
qs->send_state = NGX_QUIC_STREAM_SEND_RESET_RECVD;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic stream id:0x%xL ack reset final_size:%uL",
|
||||
qs->id, f->u.reset_stream.final_size);
|
||||
|
||||
break;
|
||||
|
||||
case NGX_QUIC_FT_STREAM:
|
||||
|
||||
qs = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id);
|
||||
if (qs == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
acked = qs->acked;
|
||||
qs->acked += f->u.stream.length;
|
||||
|
||||
if (f->u.stream.fin) {
|
||||
qs->fin_acked = 1;
|
||||
}
|
||||
|
||||
if (qs->send_state == NGX_QUIC_STREAM_SEND_DATA_SENT
|
||||
&& qs->acked == qs->sent && qs->fin_acked)
|
||||
{
|
||||
qs->send_state = NGX_QUIC_STREAM_SEND_DATA_RECVD;
|
||||
}
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic stream id:0x%xL ack len:%uL fin:%d unacked:%uL",
|
||||
qs->id, f->u.stream.length, f->u.stream.fin,
|
||||
qs->sent - qs->acked);
|
||||
|
||||
if (qs->connection
|
||||
&& qs->sent - acked == qc->conf->stream_buffer_size
|
||||
&& f->u.stream.length > 0)
|
||||
{
|
||||
ngx_quic_set_event(qs->connection->write);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (qs->connection == NULL) {
|
||||
qs->acked += f->u.stream.length;
|
||||
return;
|
||||
ngx_quic_close_stream(qs);
|
||||
}
|
||||
|
||||
sent = qs->connection->sent;
|
||||
unacked = sent - qs->acked;
|
||||
qs->acked += f->u.stream.length;
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic stream id:0x%xL ack len:%uL acked:%uL unacked:%uL",
|
||||
qs->id, f->u.stream.length, qs->acked, sent - qs->acked);
|
||||
|
||||
if (unacked != qc->conf->stream_buffer_size) {
|
||||
/* not blocked on buffer size */
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_quic_set_event(qs->connection->write);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user