Mercurial > hg > nginx-quic
comparison src/event/ngx_event_quic.c @ 7991:1b9db5c8c29b quic
QUIC: reworked ngx_quic_send_frames() function.
Instead of returning NGX_DONE/NGX_OK, the function now itself moves
passed frames range into sent queue and sets PTO timer if required.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Wed, 15 Jul 2020 15:10:17 +0300 |
parents | 3b15732ac03f |
children | 909b989ec088 |
comparison
equal
deleted
inserted
replaced
7990:3b15732ac03f | 7991:1b9db5c8c29b |
---|---|
239 | 239 |
240 static ngx_int_t ngx_quic_output(ngx_connection_t *c); | 240 static ngx_int_t ngx_quic_output(ngx_connection_t *c); |
241 static ngx_int_t ngx_quic_output_frames(ngx_connection_t *c, | 241 static ngx_int_t ngx_quic_output_frames(ngx_connection_t *c, |
242 ngx_quic_send_ctx_t *ctx); | 242 ngx_quic_send_ctx_t *ctx); |
243 static void ngx_quic_free_frames(ngx_connection_t *c, ngx_queue_t *frames); | 243 static void ngx_quic_free_frames(ngx_connection_t *c, ngx_queue_t *frames); |
244 static ngx_int_t ngx_quic_send_frames(ngx_connection_t *c, ngx_queue_t *frames); | 244 static ngx_int_t ngx_quic_send_frames(ngx_connection_t *c, |
245 ngx_quic_send_ctx_t *ctx, ngx_queue_t *frames); | |
245 | 246 |
246 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt, | 247 static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt, |
247 ngx_quic_send_ctx_t *ctx); | 248 ngx_quic_send_ctx_t *ctx); |
248 static void ngx_quic_pto_handler(ngx_event_t *ev); | 249 static void ngx_quic_pto_handler(ngx_event_t *ev); |
249 static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c, | 250 static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c, |
3258 if (!qc->send_timer_set && !qc->closing) { | 3259 if (!qc->send_timer_set && !qc->closing) { |
3259 qc->send_timer_set = 1; | 3260 qc->send_timer_set = 1; |
3260 ngx_add_timer(c->read, qc->tp.max_idle_timeout); | 3261 ngx_add_timer(c->read, qc->tp.max_idle_timeout); |
3261 } | 3262 } |
3262 | 3263 |
3263 if (!qc->pto.timer_set && !qc->closing) { | |
3264 ngx_add_timer(&qc->pto, qc->ctp.max_ack_delay + NGX_QUIC_HARDCODED_PTO); | |
3265 } | |
3266 | |
3267 return NGX_OK; | 3264 return NGX_OK; |
3268 } | 3265 } |
3269 | 3266 |
3270 | 3267 |
3271 static ngx_int_t | 3268 static ngx_int_t |
3272 ngx_quic_output_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) | 3269 ngx_quic_output_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) |
3273 { | 3270 { |
3274 size_t len, hlen, n; | 3271 size_t len, hlen, n; |
3275 ngx_int_t rc; | |
3276 ngx_uint_t need_ack; | 3272 ngx_uint_t need_ack; |
3277 ngx_queue_t *q, range; | 3273 ngx_queue_t *q, range; |
3278 ngx_quic_frame_t *f; | 3274 ngx_quic_frame_t *f; |
3279 ngx_quic_congestion_t *cg; | 3275 ngx_quic_congestion_t *cg; |
3280 ngx_quic_connection_t *qc; | 3276 ngx_quic_connection_t *qc; |
3330 | 3326 |
3331 if (ngx_queue_empty(&range)) { | 3327 if (ngx_queue_empty(&range)) { |
3332 break; | 3328 break; |
3333 } | 3329 } |
3334 | 3330 |
3335 rc = ngx_quic_send_frames(c, &range); | 3331 if (ngx_quic_send_frames(c, ctx, &range) != NGX_OK) { |
3336 | |
3337 if (rc == NGX_OK) { | |
3338 /* | |
3339 * frames are moved into the sent queue | |
3340 * to wait for ack/be retransmitted | |
3341 */ | |
3342 if (qc->closing) { | |
3343 /* if we are closing, any ack will be discarded */ | |
3344 ngx_quic_free_frames(c, &range); | |
3345 | |
3346 } else { | |
3347 ngx_queue_add(&ctx->sent, &range); | |
3348 } | |
3349 | |
3350 cg->in_flight += len; | |
3351 | |
3352 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
3353 "quic congestion send if:%uz", cg->in_flight); | |
3354 | |
3355 } else if (rc == NGX_DONE) { | |
3356 | |
3357 /* no ack is expected for this frames, can free them */ | |
3358 ngx_quic_free_frames(c, &range); | |
3359 | |
3360 } else { | |
3361 return NGX_ERROR; | 3332 return NGX_ERROR; |
3362 } | 3333 } |
3363 | 3334 |
3364 } while (q != ngx_queue_sentinel(&ctx->frames)); | 3335 } while (q != ngx_queue_sentinel(&ctx->frames)); |
3365 | 3336 |
3388 } while (1); | 3359 } while (1); |
3389 } | 3360 } |
3390 | 3361 |
3391 | 3362 |
3392 static ngx_int_t | 3363 static ngx_int_t |
3393 ngx_quic_send_frames(ngx_connection_t *c, ngx_queue_t *frames) | 3364 ngx_quic_send_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, |
3365 ngx_queue_t *frames) | |
3394 { | 3366 { |
3395 ssize_t len; | 3367 ssize_t len; |
3396 u_char *p; | 3368 u_char *p; |
3397 ngx_msec_t now; | 3369 ngx_msec_t now; |
3398 ngx_str_t out, res; | 3370 ngx_str_t out, res; |
3399 ngx_queue_t *q; | 3371 ngx_queue_t *q; |
3400 ngx_ssl_conn_t *ssl_conn; | 3372 ngx_ssl_conn_t *ssl_conn; |
3401 ngx_quic_frame_t *f, *start; | 3373 ngx_quic_frame_t *f, *start; |
3402 ngx_quic_header_t pkt; | 3374 ngx_quic_header_t pkt; |
3403 ngx_quic_secrets_t *keys; | 3375 ngx_quic_secrets_t *keys; |
3404 ngx_quic_send_ctx_t *ctx; | |
3405 ngx_quic_connection_t *qc; | 3376 ngx_quic_connection_t *qc; |
3406 static ngx_str_t initial_token = ngx_null_string; | 3377 static ngx_str_t initial_token = ngx_null_string; |
3407 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | 3378 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; |
3408 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | 3379 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; |
3409 | 3380 |
3412 | 3383 |
3413 ssl_conn = c->ssl ? c->ssl->connection : NULL; | 3384 ssl_conn = c->ssl ? c->ssl->connection : NULL; |
3414 | 3385 |
3415 q = ngx_queue_head(frames); | 3386 q = ngx_queue_head(frames); |
3416 start = ngx_queue_data(q, ngx_quic_frame_t, queue); | 3387 start = ngx_queue_data(q, ngx_quic_frame_t, queue); |
3417 | |
3418 ctx = ngx_quic_get_send_ctx(c->quic, start->level); | |
3419 | 3388 |
3420 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); | 3389 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); |
3421 | 3390 |
3422 now = ngx_current_msec; | 3391 now = ngx_current_msec; |
3423 | 3392 |
3505 } | 3474 } |
3506 | 3475 |
3507 /* len == NGX_OK || NGX_AGAIN */ | 3476 /* len == NGX_OK || NGX_AGAIN */ |
3508 ctx->pnum++; | 3477 ctx->pnum++; |
3509 | 3478 |
3510 return pkt.need_ack ? NGX_OK : NGX_DONE; | 3479 if (pkt.need_ack) { |
3480 /* move frames into the sent queue to wait for ack */ | |
3481 | |
3482 if (qc->closing) { | |
3483 /* if we are closing, any ack will be discarded */ | |
3484 ngx_quic_free_frames(c, frames); | |
3485 | |
3486 } else { | |
3487 ngx_queue_add(&ctx->sent, frames); | |
3488 ngx_add_timer(&qc->pto, NGX_QUIC_HARDCODED_PTO); | |
3489 } | |
3490 | |
3491 qc->congestion.in_flight += out.len; | |
3492 | |
3493 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
3494 "quic congestion send if:%uz", | |
3495 qc->congestion.in_flight); | |
3496 } else { | |
3497 /* no ack is expected for this frames, so we can free them */ | |
3498 ngx_quic_free_frames(c, frames); | |
3499 } | |
3500 | |
3501 return NGX_OK; | |
3511 } | 3502 } |
3512 | 3503 |
3513 | 3504 |
3514 static void | 3505 static void |
3515 ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_send_ctx_t *ctx) | 3506 ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_send_ctx_t *ctx) |
3648 | 3639 |
3649 } while (q != ngx_queue_sentinel(&ctx->sent)); | 3640 } while (q != ngx_queue_sentinel(&ctx->sent)); |
3650 | 3641 |
3651 ngx_quic_congestion_lost(c, start->last); | 3642 ngx_quic_congestion_lost(c, start->last); |
3652 | 3643 |
3653 /* NGX_DONE is impossible here, such frames don't get into this queue */ | 3644 if (ngx_quic_send_frames(c, ctx, &range) != NGX_OK) { |
3654 if (ngx_quic_send_frames(c, &range) != NGX_OK) { | |
3655 return NGX_ERROR; | 3645 return NGX_ERROR; |
3656 } | 3646 } |
3657 | |
3658 /* move frames group to the end of queue */ | |
3659 ngx_queue_add(&ctx->sent, &range); | |
3660 | |
3661 wait = qc->ctp.max_ack_delay + NGX_QUIC_HARDCODED_PTO; | |
3662 | 3647 |
3663 } while (q != ngx_queue_sentinel(&ctx->sent)); | 3648 } while (q != ngx_queue_sentinel(&ctx->sent)); |
3664 | 3649 |
3665 *waitp = wait; | 3650 *waitp = wait; |
3666 | 3651 |