comparison src/event/quic/ngx_event_quic_streams.c @ 9052:2e51cf3ffd90 quic

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.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 22 Aug 2022 15:33:23 +0400
parents 37d5dddabaea
children 740d7d6e8ff0
comparison
equal deleted inserted replaced
9051:37d5dddabaea 9052:2e51cf3ffd90
885 return NGX_CHAIN_ERROR; 885 return NGX_CHAIN_ERROR;
886 } 886 }
887 887
888 qs->send_state = NGX_QUIC_STREAM_SEND_SEND; 888 qs->send_state = NGX_QUIC_STREAM_SEND_SEND;
889 889
890 flow = qs->acked + qc->conf->stream_buffer_size - c->sent; 890 flow = qs->acked + qc->conf->stream_buffer_size - qs->sent;
891 891
892 if (flow == 0) { 892 if (flow == 0) {
893 wev->ready = 0; 893 wev->ready = 0;
894 return in; 894 return in;
895 } 895 }
898 limit = flow; 898 limit = flow;
899 } 899 }
900 900
901 n = qs->send.size; 901 n = qs->send.size;
902 902
903 in = ngx_quic_write_buffer(pc, &qs->send, in, limit, c->sent); 903 in = ngx_quic_write_buffer(pc, &qs->send, in, limit, qs->sent);
904 if (in == NGX_CHAIN_ERROR) { 904 if (in == NGX_CHAIN_ERROR) {
905 return NGX_CHAIN_ERROR; 905 return NGX_CHAIN_ERROR;
906 } 906 }
907 907
908 n = qs->send.size - n; 908 n = qs->send.size - n;
909 c->sent += n; 909 c->sent += n;
910 qs->sent += n;
910 qc->streams.sent += n; 911 qc->streams.sent += n;
911 912
912 if (flow == n) { 913 if (flow == n) {
913 wev->ready = 0; 914 wev->ready = 0;
914 } 915 }
1043 qc = ngx_quic_get_connection(pc); 1044 qc = ngx_quic_get_connection(pc);
1044 1045
1045 if (!qc->closing) { 1046 if (!qc->closing) {
1046 /* make sure everything is sent and final size is received */ 1047 /* make sure everything is sent and final size is received */
1047 1048
1048 if (qs->recv_state == NGX_QUIC_STREAM_RECV_RECV 1049 if (qs->recv_state == NGX_QUIC_STREAM_RECV_RECV) {
1049 || qs->send_state == NGX_QUIC_STREAM_SEND_READY 1050 return NGX_OK;
1050 || qs->send_state == NGX_QUIC_STREAM_SEND_SEND) 1051 }
1052
1053 if (qs->send_state != NGX_QUIC_STREAM_SEND_DATA_RECVD
1054 && qs->send_state != NGX_QUIC_STREAM_SEND_RESET_RECVD)
1051 { 1055 {
1052 return NGX_OK; 1056 return NGX_OK;
1053 } 1057 }
1054 } 1058 }
1055 1059
1486 1490
1487 1491
1488 void 1492 void
1489 ngx_quic_handle_stream_ack(ngx_connection_t *c, ngx_quic_frame_t *f) 1493 ngx_quic_handle_stream_ack(ngx_connection_t *c, ngx_quic_frame_t *f)
1490 { 1494 {
1491 uint64_t sent, unacked; 1495 uint64_t acked;
1492 ngx_quic_stream_t *qs; 1496 ngx_quic_stream_t *qs;
1493 ngx_quic_connection_t *qc; 1497 ngx_quic_connection_t *qc;
1494 1498
1495 qc = ngx_quic_get_connection(c); 1499 qc = ngx_quic_get_connection(c);
1496 1500
1497 qs = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id); 1501 switch (f->type) {
1498 if (qs == NULL) { 1502
1503 case NGX_QUIC_FT_RESET_STREAM:
1504
1505 qs = ngx_quic_find_stream(&qc->streams.tree, f->u.reset_stream.id);
1506 if (qs == NULL) {
1507 return;
1508 }
1509
1510 qs->send_state = NGX_QUIC_STREAM_SEND_RESET_RECVD;
1511
1512 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
1513 "quic stream id:0x%xL ack reset final_size:%uL",
1514 qs->id, f->u.reset_stream.final_size);
1515
1516 break;
1517
1518 case NGX_QUIC_FT_STREAM:
1519
1520 qs = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id);
1521 if (qs == NULL) {
1522 return;
1523 }
1524
1525 acked = qs->acked;
1526 qs->acked += f->u.stream.length;
1527
1528 if (f->u.stream.fin) {
1529 qs->fin_acked = 1;
1530 }
1531
1532 if (qs->send_state == NGX_QUIC_STREAM_SEND_DATA_SENT
1533 && qs->acked == qs->sent && qs->fin_acked)
1534 {
1535 qs->send_state = NGX_QUIC_STREAM_SEND_DATA_RECVD;
1536 }
1537
1538 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
1539 "quic stream id:0x%xL ack len:%uL fin:%d unacked:%uL",
1540 qs->id, f->u.stream.length, f->u.stream.fin,
1541 qs->sent - qs->acked);
1542
1543 if (qs->connection
1544 && qs->sent - acked == qc->conf->stream_buffer_size
1545 && f->u.stream.length > 0)
1546 {
1547 ngx_quic_set_event(qs->connection->write);
1548 }
1549
1550 break;
1551
1552 default:
1499 return; 1553 return;
1500 } 1554 }
1501 1555
1502 if (qs->connection == NULL) { 1556 if (qs->connection == NULL) {
1503 qs->acked += f->u.stream.length; 1557 ngx_quic_close_stream(qs);
1504 return; 1558 }
1505 }
1506
1507 sent = qs->connection->sent;
1508 unacked = sent - qs->acked;
1509 qs->acked += f->u.stream.length;
1510
1511 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
1512 "quic stream id:0x%xL ack len:%uL acked:%uL unacked:%uL",
1513 qs->id, f->u.stream.length, qs->acked, sent - qs->acked);
1514
1515 if (unacked != qc->conf->stream_buffer_size) {
1516 /* not blocked on buffer size */
1517 return;
1518 }
1519
1520 ngx_quic_set_event(qs->connection->write);
1521 } 1559 }
1522 1560
1523 1561
1524 static ngx_int_t 1562 static ngx_int_t
1525 ngx_quic_control_flow(ngx_quic_stream_t *qs, uint64_t last) 1563 ngx_quic_control_flow(ngx_quic_stream_t *qs, uint64_t last)