Latest update - GitHub 020b1db7e
This commit is contained in:
@@ -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
|
||||
;;
|
||||
|
||||
@@ -13,6 +13,10 @@ case "$CC" in
|
||||
OPENSSL_TARGET=VC-WIN64A
|
||||
;;
|
||||
|
||||
arm64)
|
||||
OPENSSL_TARGET=VC-WIN64-ARM
|
||||
;;
|
||||
|
||||
*)
|
||||
OPENSSL_TARGET=VC-WIN32
|
||||
;;
|
||||
|
||||
@@ -5,6 +5,77 @@
|
||||
<change_log title="nginx">
|
||||
|
||||
|
||||
<changes ver="1.27.5" date="2025-04-16">
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
контроль перегрузки CUBIC в соединениях QUIC.
|
||||
</para>
|
||||
<para lang="en">
|
||||
CUBIC congestion control in QUIC connections.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="change">
|
||||
<para lang="ru">
|
||||
ограничение на максимальный размер кешируемых в разделяемой памяти
|
||||
SSL-сессий поднято до 8192.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the maximum size limit for SSL sessions cached in shared memory
|
||||
has been raised to 8192.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
в директивах grpc_ssl_password_file, proxy_ssl_password_file и
|
||||
uwsgi_ssl_password_file
|
||||
при загрузке SSL-сертификатов и зашифрованных ключей из переменных;
|
||||
ошибка появилась в 1.23.1.
|
||||
</para>
|
||||
<para lang="en">
|
||||
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.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
в переменных $ssl_curve и $ssl_curves
|
||||
при использовании подключаемых кривых в OpenSSL.
|
||||
</para>
|
||||
<para lang="en">
|
||||
in the $ssl_curve and $ssl_curves variables
|
||||
when using pluggable curves in OpenSSL.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
nginx не собирался с musl libc.<br/>
|
||||
Спасибо Piotr Sikora.
|
||||
</para>
|
||||
<para lang="en">
|
||||
nginx could not be built with musl libc.<br/>
|
||||
Thanks to Piotr Sikora.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change>
|
||||
<para lang="ru">
|
||||
Улучшения производительности и исправления в HTTP/3.
|
||||
</para>
|
||||
<para lang="en">
|
||||
Performance improvements and bugfixes in HTTP/3.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
</changes>
|
||||
|
||||
|
||||
<changes ver="1.27.4" date="2025-02-05">
|
||||
|
||||
<change type="security">
|
||||
|
||||
Submodule lib/nginx-http-flv-module updated: e8a456df87...1ba6a5d0b9
+1
-1
Submodule lib/ngx_devel_kit updated: 91e30eb050...bd44d16302
+1
-1
Submodule lib/pcre updated: 804b10a572...9d1a620820
+1
-1
Submodule lib/zlib-ng updated: 860e4cff79...9d4af458ea
+2
-2
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user