comparison src/event/quic/ngx_event_quic.c @ 8724:fc64ab301bad quic

QUIC: connection shutdown. The function ngx_quic_shutdown_connection() waits until all non-cancelable streams are closed, and then closes the connection. In HTTP/3 cancelable streams are all unidirectional streams except push streams. The function is called from HTTP/3 when client reaches keepalive_requests.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 15 Mar 2021 16:39:33 +0300
parents 0a0b1de9ccab
children 90ae21799f67
comparison
equal deleted inserted replaced
8723:265062a99043 8724:fc64ab301bad
172 ngx_uint_t error; 172 ngx_uint_t error;
173 enum ssl_encryption_level_t error_level; 173 enum ssl_encryption_level_t error_level;
174 ngx_uint_t error_ftype; 174 ngx_uint_t error_ftype;
175 const char *error_reason; 175 const char *error_reason;
176 176
177 ngx_uint_t shutdown_code;
178 const char *shutdown_reason;
179
177 unsigned error_app:1; 180 unsigned error_app:1;
178 unsigned send_timer_set:1; 181 unsigned send_timer_set:1;
179 unsigned closing:1; 182 unsigned closing:1;
183 unsigned shutdown:1;
180 unsigned draining:1; 184 unsigned draining:1;
181 unsigned key_phase:1; 185 unsigned key_phase:1;
182 unsigned validated:1; 186 unsigned validated:1;
183 } ngx_quic_connection_t; 187 } ngx_quic_connection_t;
184 188
382 size_t size); 386 size_t size);
383 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c, 387 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c,
384 ngx_chain_t *in, off_t limit); 388 ngx_chain_t *in, off_t limit);
385 static size_t ngx_quic_max_stream_flow(ngx_connection_t *c); 389 static size_t ngx_quic_max_stream_flow(ngx_connection_t *c);
386 static void ngx_quic_stream_cleanup_handler(void *data); 390 static void ngx_quic_stream_cleanup_handler(void *data);
391 static void ngx_quic_shutdown_quic(ngx_connection_t *c);
387 static ngx_quic_frame_t *ngx_quic_alloc_frame(ngx_connection_t *c); 392 static ngx_quic_frame_t *ngx_quic_alloc_frame(ngx_connection_t *c);
388 static void ngx_quic_free_frame(ngx_connection_t *c, ngx_quic_frame_t *frame); 393 static void ngx_quic_free_frame(ngx_connection_t *c, ngx_quic_frame_t *frame);
389 394
390 static void ngx_quic_congestion_ack(ngx_connection_t *c, 395 static void ngx_quic_congestion_ack(ngx_connection_t *c,
391 ngx_quic_frame_t *frame); 396 ngx_quic_frame_t *frame);
682 if (qc->error_reason) { 687 if (qc->error_reason) {
683 p = ngx_slprintf(p, last, " \"%s\"", qc->error_reason); 688 p = ngx_slprintf(p, last, " \"%s\"", qc->error_reason);
684 } 689 }
685 } 690 }
686 691
692 p = ngx_slprintf(p, last, "%s", qc->shutdown ? " shutdown" : "");
687 p = ngx_slprintf(p, last, "%s", qc->closing ? " closing" : ""); 693 p = ngx_slprintf(p, last, "%s", qc->closing ? " closing" : "");
688 p = ngx_slprintf(p, last, "%s", qc->draining ? " draining" : ""); 694 p = ngx_slprintf(p, last, "%s", qc->draining ? " draining" : "");
689 p = ngx_slprintf(p, last, "%s", qc->key_phase ? " kp" : ""); 695 p = ngx_slprintf(p, last, "%s", qc->key_phase ? " kp" : "");
690 p = ngx_slprintf(p, last, "%s", qc->validated? " valid" : ""); 696 p = ngx_slprintf(p, last, "%s", qc->validated? " valid" : "");
691 697
2133 qc->error_reason = reason; 2139 qc->error_reason = reason;
2134 qc->error_app = 1; 2140 qc->error_app = 1;
2135 qc->error_ftype = 0; 2141 qc->error_ftype = 0;
2136 2142
2137 ngx_quic_close_connection(c, NGX_ERROR); 2143 ngx_quic_close_connection(c, NGX_ERROR);
2144 }
2145
2146
2147 void
2148 ngx_quic_shutdown_connection(ngx_connection_t *c, ngx_uint_t err,
2149 const char *reason)
2150 {
2151 ngx_quic_connection_t *qc;
2152
2153 qc = ngx_quic_get_connection(c);
2154 qc->shutdown = 1;
2155 qc->shutdown_code = err;
2156 qc->shutdown_reason = reason;
2157
2158 ngx_quic_shutdown_quic(c);
2138 } 2159 }
2139 2160
2140 2161
2141 static void 2162 static void
2142 ngx_quic_close_timer_handler(ngx_event_t *ev) 2163 ngx_quic_close_timer_handler(ngx_event_t *ev)
5943 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 5964 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5944 "quic stream id:0x%xL is new", id); 5965 "quic stream id:0x%xL is new", id);
5945 5966
5946 qc = ngx_quic_get_connection(c); 5967 qc = ngx_quic_get_connection(c);
5947 5968
5969 if (qc->shutdown) {
5970 return NGX_QUIC_STREAM_GONE;
5971 }
5972
5948 if (id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { 5973 if (id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
5949 5974
5950 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) { 5975 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) {
5951 if ((id >> 2) < qc->streams.server_streams_uni) { 5976 if ((id >> 2) < qc->streams.server_streams_uni) {
5952 return NGX_QUIC_STREAM_GONE; 5977 return NGX_QUIC_STREAM_GONE;
6014 if (sn == NULL) { 6039 if (sn == NULL) {
6015 return NULL; 6040 return NULL;
6016 } 6041 }
6017 6042
6018 sn->c->listening->handler(sn->c); 6043 sn->c->listening->handler(sn->c);
6044
6045 if (qc->shutdown) {
6046 return NGX_QUIC_STREAM_GONE;
6047 }
6019 } 6048 }
6020 6049
6021 return ngx_quic_create_stream(c, id, n); 6050 return ngx_quic_create_stream(c, id, n);
6022 } 6051 }
6023 6052
6408 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0) 6437 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0)
6409 { 6438 {
6410 if (!c->read->pending_eof && !c->read->error) { 6439 if (!c->read->pending_eof && !c->read->error) {
6411 frame = ngx_quic_alloc_frame(pc); 6440 frame = ngx_quic_alloc_frame(pc);
6412 if (frame == NULL) { 6441 if (frame == NULL) {
6413 return; 6442 goto done;
6414 } 6443 }
6415 6444
6416 frame->level = ssl_encryption_application; 6445 frame->level = ssl_encryption_application;
6417 frame->type = NGX_QUIC_FT_STOP_SENDING; 6446 frame->type = NGX_QUIC_FT_STOP_SENDING;
6418 frame->u.stop_sending.id = qs->id; 6447 frame->u.stop_sending.id = qs->id;
6423 } 6452 }
6424 6453
6425 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) { 6454 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) {
6426 frame = ngx_quic_alloc_frame(pc); 6455 frame = ngx_quic_alloc_frame(pc);
6427 if (frame == NULL) { 6456 if (frame == NULL) {
6428 return; 6457 goto done;
6429 } 6458 }
6430 6459
6431 frame->level = ssl_encryption_application; 6460 frame->level = ssl_encryption_application;
6432 frame->type = NGX_QUIC_FT_MAX_STREAMS; 6461 frame->type = NGX_QUIC_FT_MAX_STREAMS;
6433 6462
6442 6471
6443 ngx_quic_queue_frame(qc, frame); 6472 ngx_quic_queue_frame(qc, frame);
6444 6473
6445 if (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { 6474 if (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
6446 /* do not send fin for client unidirectional streams */ 6475 /* do not send fin for client unidirectional streams */
6447 return; 6476 goto done;
6448 } 6477 }
6449 } 6478 }
6450 6479
6451 if (c->write->error) { 6480 if (c->write->error) {
6452 goto error; 6481 goto done;
6453 } 6482 }
6454 6483
6455 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 6484 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6456 "quic stream id:0x%xL send fin", qs->id); 6485 "quic stream id:0x%xL send fin", qs->id);
6457 6486
6458 frame = ngx_quic_alloc_frame(pc); 6487 frame = ngx_quic_alloc_frame(pc);
6459 if (frame == NULL) { 6488 if (frame == NULL) {
6460 return; 6489 goto done;
6461 } 6490 }
6462 6491
6463 frame->level = ssl_encryption_application; 6492 frame->level = ssl_encryption_application;
6464 frame->type = NGX_QUIC_FT_STREAM7; /* OFF=1 LEN=1 FIN=1 */ 6493 frame->type = NGX_QUIC_FT_STREAM7; /* OFF=1 LEN=1 FIN=1 */
6465 frame->u.stream.off = 1; 6494 frame->u.stream.off = 1;
6471 frame->u.stream.offset = c->sent; 6500 frame->u.stream.offset = c->sent;
6472 frame->u.stream.length = 0; 6501 frame->u.stream.length = 0;
6473 6502
6474 ngx_quic_queue_frame(qc, frame); 6503 ngx_quic_queue_frame(qc, frame);
6475 6504
6476 error: 6505 done:
6477 6506
6478 (void) ngx_quic_output(pc); 6507 (void) ngx_quic_output(pc);
6508
6509 if (qc->shutdown) {
6510 ngx_quic_shutdown_quic(pc);
6511 }
6512 }
6513
6514
6515 static void
6516 ngx_quic_shutdown_quic(ngx_connection_t *c)
6517 {
6518 ngx_rbtree_t *tree;
6519 ngx_rbtree_node_t *node;
6520 ngx_quic_stream_t *qs;
6521 ngx_quic_connection_t *qc;
6522
6523 qc = ngx_quic_get_connection(c);
6524
6525 if (qc->closing) {
6526 return;
6527 }
6528
6529 tree = &qc->streams.tree;
6530
6531 if (tree->root != tree->sentinel) {
6532 for (node = ngx_rbtree_min(tree->root, tree->sentinel);
6533 node;
6534 node = ngx_rbtree_next(tree, node))
6535 {
6536 qs = (ngx_quic_stream_t *) node;
6537
6538 if (!qs->cancelable) {
6539 return;
6540 }
6541 }
6542 }
6543
6544 ngx_quic_finalize_connection(c, qc->shutdown_code, qc->shutdown_reason);
6479 } 6545 }
6480 6546
6481 6547
6482 static ngx_quic_frame_t * 6548 static ngx_quic_frame_t *
6483 ngx_quic_alloc_frame(ngx_connection_t *c) 6549 ngx_quic_alloc_frame(ngx_connection_t *c)