aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/event/ngx_event_quic.c107
-rw-r--r--src/event/ngx_event_quic.h2
-rw-r--r--src/http/v3/ngx_http_v3_streams.c28
3 files changed, 111 insertions, 26 deletions
diff --git a/src/event/ngx_event_quic.c b/src/event/ngx_event_quic.c
index 9a8c94243..9cf25568c 100644
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -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;
+
+ 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);
+
+ 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;
- qc->streams.id_counter++;
+ 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, 0);
+ sn = ngx_quic_create_stream(qs->parent, id, rcvbuf_size);
if (sn == NULL) {
return NULL;
}
diff --git a/src/event/ngx_event_quic.h b/src/event/ngx_event_quic.h
index a56ead272..2d43defef 100644
--- a/src/event/ngx_event_quic.h
+++ b/src/event/ngx_event_quic.h
@@ -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);
diff --git a/src/http/v3/ngx_http_v3_streams.c b/src/http/v3/ngx_http_v3_streams.c
index 63b88f259..2ac3f7d74 100644
--- a/src/http/v3/ngx_http_v3_streams.c
+++ b/src/http/v3/ngx_http_v3_streams.c
@@ -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;
}