diff --git a/auto/cc/msvc b/auto/cc/msvc index 567bac7..fe7c34e 100644 --- a/auto/cc/msvc +++ b/auto/cc/msvc @@ -26,6 +26,10 @@ ngx_msvc_ver=`echo $NGX_MSVC_VER | sed -e 's/^\([0-9]*\).*/\1/'` case "$NGX_MSVC_VER" in + *ARM64) + NGX_MACHINE=arm64 + ;; + *x64) NGX_MACHINE=amd64 ;; diff --git a/auto/lib/openssl/make b/auto/lib/openssl/make index a7e9369..f848014 100644 --- a/auto/lib/openssl/make +++ b/auto/lib/openssl/make @@ -13,6 +13,10 @@ case "$CC" in OPENSSL_TARGET=VC-WIN64A ;; + arm64) + OPENSSL_TARGET=VC-WIN64-ARM + ;; + *) OPENSSL_TARGET=VC-WIN32 ;; diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index b55177d..ecb063d 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,77 @@ + + + + +контроль перегрузки CUBIC в соединениях QUIC. + + +CUBIC congestion control in QUIC connections. + + + + + +ограничение на максимальный размер кешируемых в разделяемой памяти +SSL-сессий поднято до 8192. + + +the maximum size limit for SSL sessions cached in shared memory +has been raised to 8192. + + + + + +в директивах grpc_ssl_password_file, proxy_ssl_password_file и +uwsgi_ssl_password_file +при загрузке SSL-сертификатов и зашифрованных ключей из переменных; +ошибка появилась в 1.23.1. + + +in the "grpc_ssl_password_file", "proxy_ssl_password_file", and +"uwsgi_ssl_password_file" directives +when loading SSL certificates and encrypted keys from variables; +the bug had appeared in 1.23.1. + + + + + +в переменных $ssl_curve и $ssl_curves +при использовании подключаемых кривых в OpenSSL. + + +in the $ssl_curve and $ssl_curves variables +when using pluggable curves in OpenSSL. + + + + + +nginx не собирался с musl libc.
+Спасибо Piotr Sikora. +
+ +nginx could not be built with musl libc.
+Thanks to Piotr Sikora. +
+
+ + + +Улучшения производительности и исправления в HTTP/3. + + +Performance improvements and bugfixes in HTTP/3. + + + +
+ + diff --git a/lib/nginx-http-flv-module b/lib/nginx-http-flv-module index e8a456d..1ba6a5d 160000 --- a/lib/nginx-http-flv-module +++ b/lib/nginx-http-flv-module @@ -1 +1 @@ -Subproject commit e8a456df874e6c465f07e4a7ea57b0ac8f0e8c44 +Subproject commit 1ba6a5d0b98bc4229c096b4591d8f10021663682 diff --git a/lib/ngx_devel_kit b/lib/ngx_devel_kit index 91e30eb..bd44d16 160000 --- a/lib/ngx_devel_kit +++ b/lib/ngx_devel_kit @@ -1 +1 @@ -Subproject commit 91e30eb05085e7f9762f130cbb883a0e753cf74d +Subproject commit bd44d16302273052d6005d7bdb55f74e23813de3 diff --git a/lib/pcre b/lib/pcre index 804b10a..9d1a620 160000 --- a/lib/pcre +++ b/lib/pcre @@ -1 +1 @@ -Subproject commit 804b10a5727668e4e66a1c13839be4beeda7ed16 +Subproject commit 9d1a620820561354b2ac8c1abb17cd57b6149102 diff --git a/lib/zlib-ng b/lib/zlib-ng index 860e4cf..9d4af45 160000 --- a/lib/zlib-ng +++ b/lib/zlib-ng @@ -1 +1 @@ -Subproject commit 860e4cff7917d93f54f5d7f0bc1d0e8b1a3cb988 +Subproject commit 9d4af458ea8a56fb208e3e89c903648c11460a3d diff --git a/src/core/nginx.h b/src/core/nginx.h index 2cc8372..cd09635 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1027005 -#define NGINX_VERSION "1.27.5" +#define nginx_version 1027006 +#define NGINX_VERSION "1.27.6" #define NGINX_VER "nginx/" NGINX_VERSION " by Hakase" #ifndef NGINX_SERVER diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h index 1861be6..707ab21 100644 --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -94,7 +94,7 @@ typedef intptr_t ngx_flag_t; #ifndef NGX_ALIGNMENT -#define NGX_ALIGNMENT sizeof(unsigned long) /* platform word */ +#define NGX_ALIGNMENT sizeof(uintptr_t) /* platform word */ #endif #define ngx_align(d, a) (((d) + (a - 1)) & ~(a - 1)) diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 4b7dfa8..83c64d4 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -5079,7 +5079,8 @@ ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { #ifdef SSL_get_negotiated_group - int nid; + int nid; + const char *name; nid = SSL_get_negotiated_group(c->ssl->connection); @@ -5091,14 +5092,24 @@ ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) return NGX_OK; } - s->len = sizeof("0x0000") - 1; +#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL) + name = SSL_group_to_name(c->ssl->connection, nid); +#else + name = NULL; +#endif + s->len = name ? ngx_strlen(name) : sizeof("0x0000") - 1; s->data = ngx_pnalloc(pool, s->len); if (s->data == NULL) { return NGX_ERROR; } - ngx_sprintf(s->data, "0x%04xd", nid & 0xffff); + if (name) { + ngx_memcpy(s->data, name, s->len); + + } else { + ngx_sprintf(s->data, "0x%04xd", nid & 0xffff); + } return NGX_OK; } @@ -5118,6 +5129,7 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) int *curves, n, i, nid; u_char *p; size_t len; + const char *name; n = SSL_get1_curves(c->ssl->connection, NULL); @@ -5138,7 +5150,13 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) nid = curves[i]; if (nid & TLSEXT_nid_unknown) { - len += sizeof("0x0000") - 1; +#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL) + name = SSL_group_to_name(c->ssl->connection, nid); +#else + name = NULL; +#endif + + len += name ? ngx_strlen(name) : sizeof("0x0000") - 1; } else { len += ngx_strlen(OBJ_nid2sn(nid)); @@ -5158,7 +5176,14 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) nid = curves[i]; if (nid & TLSEXT_nid_unknown) { - p = ngx_sprintf(p, "0x%04xd", nid & 0xffff); +#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL) + name = SSL_group_to_name(c->ssl->connection, nid); +#else + name = NULL; +#endif + + p = name ? ngx_cpymem(p, name, ngx_strlen(name)) + : ngx_sprintf(p, "0x%04xd", nid & 0xffff); } else { p = ngx_sprintf(p, "%s", OBJ_nid2sn(nid)); diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c index 308597e..4682eca 100644 --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -308,11 +308,16 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf, qc->streams.client_max_streams_uni = qc->tp.initial_max_streams_uni; qc->streams.client_max_streams_bidi = qc->tp.initial_max_streams_bidi; - qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size, - ngx_max(2 * qc->tp.max_udp_payload_size, + qc->congestion.window = ngx_min(10 * NGX_QUIC_MIN_INITIAL_SIZE, + ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE, 14720)); qc->congestion.ssthresh = (size_t) -1; - qc->congestion.recovery_start = ngx_current_msec; + qc->congestion.mtu = NGX_QUIC_MIN_INITIAL_SIZE; + qc->congestion.recovery_start = ngx_current_msec - 1; + + qc->max_frames = (conf->max_concurrent_streams_uni + + conf->max_concurrent_streams_bidi) + * conf->stream_buffer_size / 2000; if (pkt->validated && pkt->retried) { qc->tp.retry_scid.len = pkt->dcid.len; diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index c953b80..b8b72e9 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -20,6 +20,10 @@ /* RFC 9002, 7.6.1. Duration: kPersistentCongestionThreshold */ #define NGX_QUIC_PERSISTENT_CONGESTION_THR 3 +/* CUBIC parameters x10 */ +#define NGX_QUIC_CUBIC_BETA 7 +#define MGX_QUIC_CUBIC_C 4 + /* send time of ACK'ed packets */ typedef struct { @@ -29,18 +33,22 @@ typedef struct { } ngx_quic_ack_stat_t; -static ngx_inline ngx_msec_t ngx_quic_lost_threshold(ngx_quic_connection_t *qc); +static ngx_inline ngx_msec_t ngx_quic_time_threshold(ngx_quic_connection_t *qc); +static uint64_t ngx_quic_packet_threshold(ngx_quic_send_ctx_t *ctx); static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack, enum ssl_encryption_level_t level, ngx_msec_t send_time); static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, uint64_t min, uint64_t max, ngx_quic_ack_stat_t *st); +static size_t ngx_quic_congestion_cubic(ngx_connection_t *c); static void ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, uint64_t pn); static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st); +static ngx_msec_t ngx_quic_congestion_cubic_time(ngx_connection_t *c); static ngx_msec_t ngx_quic_pcg_duration(ngx_connection_t *c); static void ngx_quic_persistent_congestion(ngx_connection_t *c); +static ngx_msec_t ngx_quic_oldest_sent_packet(ngx_connection_t *c); static void ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *frame); static void ngx_quic_lost_handler(ngx_event_t *ev); @@ -48,7 +56,7 @@ static void ngx_quic_lost_handler(ngx_event_t *ev); /* RFC 9002, 6.1.2. Time Threshold: kTimeThreshold, kGranularity */ static ngx_inline ngx_msec_t -ngx_quic_lost_threshold(ngx_quic_connection_t *qc) +ngx_quic_time_threshold(ngx_quic_connection_t *qc) { ngx_msec_t thr; @@ -59,6 +67,29 @@ ngx_quic_lost_threshold(ngx_quic_connection_t *qc) } +static uint64_t +ngx_quic_packet_threshold(ngx_quic_send_ctx_t *ctx) +{ + uint64_t pkt_thr; + ngx_queue_t *q; + ngx_quic_frame_t *f; + + if (ngx_queue_empty(&ctx->sent)) { + return NGX_QUIC_PKT_THR; + } + + q = ngx_queue_head(&ctx->sent); + f = ngx_queue_data(q, ngx_quic_frame_t, queue); + pkt_thr = (ctx->pnum - f->pnum) / 2; + + if (pkt_thr <= NGX_QUIC_PKT_THR) { + return NGX_QUIC_PKT_THR; + } + + return pkt_thr; +} + + ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, ngx_quic_frame_t *f) @@ -313,8 +344,9 @@ ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, void ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) { + size_t w_cubic; ngx_uint_t blocked; - ngx_msec_t timer; + ngx_msec_t now, timer; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; @@ -329,16 +361,34 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) return; } + now = ngx_current_msec; + blocked = (cg->in_flight >= cg->window) ? 1 : 0; cg->in_flight -= f->plen; + /* prevent recovery_start from wrapping */ + + timer = now - cg->recovery_start; + + if ((ngx_msec_int_t) timer < 0) { + cg->recovery_start = ngx_quic_oldest_sent_packet(c) - 1; + } + timer = f->send_time - cg->recovery_start; if ((ngx_msec_int_t) timer <= 0) { ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion ack recovery win:%uz ss:%z if:%uz", - cg->window, cg->ssthresh, cg->in_flight); + "quic congestion ack rec t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); + + goto done; + } + + if (cg->idle) { + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion ack idle t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); goto done; } @@ -346,24 +396,51 @@ ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *f) if (cg->window < cg->ssthresh) { cg->window += f->plen; - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion slow start win:%uz ss:%z if:%uz", - cg->window, cg->ssthresh, cg->in_flight); + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion ack ss t:%M win:%uz ss:%z if:%uz", + now, cg->window, cg->ssthresh, cg->in_flight); } else { - cg->window += qc->tp.max_udp_payload_size * f->plen / cg->window; - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion avoidance win:%uz ss:%z if:%uz", - cg->window, cg->ssthresh, cg->in_flight); - } + /* RFC 9438, 4.2. Window Increase Function */ - /* prevent recovery_start from wrapping */ + w_cubic = ngx_quic_congestion_cubic(c); - timer = cg->recovery_start - ngx_current_msec + qc->tp.max_idle_timeout * 2; + if (cg->window < cg->w_prior) { + cg->w_est += (uint64_t) cg->mtu * f->plen + * 3 * (10 - NGX_QUIC_CUBIC_BETA) + / (10 + NGX_QUIC_CUBIC_BETA) / cg->window; - if ((ngx_msec_int_t) timer < 0) { - cg->recovery_start = ngx_current_msec - qc->tp.max_idle_timeout * 2; + } else { + cg->w_est += (uint64_t) cg->mtu * f->plen / cg->window; + } + + if (w_cubic < cg->w_est) { + cg->window = cg->w_est; + + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion ack reno t:%M win:%uz c:%uz if:%uz", + now, cg->window, w_cubic, cg->in_flight); + + } else if (w_cubic > cg->window) { + + if (w_cubic >= cg->window * 3 / 2) { + cg->window += cg->mtu / 2; + + } else { + cg->window += (uint64_t) cg->mtu * (w_cubic - cg->window) + / cg->window; + } + + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion ack cubic t:%M win:%uz c:%uz if:%uz", + now, cg->window, w_cubic, cg->in_flight); + + } else { + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion ack skip t:%M win:%uz c:%uz if:%uz", + now, cg->window, w_cubic, cg->in_flight); + } } done: @@ -374,6 +451,87 @@ done: } +static size_t +ngx_quic_congestion_cubic(ngx_connection_t *c) +{ + int64_t w, t, cc; + ngx_msec_t now; + ngx_quic_congestion_t *cg; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + cg = &qc->congestion; + + ngx_quic_congestion_idle(c, cg->idle); + + now = ngx_current_msec; + t = (ngx_msec_int_t) (now - cg->k); + + if (t > 1000000) { + w = NGX_MAX_SIZE_T_VALUE; + goto done; + } + + if (t < -1000000) { + w = 0; + goto done; + } + + /* + * RFC 9438, Figure 1 + * + * w_cubic = C * (t_msec / 1000) ^ 3 * mtu + w_max + */ + + cc = 10000000000ll / (int64_t) cg->mtu / MGX_QUIC_CUBIC_C; + w = t * t * t / cc + (int64_t) cg->w_max; + + if (w > NGX_MAX_SIZE_T_VALUE) { + w = NGX_MAX_SIZE_T_VALUE; + } + + if (w < 0) { + w = 0; + } + +done: + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic cubic t:%L w:%L wm:%uz", t, w, cg->w_max); + + return w; +} + + +void +ngx_quic_congestion_idle(ngx_connection_t *c, ngx_uint_t idle) +{ + ngx_msec_t now; + ngx_quic_congestion_t *cg; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + cg = &qc->congestion; + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion idle:%ui", idle); + + if (cg->window >= cg->ssthresh) { + /* RFC 9438, 5.8. Behavior for Application-Limited Flows */ + + now = ngx_current_msec; + + if (cg->idle) { + cg->k += now - cg->idle_start; + } + + cg->idle_start = now; + } + + cg->idle = idle; +} + + static void ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, uint64_t pn) @@ -435,6 +593,7 @@ ngx_quic_drop_ack_ranges(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) { + uint64_t pkt_thr; ngx_uint_t i, nlost; ngx_msec_t now, wait, thr, oldest, newest; ngx_queue_t *q; @@ -444,11 +603,12 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) qc = ngx_quic_get_connection(c); now = ngx_current_msec; - thr = ngx_quic_lost_threshold(qc); + thr = ngx_quic_time_threshold(qc); - /* send time of lost packets across all send contexts */ - oldest = NGX_TIMER_INFINITE; - newest = NGX_TIMER_INFINITE; +#if (NGX_SUPPRESS_WARN) + oldest = now; + newest = now; +#endif nlost = 0; @@ -460,6 +620,8 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) continue; } + pkt_thr = ngx_quic_packet_threshold(ctx); + while (!ngx_queue_empty(&ctx->sent)) { q = ngx_queue_head(&ctx->sent); @@ -471,23 +633,27 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) wait = start->send_time + thr - now; - ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic detect_lost pnum:%uL thr:%M wait:%i level:%d", - start->pnum, thr, (ngx_int_t) wait, start->level); + ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic detect_lost pnum:%uL thr:%M pthr:%uL wait:%i level:%d", + start->pnum, thr, pkt_thr, (ngx_int_t) wait, start->level); if ((ngx_msec_int_t) wait > 0 - && ctx->largest_ack - start->pnum < NGX_QUIC_PKT_THR) + && ctx->largest_ack - start->pnum < pkt_thr) { break; } - if (start->send_time > qc->first_rtt) { + if ((ngx_msec_int_t) (start->send_time - qc->first_rtt) > 0) { - if (oldest == NGX_TIMER_INFINITE || start->send_time < oldest) { + if (nlost == 0 + || (ngx_msec_int_t) (start->send_time - oldest) < 0) + { oldest = start->send_time; } - if (newest == NGX_TIMER_INFINITE || start->send_time > newest) { + if (nlost == 0 + || (ngx_msec_int_t) (start->send_time - newest) > 0) + { newest = start->send_time; } @@ -508,8 +674,9 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st) * latest ACK frame. */ - if (st && nlost >= 2 && (st->newest < oldest || st->oldest > newest)) { - + if (st && nlost >= 2 && ((ngx_msec_int_t) (st->newest - oldest) < 0 + || (ngx_msec_int_t) (st->oldest - newest) > 0)) + { if (newest - oldest > ngx_quic_pcg_duration(c)) { ngx_quic_persistent_congestion(c); } @@ -547,11 +714,43 @@ ngx_quic_persistent_congestion(ngx_connection_t *c) qc = ngx_quic_get_connection(c); cg = &qc->congestion; - cg->recovery_start = ngx_current_msec; - cg->window = qc->tp.max_udp_payload_size * 2; + cg->mtu = qc->path->mtu; + cg->recovery_start = ngx_quic_oldest_sent_packet(c) - 1; + cg->window = cg->mtu * 2; - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic persistent congestion win:%uz", cg->window); + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion persistent t:%M win:%uz", + ngx_current_msec, cg->window); +} + + +static ngx_msec_t +ngx_quic_oldest_sent_packet(ngx_connection_t *c) +{ + ngx_msec_t oldest; + ngx_uint_t i; + ngx_queue_t *q; + ngx_quic_frame_t *start; + ngx_quic_send_ctx_t *ctx; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + oldest = ngx_current_msec; + + for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { + ctx = &qc->send_ctx[i]; + + if (!ngx_queue_empty(&ctx->sent)) { + q = ngx_queue_head(&ctx->sent); + start = ngx_queue_data(q, ngx_quic_frame_t, queue); + + if ((ngx_msec_int_t) (start->send_time - oldest) < 0) { + oldest = start->send_time; + } + } + } + + return oldest; } @@ -659,7 +858,7 @@ static void ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f) { ngx_uint_t blocked; - ngx_msec_t timer; + ngx_msec_t now, timer; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; @@ -681,26 +880,41 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f) timer = f->send_time - cg->recovery_start; + now = ngx_current_msec; + if ((ngx_msec_int_t) timer <= 0) { ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion lost recovery win:%uz ss:%z if:%uz", - cg->window, cg->ssthresh, cg->in_flight); + "quic congestion lost rec t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); goto done; } - cg->recovery_start = ngx_current_msec; - cg->window /= 2; + if (f->ignore_loss) { + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic congestion lost ignore t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); - if (cg->window < qc->tp.max_udp_payload_size * 2) { - cg->window = qc->tp.max_udp_payload_size * 2; + goto done; } - cg->ssthresh = cg->window; + /* RFC 9438, 4.6. Multiplicative Decrease */ + + cg->mtu = qc->path->mtu; + cg->recovery_start = now; + cg->w_prior = cg->window; + /* RFC 9438, 4.7. Fast Convergence */ + cg->w_max = (cg->window < cg->w_max) + ? cg->window * (10 + NGX_QUIC_CUBIC_BETA) / 20 : cg->window; + cg->ssthresh = cg->in_flight * NGX_QUIC_CUBIC_BETA / 10; + cg->window = ngx_max(cg->ssthresh, cg->mtu * 2); + cg->w_est = cg->window; + cg->k = now + ngx_quic_congestion_cubic_time(c); + cg->idle_start = now; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "quic congestion lost win:%uz ss:%z if:%uz", - cg->window, cg->ssthresh, cg->in_flight); + "quic congestion lost t:%M win:%uz if:%uz", + now, cg->window, cg->in_flight); done: @@ -710,9 +924,62 @@ done: } +static ngx_msec_t +ngx_quic_congestion_cubic_time(ngx_connection_t *c) +{ + int64_t v, x, d, cc; + ngx_uint_t n; + ngx_quic_congestion_t *cg; + ngx_quic_connection_t *qc; + + qc = ngx_quic_get_connection(c); + cg = &qc->congestion; + + /* + * RFC 9438, Figure 2 + * + * k_msec = ((w_max - cwnd_epoch) / C / mtu) ^ 1/3 * 1000 + */ + + if (cg->w_max <= cg->window) { + return 0; + } + + cc = 10000000000ll / (int64_t) cg->mtu / MGX_QUIC_CUBIC_C; + v = (int64_t) (cg->w_max - cg->window) * cc; + + /* + * Newton-Raphson method for x ^ 3 = v: + * + * x_next = (2 * x_prev + v / x_prev ^ 2) / 3 + */ + + x = 5000; + + for (n = 1; n <= 10; n++) { + d = (v / x / x - x) / 3; + x += d; + + if (ngx_abs(d) <= 100) { + break; + } + } + + if (x > NGX_MAX_SIZE_T_VALUE) { + return NGX_MAX_SIZE_T_VALUE; + } + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic cubic time:%L n:%ui", x, n); + + return x; +} + + void ngx_quic_set_lost_timer(ngx_connection_t *c) { + uint64_t pkt_thr; ngx_uint_t i; ngx_msec_t now; ngx_queue_t *q; @@ -738,10 +1005,12 @@ ngx_quic_set_lost_timer(ngx_connection_t *c) q = ngx_queue_head(&ctx->sent); f = ngx_queue_data(q, ngx_quic_frame_t, queue); w = (ngx_msec_int_t) - (f->send_time + ngx_quic_lost_threshold(qc) - now); + (f->send_time + ngx_quic_time_threshold(qc) - now); if (f->pnum <= ctx->largest_ack) { - if (w < 0 || ctx->largest_ack - f->pnum >= NGX_QUIC_PKT_THR) { + pkt_thr = ngx_quic_packet_threshold(ctx); + + if (w < 0 || ctx->largest_ack - f->pnum >= pkt_thr) { w = 0; } diff --git a/src/event/quic/ngx_event_quic_ack.h b/src/event/quic/ngx_event_quic_ack.h index 56920c2..4ad5966 100644 --- a/src/event/quic/ngx_event_quic_ack.h +++ b/src/event/quic/ngx_event_quic_ack.h @@ -17,6 +17,7 @@ ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c, void ngx_quic_congestion_ack(ngx_connection_t *c, ngx_quic_frame_t *frame); +void ngx_quic_congestion_idle(ngx_connection_t *c, ngx_uint_t idle); void ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx); void ngx_quic_set_lost_timer(ngx_connection_t *c); void ngx_quic_pto_handler(ngx_event_t *ev); diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h index 824c92b..04cda85 100644 --- a/src/event/quic/ngx_event_quic_connection.h +++ b/src/event/quic/ngx_event_quic_connection.h @@ -168,7 +168,14 @@ typedef struct { size_t in_flight; size_t window; size_t ssthresh; + size_t w_max; + size_t w_est; + size_t w_prior; + size_t mtu; ngx_msec_t recovery_start; + ngx_msec_t idle_start; + ngx_msec_t k; + ngx_uint_t idle; /* unsigned idle:1; */ } ngx_quic_congestion_t; @@ -254,6 +261,7 @@ struct ngx_quic_connection_s { ngx_buf_t *free_shadow_bufs; ngx_uint_t nframes; + ngx_uint_t max_frames; #ifdef NGX_QUIC_DEBUG_ALLOC ngx_uint_t nbufs; ngx_uint_t nshadowbufs; diff --git a/src/event/quic/ngx_event_quic_frames.c b/src/event/quic/ngx_event_quic_frames.c index 6ea908c..888e8bd 100644 --- a/src/event/quic/ngx_event_quic_frames.c +++ b/src/event/quic/ngx_event_quic_frames.c @@ -214,7 +214,7 @@ ngx_quic_alloc_frame(ngx_connection_t *c) "quic reuse frame n:%ui", qc->nframes); #endif - } else if (qc->nframes < 10000) { + } else if (qc->nframes < qc->max_frames) { frame = ngx_palloc(c->pool, sizeof(ngx_quic_frame_t)); if (frame == NULL) { return NULL; diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c index 2d1467e..6befc34 100644 --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -182,11 +182,12 @@ valid: ngx_memzero(&qc->congestion, sizeof(ngx_quic_congestion_t)); - qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size, - ngx_max(2 * qc->tp.max_udp_payload_size, + qc->congestion.window = ngx_min(10 * NGX_QUIC_MIN_INITIAL_SIZE, + ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE, 14720)); qc->congestion.ssthresh = (size_t) -1; - qc->congestion.recovery_start = ngx_current_msec; + qc->congestion.mtu = NGX_QUIC_MIN_INITIAL_SIZE; + qc->congestion.recovery_start = ngx_current_msec - 1; ngx_quic_init_rtt(qc); } @@ -923,6 +924,8 @@ ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path) frame->level = ssl_encryption_application; frame->type = NGX_QUIC_FT_PING; + frame->ignore_loss = 1; + frame->ignore_congestion = 1; qc = ngx_quic_get_connection(c); ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application); diff --git a/src/event/quic/ngx_event_quic_output.c b/src/event/quic/ngx_event_quic_output.c index f087e2b..a92a539 100644 --- a/src/event/quic/ngx_event_quic_output.c +++ b/src/event/quic/ngx_event_quic_output.c @@ -45,9 +45,9 @@ static ngx_int_t ngx_quic_create_datagrams(ngx_connection_t *c); -static void ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx); -static void ngx_quic_revert_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, - uint64_t pnum); +static void ngx_quic_commit_send(ngx_connection_t *c); +static void ngx_quic_revert_send(ngx_connection_t *c, + uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]); #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL)) static ngx_uint_t ngx_quic_allow_segmentation(ngx_connection_t *c); static ngx_int_t ngx_quic_create_segments(ngx_connection_t *c); @@ -127,6 +127,10 @@ ngx_quic_create_datagrams(ngx_connection_t *c) cg = &qc->congestion; path = qc->path; +#if (NGX_SUPPRESS_WARN) + ngx_memzero(preserved_pnum, sizeof(preserved_pnum)); +#endif + while (cg->in_flight < cg->window) { p = dst; @@ -150,12 +154,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c) if (min > len) { /* padding can't be applied - avoid sending the packet */ - - while (i-- > 0) { - ctx = &qc->send_ctx[i]; - ngx_quic_revert_send(c, ctx, preserved_pnum[i]); - } - + ngx_quic_revert_send(c, preserved_pnum); return NGX_OK; } @@ -180,17 +179,12 @@ ngx_quic_create_datagrams(ngx_connection_t *c) } if (n == NGX_AGAIN) { - for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { - ngx_quic_revert_send(c, &qc->send_ctx[i], preserved_pnum[i]); - } - + ngx_quic_revert_send(c, preserved_pnum); ngx_add_timer(&qc->push, NGX_QUIC_SOCKET_RETRY_DELAY); break; } - for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { - ngx_quic_commit_send(c, &qc->send_ctx[i]); - } + ngx_quic_commit_send(c); path->sent += len; } @@ -200,53 +194,79 @@ ngx_quic_create_datagrams(ngx_connection_t *c) static void -ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) +ngx_quic_commit_send(ngx_connection_t *c) { + ngx_uint_t i, idle; ngx_queue_t *q; ngx_quic_frame_t *f; + ngx_quic_send_ctx_t *ctx; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; qc = ngx_quic_get_connection(c); - cg = &qc->congestion; - while (!ngx_queue_empty(&ctx->sending)) { + idle = 1; - q = ngx_queue_head(&ctx->sending); - f = ngx_queue_data(q, ngx_quic_frame_t, queue); + for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { + ctx = &qc->send_ctx[i]; - ngx_queue_remove(q); + if (!ngx_queue_empty(&ctx->frames)) { + idle = 0; + } - if (f->pkt_need_ack && !qc->closing) { - ngx_queue_insert_tail(&ctx->sent, q); + while (!ngx_queue_empty(&ctx->sending)) { - cg->in_flight += f->plen; + q = ngx_queue_head(&ctx->sending); + f = ngx_queue_data(q, ngx_quic_frame_t, queue); - } else { - ngx_quic_free_frame(c, f); + ngx_queue_remove(q); + + if (f->pkt_need_ack && !qc->closing) { + ngx_queue_insert_tail(&ctx->sent, q); + + cg->in_flight += f->plen; + + } else { + ngx_quic_free_frame(c, f); + } } } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic congestion send if:%uz", cg->in_flight); + + ngx_quic_congestion_idle(c, idle); } static void -ngx_quic_revert_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, - uint64_t pnum) +ngx_quic_revert_send(ngx_connection_t *c, uint64_t pnum[NGX_QUIC_SEND_CTX_LAST]) { - ngx_queue_t *q; + ngx_uint_t i; + ngx_queue_t *q; + ngx_quic_send_ctx_t *ctx; + ngx_quic_connection_t *qc; - while (!ngx_queue_empty(&ctx->sending)) { + qc = ngx_quic_get_connection(c); - q = ngx_queue_last(&ctx->sending); - ngx_queue_remove(q); - ngx_queue_insert_head(&ctx->frames, q); + for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { + ctx = &qc->send_ctx[i]; + + if (ngx_queue_empty(&ctx->sending)) { + continue; + } + + do { + q = ngx_queue_last(&ctx->sending); + ngx_queue_remove(q); + ngx_queue_insert_head(&ctx->frames, q); + } while (!ngx_queue_empty(&ctx->sending)); + + ctx->pnum = pnum[i]; } - ctx->pnum = pnum; + ngx_quic_congestion_idle(c, 1); } @@ -311,13 +331,13 @@ ngx_quic_create_segments(ngx_connection_t *c) size_t len, segsize; ssize_t n; u_char *p, *end; - uint64_t preserved_pnum; - ngx_uint_t nseg; + ngx_uint_t nseg, level; ngx_quic_path_t *path; ngx_quic_send_ctx_t *ctx; ngx_quic_congestion_t *cg; ngx_quic_connection_t *qc; static u_char dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF]; + static uint64_t preserved_pnum[NGX_QUIC_SEND_CTX_LAST]; qc = ngx_quic_get_connection(c); cg = &qc->congestion; @@ -335,7 +355,8 @@ ngx_quic_create_segments(ngx_connection_t *c) nseg = 0; - preserved_pnum = ctx->pnum; + level = ctx - qc->send_ctx; + preserved_pnum[level] = ctx->pnum; for ( ;; ) { @@ -369,19 +390,18 @@ ngx_quic_create_segments(ngx_connection_t *c) } if (n == NGX_AGAIN) { - ngx_quic_revert_send(c, ctx, preserved_pnum); - + ngx_quic_revert_send(c, preserved_pnum); ngx_add_timer(&qc->push, NGX_QUIC_SOCKET_RETRY_DELAY); break; } - ngx_quic_commit_send(c, ctx); + ngx_quic_commit_send(c); path->sent += n; p = dst; nseg = 0; - preserved_pnum = ctx->pnum; + preserved_pnum[level] = ctx->pnum; } } diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c index 3f249b3..e5c0df7 100644 --- a/src/event/quic/ngx_event_quic_protection.c +++ b/src/event/quic/ngx_event_quic_protection.c @@ -125,9 +125,10 @@ ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret, ngx_quic_secret_t *client, *server; ngx_quic_ciphers_t ciphers; - static const uint8_t salt[20] = - "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17" - "\x9a\xe6\xa4\xc8\x0c\xad\xcc\xbb\x7f\x0a"; + static const uint8_t salt[20] = { + 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, + 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a + }; client = &keys->secrets[ssl_encryption_initial].client; server = &keys->secrets[ssl_encryption_initial].server; @@ -958,8 +959,9 @@ ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res) /* 5.8. Retry Packet Integrity */ static ngx_quic_md_t key = ngx_quic_md( "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e"); - static const u_char nonce[NGX_QUIC_IV_LEN] = - "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb"; + static const u_char nonce[NGX_QUIC_IV_LEN] = { + 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb + }; static ngx_str_t in = ngx_string(""); ad.data = res->data; diff --git a/src/event/quic/ngx_event_quic_transport.c b/src/event/quic/ngx_event_quic_transport.c index bb13447..0b3ef4b 100644 --- a/src/event/quic/ngx_event_quic_transport.c +++ b/src/event/quic/ngx_event_quic_transport.c @@ -1773,7 +1773,7 @@ ngx_quic_parse_transport_params(u_char *p, u_char *end, ngx_quic_tp_t *tp, } if (rc == NGX_DECLINED) { - ngx_log_error(NGX_LOG_INFO, log, 0, + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0, "quic %s transport param id:0x%xL, skipped", (id % 31 == 27) ? "reserved" : "unknown", id); } diff --git a/src/event/quic/ngx_event_quic_transport.h b/src/event/quic/ngx_event_quic_transport.h index 3e32039..dcd763d 100644 --- a/src/event/quic/ngx_event_quic_transport.h +++ b/src/event/quic/ngx_event_quic_transport.h @@ -271,6 +271,7 @@ struct ngx_quic_frame_s { unsigned need_ack:1; unsigned pkt_need_ack:1; unsigned ignore_congestion:1; + unsigned ignore_loss:1; ngx_chain_t *data; union { diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c index e52b96e..d44da62 100644 --- a/src/http/modules/ngx_http_charset_filter_module.c +++ b/src/http/modules/ngx_http_charset_filter_module.c @@ -1332,6 +1332,12 @@ ngx_http_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) table = ctx->table; if (ctx->charset->utf8) { + if (value[1].len / 2 > NGX_UTF_LEN - 1) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid value \"%V\"", &value[1]); + return NGX_CONF_ERROR; + } + p = &table->src2dst[src * NGX_UTF_LEN]; *p++ = (u_char) (value[1].len / 2); diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c index 8e246c3..80046d6 100644 --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -4509,8 +4509,13 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) prev->upstream.ssl_certificate_key, NULL); ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_cache, prev->upstream.ssl_certificate_cache, NULL); - ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, - prev->upstream.ssl_passwords, NULL); + + if (ngx_http_upstream_merge_ssl_passwords(cf, &conf->upstream, + &prev->upstream) + != NGX_OK) + { + return NGX_CONF_ERROR; + } ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -5077,16 +5082,9 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf) return NGX_ERROR; } - if (glcf->upstream.ssl_certificate->lengths - || glcf->upstream.ssl_certificate_key->lengths) + if (glcf->upstream.ssl_certificate->lengths == NULL + && glcf->upstream.ssl_certificate_key->lengths == NULL) { - glcf->upstream.ssl_passwords = - ngx_ssl_preserve_passwords(cf, glcf->upstream.ssl_passwords); - if (glcf->upstream.ssl_passwords == NULL) { - return NGX_ERROR; - } - - } else { if (ngx_ssl_certificate(cf, glcf->upstream.ssl, &glcf->upstream.ssl_certificate->value, &glcf->upstream.ssl_certificate_key->value, diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 877d64c..6f5f197 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -3767,8 +3767,13 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) prev->upstream.ssl_certificate_key, NULL); ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_cache, prev->upstream.ssl_certificate_cache, NULL); - ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, - prev->upstream.ssl_passwords, NULL); + + if (ngx_http_upstream_merge_ssl_passwords(cf, &conf->upstream, + &prev->upstream) + != NGX_OK) + { + return NGX_CONF_ERROR; + } ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -5128,16 +5133,9 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf) return NGX_ERROR; } - if (plcf->upstream.ssl_certificate->lengths - || plcf->upstream.ssl_certificate_key->lengths) + if (plcf->upstream.ssl_certificate->lengths == NULL + && plcf->upstream.ssl_certificate_key->lengths == NULL) { - plcf->upstream.ssl_passwords = - ngx_ssl_preserve_passwords(cf, plcf->upstream.ssl_passwords); - if (plcf->upstream.ssl_passwords == NULL) { - return NGX_ERROR; - } - - } else { if (ngx_ssl_certificate(cf, plcf->upstream.ssl, &plcf->upstream.ssl_certificate->value, &plcf->upstream.ssl_certificate_key->value, diff --git a/src/http/modules/ngx_http_slice_filter_module.c b/src/http/modules/ngx_http_slice_filter_module.c index 3b0bef6..67dc14c 100644 --- a/src/http/modules/ngx_http_slice_filter_module.c +++ b/src/http/modules/ngx_http_slice_filter_module.c @@ -419,13 +419,13 @@ ngx_http_slice_range_variable(ngx_http_request_t *r, return NGX_ERROR; } - ngx_http_set_ctx(r, ctx, ngx_http_slice_filter_module); - p = ngx_pnalloc(r->pool, sizeof("bytes=-") - 1 + 2 * NGX_OFF_T_LEN); if (p == NULL) { return NGX_ERROR; } + ngx_http_set_ctx(r, ctx, ngx_http_slice_filter_module); + ctx->start = slcf->size * (ngx_http_slice_get_start(r) / slcf->size); ctx->range.data = p; diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c index 14aae5b..51a861d 100644 --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -1933,8 +1933,13 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) prev->upstream.ssl_certificate_key, NULL); ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_cache, prev->upstream.ssl_certificate_cache, NULL); - ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, - prev->upstream.ssl_passwords, NULL); + + if (ngx_http_upstream_merge_ssl_passwords(cf, &conf->upstream, + &prev->upstream) + != NGX_OK) + { + return NGX_CONF_ERROR; + } ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -2685,16 +2690,9 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf) return NGX_ERROR; } - if (uwcf->upstream.ssl_certificate->lengths - || uwcf->upstream.ssl_certificate_key->lengths) + if (uwcf->upstream.ssl_certificate->lengths == NULL + && uwcf->upstream.ssl_certificate_key->lengths == NULL) { - uwcf->upstream.ssl_passwords = - ngx_ssl_preserve_passwords(cf, uwcf->upstream.ssl_passwords); - if (uwcf->upstream.ssl_passwords == NULL) { - return NGX_ERROR; - } - - } else { if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, &uwcf->upstream.ssl_certificate->value, &uwcf->upstream.ssl_certificate_key->value, diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 77dc032..d4cf1b7 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -6921,6 +6921,61 @@ ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf, } +#if (NGX_HTTP_SSL) + +ngx_int_t +ngx_http_upstream_merge_ssl_passwords(ngx_conf_t *cf, + ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev) +{ + ngx_uint_t preserve; + + ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + + if (conf->ssl_certificate == NULL + || conf->ssl_certificate->value.len == 0 + || conf->ssl_certificate_key == NULL) + { + return NGX_OK; + } + + if (conf->ssl_certificate->lengths == NULL + && conf->ssl_certificate_key->lengths == NULL) + { + if (conf->ssl_passwords && conf->ssl_passwords->pool == NULL) { + /* un-preserve empty password list */ + conf->ssl_passwords = NULL; + } + + return NGX_OK; + } + + if (conf->ssl_passwords && conf->ssl_passwords->pool != cf->temp_pool) { + /* already preserved */ + return NGX_OK; + } + + preserve = (conf->ssl_passwords == prev->ssl_passwords) ? 1 : 0; + + conf->ssl_passwords = ngx_ssl_preserve_passwords(cf, conf->ssl_passwords); + if (conf->ssl_passwords == NULL) { + return NGX_ERROR; + } + + /* + * special handling to keep a preserved ssl_passwords copy + * in the previous configuration to inherit it to all children + */ + + if (preserve) { + prev->ssl_passwords = conf->ssl_passwords; + } + + return NGX_OK; +} + +#endif + + static void * ngx_http_upstream_create_main_conf(ngx_conf_t *cf) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index d48de57..f906f53 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -437,6 +437,10 @@ char *ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, ngx_int_t ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf, ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev, ngx_str_t *default_hide_headers, ngx_hash_init_t *hash); +#if (NGX_HTTP_SSL) +ngx_int_t ngx_http_upstream_merge_ssl_passwords(ngx_conf_t *cf, + ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev); +#endif #define ngx_http_conf_upstream_srv_conf(uscf, module) \ diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index a3dc06d..7d46ab8 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -148,8 +148,9 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) u_char addr[NGX_SOCKADDR_STRLEN]; #if (NGX_HTTP_GZIP) - static const u_char accept_encoding[12] = - "\x8b\x84\x84\x2d\x69\x5b\x05\x44\x3c\x86\xaa\x6f"; + static const u_char accept_encoding[12] = { + 0x8b, 0x84, 0x84, 0x2d, 0x69, 0x5b, 0x05, 0x44, 0x3c, 0x86, 0xaa, 0x6f + }; #endif static size_t nginx_len = ngx_http_v2_literal_size(NGINX_SERVER); diff --git a/src/http/v3/ngx_http_v3.c b/src/http/v3/ngx_http_v3.c index 8db229b..d8597ec 100644 --- a/src/http/v3/ngx_http_v3.c +++ b/src/http/v3/ngx_http_v3.c @@ -70,7 +70,7 @@ ngx_http_v3_keepalive_handler(ngx_event_t *ev) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 keepalive handler"); - ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR, + ngx_http_v3_shutdown_connection(c, NGX_HTTP_V3_ERR_NO_ERROR, "keepalive timeout"); } diff --git a/src/http/v3/ngx_http_v3.h b/src/http/v3/ngx_http_v3.h index 9dcb5e6..8fd212c 100644 --- a/src/http/v3/ngx_http_v3.h +++ b/src/http/v3/ngx_http_v3.h @@ -23,7 +23,7 @@ #define NGX_HTTP_V3_HQ_ALPN_PROTO "\x0Ahq-interop" #define NGX_HTTP_V3_HQ_PROTO "hq-interop" -#define NGX_HTTP_V3_VARLEN_INT_LEN 4 +#define NGX_HTTP_V3_VARLEN_INT_LEN 8 #define NGX_HTTP_V3_PREFIX_INT_LEN 11 #define NGX_HTTP_V3_STREAM_CONTROL 0x00 diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index 7f8bfc4..6e51585 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -108,6 +108,8 @@ static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s); static ngx_int_t ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s); static ngx_int_t ngx_stream_proxy_merge_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *conf, ngx_stream_proxy_srv_conf_t *prev); +static ngx_int_t ngx_stream_proxy_merge_ssl_passwords(ngx_conf_t *cf, + ngx_stream_proxy_srv_conf_t *conf, ngx_stream_proxy_srv_conf_t *prev); static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf); @@ -2315,7 +2317,9 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_ptr_value(conf->ssl_certificate_cache, prev->ssl_certificate_cache, NULL); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + if (ngx_stream_proxy_merge_ssl_passwords(cf, conf, prev) != NGX_OK) { + return NGX_CONF_ERROR; + } ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -2381,6 +2385,57 @@ ngx_stream_proxy_merge_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *conf, } +static ngx_int_t +ngx_stream_proxy_merge_ssl_passwords(ngx_conf_t *cf, + ngx_stream_proxy_srv_conf_t *conf, ngx_stream_proxy_srv_conf_t *prev) +{ + ngx_uint_t preserve; + + ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + + if (conf->ssl_certificate == NULL + || conf->ssl_certificate->value.len == 0 + || conf->ssl_certificate_key == NULL) + { + return NGX_OK; + } + + if (conf->ssl_certificate->lengths == NULL + && conf->ssl_certificate_key->lengths == NULL) + { + if (conf->ssl_passwords && conf->ssl_passwords->pool == NULL) { + /* un-preserve empty password list */ + conf->ssl_passwords = NULL; + } + + return NGX_OK; + } + + if (conf->ssl_passwords && conf->ssl_passwords->pool != cf->temp_pool) { + /* already preserved */ + return NGX_OK; + } + + preserve = (conf->ssl_passwords == prev->ssl_passwords) ? 1 : 0; + + conf->ssl_passwords = ngx_ssl_preserve_passwords(cf, conf->ssl_passwords); + if (conf->ssl_passwords == NULL) { + return NGX_ERROR; + } + + /* + * special handling to keep a preserved ssl_passwords copy + * in the previous configuration to inherit it to all children + */ + + if (preserve) { + prev->ssl_passwords = conf->ssl_passwords; + } + + return NGX_OK; +} + + static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf) { @@ -2418,16 +2473,9 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf) return NGX_ERROR; } - if (pscf->ssl_certificate->lengths - || pscf->ssl_certificate_key->lengths) + if (pscf->ssl_certificate->lengths == NULL + && pscf->ssl_certificate_key->lengths == NULL) { - pscf->ssl_passwords = - ngx_ssl_preserve_passwords(cf, pscf->ssl_passwords); - if (pscf->ssl_passwords == NULL) { - return NGX_ERROR; - } - - } else { if (ngx_ssl_certificate(cf, pscf->ssl, &pscf->ssl_certificate->value, &pscf->ssl_certificate_key->value,