comparison src/event/quic/ngx_event_quic_streams.c @ 8908:e8cbbfabe547 quic

QUIC: update stream flow control credit on STREAM_DATA_BLOCKED. Previously, after receiving STREAM_DATA_BLOCKED, current flow control limit was sent to client. Now, if the limit can be updated to the full window size, it is updated and the new value is sent to client, otherwise nothing is sent. The change lets client update flow control credit on demand. Also, it saves traffic by not sending MAX_STREAM_DATA with the same value twice.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 17 Nov 2021 23:07:38 +0300
parents 41caf5410110
children d041b8d6ab0b
comparison
equal deleted inserted replaced
8907:122bfa14465b 8908:e8cbbfabe547
29 ngx_chain_t *in, off_t limit); 29 ngx_chain_t *in, off_t limit);
30 static size_t ngx_quic_max_stream_flow(ngx_connection_t *c); 30 static size_t ngx_quic_max_stream_flow(ngx_connection_t *c);
31 static void ngx_quic_stream_cleanup_handler(void *data); 31 static void ngx_quic_stream_cleanup_handler(void *data);
32 static ngx_int_t ngx_quic_control_flow(ngx_connection_t *c, uint64_t last); 32 static ngx_int_t ngx_quic_control_flow(ngx_connection_t *c, uint64_t last);
33 static ngx_int_t ngx_quic_update_flow(ngx_connection_t *c, uint64_t last); 33 static ngx_int_t ngx_quic_update_flow(ngx_connection_t *c, uint64_t last);
34 static ngx_int_t ngx_quic_update_max_stream_data(ngx_connection_t *c);
34 35
35 36
36 ngx_connection_t * 37 ngx_connection_t *
37 ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi) 38 ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi)
38 { 39 {
1188 1189
1189 ngx_int_t 1190 ngx_int_t
1190 ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c, 1191 ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c,
1191 ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f) 1192 ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f)
1192 { 1193 {
1193 uint64_t limit;
1194 ngx_quic_frame_t *frame;
1195 ngx_quic_stream_t *qs; 1194 ngx_quic_stream_t *qs;
1196 ngx_quic_connection_t *qc; 1195 ngx_quic_connection_t *qc;
1197 1196
1198 qc = ngx_quic_get_connection(c); 1197 qc = ngx_quic_get_connection(c);
1199 1198
1215 1214
1216 if (qs == NGX_QUIC_STREAM_GONE) { 1215 if (qs == NGX_QUIC_STREAM_GONE) {
1217 return NGX_OK; 1216 return NGX_OK;
1218 } 1217 }
1219 1218
1220 limit = qs->recv_max_data; 1219 return ngx_quic_init_stream(qs);
1221 1220 }
1222 if (ngx_quic_init_stream(qs) != NGX_OK) { 1221
1223 return NGX_ERROR; 1222 return ngx_quic_update_max_stream_data(qs->connection);
1224 }
1225
1226 } else {
1227 limit = qs->recv_max_data;
1228 }
1229
1230 frame = ngx_quic_alloc_frame(c);
1231 if (frame == NULL) {
1232 return NGX_ERROR;
1233 }
1234
1235 frame->level = pkt->level;
1236 frame->type = NGX_QUIC_FT_MAX_STREAM_DATA;
1237 frame->u.max_stream_data.id = f->id;
1238 frame->u.max_stream_data.limit = limit;
1239
1240 ngx_quic_queue_frame(qc, frame);
1241
1242 return NGX_OK;
1243 } 1223 }
1244 1224
1245 1225
1246 ngx_int_t 1226 ngx_int_t
1247 ngx_quic_handle_max_stream_data_frame(ngx_connection_t *c, 1227 ngx_quic_handle_max_stream_data_frame(ngx_connection_t *c,
1585 qs->recv_offset += len; 1565 qs->recv_offset += len;
1586 1566
1587 if (!rev->pending_eof && !rev->error 1567 if (!rev->pending_eof && !rev->error
1588 && qs->recv_max_data <= qs->recv_offset + qs->recv_window / 2) 1568 && qs->recv_max_data <= qs->recv_offset + qs->recv_window / 2)
1589 { 1569 {
1590 qs->recv_max_data = qs->recv_offset + qs->recv_window; 1570 if (ngx_quic_update_max_stream_data(c) != NGX_OK) {
1591
1592 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1593 "quic flow update msd:%uL", qs->recv_max_data);
1594
1595 frame = ngx_quic_alloc_frame(pc);
1596 if (frame == NULL) {
1597 return NGX_ERROR; 1571 return NGX_ERROR;
1598 } 1572 }
1599
1600 frame->level = ssl_encryption_application;
1601 frame->type = NGX_QUIC_FT_MAX_STREAM_DATA;
1602 frame->u.max_stream_data.id = qs->id;
1603 frame->u.max_stream_data.limit = qs->recv_max_data;
1604
1605 ngx_quic_queue_frame(qc, frame);
1606 } 1573 }
1607 1574
1608 qc->streams.recv_offset += len; 1575 qc->streams.recv_offset += len;
1609 1576
1610 if (qc->streams.recv_max_data 1577 if (qc->streams.recv_max_data
1630 1597
1631 return NGX_OK; 1598 return NGX_OK;
1632 } 1599 }
1633 1600
1634 1601
1602 static ngx_int_t
1603 ngx_quic_update_max_stream_data(ngx_connection_t *c)
1604 {
1605 uint64_t recv_max_data;
1606 ngx_connection_t *pc;
1607 ngx_quic_frame_t *frame;
1608 ngx_quic_stream_t *qs;
1609 ngx_quic_connection_t *qc;
1610
1611 qs = c->quic;
1612 pc = qs->parent;
1613 qc = ngx_quic_get_connection(pc);
1614
1615 recv_max_data = qs->recv_offset + qs->recv_window;
1616
1617 if (qs->recv_max_data == recv_max_data) {
1618 return NGX_OK;
1619 }
1620
1621 qs->recv_max_data = recv_max_data;
1622
1623 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1624 "quic flow update msd:%uL", qs->recv_max_data);
1625
1626 frame = ngx_quic_alloc_frame(pc);
1627 if (frame == NULL) {
1628 return NGX_ERROR;
1629 }
1630
1631 frame->level = ssl_encryption_application;
1632 frame->type = NGX_QUIC_FT_MAX_STREAM_DATA;
1633 frame->u.max_stream_data.id = qs->id;
1634 frame->u.max_stream_data.limit = qs->recv_max_data;
1635
1636 ngx_quic_queue_frame(qc, frame);
1637
1638 return NGX_OK;
1639 }
1640
1641
1635 ngx_int_t 1642 ngx_int_t
1636 ngx_quic_handle_read_event(ngx_event_t *rev, ngx_uint_t flags) 1643 ngx_quic_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)
1637 { 1644 {
1638 if (!rev->active && !rev->ready) { 1645 if (!rev->active && !rev->ready) {
1639 rev->active = 1; 1646 rev->active = 1;