QUIC: limited the number of server-initiated streams.
Also, ngx_quic_create_uni_stream() is replaced with ngx_quic_open_stream() which is capable of creating a bidi stream.
This commit is contained in:
parent
da55aaa1f3
commit
d6157edc80
3 changed files with 111 additions and 26 deletions
|
@ -39,12 +39,15 @@ typedef struct {
|
|||
ngx_rbtree_t tree;
|
||||
ngx_rbtree_node_t sentinel;
|
||||
|
||||
ngx_uint_t id_counter;
|
||||
|
||||
uint64_t received;
|
||||
uint64_t sent;
|
||||
uint64_t recv_max_data;
|
||||
uint64_t send_max_data;
|
||||
|
||||
uint64_t server_max_streams_uni;
|
||||
uint64_t server_max_streams_bidi;
|
||||
uint64_t server_streams_uni;
|
||||
uint64_t server_streams_bidi;
|
||||
} ngx_quic_streams_t;
|
||||
|
||||
|
||||
|
@ -243,6 +246,8 @@ static ngx_int_t ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
|
|||
ngx_quic_header_t *pkt, ngx_quic_reset_stream_frame_t *f);
|
||||
static ngx_int_t ngx_quic_handle_stop_sending_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_stop_sending_frame_t *f);
|
||||
static ngx_int_t ngx_quic_handle_max_streams_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f);
|
||||
|
||||
static void ngx_quic_queue_frame(ngx_quic_connection_t *qc,
|
||||
ngx_quic_frame_t *frame);
|
||||
|
@ -494,6 +499,9 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
|
|||
}
|
||||
#endif
|
||||
|
||||
qc->streams.server_max_streams_bidi = qc->ctp.initial_max_streams_bidi;
|
||||
qc->streams.server_max_streams_uni = qc->ctp.initial_max_streams_uni;
|
||||
|
||||
qc->client_tp_done = 1;
|
||||
}
|
||||
|
||||
|
@ -2100,6 +2108,17 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||
|
||||
break;
|
||||
|
||||
case NGX_QUIC_FT_MAX_STREAMS:
|
||||
case NGX_QUIC_FT_MAX_STREAMS2:
|
||||
|
||||
if (ngx_quic_handle_max_streams_frame(c, pkt, &frame.u.max_streams)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NGX_QUIC_FT_NEW_CONNECTION_ID:
|
||||
case NGX_QUIC_FT_RETIRE_CONNECTION_ID:
|
||||
case NGX_QUIC_FT_PATH_CHALLENGE:
|
||||
|
@ -3273,6 +3292,35 @@ ngx_quic_handle_stop_sending_frame(ngx_connection_t *c,
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_handle_max_streams_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f)
|
||||
{
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qc = c->quic;
|
||||
|
||||
if (f->bidi) {
|
||||
if (qc->streams.server_max_streams_bidi < f->limit) {
|
||||
qc->streams.server_max_streams_bidi = f->limit;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic max_streams_bidi:%uL", f->limit);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (qc->streams.server_max_streams_uni < f->limit) {
|
||||
qc->streams.server_max_streams_uni = f->limit;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic max_streams_uni:%uL", f->limit);
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame)
|
||||
{
|
||||
|
@ -3750,26 +3798,61 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_uint_t ack)
|
|||
|
||||
|
||||
ngx_connection_t *
|
||||
ngx_quic_create_uni_stream(ngx_connection_t *c)
|
||||
ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi)
|
||||
{
|
||||
ngx_uint_t id;
|
||||
size_t rcvbuf_size;
|
||||
uint64_t id;
|
||||
ngx_quic_stream_t *qs, *sn;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qs = c->qs;
|
||||
qc = qs->parent->quic;
|
||||
|
||||
id = (qc->streams.id_counter << 2)
|
||||
| NGX_QUIC_STREAM_SERVER_INITIATED
|
||||
| NGX_QUIC_STREAM_UNIDIRECTIONAL;
|
||||
if (bidi) {
|
||||
if (qc->streams.server_streams_bidi
|
||||
>= qc->streams.server_max_streams_bidi)
|
||||
{
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic too many server bidi streams: %uL",
|
||||
qc->streams.server_streams_bidi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic creating server uni stream #%ui id %ui",
|
||||
qc->streams.id_counter, id);
|
||||
id = (qc->streams.server_streams_bidi << 2)
|
||||
| NGX_QUIC_STREAM_SERVER_INITIATED;
|
||||
|
||||
qc->streams.id_counter++;
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic creating server bidi stream %uL/%uL id:%uL",
|
||||
qc->streams.server_streams_bidi,
|
||||
qc->streams.server_max_streams_bidi, id);
|
||||
|
||||
sn = ngx_quic_create_stream(qs->parent, id, 0);
|
||||
qc->streams.server_streams_bidi++;
|
||||
rcvbuf_size = qc->tp.initial_max_stream_data_bidi_local;
|
||||
|
||||
} else {
|
||||
if (qc->streams.server_streams_uni
|
||||
>= qc->streams.server_max_streams_uni)
|
||||
{
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic too many server uni streams: %uL",
|
||||
qc->streams.server_streams_uni);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
id = (qc->streams.server_streams_uni << 2)
|
||||
| NGX_QUIC_STREAM_SERVER_INITIATED
|
||||
| NGX_QUIC_STREAM_UNIDIRECTIONAL;
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic creating server uni stream %uL/%uL id:%uL",
|
||||
qc->streams.server_streams_uni,
|
||||
qc->streams.server_max_streams_uni, id);
|
||||
|
||||
qc->streams.server_streams_uni++;
|
||||
rcvbuf_size = 0;
|
||||
}
|
||||
|
||||
sn = ngx_quic_create_stream(qs->parent, id, rcvbuf_size);
|
||||
if (sn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ struct ngx_quic_stream_s {
|
|||
|
||||
|
||||
void ngx_quic_run(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_quic_conf_t *conf);
|
||||
ngx_connection_t *ngx_quic_create_uni_stream(ngx_connection_t *c);
|
||||
ngx_connection_t *ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi);
|
||||
void ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err,
|
||||
const char *reason);
|
||||
|
||||
|
|
|
@ -55,16 +55,8 @@ ngx_http_v3_init_connection(ngx_connection_t *c)
|
|||
return NGX_OK;
|
||||
}
|
||||
|
||||
h3c = c->qs->parent->data;
|
||||
|
||||
if (!h3c->settings_sent) {
|
||||
h3c->settings_sent = 1;
|
||||
|
||||
if (ngx_http_v3_send_settings(c) != NGX_OK) {
|
||||
ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
|
||||
"could not send settings");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
if (ngx_http_v3_send_settings(c) == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if ((c->qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0) {
|
||||
|
@ -361,7 +353,7 @@ ngx_http_v3_get_uni_stream(ngx_connection_t *c, ngx_uint_t type)
|
|||
}
|
||||
}
|
||||
|
||||
sc = ngx_quic_create_uni_stream(c);
|
||||
sc = ngx_quic_open_stream(c, 0);
|
||||
if (sc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -410,14 +402,19 @@ ngx_http_v3_send_settings(ngx_connection_t *c)
|
|||
ngx_http_v3_srv_conf_t *h3scf;
|
||||
ngx_http_v3_connection_t *h3c;
|
||||
|
||||
h3c = c->qs->parent->data;
|
||||
|
||||
if (h3c->settings_sent) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 send settings");
|
||||
|
||||
cc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL);
|
||||
if (cc == NULL) {
|
||||
return NGX_ERROR;
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
h3c = c->qs->parent->data;
|
||||
h3scf = ngx_http_get_module_srv_conf(h3c->hc.conf_ctx, ngx_http_v3_module);
|
||||
|
||||
n = ngx_http_v3_encode_varlen_int(NULL,
|
||||
|
@ -441,12 +438,17 @@ ngx_http_v3_send_settings(ngx_connection_t *c)
|
|||
goto failed;
|
||||
}
|
||||
|
||||
h3c->settings_sent = 1;
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
failed:
|
||||
|
||||
ngx_http_v3_close_uni_stream(cc);
|
||||
|
||||
ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
|
||||
"could not send settings");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue