comparison src/event/ngx_event_quic.c @ 8314:de8981bf2dd5 quic

Advertizing MAX_STREAMS (0x12) credit in advance. This makes sending large number of bidirectional stream work within ngtcp2, which doesn't bother sending optional STREAMS_BLOCKED when exhausted. This also introduces tracking currently opened and maximum allowed streams.
author Sergey Kandaurov <pluknet@nginx.com>
date Fri, 03 Apr 2020 13:49:44 +0300
parents 053fa468b044
children fdda518d10ba
comparison
equal deleted inserted replaced
8313:c625bde6cb77 8314:de8981bf2dd5
20 ((level) == ssl_encryption_initial) ? 0 \ 20 ((level) == ssl_encryption_initial) ? 0 \
21 : (((level) == ssl_encryption_handshake) ? 1 : 2) 21 : (((level) == ssl_encryption_handshake) ? 1 : 2)
22 22
23 #define NGX_QUIC_NAMESPACE_LAST (NGX_QUIC_ENCRYPTION_LAST - 1) 23 #define NGX_QUIC_NAMESPACE_LAST (NGX_QUIC_ENCRYPTION_LAST - 1)
24 24
25 #define NGX_QUIC_STREAMS_INC 16
26 #define NGX_QUIC_STREAMS_LIMIT (1ULL < 60)
27
25 28
26 typedef enum { 29 typedef enum {
27 NGX_QUIC_ST_INITIAL, /* connection just created */ 30 NGX_QUIC_ST_INITIAL, /* connection just created */
28 NGX_QUIC_ST_HANDSHAKE, /* handshake started */ 31 NGX_QUIC_ST_HANDSHAKE, /* handshake started */
29 NGX_QUIC_ST_EARLY_DATA, /* handshake in progress */ 32 NGX_QUIC_ST_EARLY_DATA, /* handshake in progress */
77 ngx_uint_t nframes; 80 ngx_uint_t nframes;
78 #endif 81 #endif
79 82
80 ngx_quic_streams_t streams; 83 ngx_quic_streams_t streams;
81 ngx_uint_t max_data; 84 ngx_uint_t max_data;
85
86 uint64_t cur_streams;
87 uint64_t max_streams;
82 88
83 unsigned send_timer_set:1; 89 unsigned send_timer_set:1;
84 unsigned closing:1; 90 unsigned closing:1;
85 }; 91 };
86 92
128 ngx_quic_header_t *pkt, ngx_quic_ack_frame_t *f); 134 ngx_quic_header_t *pkt, ngx_quic_ack_frame_t *f);
129 static ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c, 135 static ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c,
130 ngx_quic_header_t *pkt, ngx_quic_crypto_frame_t *frame); 136 ngx_quic_header_t *pkt, ngx_quic_crypto_frame_t *frame);
131 static ngx_int_t ngx_quic_handle_stream_frame(ngx_connection_t *c, 137 static ngx_int_t ngx_quic_handle_stream_frame(ngx_connection_t *c,
132 ngx_quic_header_t *pkt, ngx_quic_stream_frame_t *frame); 138 ngx_quic_header_t *pkt, ngx_quic_stream_frame_t *frame);
139 static ngx_int_t ngx_quic_handle_max_streams(ngx_connection_t *c);
133 static ngx_int_t ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c, 140 static ngx_int_t ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c,
134 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f); 141 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f);
135 static ngx_int_t ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c, 142 static ngx_int_t ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c,
136 ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f); 143 ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f);
137 144
580 ngx_log_error(NGX_LOG_INFO, c->log, 0, 587 ngx_log_error(NGX_LOG_INFO, c->log, 0,
581 "SSL_set_quic_transport_params() failed"); 588 "SSL_set_quic_transport_params() failed");
582 return NGX_ERROR; 589 return NGX_ERROR;
583 } 590 }
584 591
592 qc->max_streams = qc->tp.initial_max_streams_bidi;
585 qc->state = NGX_QUIC_ST_HANDSHAKE; 593 qc->state = NGX_QUIC_ST_HANDSHAKE;
586 594
587 n = SSL_do_handshake(ssl_conn); 595 n = SSL_do_handshake(ssl_conn);
588 596
589 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); 597 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
1398 1406
1399 if (f->fin) { 1407 if (f->fin) {
1400 rev->pending_eof = 1; 1408 rev->pending_eof = 1;
1401 } 1409 }
1402 1410
1411 if ((f->stream_id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0) {
1412 ngx_quic_handle_max_streams(c);
1413 }
1414
1403 qc->streams.handler(sn->c); 1415 qc->streams.handler(sn->c);
1416
1417 return NGX_OK;
1418 }
1419
1420
1421 static ngx_int_t
1422 ngx_quic_handle_max_streams(ngx_connection_t *c)
1423 {
1424 ngx_quic_frame_t *frame;
1425 ngx_quic_connection_t *qc;
1426
1427 qc = c->quic;
1428 qc->cur_streams++;
1429
1430 if (qc->cur_streams + NGX_QUIC_STREAMS_INC / 2 < qc->max_streams) {
1431 return NGX_OK;
1432 }
1433
1434 frame = ngx_quic_alloc_frame(c, 0);
1435 if (frame == NULL) {
1436 return NGX_ERROR;
1437 }
1438
1439 qc->max_streams = ngx_max(qc->max_streams + NGX_QUIC_STREAMS_INC,
1440 NGX_QUIC_STREAMS_LIMIT);
1441
1442 frame->level = ssl_encryption_application;
1443 frame->type = NGX_QUIC_FT_MAX_STREAMS;
1444 frame->u.max_streams.limit = qc->max_streams;
1445 frame->u.max_streams.bidi = 1;
1446
1447 ngx_sprintf(frame->info, "MAX_STREAMS limit:%d bidi:%d level=%d",
1448 (int) frame->u.max_streams.limit,
1449 (int) frame->u.max_streams.bidi,
1450 frame->level);
1451
1452 ngx_quic_queue_frame(qc, frame);
1404 1453
1405 return NGX_OK; 1454 return NGX_OK;
1406 } 1455 }
1407 1456
1408 1457
1417 return NGX_ERROR; 1466 return NGX_ERROR;
1418 } 1467 }
1419 1468
1420 frame->level = pkt->level; 1469 frame->level = pkt->level;
1421 frame->type = NGX_QUIC_FT_MAX_STREAMS; 1470 frame->type = NGX_QUIC_FT_MAX_STREAMS;
1422 frame->u.max_streams.limit = f->limit * 2; 1471 frame->u.max_streams.limit = ngx_max(f->limit * 2, NGX_QUIC_STREAMS_LIMIT);
1423 frame->u.max_streams.bidi = f->bidi; 1472 frame->u.max_streams.bidi = f->bidi;
1473
1474 c->quic->max_streams = frame->u.max_streams.limit;
1424 1475
1425 ngx_sprintf(frame->info, "MAX_STREAMS limit:%d bidi:%d level=%d", 1476 ngx_sprintf(frame->info, "MAX_STREAMS limit:%d bidi:%d level=%d",
1426 (int) frame->u.max_streams.limit, 1477 (int) frame->u.max_streams.limit,
1427 (int) frame->u.max_streams.bidi, 1478 (int) frame->u.max_streams.bidi,
1428 frame->level); 1479 frame->level);