QUIC: optimized immediate close.

Previously, before sending CONNECTION_CLOSE to client, all pending frames
were sent.  This is redundant and could prevent CONNECTION_CLOSE from being
sent due to congestion control.  Now pending frames are freed and
CONNECTION_CLOSE is sent without congestion control, as advised by RFC 9002:

  Packets containing frames besides ACK or CONNECTION_CLOSE frames
  count toward congestion control limits and are considered to be in flight.
This commit is contained in:
Roman Arutyunyan 2023-05-02 17:54:53 +04:00
parent af18ce3506
commit 2187e5e1d9
2 changed files with 11 additions and 15 deletions

View File

@ -482,6 +482,7 @@ ngx_quic_close_connection(ngx_connection_t *c, ngx_int_t rc)
/* drop packets from retransmit queues, no ack is expected */ /* drop packets from retransmit queues, no ack is expected */
for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
ngx_quic_free_frames(c, &qc->send_ctx[i].frames);
ngx_quic_free_frames(c, &qc->send_ctx[i].sent); ngx_quic_free_frames(c, &qc->send_ctx[i].sent);
} }

View File

@ -882,7 +882,7 @@ ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
ngx_int_t ngx_int_t
ngx_quic_send_cc(ngx_connection_t *c) ngx_quic_send_cc(ngx_connection_t *c)
{ {
ngx_quic_frame_t *frame; ngx_quic_frame_t frame;
ngx_quic_connection_t *qc; ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c); qc = ngx_quic_get_connection(c);
@ -898,27 +898,22 @@ ngx_quic_send_cc(ngx_connection_t *c)
return NGX_OK; return NGX_OK;
} }
frame = ngx_quic_alloc_frame(c); ngx_memzero(&frame, sizeof(ngx_quic_frame_t));
if (frame == NULL) {
return NGX_ERROR;
}
frame->level = qc->error_level; frame.level = qc->error_level;
frame->type = qc->error_app ? NGX_QUIC_FT_CONNECTION_CLOSE_APP frame.type = qc->error_app ? NGX_QUIC_FT_CONNECTION_CLOSE_APP
: NGX_QUIC_FT_CONNECTION_CLOSE; : NGX_QUIC_FT_CONNECTION_CLOSE;
frame->u.close.error_code = qc->error; frame.u.close.error_code = qc->error;
frame->u.close.frame_type = qc->error_ftype; frame.u.close.frame_type = qc->error_ftype;
if (qc->error_reason) { if (qc->error_reason) {
frame->u.close.reason.len = ngx_strlen(qc->error_reason); frame.u.close.reason.len = ngx_strlen(qc->error_reason);
frame->u.close.reason.data = (u_char *) qc->error_reason; frame.u.close.reason.data = (u_char *) qc->error_reason;
} }
ngx_quic_queue_frame(qc, frame);
qc->last_cc = ngx_current_msec; qc->last_cc = ngx_current_msec;
return ngx_quic_output(c); return ngx_quic_frame_sendto(c, &frame, 0, qc->path);
} }