aboutsummaryrefslogtreecommitdiff
path: root/src/event/quic/ngx_event_quic_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/event/quic/ngx_event_quic_output.c')
-rw-r--r--src/event/quic/ngx_event_quic_output.c65
1 files changed, 55 insertions, 10 deletions
diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c
index 338451e8b..1497b7831 100644
--- a/src/event/quic/ngx_event_quic_output.c
+++ b/src/event/quic/ngx_event_quic_output.c
@@ -844,7 +844,7 @@ ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
ngx_int_t
ngx_quic_send_cc(ngx_connection_t *c)
{
- ngx_quic_frame_t frame;
+ ngx_quic_frame_t *frame;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
@@ -860,22 +860,27 @@ ngx_quic_send_cc(ngx_connection_t *c)
return NGX_OK;
}
- ngx_memzero(&frame, sizeof(ngx_quic_frame_t));
+ frame = ngx_quic_alloc_frame(c);
+ if (frame == NULL) {
+ return NGX_ERROR;
+ }
- frame.level = qc->error_level;
- frame.type = qc->error_app ? NGX_QUIC_FT_CONNECTION_CLOSE_APP
- : NGX_QUIC_FT_CONNECTION_CLOSE;
- frame.u.close.error_code = qc->error;
- frame.u.close.frame_type = qc->error_ftype;
+ frame->level = qc->error_level;
+ frame->type = qc->error_app ? NGX_QUIC_FT_CONNECTION_CLOSE_APP
+ : NGX_QUIC_FT_CONNECTION_CLOSE;
+ frame->u.close.error_code = qc->error;
+ frame->u.close.frame_type = qc->error_ftype;
if (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.len = ngx_strlen(qc->error_reason);
+ frame->u.close.reason.data = (u_char *) qc->error_reason;
}
+ frame->ignore_congestion = 1;
+
qc->last_cc = ngx_current_msec;
- return ngx_quic_frame_sendto(c, &frame, 0, qc->path);
+ return ngx_quic_frame_sendto(c, frame, 0, qc->path);
}
@@ -1184,22 +1189,32 @@ ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame,
size_t max, max_payload, min_payload, pad;
ssize_t len, sent;
ngx_str_t res;
+ ngx_msec_t now;
ngx_quic_header_t pkt;
ngx_quic_send_ctx_t *ctx;
+ ngx_quic_congestion_t *cg;
ngx_quic_connection_t *qc;
static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
qc = ngx_quic_get_connection(c);
+ cg = &qc->congestion;
ctx = ngx_quic_get_send_ctx(qc, frame->level);
+ now = ngx_current_msec;
+
max = ngx_quic_path_limit(c, path, path->mtu);
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic sendto %s packet max:%uz min:%uz",
ngx_quic_level_name(ctx->level), max, min);
+ if (cg->in_flight >= cg->window && !frame->ignore_congestion) {
+ ngx_quic_free_frame(c, frame);
+ return NGX_AGAIN;
+ }
+
ngx_quic_init_packet(c, ctx, &pkt, path);
min_payload = ngx_quic_payload_size(&pkt, min);
@@ -1210,6 +1225,7 @@ ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame,
min_payload = ngx_max(min_payload, pad);
if (min_payload > max_payload) {
+ ngx_quic_free_frame(c, frame);
return NGX_AGAIN;
}
@@ -1221,11 +1237,13 @@ ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame,
len = ngx_quic_create_frame(NULL, frame);
if ((size_t) len > max_payload) {
+ ngx_quic_free_frame(c, frame);
return NGX_AGAIN;
}
len = ngx_quic_create_frame(src, frame);
if (len == -1) {
+ ngx_quic_free_frame(c, frame);
return NGX_ERROR;
}
@@ -1242,18 +1260,45 @@ ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame,
ngx_quic_log_packet(c->log, &pkt);
if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
+ ngx_quic_free_frame(c, frame);
return NGX_ERROR;
}
+ frame->pnum = ctx->pnum;
+ frame->first = now;
+ frame->last = now;
+ frame->plen = res.len;
+
ctx->pnum++;
sent = ngx_quic_send(c, res.data, res.len, path->sockaddr, path->socklen);
if (sent < 0) {
+ ngx_quic_free_frame(c, frame);
return sent;
}
path->sent += sent;
+ if (frame->need_ack && !qc->closing) {
+ ngx_queue_insert_tail(&ctx->sent, &frame->queue);
+
+ cg->in_flight += frame->plen;
+
+ } else {
+ ngx_quic_free_frame(c, frame);
+ return NGX_OK;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "quic congestion send if:%uz", cg->in_flight);
+
+ if (!qc->send_timer_set) {
+ qc->send_timer_set = 1;
+ ngx_add_timer(c->read, qc->tp.max_idle_timeout);
+ }
+
+ ngx_quic_set_lost_timer(c);
+
return NGX_OK;
}