From xeioex at nginx.com Tue Apr 2 15:52:18 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 02 Apr 2024 15:52:18 +0000 Subject: [njs] Tests: removed stream_js_import.t. Message-ID: details: https://hg.nginx.org/njs/rev/e16e93f43303 branches: changeset: 2304:e16e93f43303 user: Dmitry Volyntsev date: Mon Apr 01 23:13:21 2024 -0700 description: Tests: removed stream_js_import.t. js_import is the only directive to load JS code since 0.7.1, so the test is redundant. diffstat: nginx/t/stream_js_import.t | 117 --------------------------------------------- 1 files changed, 0 insertions(+), 117 deletions(-) diffs (121 lines): diff -r f632fe16ba05 -r e16e93f43303 nginx/t/stream_js_import.t --- a/nginx/t/stream_js_import.t Tue Mar 19 21:05:51 2024 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -#!/usr/bin/perl - -# (C) Dmitry Volyntsev -# (C) Nginx, Inc. - -# Tests for stream njs module, js_import directive. - -############################################################################### - -use warnings; -use strict; - -use Test::More; - -BEGIN { use FindBin; chdir($FindBin::Bin); } - -use lib 'lib'; -use Test::Nginx; -use Test::Nginx::Stream qw/ stream /; - -############################################################################### - -select STDERR; $| = 1; -select STDOUT; $| = 1; - -my $t = Test::Nginx->new()->has(qw/http stream stream_return/) - ->write_file_expand('nginx.conf', <<'EOF'); - -%%TEST_GLOBALS%% - -daemon off; - -events { -} - -stream { - %%TEST_GLOBALS_STREAM%% - - js_set $test foo.bar.p; - - js_import lib.js; - js_import foo from ./main.js; - - server { - listen 127.0.0.1:8081; - return $test; - } - - server { - listen 127.0.0.1:8082; - js_access lib.access; - js_preread lib.preread; - js_filter lib.filter; - proxy_pass 127.0.0.1:8083; - } - - server { - listen 127.0.0.1:8083; - return "x"; - } -} - -EOF - -$t->write_file('lib.js', <= 3) { - s.done(); - } - }); - } - - function filter(s) { - s.on('upload', function(data, flags) { - s.send(data); - res += '3'; - }); - - s.on('download', function(data, flags) { - if (!flags.last) { - res += '4'; - s.send(data); - - } else { - res += '5'; - s.send(res, {last:1}); - s.off('download'); - } - }); - } - - export default {access, preread, filter}; - -EOF - -$t->write_file('main.js', <try_run('no njs available')->plan(2); - -############################################################################### - -is(stream('127.0.0.1:' . port(8081))->read(), 'P-TEST', 'foo.bar.p'); -is(stream('127.0.0.1:' . port(8082))->io('0'), 'x122345', 'lib.access'); - -############################################################################### From xeioex at nginx.com Tue Apr 2 15:52:20 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 02 Apr 2024 15:52:20 +0000 Subject: [njs] Tests: simplified stream_js_import2.t. Message-ID: details: https://hg.nginx.org/njs/rev/498b2387ef04 branches: changeset: 2305:498b2387ef04 user: Dmitry Volyntsev date: Mon Apr 01 23:13:23 2024 -0700 description: Tests: simplified stream_js_import2.t. The test should only verify js_import directive in server context according to its description. diffstat: nginx/t/stream_js_import2.t | 59 +-------------------------------------------- 1 files changed, 1 insertions(+), 58 deletions(-) diffs (81 lines): diff -r e16e93f43303 -r 498b2387ef04 nginx/t/stream_js_import2.t --- a/nginx/t/stream_js_import2.t Mon Apr 01 23:13:21 2024 -0700 +++ b/nginx/t/stream_js_import2.t Mon Apr 01 23:13:23 2024 -0700 @@ -42,76 +42,19 @@ stream { js_set $test foo.bar.p; return $test; } - - server { - listen 127.0.0.1:8082; - - js_import lib.js; - - js_access lib.access; - js_preread lib.preread; - js_filter lib.filter; - proxy_pass 127.0.0.1:8083; - } - - server { - listen 127.0.0.1:8083; - return "x"; - } } EOF -$t->write_file('lib.js', <= 3) { - s.done(); - } - }); - } - - function filter(s) { - s.on('upload', function(data, flags) { - s.send(data); - res += '3'; - }); - - s.on('download', function(data, flags) { - if (!flags.last) { - res += '4'; - s.send(data); - - } else { - res += '5'; - s.send(res, {last:1}); - s.off('download'); - } - }); - } - - export default {access, preread, filter}; - -EOF - $t->write_file('main.js', <try_run('no njs available')->plan(2); +$t->try_run('no njs available')->plan(1); ############################################################################### is(stream('127.0.0.1:' . port(8081))->read(), 'P-TEST', 'foo.bar.p'); -is(stream('127.0.0.1:' . port(8082))->io('0'), 'x122345', 'lib.access'); ############################################################################### From xeioex at nginx.com Tue Apr 2 15:52:22 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 02 Apr 2024 15:52:22 +0000 Subject: [njs] Tests: adapt stream_js_preload_object.t to nginx changes. Message-ID: details: https://hg.nginx.org/njs/rev/454d9c032c60 branches: changeset: 2306:454d9c032c60 user: Dmitry Volyntsev date: Mon Apr 01 23:13:24 2024 -0700 description: Tests: adapt stream_js_preload_object.t to nginx changes. Make the test more robust against changes in nginx, specifically cf890df37bb6 (Stream: socket peek in preread phase). The filter callbacks may be called multiple times by nginx and the exact number is not specified. The new test avoids relying on the exact number of calls from nginx. diffstat: nginx/t/stream_js_preload_object.t | 21 ++++++++++----------- 1 files changed, 10 insertions(+), 11 deletions(-) diffs (56 lines): diff -r 498b2387ef04 -r 454d9c032c60 nginx/t/stream_js_preload_object.t --- a/nginx/t/stream_js_preload_object.t Mon Apr 01 23:13:23 2024 -0700 +++ b/nginx/t/stream_js_preload_object.t Mon Apr 01 23:13:24 2024 -0700 @@ -66,16 +66,17 @@ EOF $t->write_file('lib.js', <= 3) { + pup = g1.b[1]; + if (data.length > 0) { s.done(); } }); @@ -83,18 +84,16 @@ EOF function filter(s) { s.on('upload', function(data, flags) { + fup = g1.c.prop[0].a; s.send(data); - res += g1.c.prop[0].a; }); s.on('download', function(data, flags) { - if (!flags.last) { - res += g1.b[3]; - s.send(data); + fdown = g1.b[3]; + s.send(data); - } else { - res += g1.b[4]; - s.send(res, {last:1}); + if (flags.last) { + s.send(`\${acc}\${pup}\${fup}\${fdown}`, flags); s.off('download'); } }); @@ -117,6 +116,6 @@ EOF ############################################################################### is(stream('127.0.0.1:' . port(8081))->read(), 'element', 'foo.bar.p'); -is(stream('127.0.0.1:' . port(8082))->io('0'), 'x122345', 'lib.access'); +is(stream('127.0.0.1:' . port(8082))->io('0'), 'x1234', 'filter chain'); ############################################################################### From xeioex at nginx.com Tue Apr 2 15:52:24 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 02 Apr 2024 15:52:24 +0000 Subject: [njs] Tests: adapt stream_js.t to nginx changes. Message-ID: details: https://hg.nginx.org/njs/rev/17af51d42ad9 branches: changeset: 2307:17af51d42ad9 user: Dmitry Volyntsev date: Mon Apr 01 23:13:25 2024 -0700 description: Tests: adapt stream_js.t to nginx changes. Make the test more robust against changes in nginx, specifically cf890df37bb6 (Stream: socket peek in preread phase). The filter callbacks may be called multiple times by nginx and the exact number is not specified. The new test avoids relying on the exact number of calls from nginx. diffstat: nginx/t/stream_js.t | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) diffs (57 lines): diff -r 454d9c032c60 -r 17af51d42ad9 nginx/t/stream_js.t --- a/nginx/t/stream_js.t Mon Apr 01 23:13:24 2024 -0700 +++ b/nginx/t/stream_js.t Mon Apr 01 23:13:25 2024 -0700 @@ -227,9 +227,10 @@ EOF } var res = ''; + var step = (v) => { if (!res || res[res.length - 1] != v) res += v }; function access_step(s) { - res += '1'; + step(1); setTimeout(function() { if (s.remoteAddress.match('127.0.0.1')) { @@ -240,8 +241,8 @@ EOF function preread_step(s) { s.on('upload', function (data) { - res += '2'; - if (res.length >= 3) { + step(2); + if (data.length > 0) { s.done(); } }); @@ -249,18 +250,18 @@ EOF function filter_step(s) { s.on('upload', function(data, flags) { + step(3); s.send(data); - res += '3'; }); s.on('download', function(data, flags) { if (!flags.last) { - res += '4'; + step(4); s.send(data); } else { - res += '5'; + step(5); s.send(res, {last:1}); s.off('download'); } @@ -409,7 +410,7 @@ is(stream('127.0.0.1:' . port(8082))->re is(stream('127.0.0.1:' . port(8083))->read(), '', 'stream js unknown function'); is(stream('127.0.0.1:' . port(8084))->read(), 'sess_unk=undefined', 's.unk'); -is(stream('127.0.0.1:' . port(8086))->io('0'), '0122345', +is(stream('127.0.0.1:' . port(8086))->io('0'), '012345', 'async handlers order'); is(stream('127.0.0.1:' . port(8087))->io('#'), 'OK', 'access_undecided'); is(stream('127.0.0.1:' . port(8088))->io('#'), 'OK', 'access_allow'); From xeioex at nginx.com Tue Apr 2 16:13:44 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 02 Apr 2024 16:13:44 +0000 Subject: [njs] HTTP: validating URI and args arguments in r.subrequest(). Message-ID: details: https://hg.nginx.org/njs/rev/2d6d9d1e8b8f branches: changeset: 2308:2d6d9d1e8b8f user: Dmitry Volyntsev date: Tue Apr 02 08:52:56 2024 -0700 description: HTTP: validating URI and args arguments in r.subrequest(). diffstat: nginx/ngx_http_js_module.c | 37 +++++++++++++++++++++++++++++++++++++ nginx/t/js_subrequests.t | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 2 deletions(-) diffs (138 lines): diff -r 17af51d42ad9 -r 2d6d9d1e8b8f nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Apr 01 23:13:25 2024 -0700 +++ b/nginx/ngx_http_js_module.c Tue Apr 02 08:52:56 2024 -0700 @@ -305,6 +305,9 @@ static char *ngx_http_js_merge_loc_conf( static ngx_ssl_t *ngx_http_js_ssl(njs_vm_t *vm, ngx_http_request_t *r); static ngx_flag_t ngx_http_js_ssl_verify(njs_vm_t *vm, ngx_http_request_t *r); +static ngx_int_t ngx_http_js_parse_unsafe_uri(ngx_http_request_t *r, + njs_str_t *uri, njs_str_t *args); + #if (NGX_HTTP_SSL) static ngx_conf_bitmask_t ngx_http_js_ssl_protocols[] = { @@ -3272,6 +3275,11 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, } } + if (ngx_http_js_parse_unsafe_uri(r, &uri_arg, &args_arg) != NGX_OK) { + njs_vm_error(vm, "unsafe uri"); + return NJS_ERROR; + } + arg = njs_arg(args, nargs, 3); if (callback == NULL && !njs_value_is_undefined(arg)) { @@ -4979,3 +4987,32 @@ ngx_http_js_ssl_verify(njs_vm_t *vm, ngx return 0; #endif } + + +static ngx_int_t +ngx_http_js_parse_unsafe_uri(ngx_http_request_t *r, njs_str_t *uri, + njs_str_t *args) +{ + ngx_str_t uri_arg, args_arg; + ngx_uint_t flags; + + flags = NGX_HTTP_LOG_UNSAFE; + + uri_arg.data = uri->start; + uri_arg.len = uri->length; + + args_arg.data = args->start; + args_arg.len = args->length; + + if (ngx_http_parse_unsafe_uri(r, &uri_arg, &args_arg, &flags) != NGX_OK) { + return NGX_ERROR; + } + + uri->start = uri_arg.data; + uri->length = uri_arg.len; + + args->start = args_arg.data; + args->length = args_arg.len; + + return NGX_OK; +} diff -r 17af51d42ad9 -r 2d6d9d1e8b8f nginx/t/js_subrequests.t --- a/nginx/t/js_subrequests.t Mon Apr 01 23:13:25 2024 -0700 +++ b/nginx/t/js_subrequests.t Tue Apr 02 08:52:56 2024 -0700 @@ -148,6 +148,10 @@ http { js_content test.sr_unavail_pr; } + location /sr_unsafe { + js_content test.sr_unsafe; + } + location /sr_broken { js_content test.sr_broken; } @@ -385,6 +389,11 @@ EOF subrequest_fn_pr(req, ['/unavail'], ['uri', 'status']); } + function sr_unsafe(r) { + r.subrequest('../dir'); + r.return(200); + } + function sr_broken(r) { r.subrequest('/daemon/unfinished', reply => { r.return(200, JSON.stringify({code:reply.status})); @@ -498,13 +507,14 @@ EOF sr_unavail_pr, sr_broken, sr_too_large, sr_in_sr, sr_js_in_subrequest, sr_js_in_subrequest_pr, js_sub, sr_in_sr_callback, sr_out_of_order, sr_except_not_a_func, - sr_uri_except, sr_except_failed_to_convert_options_arg}; + sr_uri_except, sr_except_failed_to_convert_options_arg, + sr_unsafe}; EOF $t->write_file('t', '["SEE-THIS"]'); -$t->try_run('no njs available')->plan(32); +$t->try_run('no njs available')->plan(33); $t->run_daemon(\&http_daemon); ############################################################################### @@ -558,6 +568,13 @@ is(get_json('/sr_in_sr_callback'), '{"e":"subrequest can only be created for the primary request"}', 'subrequest for non-primary request'); +TODO: { +local $TODO = 'not yet' unless has_version('0.8.4'); + +like(http_get('/sr_unsafe'), qr/500/s, 'unsafe subrequest uri'); + +} + $t->stop(); ok(index($t->read_file('error.log'), 'callback is not a function') > 0, @@ -634,3 +651,22 @@ sub http_daemon { } ############################################################################### + +sub has_version { + my $need = shift; + + http_get('/njs') =~ /^([.0-9]+)$/m; + + my @v = split(/\./, $1); + my ($n, $v); + + for $n (split(/\./, $need)) { + $v = shift @v || 0; + return 0 if $n > $v; + return 1 if $v > $n; + } + + return 1; +} + +############################################################################### From yar at nginx.com Wed Apr 3 09:59:15 2024 From: yar at nginx.com (Yaroslav Zhuravlev) Date: Wed, 3 Apr 2024 10:59:15 +0100 Subject: [PATCH] Documented accept_filter, deferred, setfib in stream listen In-Reply-To: <9C6A2C82-932E-400C-816F-58A79C1CC927@nginx.com> References: <24664fe8ba2cc09e285d.1711379169@ORK-ML-00007151> <9C6A2C82-932E-400C-816F-58A79C1CC927@nginx.com> Message-ID: <47AD39B0-511F-4C50-BD9F-3EA94EBA6E5F@nginx.com> [...] >> @@ -154,6 +157,15 @@ >> >> >> >> +setfib=number >> + >> + >> +this parameter (1.25.4) sets the associated routing table, FIB > > Wrong version here and throughout the patch, > otherwise looks good (together with the "fastopen bind" patch). [...] Thank you for the review, the patches updated and committed: http://hg.nginx.org/nginx.org/rev/89e352295f7d http://hg.nginx.org/nginx.org/rev/c2a7e48c47bd From xeioex at nginx.com Fri Apr 5 01:38:38 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Fri, 05 Apr 2024 01:38:38 +0000 Subject: [njs] Configure: sorted options alphabetically in configure --help. Message-ID: details: https://hg.nginx.org/njs/rev/3a5b8b59cce9 branches: changeset: 2309:3a5b8b59cce9 user: Dmitry Volyntsev date: Thu Apr 04 16:07:37 2024 -0700 description: Configure: sorted options alphabetically in configure --help. diffstat: auto/help | 68 +++++++++++++++++++++++++++----------------------------------- 1 files changed, 30 insertions(+), 38 deletions(-) diffs (85 lines): diff -r 2d6d9d1e8b8f -r 3a5b8b59cce9 auto/help --- a/auto/help Tue Apr 02 08:52:56 2024 -0700 +++ b/auto/help Thu Apr 04 16:07:37 2024 -0700 @@ -7,46 +7,15 @@ cat << END ./configure options: - --cc=FILE set C compiler filename, default: "$CC" - --cc-opt=OPTIONS set additional C compiler options, \ -default: "$NJS_CC_OPT" - --ld-opt=OPTIONS set additional linker options, \ -default: "$NJS_LD_OPT" - --ar=FILE set static linking program, default: "$AR" - - --build-dir=DIR set build directory, default: "$NJS_BUILD_DIR" - - --no-pcre disables PCRE/PCRE2 discovery for RegExp - backend. This flag allows to build PCRE/PCRE2 - outside of libnjs.a. When this option is enabled - functions described in njs_regex.h are not built. - Instead this functions are expected to be provided - while linking. - - --no-pcre2 disables PCRE2 discovery for RegExp backend. - When this option is enabled only PCRE library - is discovered. - - --no-goto disables computed goto discovery. - When this option is enabled 'switch' statement - will be always used in instead of computed goto. - - --no-openssl disables OpenSSL discovery. When this option is - enabled OpenSSL dependant code is not built as a - part of libnjs.a. - - --no-libxml2 disabled libxml2 discovery. When this option is - enabled libxml2 dependant code is not built as a - part of libnjs.a. - - --no-zlib disabled zlib discovery. When this option is - enabled zlib dependant code is not built as a - part of libnjs.a. - + --addr2line=YES enables native function symbolization, \ +default: "$NJS_ADDR2LINE" --address-sanitizer=YES enables build with address sanitizer, \ default: "$NJS_ADDRESS_SANITIZER" - --addr2line=YES enables native function symbolization, \ -default: "$NJS_ADDR2LINE" + --ar=FILE sets static linking program, default: "$AR" + --build-dir=DIR sets build directory, default: "$NJS_BUILD_DIR" + --cc=FILE sets C compiler filename, default: "$CC" + --cc-opt=OPTIONS sets additional C compiler options, \ +default: "$NJS_CC_OPT" --debug=YES enables additional runtime checks, \ default: "$NJS_DEBUG" --debug-memory=YES enables memory alloc debug, \ @@ -55,4 +24,27 @@ default: "$NJS_DEBUG_MEMORY" default: "$NJS_DEBUG_OPCODE" --debug-generator=YES enables generator debug, \ default: "$NJS_DEBUG_GENERATOR" + --ld-opt=OPTIONS sets additional linker options, \ +default: "$NJS_LD_OPT" + --no-goto disables computed goto discovery. + When this option is enabled 'switch' statement + will be always used in instead of computed goto. + --no-libxml2 disables libxml2 discovery. When this option is + enabled libxml2 dependant code is not built as a + part of libnjs.a. + --no-openssl disables OpenSSL discovery. When this option is + enabled OpenSSL dependant code is not built as a + part of libnjs.a. + --no-pcre disables PCRE/PCRE2 discovery for RegExp + backend. This flag allows to build PCRE/PCRE2 + outside of libnjs.a. When this option is enabled + functions described in njs_regex.h are not built. + Instead this functions are expected to be provided + while linking. + --no-pcre2 disables PCRE2 discovery for RegExp backend. + When this option is enabled only PCRE library + is discovered. + --no-zlib disables zlib discovery. When this option is + enabled zlib dependant code is not built as a + part of libnjs.a. END From xeioex at nginx.com Fri Apr 5 01:38:40 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Fri, 05 Apr 2024 01:38:40 +0000 Subject: [njs] Configure: added --no-quickjs description in configure --help. Message-ID: details: https://hg.nginx.org/njs/rev/b83e2ae81937 branches: changeset: 2310:b83e2ae81937 user: Dmitry Volyntsev date: Thu Apr 04 16:07:39 2024 -0700 description: Configure: added --no-quickjs description in configure --help. Forgotten in cb3e068a511c. diffstat: auto/help | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r 3a5b8b59cce9 -r b83e2ae81937 auto/help --- a/auto/help Thu Apr 04 16:07:37 2024 -0700 +++ b/auto/help Thu Apr 04 16:07:39 2024 -0700 @@ -44,6 +44,7 @@ default: "$NJS_LD_OPT" --no-pcre2 disables PCRE2 discovery for RegExp backend. When this option is enabled only PCRE library is discovered. + --no-quickjs disables QuickJS engine discovery. --no-zlib disables zlib discovery. When this option is enabled zlib dependant code is not built as a part of libnjs.a. From xeioex at nginx.com Fri Apr 5 01:38:42 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Fri, 05 Apr 2024 01:38:42 +0000 Subject: [njs] Configure: improved QuickJS discovery. Message-ID: details: https://hg.nginx.org/njs/rev/834096122cef branches: changeset: 2311:834096122cef user: Dmitry Volyntsev date: Thu Apr 04 16:07:46 2024 -0700 description: Configure: improved QuickJS discovery. At the first try do not assume the exact library and includes location. diffstat: auto/quickjs | 16 ++++++++++++---- 1 files changed, 12 insertions(+), 4 deletions(-) diffs (43 lines): diff -r b83e2ae81937 -r 834096122cef auto/quickjs --- a/auto/quickjs Thu Apr 04 16:07:39 2024 -0700 +++ b/auto/quickjs Thu Apr 04 16:07:46 2024 -0700 @@ -9,11 +9,11 @@ NJS_HAVE_QUICKJS=NO if [ $NJS_QUICKJS = YES ]; then njs_found=no - njs_feature="QuickJS library" + njs_feature="QuickJS library -lquickjs.lto" njs_feature_name=NJS_HAVE_QUICKJS njs_feature_run=yes njs_feature_incs= - njs_feature_libs="" + njs_feature_libs="-lquickjs.lto -lm -ldl -lpthread" njs_feature_test="#if defined(__GNUC__) && (__GNUC__ >= 8) #pragma GCC diagnostic push #pragma GCC diagnostic ignored \"-Wcast-function-type\" @@ -31,7 +31,14 @@ if [ $NJS_QUICKJS = YES ]; then . auto/feature if [ $njs_found = no ]; then - njs_feature="QuickJS library -lquickjs.lto" + njs_feature="QuickJS library -lquickjs" + njs_feature_libs="-lquickjs -lm -ldl -lpthread" + + . auto/feature + fi + + if [ $njs_found = no ]; then + njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs.lto" njs_feature_incs="/usr/include/quickjs/" njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs.lto -lm -ldl -lpthread" @@ -39,7 +46,8 @@ if [ $NJS_QUICKJS = YES ]; then fi if [ $njs_found = no ]; then - njs_feature="QuickJS library -lquickjs" + njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs" + njs_feature_incs="/usr/include/quickjs/" njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs -lm -ldl -lpthread" . auto/feature From xeioex at nginx.com Fri Apr 5 01:38:44 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Fri, 05 Apr 2024 01:38:44 +0000 Subject: [njs] Configure: added --with-quickjs option. Message-ID: details: https://hg.nginx.org/njs/rev/1c8b6b9bc06c branches: changeset: 2312:1c8b6b9bc06c user: Dmitry Volyntsev date: Thu Apr 04 16:07:53 2024 -0700 description: Configure: added --with-quickjs option. diffstat: auto/help | 1 + auto/options | 6 ++++-- auto/quickjs | 13 ++++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diffs (81 lines): diff -r 834096122cef -r 1c8b6b9bc06c auto/help --- a/auto/help Thu Apr 04 16:07:46 2024 -0700 +++ b/auto/help Thu Apr 04 16:07:53 2024 -0700 @@ -48,4 +48,5 @@ default: "$NJS_LD_OPT" --no-zlib disables zlib discovery. When this option is enabled zlib dependant code is not built as a part of libnjs.a. + --with-quickjs requires QuickJS engine. END diff -r 834096122cef -r 1c8b6b9bc06c auto/options --- a/auto/options Thu Apr 04 16:07:46 2024 -0700 +++ b/auto/options Thu Apr 04 16:07:53 2024 -0700 @@ -14,7 +14,8 @@ NJS_DEBUG_GENERATOR=NO NJS_ADDRESS_SANITIZER=NO NJS_ADDR2LINE=NO -NJS_QUICKJS=YES +NJS_QUICKJS=NO +NJS_TRY_QUICKJS=YES NJS_OPENSSL=YES NJS_LIBXML2=YES NJS_ZLIB=YES @@ -48,7 +49,7 @@ do --debug-opcode=*) NJS_DEBUG_OPCODE="$value" ;; --debug-generator=*) NJS_DEBUG_GENERATOR="$value" ;; - --no-quickjs) NJS_QUICKJS=NO ;; + --no-quickjs) NJS_TRY_QUICKJS=NO ;; --no-openssl) NJS_OPENSSL=NO ;; --no-libxml2) NJS_LIBXML2=NO ;; --no-zlib) NJS_ZLIB=NO ;; @@ -57,6 +58,7 @@ do --no-pcre2) NJS_TRY_PCRE2=NO ;; --no-goto) NJS_TRY_GOTO=NO ;; + --with-quickjs) NJS_TRY_QUICKJS=YES; NJS_QUICKJS=YES ;; --help) . auto/help diff -r 834096122cef -r 1c8b6b9bc06c auto/quickjs --- a/auto/quickjs Thu Apr 04 16:07:46 2024 -0700 +++ b/auto/quickjs Thu Apr 04 16:07:53 2024 -0700 @@ -6,7 +6,7 @@ NJS_QUICKJS_LIB= NJS_HAVE_QUICKJS=NO -if [ $NJS_QUICKJS = YES ]; then +if [ $NJS_TRY_QUICKJS = YES ]; then njs_found=no njs_feature="QuickJS library -lquickjs.lto" @@ -40,7 +40,7 @@ if [ $NJS_QUICKJS = YES ]; then if [ $njs_found = no ]; then njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs.lto" njs_feature_incs="/usr/include/quickjs/" - njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs.lto -lm -ldl -lpthread" + njs_feature_libs="-L/usr/lib/quickjs/ -lquijs.lto -lm -ldl -lpthread" . auto/feature fi @@ -48,7 +48,7 @@ if [ $NJS_QUICKJS = YES ]; then if [ $njs_found = no ]; then njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs" njs_feature_incs="/usr/include/quickjs/" - njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs -lm -ldl -lpthread" + njs_feature_libs="-L/usr/lib/quickjs/ -lquijs -lm -ldl -lpthread" . auto/feature fi @@ -60,4 +60,11 @@ if [ $NJS_QUICKJS = YES ]; then NJS_LIB_AUX_LIBS="$NJS_LIB_AUX_LIBS $njs_feature_libs" fi + if [ $NJS_QUICKJS = YES -a $njs_found = no ]; then + echo + echo $0: error: no QuickJS library found. + echo + exit 1; + fi + fi From leesm815 at gmail.com Fri Apr 5 02:12:27 2024 From: leesm815 at gmail.com (Sangmin Lee) Date: Fri, 5 Apr 2024 11:12:27 +0900 Subject: No subject Message-ID: Hello, I think I found the main casue of memory leak issue when using gRPC stream so I made a patch for it. Please find the test scenario and details here -- This is what I wrote.: https://trac.nginx.org/nginx/ticket/2614 After I have changed memory pool totally on nginx and test our workload -- long-lived gRPC streams with many connections -- using Valgrind and massif, I was able to find what brought up the memory leak issue. like below picture. [image: Screenshot from 2024-04-02 11-49-29.png] After I patched one part, it seems okay now I have tested it for 1 week with out workload. [image: Screenshot from 2024-04-04 15-47-14.png] But because I am not familiar with the Mercurial so I couldn't find a way to create PR like on github. I guess this mailing list is for this patch. So I would like to further discuss here. >From my point of view, it is more like a workaround and I think the way of using ngx_chain_add_copy() or itself needs to be changed because it allocates a ngx_chain_t structure using ngx_alloc_chain_link() but inside of that, it just copies pointer, like cl->buf = in->buf; so this ngx_chain_t instance should be dealt with differently unlike other ngx_chain_t instances. But I am quite new to nginx codes so my view could be wrong. Anyhow, please consider this diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c index dfe49c586..1db67bd0a 100644 --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -1462,6 +1462,12 @@ ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in) in = in->next; } + ngx_chain_t *nl; + for (ngx_chain_t *dl = ctx->in; dl != in; dl = nl ) { + nl = dl->next; + ngx_free_chain(r->pool, dl); + } + ctx->in = in; if (last) { -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot from 2024-04-02 11-49-29.png Type: image/png Size: 371470 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot from 2024-04-04 15-47-14.png Type: image/png Size: 65011 bytes Desc: not available URL: From leesm815 at gmail.com Fri Apr 5 02:28:31 2024 From: leesm815 at gmail.com (Sangmin Lee) Date: Fri, 5 Apr 2024 11:28:31 +0900 Subject: I think I found a fix for the memory leak issue on gRPC module Message-ID: I am sending this mail again because I did a mistake while I was writing a mail. I didn't know, in gmail, "Ctrl - Enter" would send a mail immediately even without a title! I am sorry for that, so I am sending again. Hello, I think I found the main cause of the memory leak issue when using gRPC stream so I made a patch for it. Please find the test scenario and details here -- This is what I wrote.: https://trac.nginx.org/nginx/ticket/2614 After I changed the memory pool totally on nginx and tested our workload -- long-lived gRPC streams with many connections -- using Valgrind and massif, I was able to find what brought up the memory leak issue. like the picture below. [image: Screenshot from 2024-04-02 11-49-29.png] ( I am not sure whether this picture will be sent properly ) After I patched one part, it seems okay now I have tested it for 1 week with out workload. [image: Screenshot from 2024-04-04 15-47-14.png] ( I am not sure whether this picture will be sent properly ) But because I am not familiar with Mercurial, I couldn't find a way to create PR like on github. I guess this mailing list is for this patch. >From my point of view, it is more like a workaround and I think the way of using ngx_chain_add_copy() or itself needs to be changed because it allocates a ngx_chain_t structure using ngx_alloc_chain_link() but inside of that, it just copies pointer, like cl->buf = in->buf; so this ngx_chain_t instance should be dealt with differently unlike other ngx_chain_t instances. But I am quite new to nginx codes so my view might be wrong. Anyhow, please go over this patch and I would like to further talk here. -------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c index dfe49c586..1db67bd0a 100644 --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -1462,6 +1462,12 @@ ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in) in = in->next; } + ngx_chain_t *nl; + for (ngx_chain_t *dl = ctx->in; dl != in; dl = nl ) { + nl = dl->next; + ngx_free_chain(r->pool, dl); + } + ctx->in = in; if (last) { -------------------------------------------------------------------------------------------------------------------------------------------- Best regards, Sangmin -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot from 2024-04-02 11-49-29.png Type: image/png Size: 371470 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot from 2024-04-04 15-47-14.png Type: image/png Size: 65011 bytes Desc: not available URL: From pluknet at nginx.com Fri Apr 5 20:32:12 2024 From: pluknet at nginx.com (=?iso-8859-1?q?Sergey_Kandaurov?=) Date: Sat, 06 Apr 2024 00:32:12 +0400 Subject: [PATCH] Detecting duplicate addresses in listen among different modules Message-ID: <5fe21225ab3105aeea5e.1712349132@enoparse.local> # HG changeset patch # User Sergey Kandaurov # Date 1712349104 -14400 # Sat Apr 06 00:31:44 2024 +0400 # Node ID 5fe21225ab3105aeea5e381a5d39ec1d3cfc04e6 # Parent 47df39ea9e21c4359e0ca96dcc452f2bc8a82c44 Detecting duplicate addresses in listen among different modules. This is used to gracefully reject the following configurations during syntax checking with a "duplicate ... address and port pair" error: http { server { listen 127.0.0.1:8080; ... } } stream { server { listen 127.0.0.1:8080; ... } } Also for wildcard addresses: stream { server { listen 8080; ... } } mail { server { listen 8080; ... } } Notably, this won't catch mixed wildcard and non-wildcard addresses as follows, where http server block with a specific address never accepts new connections. The reason is that http will end up listening on the wildcard address, and stream is configured to listen on the specific address, which is technically a valid case. http { server { listen 127.0.0.1:8080; ... } server { listen 8080; ... } } stream { server { listen 127.0.0.1:8080; ... } } diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -21,10 +21,27 @@ ngx_create_listening(ngx_conf_t *cf, str socklen_t socklen) { size_t len; + ngx_uint_t i; ngx_listening_t *ls; struct sockaddr *sa; u_char text[NGX_SOCKADDR_STRLEN]; + ls = cf->cycle->listening.elts; + for (i = 0; i < cf->cycle->listening.nelts; i++) { + + if (ngx_cmp_sockaddr(ls[i].sockaddr, ls[i].socklen, + sockaddr, socklen, 1) + == NGX_DECLINED) + { + continue; + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate \"%V\" address and port pair", + &ls[i].addr_text); + return NULL; + } + ls = ngx_array_push(&cf->cycle->listening); if (ls == NULL) { return NULL; From arut at nginx.com Mon Apr 8 12:00:29 2024 From: arut at nginx.com (Roman Arutyunyan) Date: Mon, 8 Apr 2024 16:00:29 +0400 Subject: [PATCH] Detecting duplicate addresses in listen among different modules In-Reply-To: <5fe21225ab3105aeea5e.1712349132@enoparse.local> References: <5fe21225ab3105aeea5e.1712349132@enoparse.local> Message-ID: <44351E16-D2A7-4422-AF67-1C1FE7B88C25@nginx.com> Hi > On 6 Apr 2024, at 12:32 AM, Sergey Kandaurov wrote: > > # HG changeset patch > # User Sergey Kandaurov > # Date 1712349104 -14400 > # Sat Apr 06 00:31:44 2024 +0400 > # Node ID 5fe21225ab3105aeea5e381a5d39ec1d3cfc04e6 > # Parent 47df39ea9e21c4359e0ca96dcc452f2bc8a82c44 > Detecting duplicate addresses in listen among different modules. > > This is used to gracefully reject the following configurations during > syntax checking with a "duplicate ... address and port pair" error: > > http { > server { > listen 127.0.0.1:8080; > ... > } > } > > stream { > server { > listen 127.0.0.1:8080; > ... > } > } > > Also for wildcard addresses: > > stream { > server { > listen 8080; > ... > } > } > > mail { > server { > listen 8080; > ... > } > } > > Notably, this won't catch mixed wildcard and non-wildcard addresses as > follows, where http server block with a specific address never accepts > new connections. Not sure what you mean mean by 'never accepts', but new connections surely will be accepted by this server, just not directly. You probably mean there's no designated listen socket for that address. > The reason is that http will end up listening on the > wildcard address, and stream is configured to listen on the specific > address, which is technically a valid case. > > http { > server { > listen 127.0.0.1:8080; > ... > } > > server { > listen 8080; > ... > } > } > > stream { > server { > listen 127.0.0.1:8080; > ... > } > } > > diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c > --- a/src/core/ngx_connection.c > +++ b/src/core/ngx_connection.c > @@ -21,10 +21,27 @@ ngx_create_listening(ngx_conf_t *cf, str > socklen_t socklen) > { > size_t len; > + ngx_uint_t i; > ngx_listening_t *ls; > struct sockaddr *sa; > u_char text[NGX_SOCKADDR_STRLEN]; > > + ls = cf->cycle->listening.elts; > + for (i = 0; i < cf->cycle->listening.nelts; i++) { > + > + if (ngx_cmp_sockaddr(ls[i].sockaddr, ls[i].socklen, > + sockaddr, socklen, 1) > + == NGX_DECLINED) > + { > + continue; > + } > + > + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, > + "duplicate \"%V\" address and port pair", > + &ls[i].addr_text); > + return NULL; > + } > + > ls = ngx_array_push(&cf->cycle->listening); > if (ls == NULL) { > return NULL; > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel I like the idea of fixing address collisions between modules. However, the patch does not fix the problem entirely and leaves room for misconfigurations. IMHO we need to think how to properly fix this. One way for fixing this is rejecting any overlapping listen addresses. We need to evaluate how likely it is that reasonable configurations will be restricted by this. It doesn't seem likely to me. ---- Roman Arutyunyan arut at nginx.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From vl at inspert.ru Mon Apr 8 12:03:27 2024 From: vl at inspert.ru (Vladimir Homutov) Date: Mon, 8 Apr 2024 15:03:27 +0300 Subject: [nginx] QUIC: "handshake_timeout" configuration parameter. In-Reply-To: References: Message-ID: On Fri, Sep 22, 2023 at 03:36:25PM +0000, Roman Arutyunyan wrote: > details: https://hg.nginx.org/nginx/rev/ad3d34ddfdcc > branches: > changeset: 9158:ad3d34ddfdcc > user: Roman Arutyunyan > date: Wed Sep 13 17:59:37 2023 +0400 > description: > QUIC: "handshake_timeout" configuration parameter. > > Previously QUIC did not have such parameter and handshake duration was > controlled by HTTP/3. However that required creating and storing HTTP/3 > session on first client datagram. Apparently there's no convenient way to > store the session object until QUIC handshake is complete. In the followup > patches session creation will be postponed to init() callback. > [...] > diff -r daf8f5ba23d8 -r ad3d34ddfdcc src/event/quic/ngx_event_quic.c > --- a/src/event/quic/ngx_event_quic.c Fri Sep 01 20:31:46 2023 +0400 > +++ b/src/event/quic/ngx_event_quic.c Wed Sep 13 17:59:37 2023 +0400 > @@ -211,6 +211,8 @@ ngx_quic_run(ngx_connection_t *c, ngx_qu > qc = ngx_quic_get_connection(c); > > ngx_add_timer(c->read, qc->tp.max_idle_timeout); > + ngx_add_timer(&qc->close, qc->conf->handshake_timeout); > + It looks like I've hit an issue with early data in such case. See the attached patch with details. While there, I suggest a little debug improvement to better track stream and their parent connections. -------------- next part -------------- # HG changeset patch # User Vladimir Khomutov # Date 1712576340 -10800 # Mon Apr 08 14:39:00 2024 +0300 # Node ID 6e79f4ec40ed1c1ffec6a46b453051c01e556610 # Parent 99e7050ac886f7c70a4048691e46846b930b1e28 QUIC: fixed close timer processing with early data. The ngx_quic_run() function uses qc->close timer to limit the handshake duration. Normally it is removed by ngx_quic_do_init_streams() which is called once when we are done with initial SSL processing. The problem happens when the client sends early data and streams are initialized in the ngx_quic_run() -> ngx_quic_handle_datagram() call. The order of set/remove timer calls is now reversed; the close timer is set up and the timer fires when assigned, starting the unexpected connection close process. The patch moves timer cancelling right before the place where the stream initialization flag is tested, thus making it work with early data. The issue was introduced in ad3d34ddfdcc. diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c --- a/src/event/quic/ngx_event_quic_streams.c +++ b/src/event/quic/ngx_event_quic_streams.c @@ -575,6 +575,10 @@ ngx_quic_init_streams(ngx_connection_t * qc = ngx_quic_get_connection(c); + if (!qc->closing && qc->close.timer_set) { + ngx_del_timer(&qc->close); + } + if (qc->streams.initialized) { return NGX_OK; } @@ -630,10 +634,6 @@ ngx_quic_do_init_streams(ngx_connection_ qc->streams.initialized = 1; - if (!qc->closing && qc->close.timer_set) { - ngx_del_timer(&qc->close); - } - return NGX_OK; } -------------- next part -------------- # HG changeset patch # User Vladimir Khomutov # Date 1712575741 -10800 # Mon Apr 08 14:29:01 2024 +0300 # Node ID d9b80de50040bb8ac2a7e193971d1dfeb579cfc9 # Parent 6e79f4ec40ed1c1ffec6a46b453051c01e556610 QUIC: added debug logging of stream creation. Currently, it is hard to associate stream connection number with its parent connection. The typical case is to identify QUIC connection number given some user-visible URI (which occurs in request stream). The patch adds the debug log message which reports about stream creation in the stream log and also shows the parent connection number. diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c --- a/src/event/quic/ngx_event_quic_streams.c +++ b/src/event/quic/ngx_event_quic_streams.c @@ -805,6 +805,10 @@ ngx_quic_create_stream(ngx_connection_t ngx_rbtree_insert(&qc->streams.tree, &qs->node); + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, sc->log, 0, + "quic stream id:0x%xL created in connection *%uA", id, + c->log->connection); + return qs; } From xeioex at nginx.com Tue Apr 9 05:48:00 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 09 Apr 2024 05:48:00 +0000 Subject: [njs] Modules: checking for duplicate js_set variables. Message-ID: details: https://hg.nginx.org/njs/rev/6fb1aca4eeaf branches: changeset: 2313:6fb1aca4eeaf user: Dmitry Volyntsev date: Mon Apr 08 22:47:24 2024 -0700 description: Modules: checking for duplicate js_set variables. This closes #700 issue on Github. diffstat: nginx/ngx_http_js_module.c | 6 ++++++ nginx/ngx_stream_js_module.c | 6 ++++++ 2 files changed, 12 insertions(+), 0 deletions(-) diffs (32 lines): diff -r 1c8b6b9bc06c -r 6fb1aca4eeaf nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Thu Apr 04 16:07:53 2024 -0700 +++ b/nginx/ngx_http_js_module.c Mon Apr 08 22:47:24 2024 -0700 @@ -4773,6 +4773,12 @@ ngx_http_js_set(ngx_conf_t *cf, ngx_comm *fname = value[2]; + if (v->get_handler == ngx_http_js_variable_set) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "variable \"%V\" is already declared", &value[1]); + return NGX_CONF_ERROR; + } + v->get_handler = ngx_http_js_variable_set; v->data = (uintptr_t) fname; diff -r 1c8b6b9bc06c -r 6fb1aca4eeaf nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Thu Apr 04 16:07:53 2024 -0700 +++ b/nginx/ngx_stream_js_module.c Mon Apr 08 22:47:24 2024 -0700 @@ -2217,6 +2217,12 @@ ngx_stream_js_set(ngx_conf_t *cf, ngx_co *fname = value[2]; + if (v->get_handler == ngx_stream_js_variable_set) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "variable \"%V\" is already declared", &value[1]); + return NGX_CONF_ERROR; + } + v->get_handler = ngx_stream_js_variable_set; v->data = (uintptr_t) fname; From xeioex at nginx.com Tue Apr 9 05:48:01 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 09 Apr 2024 05:48:01 +0000 Subject: [njs] HTTP: fixed r.send() with Buffer argument. Message-ID: details: https://hg.nginx.org/njs/rev/adaeb3c3f59a branches: changeset: 2314:adaeb3c3f59a user: Dmitry Volyntsev date: Mon Apr 08 22:47:28 2024 -0700 description: HTTP: fixed r.send() with Buffer argument. Previously, only string value type was accepted. This closes #701 issue on Github. diffstat: nginx/ngx_http_js_module.c | 69 ++++++++++++++++++---------------------------- nginx/t/js.t | 22 +++++++++++++- src/njs.h | 2 - src/njs_vm.c | 41 --------------------------- 4 files changed, 47 insertions(+), 87 deletions(-) diffs (208 lines): diff -r 6fb1aca4eeaf -r adaeb3c3f59a nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Apr 08 22:47:24 2024 -0700 +++ b/nginx/ngx_http_js_module.c Mon Apr 08 22:47:28 2024 -0700 @@ -2199,10 +2199,8 @@ static njs_int_t ngx_http_js_ext_send(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - njs_int_t ret; njs_str_t s; ngx_buf_t *b; - uintptr_t next; ngx_uint_t n; ngx_chain_t *out, *cl, **ll; ngx_http_js_ctx_t *ctx; @@ -2226,47 +2224,34 @@ ngx_http_js_ext_send(njs_vm_t *vm, njs_v ll = &out; for (n = 1; n < nargs; n++) { - next = 0; - - for ( ;; ) { - ret = njs_vm_value_string_copy(vm, &s, njs_argument(args, n), - &next); - - if (ret == NJS_DECLINED) { - break; - } - - if (ret == NJS_ERROR) { - return NJS_ERROR; - } - - if (s.length == 0) { - continue; - } - - /* TODO: njs_value_release(vm, value) in buf completion */ - - b = ngx_calloc_buf(r->pool); - if (b == NULL) { - return NJS_ERROR; - } - - b->start = s.start; - b->pos = b->start; - b->end = s.start + s.length; - b->last = b->end; - b->memory = 1; - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NJS_ERROR; - } - - cl->buf = b; - - *ll = cl; - ll = &cl->next; + if (ngx_js_string(vm, njs_argument(args, n), &s) != NGX_OK) { + return NJS_ERROR; + } + + if (s.length == 0) { + continue; + } + + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NJS_ERROR; } + + b->start = s.start; + b->pos = b->start; + b->end = s.start + s.length; + b->last = b->end; + b->memory = 1; + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NJS_ERROR; + } + + cl->buf = b; + + *ll = cl; + ll = &cl->next; } *ll = NULL; diff -r 6fb1aca4eeaf -r adaeb3c3f59a nginx/t/js.t --- a/nginx/t/js.t Mon Apr 08 22:47:24 2024 -0700 +++ b/nginx/t/js.t Mon Apr 08 22:47:28 2024 -0700 @@ -112,6 +112,10 @@ http { js_content test.send; } + location /send_buffer { + js_content test.send_buffer; + } + location /return_method { js_content test.return_method; } @@ -219,6 +223,13 @@ EOF r.finish(); } + function send_buffer(r) { + r.status = 200; + r.sendHeader(); + r.send(Buffer.from("send_buffer")); + r.finish(); + } + function return_method(r) { r.return(Number(r.args.c), r.args.t); } @@ -265,11 +276,11 @@ EOF variable, global_obj, status, request_body, internal, request_body_cache, send, return_method, sub_internal, type, log, buffer_variable, except, content_except, - content_empty}; + content_empty, send_buffer}; EOF -$t->try_run('no njs available')->plan(28); +$t->try_run('no njs available')->plan(29); ############################################################################### @@ -289,6 +300,13 @@ like(http_post_big('/body'), qr/200.*^(1 like(http_get('/send?foo=12345&n=11&foo-2=bar&ndd=&foo-3=z'), qr/n=foo, v=12 n=foo-2, v=ba n=foo-3, v=z/, 'r.send'); +TODO: { +local $TODO = 'not yet' unless has_version('0.8.4'); + +like(http_get('/send_buffer'), qr/send_buffer/, 'r.send accepts buffer'); + +} + like(http_get('/return_method?c=200'), qr/200 OK.*\x0d\x0a?\x0d\x0a?$/s, 'return code'); like(http_get('/return_method?c=200&t=SEE-THIS'), qr/200 OK.*^SEE-THIS$/ms, diff -r 6fb1aca4eeaf -r adaeb3c3f59a src/njs.h --- a/src/njs.h Mon Apr 08 22:47:24 2024 -0700 +++ b/src/njs.h Mon Apr 08 22:47:28 2024 -0700 @@ -412,8 +412,6 @@ NJS_EXPORT njs_int_t njs_vm_value_string njs_value_t *value, const u_char *start, uint32_t size); NJS_EXPORT njs_int_t njs_vm_value_string_create_chb(njs_vm_t *vm, njs_value_t *value, njs_chb_t *chain); -NJS_EXPORT njs_int_t njs_vm_value_string_copy(njs_vm_t *vm, njs_str_t *retval, - njs_value_t *value, uintptr_t *next); NJS_EXPORT njs_int_t njs_vm_string_compare(const njs_value_t *v1, const njs_value_t *v2); diff -r 6fb1aca4eeaf -r adaeb3c3f59a src/njs_vm.c --- a/src/njs_vm.c Mon Apr 08 22:47:24 2024 -0700 +++ b/src/njs_vm.c Mon Apr 08 22:47:28 2024 -0700 @@ -1662,47 +1662,6 @@ njs_vm_string_compare(const njs_value_t } -njs_int_t -njs_vm_value_string_copy(njs_vm_t *vm, njs_str_t *retval, - njs_value_t *value, uintptr_t *next) -{ - uintptr_t n; - njs_array_t *array; - - switch (value->type) { - - case NJS_STRING: - if (*next != 0) { - return NJS_DECLINED; - } - - *next = 1; - break; - - case NJS_ARRAY: - array = njs_array(value); - - do { - n = (*next)++; - - if (n == array->length) { - return NJS_DECLINED; - } - - value = &array->start[n]; - - } while (!njs_is_valid(value)); - - break; - - default: - return NJS_ERROR; - } - - return njs_vm_value_to_string(vm, retval, value); -} - - void * njs_lvlhsh_alloc(void *data, size_t size) { From arut at nginx.com Tue Apr 9 11:02:21 2024 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 9 Apr 2024 15:02:21 +0400 Subject: [nginx] QUIC: "handshake_timeout" configuration parameter. In-Reply-To: References: Message-ID: <20240408174935.omy57pu6dxijkvab@N00W24XTQX> Hello Vladimir, On Mon, Apr 08, 2024 at 03:03:27PM +0300, Vladimir Homutov via nginx-devel wrote: > On Fri, Sep 22, 2023 at 03:36:25PM +0000, Roman Arutyunyan wrote: > > details: https://hg.nginx.org/nginx/rev/ad3d34ddfdcc > > branches: > > changeset: 9158:ad3d34ddfdcc > > user: Roman Arutyunyan > > date: Wed Sep 13 17:59:37 2023 +0400 > > description: > > QUIC: "handshake_timeout" configuration parameter. > > > > Previously QUIC did not have such parameter and handshake duration was > > controlled by HTTP/3. However that required creating and storing HTTP/3 > > session on first client datagram. Apparently there's no convenient way to > > store the session object until QUIC handshake is complete. In the followup > > patches session creation will be postponed to init() callback. > > > > [...] > > > diff -r daf8f5ba23d8 -r ad3d34ddfdcc src/event/quic/ngx_event_quic.c > > --- a/src/event/quic/ngx_event_quic.c Fri Sep 01 20:31:46 2023 +0400 > > +++ b/src/event/quic/ngx_event_quic.c Wed Sep 13 17:59:37 2023 +0400 > > @@ -211,6 +211,8 @@ ngx_quic_run(ngx_connection_t *c, ngx_qu > > qc = ngx_quic_get_connection(c); > > > > ngx_add_timer(c->read, qc->tp.max_idle_timeout); > > + ngx_add_timer(&qc->close, qc->conf->handshake_timeout); > > + > > It looks like I've hit an issue with early data in such case. > See the attached patch with details. Indeed, there's an issue there. > While there, I suggest a little debug improvement to better track > stream and their parent connections. > > > # HG changeset patch > # User Vladimir Khomutov > # Date 1712576340 -10800 > # Mon Apr 08 14:39:00 2024 +0300 > # Node ID 6e79f4ec40ed1c1ffec6a46b453051c01e556610 > # Parent 99e7050ac886f7c70a4048691e46846b930b1e28 > QUIC: fixed close timer processing with early data. > > The ngx_quic_run() function uses qc->close timer to limit the handshake > duration. Normally it is removed by ngx_quic_do_init_streams() which is > called once when we are done with initial SSL processing. > > The problem happens when the client sends early data and streams are > initialized in the ngx_quic_run() -> ngx_quic_handle_datagram() call. > The order of set/remove timer calls is now reversed; the close timer is > set up and the timer fires when assigned, starting the unexpected connection > close process. > > The patch moves timer cancelling right before the place where the stream > initialization flag is tested, thus making it work with early data. > > The issue was introduced in ad3d34ddfdcc. > > diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c > --- a/src/event/quic/ngx_event_quic_streams.c > +++ b/src/event/quic/ngx_event_quic_streams.c > @@ -575,6 +575,10 @@ ngx_quic_init_streams(ngx_connection_t * > > qc = ngx_quic_get_connection(c); > > + if (!qc->closing && qc->close.timer_set) { > + ngx_del_timer(&qc->close); > + } > + > if (qc->streams.initialized) { > return NGX_OK; > } > @@ -630,10 +634,6 @@ ngx_quic_do_init_streams(ngx_connection_ > > qc->streams.initialized = 1; > > - if (!qc->closing && qc->close.timer_set) { > - ngx_del_timer(&qc->close); > - } > - > return NGX_OK; > } This assumes that ngx_quic_init_streams() is always called on handshake end, even if not needed. This is true now, but it's not something we can to rely on. Also, we probably don't need to limit handshake duration after streams are initialized. Application level will set the required keepalive timeout for this. Also, we need to include OCSP validation time in handshake timeout, which your removed. I assume a simpler solution would be not to set the timer in ngx_quic_run() if streams are already initialized. > # HG changeset patch > # User Vladimir Khomutov > # Date 1712575741 -10800 > # Mon Apr 08 14:29:01 2024 +0300 > # Node ID d9b80de50040bb8ac2a7e193971d1dfeb579cfc9 > # Parent 6e79f4ec40ed1c1ffec6a46b453051c01e556610 > QUIC: added debug logging of stream creation. > > Currently, it is hard to associate stream connection number with its parent > connection. The typical case is to identify QUIC connection number given > some user-visible URI (which occurs in request stream). > > The patch adds the debug log message which reports about stream creation in > the stream log and also shows the parent connection number. > > diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c > --- a/src/event/quic/ngx_event_quic_streams.c > +++ b/src/event/quic/ngx_event_quic_streams.c > @@ -805,6 +805,10 @@ ngx_quic_create_stream(ngx_connection_t > > ngx_rbtree_insert(&qc->streams.tree, &qs->node); > > + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, sc->log, 0, > + "quic stream id:0x%xL created in connection *%uA", id, > + c->log->connection); > + > return qs; > } > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel -- Roman Arutyunyan From vl at inspert.ru Wed Apr 10 06:57:16 2024 From: vl at inspert.ru (Vladimir Homutov) Date: Wed, 10 Apr 2024 09:57:16 +0300 Subject: [nginx] QUIC: "handshake_timeout" configuration parameter. In-Reply-To: <20240408174935.omy57pu6dxijkvab@N00W24XTQX> References: <20240408174935.omy57pu6dxijkvab@N00W24XTQX> Message-ID: On Tue, Apr 09, 2024 at 03:02:21PM +0400, Roman Arutyunyan wrote: > Hello Vladimir, > > On Mon, Apr 08, 2024 at 03:03:27PM +0300, Vladimir Homutov via nginx-devel wrote: > > On Fri, Sep 22, 2023 at 03:36:25PM +0000, Roman Arutyunyan wrote: > > > details: https://hg.nginx.org/nginx/rev/ad3d34ddfdcc > > > branches: > > > changeset: 9158:ad3d34ddfdcc > > > user: Roman Arutyunyan > > > date: Wed Sep 13 17:59:37 2023 +0400 > > > description: > > > QUIC: "handshake_timeout" configuration parameter. > > > > > > Previously QUIC did not have such parameter and handshake duration was > > > controlled by HTTP/3. However that required creating and storing HTTP/3 > > > session on first client datagram. Apparently there's no convenient way to > > > store the session object until QUIC handshake is complete. In the followup > > > patches session creation will be postponed to init() callback. > > > > > > > [...] > > > > > diff -r daf8f5ba23d8 -r ad3d34ddfdcc src/event/quic/ngx_event_quic.c > > > --- a/src/event/quic/ngx_event_quic.c Fri Sep 01 20:31:46 2023 +0400 > > > +++ b/src/event/quic/ngx_event_quic.c Wed Sep 13 17:59:37 2023 +0400 > > > @@ -211,6 +211,8 @@ ngx_quic_run(ngx_connection_t *c, ngx_qu > > > qc = ngx_quic_get_connection(c); > > > > > > ngx_add_timer(c->read, qc->tp.max_idle_timeout); > > > + ngx_add_timer(&qc->close, qc->conf->handshake_timeout); > > > + > > > > It looks like I've hit an issue with early data in such case. > > See the attached patch with details. > > Indeed, there's an issue there. > > > While there, I suggest a little debug improvement to better track > > stream and their parent connections. > > > > > > > # HG changeset patch > > # User Vladimir Khomutov > > # Date 1712576340 -10800 > > # Mon Apr 08 14:39:00 2024 +0300 > > # Node ID 6e79f4ec40ed1c1ffec6a46b453051c01e556610 > > # Parent 99e7050ac886f7c70a4048691e46846b930b1e28 > > QUIC: fixed close timer processing with early data. > > > > The ngx_quic_run() function uses qc->close timer to limit the handshake > > duration. Normally it is removed by ngx_quic_do_init_streams() which is > > called once when we are done with initial SSL processing. > > > > The problem happens when the client sends early data and streams are > > initialized in the ngx_quic_run() -> ngx_quic_handle_datagram() call. > > The order of set/remove timer calls is now reversed; the close timer is > > set up and the timer fires when assigned, starting the unexpected connection > > close process. > > > > The patch moves timer cancelling right before the place where the stream > > initialization flag is tested, thus making it work with early data. > > > > The issue was introduced in ad3d34ddfdcc. > > > > diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c > > --- a/src/event/quic/ngx_event_quic_streams.c > > +++ b/src/event/quic/ngx_event_quic_streams.c > > @@ -575,6 +575,10 @@ ngx_quic_init_streams(ngx_connection_t * > > > > qc = ngx_quic_get_connection(c); > > > > + if (!qc->closing && qc->close.timer_set) { > > + ngx_del_timer(&qc->close); > > + } > > + > > if (qc->streams.initialized) { > > return NGX_OK; > > } > > @@ -630,10 +634,6 @@ ngx_quic_do_init_streams(ngx_connection_ > > > > qc->streams.initialized = 1; > > > > - if (!qc->closing && qc->close.timer_set) { > > - ngx_del_timer(&qc->close); > > - } > > - > > return NGX_OK; > > } > > This assumes that ngx_quic_init_streams() is always called on handshake end, > even if not needed. This is true now, but it's not something we can to rely on. > > Also, we probably don't need to limit handshake duration after streams are > initialized. Application level will set the required keepalive timeout for > this. Also, we need to include OCSP validation time in handshake timeout, > which your removed. > > I assume a simpler solution would be not to set the timer in ngx_quic_run() > if streams are already initialized. Agreed, see the updated patch: -------------- next part -------------- # HG changeset patch # User Vladimir Khomutov # Date 1712731090 -10800 # Wed Apr 10 09:38:10 2024 +0300 # Node ID 155c9093de9db02e3c0a511a45930d39ff51c709 # Parent 99e7050ac886f7c70a4048691e46846b930b1e28 QUIC: fixed close timer processing with early data. The ngx_quic_run() function uses qc->close timer to limit the handshake duration. Normally it is removed by ngx_quic_do_init_streams() which is called once when we are done with initial SSL processing. The problem happens when the client sends early data and streams are initialized in the ngx_quic_run() -> ngx_quic_handle_datagram() call. The order of set/remove timer calls is now reversed; the close timer is set up and the timer fires when assigned, starting the unexpected connection close process. The fix is to skip setting the timer if streams were initialized during handling of the initial datagram. The idle timer for quic is set anyway, and stream-related timeouts are managed by application layer. diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -211,7 +211,10 @@ ngx_quic_run(ngx_connection_t *c, ngx_qu qc = ngx_quic_get_connection(c); ngx_add_timer(c->read, qc->tp.max_idle_timeout); - ngx_add_timer(&qc->close, qc->conf->handshake_timeout); + + if (!qc->streams.initialized) { + ngx_add_timer(&qc->close, qc->conf->handshake_timeout); + } ngx_quic_connstate_dbg(c); From arut at nginx.com Wed Apr 10 11:47:40 2024 From: arut at nginx.com (=?utf-8?q?Roman_Arutyunyan?=) Date: Wed, 10 Apr 2024 11:47:40 +0000 Subject: [nginx] QUIC: fixed close timer processing with early data. Message-ID: details: https://hg.nginx.org/nginx/rev/155c9093de9d branches: changeset: 9236:155c9093de9d user: Vladimir Khomutov date: Wed Apr 10 09:38:10 2024 +0300 description: QUIC: fixed close timer processing with early data. The ngx_quic_run() function uses qc->close timer to limit the handshake duration. Normally it is removed by ngx_quic_do_init_streams() which is called once when we are done with initial SSL processing. The problem happens when the client sends early data and streams are initialized in the ngx_quic_run() -> ngx_quic_handle_datagram() call. The order of set/remove timer calls is now reversed; the close timer is set up and the timer fires when assigned, starting the unexpected connection close process. The fix is to skip setting the timer if streams were initialized during handling of the initial datagram. The idle timer for quic is set anyway, and stream-related timeouts are managed by application layer. diffstat: src/event/quic/ngx_event_quic.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diffs (15 lines): diff -r 99e7050ac886 -r 155c9093de9d src/event/quic/ngx_event_quic.c --- a/src/event/quic/ngx_event_quic.c Mon Feb 26 20:00:48 2024 +0000 +++ b/src/event/quic/ngx_event_quic.c Wed Apr 10 09:38:10 2024 +0300 @@ -211,7 +211,10 @@ ngx_quic_run(ngx_connection_t *c, ngx_qu qc = ngx_quic_get_connection(c); ngx_add_timer(c->read, qc->tp.max_idle_timeout); - ngx_add_timer(&qc->close, qc->conf->handshake_timeout); + + if (!qc->streams.initialized) { + ngx_add_timer(&qc->close, qc->conf->handshake_timeout); + } ngx_quic_connstate_dbg(c); From arut at nginx.com Wed Apr 10 11:57:33 2024 From: arut at nginx.com (Roman Arutyunyan) Date: Wed, 10 Apr 2024 15:57:33 +0400 Subject: [nginx] QUIC: "handshake_timeout" configuration parameter. In-Reply-To: References: <20240408174935.omy57pu6dxijkvab@N00W24XTQX> Message-ID: <60198A82-55F9-48BB-9E22-21CEB2059106@nginx.com> Hi, > On 10 Apr 2024, at 10:57 AM, Vladimir Homutov wrote: > > On Tue, Apr 09, 2024 at 03:02:21PM +0400, Roman Arutyunyan wrote: >> Hello Vladimir, >> >> On Mon, Apr 08, 2024 at 03:03:27PM +0300, Vladimir Homutov via nginx-devel wrote: >>> On Fri, Sep 22, 2023 at 03:36:25PM +0000, Roman Arutyunyan wrote: >>>> details: https://hg.nginx.org/nginx/rev/ad3d34ddfdcc >>>> branches: >>>> changeset: 9158:ad3d34ddfdcc >>>> user: Roman Arutyunyan >>>> date: Wed Sep 13 17:59:37 2023 +0400 >>>> description: >>>> QUIC: "handshake_timeout" configuration parameter. >>>> >>>> Previously QUIC did not have such parameter and handshake duration was >>>> controlled by HTTP/3. However that required creating and storing HTTP/3 >>>> session on first client datagram. Apparently there's no convenient way to >>>> store the session object until QUIC handshake is complete. In the followup >>>> patches session creation will be postponed to init() callback. >>>> >>> >>> [...] >>> >>>> diff -r daf8f5ba23d8 -r ad3d34ddfdcc src/event/quic/ngx_event_quic.c >>>> --- a/src/event/quic/ngx_event_quic.c Fri Sep 01 20:31:46 2023 +0400 >>>> +++ b/src/event/quic/ngx_event_quic.c Wed Sep 13 17:59:37 2023 +0400 >>>> @@ -211,6 +211,8 @@ ngx_quic_run(ngx_connection_t *c, ngx_qu >>>> qc = ngx_quic_get_connection(c); >>>> >>>> ngx_add_timer(c->read, qc->tp.max_idle_timeout); >>>> + ngx_add_timer(&qc->close, qc->conf->handshake_timeout); >>>> + >>> >>> It looks like I've hit an issue with early data in such case. >>> See the attached patch with details. >> >> Indeed, there's an issue there. >> >>> While there, I suggest a little debug improvement to better track >>> stream and their parent connections. >>> >>> >> >>> # HG changeset patch >>> # User Vladimir Khomutov >>> # Date 1712576340 -10800 >>> # Mon Apr 08 14:39:00 2024 +0300 >>> # Node ID 6e79f4ec40ed1c1ffec6a46b453051c01e556610 >>> # Parent 99e7050ac886f7c70a4048691e46846b930b1e28 >>> QUIC: fixed close timer processing with early data. >>> >>> The ngx_quic_run() function uses qc->close timer to limit the handshake >>> duration. Normally it is removed by ngx_quic_do_init_streams() which is >>> called once when we are done with initial SSL processing. >>> >>> The problem happens when the client sends early data and streams are >>> initialized in the ngx_quic_run() -> ngx_quic_handle_datagram() call. >>> The order of set/remove timer calls is now reversed; the close timer is >>> set up and the timer fires when assigned, starting the unexpected connection >>> close process. >>> >>> The patch moves timer cancelling right before the place where the stream >>> initialization flag is tested, thus making it work with early data. >>> >>> The issue was introduced in ad3d34ddfdcc. >>> >>> diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c >>> --- a/src/event/quic/ngx_event_quic_streams.c >>> +++ b/src/event/quic/ngx_event_quic_streams.c >>> @@ -575,6 +575,10 @@ ngx_quic_init_streams(ngx_connection_t * >>> >>> qc = ngx_quic_get_connection(c); >>> >>> + if (!qc->closing && qc->close.timer_set) { >>> + ngx_del_timer(&qc->close); >>> + } >>> + >>> if (qc->streams.initialized) { >>> return NGX_OK; >>> } >>> @@ -630,10 +634,6 @@ ngx_quic_do_init_streams(ngx_connection_ >>> >>> qc->streams.initialized = 1; >>> >>> - if (!qc->closing && qc->close.timer_set) { >>> - ngx_del_timer(&qc->close); >>> - } >>> - >>> return NGX_OK; >>> } >> >> This assumes that ngx_quic_init_streams() is always called on handshake end, >> even if not needed. This is true now, but it's not something we can to rely on. >> >> Also, we probably don't need to limit handshake duration after streams are >> initialized. Application level will set the required keepalive timeout for >> this. Also, we need to include OCSP validation time in handshake timeout, >> which your removed. >> >> I assume a simpler solution would be not to set the timer in ngx_quic_run() >> if streams are already initialized. > > Agreed, see the updated patch: > > > Thanks, committed! ---- Roman Arutyunyan arut at nginx.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From amdeich at gmail.com Wed Apr 10 23:27:39 2024 From: amdeich at gmail.com (Andrey Kulikov) Date: Thu, 11 Apr 2024 02:27:39 +0300 Subject: [PROPOSAL]: Extend list of Stream phases Message-ID: Hello, Consider the following test-case: I, as admin, would like to limit access to certain resources, based on Client TLS certificate content, fields, etc... Solution for HTTP: Easy! There is NGX_HTTP_ACCESS_PHASE phase, where connections have been already accepted, and I have access to all $ssl_client_* variables. And I control whatever I want, either using the if directive, or by implementing arbitrary sophisticated logic with some custom module. Solution for Stream: Simply impossible! On NGX_STREAM_ACCESS_PHASE only IP-addresses can be checked, as TLS has not taken place yet. NGX_STREAM_SSL_PHASE seems to be intended to specify certificates/keys for performing TLS handshake. On NGX_STREAM_PREREAD_PHASE no $ssl_client_* variables available, as TLS handshake has not finished yet. On NGX_STREAM_CONTENT_PHASE it is too late to do anything, as connection to the destination server was already established. Hard way: implement a custom stream filter module, which checks access criteria on NGX_STREAM_CONTENT_PHASE. But it looks overcomplicated... Proposal: Extend list of Stream phases at least to following: typedef enum { NGX_STREAM_POST_ACCEPT_PHASE = 0, NGX_STREAM_PREACCESS_PHASE, NGX_STREAM_ACCESS_PHASE, NGX_STREAM_SSL_PHASE, NGX_STREAM_PREREAD_PHASE, + NGX_STREAM_PRE_CONTENT_PHASE, // Change name to whatever seems suitable. NGX_STREAM_CONTENT_PHASE, NGX_STREAM_LOG_PHASE } ngx_stream_phases; Questions: Does it look feasible? Are there any objectives NOT to do anything like this? (binary compatibility, etc...) If I implement a trivial patch to extend the number of phases, will it be considered for review? -- Regards, Andrey -------------- next part -------------- An HTML attachment was scrubbed... URL: From arut at nginx.com Thu Apr 11 10:49:33 2024 From: arut at nginx.com (=?utf-8?q?Roman_Arutyunyan?=) Date: Thu, 11 Apr 2024 10:49:33 +0000 Subject: [nginx] Stream pass: limited the number of passes per connection. Message-ID: details: https://hg.nginx.org/nginx/rev/9f84f2e49c62 branches: changeset: 9237:9f84f2e49c62 user: Roman Arutyunyan date: Thu Apr 11 11:37:30 2024 +0400 description: Stream pass: limited the number of passes per connection. Previously a cycle in pass configuration resulted in stack overflow. diffstat: src/stream/ngx_stream_pass_module.c | 51 +++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-) diffs (82 lines): diff -r 155c9093de9d -r 9f84f2e49c62 src/stream/ngx_stream_pass_module.c --- a/src/stream/ngx_stream_pass_module.c Wed Apr 10 09:38:10 2024 +0300 +++ b/src/stream/ngx_stream_pass_module.c Thu Apr 11 11:37:30 2024 +0400 @@ -10,6 +10,9 @@ #include +#define NGX_STREAM_PASS_MAX_PASSES 10 + + typedef struct { ngx_addr_t *addr; ngx_stream_complex_value_t *addr_value; @@ -17,6 +20,8 @@ typedef struct { static void ngx_stream_pass_handler(ngx_stream_session_t *s); +static ngx_int_t ngx_stream_pass_check_cycle(ngx_connection_t *c); +static void ngx_stream_pass_cleanup(void *data); static ngx_int_t ngx_stream_pass_match(ngx_listening_t *ls, ngx_addr_t *addr); static void *ngx_stream_pass_create_srv_conf(ngx_conf_t *cf); static char *ngx_stream_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -125,6 +130,10 @@ ngx_stream_pass_handler(ngx_stream_sessi ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream pass addr: \"%V\"", &addr->name); + if (ngx_stream_pass_check_cycle(c) != NGX_OK) { + goto failed; + } + ls = ngx_cycle->listening.elts; for (i = 0; i < ngx_cycle->listening.nelts; i++) { @@ -164,6 +173,48 @@ failed: static ngx_int_t +ngx_stream_pass_check_cycle(ngx_connection_t *c) +{ + ngx_uint_t *num; + ngx_pool_cleanup_t *cln; + + for (cln = c->pool->cleanup; cln; cln = cln->next) { + if (cln->handler != ngx_stream_pass_cleanup) { + continue; + } + + num = cln->data; + + if (++(*num) > NGX_STREAM_PASS_MAX_PASSES) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, "stream pass cycle"); + return NGX_ERROR; + } + + return NGX_OK; + } + + cln = ngx_pool_cleanup_add(c->pool, sizeof(ngx_uint_t)); + if (cln == NULL) { + return NGX_ERROR; + } + + cln->handler = ngx_stream_pass_cleanup; + + num = cln->data; + *num = 1; + + return NGX_OK; +} + + +static void +ngx_stream_pass_cleanup(void *data) +{ + return; +} + + +static ngx_int_t ngx_stream_pass_match(ngx_listening_t *ls, ngx_addr_t *addr) { if (!ls->wildcard) { From teo.en.ming at protonmail.com Mon Apr 15 13:16:46 2024 From: teo.en.ming at protonmail.com (Turritopsis Dohrnii Teo En Ming) Date: Mon, 15 Apr 2024 13:16:46 +0000 Subject: nginx web server configuration file for Suprema BioStar 2 Door Access System In-Reply-To: References: Message-ID: <5ZryaIopks2TBJmjUAXgRO6ajaQXzsBRlP00vZclXVEFY7i9ylQjV6V9ipWpYxLepQrOfX1ii_-8-NOPH5QOYeW9HMgXrVVgxGbwLk1_BYw=@protonmail.com> Noted with thanks. Regards, Mr. Turritopsis Dohrnii Teo En Ming Targeted Individual in Singapore On Saturday, March 9th, 2024 at 3:57 PM, Muhammad Nuzaihan wrote: > Hello, > > I don't think nginx uses Java key store and that's specific only for > Java applications. you should ask your manufacturer the details on how > your door works. > > Also this (nginx-devel at nginx.org) mailing list is specifically for > developers to discuss about code/bugfix/features and not for problems > from end-users. > > Regards, > A Singaporean living in Malaysia > > On Sat, Mar 9, 2024 at 3:18 PM Turritopsis Dohrnii Teo En Ming via > nginx-devel nginx-devel at nginx.org wrote: > > > Subject: nginx web server configuration file for Suprema BioStar 2 Door Access System > > > > Good day from Singapore, > > > > On 7 Mar 2024 Thursday, I was installing NEW self-signed SSL certificate for Suprema BioStar 2 door access system version 2.7.12.39 for a law firm in Singapore because the common name (CN) in the existing SSL certificate was pointing to the WRONG private IPv4 address 192.168.0.149. > > > > I have referred to the following Suprema technical support guide to install new self-signed SSL certificate for the door access system. > > > > Article: [BioStar 2] How to Apply a Private Certificate for HTTPS > > Link: https://support.supremainc.com/en/support/solutions/articles/24000005211--biostar-2-how-to-apply-a-private-certificate-for-https > > > > The server certificate/public key (biostar_cert.crt), private key (biostar_cert.key), PKCS12 file (biostar_cert.p12) and Java Keystore (keystore.jks) are all located inside the folder C:\Program Files\BioStar 2(x64)\nginx\conf > > > > Looking at the above directory pathname, it is apparent that the South Korean Suprema BioStar 2 door access system is using the open source nginx web server. > > > > But why are ssl_certificate and ssl_certificate_key directives NOT configured for the HTTPS section in the nginx configuration file? The entire HTTPS section was also commented out. > > > > I am baffled. > > > > Why is there a Java Keystore (keystore.jks)? Is nginx web server being used in conjunction with some type of open source Java web server? > > > > Looking forward to your reply. > > > > Thank you. > > > > I shall reproduce the nginx web server configuration file for the Suprema BioStar 2 door access system below for your reference. > > > > nginx.conf is inside C:\Program Files\BioStar 2(x64)\nginx\conf > > > > > > > > #user nobody; > > worker_processes 1; > > > > #error_log logs/error.log; > > #error_log logs/error.log notice; > > #error_log logs/error.log info; > > > > #pid logs/nginx.pid; > > > > events { > > worker_connections 1024; > > } > > > > http { > > include mime.types; > > default_type application/octet-stream; > > > > #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' > > # '$status $body_bytes_sent "$http_referer" ' > > # '"$http_user_agent" "$http_x_forwarded_for"'; > > > > #access_log logs/access.log main; > > > > sendfile on; > > #tcp_nopush on; > > > > #keepalive_timeout 0; > > keepalive_timeout 65; > > > > #gzip on; > > > > server { > > listen 80; > > server_name localhost; > > > > #charset koi8-r; > > > > #access_log logs/host.access.log main; > > > > location / { > > root html; > > index index.html index.htm; > > } > > > > #error_page 404 /404.html; > > > > # redirect server error pages to the static page /50x.html > > # > > error_page 500 502 503 504 /50x.html; > > location = /50x.html { > > root html; > > } > > > > # proxy the PHP scripts to Apache listening on 127.0.0.1:80 > > # > > #location ~ \.php$ { > > # proxy_pass http://127.0.0.1; > > #} > > > > # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 > > # > > #location ~ \.php$ { > > # root html; > > # fastcgi_pass 127.0.0.1:9000; > > # fastcgi_index index.php; > > # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; > > # include fastcgi_params; > > #} > > > > # Swagger document location > > location /biostar { > > root html; > > } > > > > # Report document location > > location /report { > > root html; > > } > > > > # FASTCGI location > > location /api { > > fastcgi_pass 127.0.0.1:9000; > > fastcgi_read_timeout 300; > > include fastcgi_params; > > } > > > > # WEBSOCKET location > > location /wsapi { > > proxy_pass http://127.0.0.1:9002; > > proxy_http_version 1.1; > > proxy_set_header Upgrade $http_upgrade; > > proxy_set_header Connection "upgrade"; > > } > > > > location /webdav { > > autoindex on; > > alias html/download; > > client_body_temp_path html/download; > > dav_methods PUT DELETE MKCOL COPY MOVE; > > create_full_put_path on; > > client_body_in_file_only on; > > client_body_buffer_size 128K; > > client_max_body_size 1000M; > > dav_access user:rw group:rw all:r; > > } > > > > location /resources { > > root html; > > autoindex on; > > } > > > > # deny access to .htaccess files, if Apache's document root > > # concurs with nginx's one > > # > > #location ~ /\.ht { > > # deny all; > > #} > > } > > > > # another virtual host using mix of IP-, name-, and port-based configuration > > # > > #server { > > # listen 8000; > > # listen somename:8080; > > # server_name somename alias another.alias; > > > > # location / { > > # root html; > > # index index.html index.htm; > > # } > > #} > > > > # HTTPS server > > # > > #server { > > # listen 443; > > # server_name localhost; > > > > # ssl on; > > # ssl_certificate cert.pem; > > # ssl_certificate_key cert.key; > > > > # ssl_session_timeout 5m; > > > > # ssl_protocols SSLv2 SSLv3 TLSv1; > > # ssl_ciphers HIGH:!aNULL:!MD5; > > # ssl_prefer_server_ciphers on; > > > > # location / { > > # root html; > > # index index.html index.htm; > > # } > > #} > > > > } > > > > > > > > Regards, > > > > Mr. Turritopsis Dohrnii Teo En Ming > > Targeted Individual in Singapore > > Blogs: > > https://tdtemcerts.blogspot.com > > https://tdtemcerts.wordpress.com > > GIMP also stands for Government-Induced Medical Problems. > > > > _______________________________________________ > > nginx-devel mailing list > > nginx-devel at nginx.org > > https://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel From xeioex at nginx.com Mon Apr 15 23:44:49 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Mon, 15 Apr 2024 23:44:49 +0000 Subject: [njs] Version 0.8.4. Message-ID: details: https://hg.nginx.org/njs/rev/11d956c1577c branches: changeset: 2315:11d956c1577c user: Dmitry Volyntsev date: Mon Apr 15 16:40:21 2024 -0700 description: Version 0.8.4. diffstat: CHANGES | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diffs (28 lines): diff -r adaeb3c3f59a -r 11d956c1577c CHANGES --- a/CHANGES Mon Apr 08 22:47:28 2024 -0700 +++ b/CHANGES Mon Apr 15 16:40:21 2024 -0700 @@ -1,3 +1,24 @@ +Changes with njs 0.8.4 16 Apr 2024 + + nginx modules: + + *) Feature: allowing to set Server header for outgoing headers. + + *) Improvement: validating URI and args arguments in r.subrequest(). + + *) Improvement: checking for duplicate js_set variables. + + *) Bugfix: fixed clear() method of a shared dictionary without + timeout introduced in 0.8.3. + + *) Bugfix: fixed r.send() with Buffer argument. + + Core: + + *) Feature: added QuickJS engine support in CLI. + + *) Bugfix: fixed atob() with non-padded base64 strings. + Changes with njs 0.8.3 07 Feb 2024 nginx modules: From xeioex at nginx.com Mon Apr 15 23:44:51 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Mon, 15 Apr 2024 23:44:51 +0000 Subject: [njs] Added tag 0.8.4 for changeset 11d956c1577c Message-ID: details: https://hg.nginx.org/njs/rev/7133f0400019 branches: changeset: 2316:7133f0400019 user: Dmitry Volyntsev date: Mon Apr 15 16:44:33 2024 -0700 description: Added tag 0.8.4 for changeset 11d956c1577c diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 11d956c1577c -r 7133f0400019 .hgtags --- a/.hgtags Mon Apr 15 16:40:21 2024 -0700 +++ b/.hgtags Mon Apr 15 16:44:33 2024 -0700 @@ -66,3 +66,4 @@ 0ed1952588ab1e0e1c18425fe7923b2b76f38a65 a52b49f9afcf410597dc6657ad39ae3dbbfeec56 0.8.1 45f81882c780a12e56be519cd3106c4fe5567a64 0.8.2 3aba7ee620807ad10bc34bff3677350fa8a3c3b2 0.8.3 +11d956c1577c91037a2c122d4a9d818a9733562d 0.8.4 From arut at nginx.com Tue Apr 16 14:44:00 2024 From: arut at nginx.com (=?utf-8?q?Roman_Arutyunyan?=) Date: Tue, 16 Apr 2024 14:44:00 +0000 Subject: [nginx] nginx-1.25.5-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/8618e4d900cc branches: changeset: 9238:8618e4d900cc user: Roman Arutyunyan date: Tue Apr 16 18:27:50 2024 +0400 description: nginx-1.25.5-RELEASE diffstat: docs/xml/nginx/changes.xml | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 77 insertions(+), 0 deletions(-) diffs (87 lines): diff -r 9f84f2e49c62 -r 8618e4d900cc docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml Thu Apr 11 11:37:30 2024 +0400 +++ b/docs/xml/nginx/changes.xml Tue Apr 16 18:27:50 2024 +0400 @@ -5,6 +5,83 @@ + + + + +виртуальные сервера в модуле stream. + + +virtual servers in the stream module. + + + + + +модуль ngx_stream_pass_module. + + +the ngx_stream_pass_module. + + + + + +параметры deferred, accept_filter и setfib директивы listen в модуле stream. + + +the "deferred", "accept_filter", and "setfib" parameters of the "listen" +directive in the stream module. + + + + + +определение размера строки кеша процессора для некоторых архитектур.
+Спасибо Piotr Sikora. +
+ +cache line size detection for some architectures.
+Thanks to Piotr Sikora. +
+
+ + + +поддержка Homebrew на Apple Silicon.
+Спасибо Piotr Sikora. +
+ +support for Homebrew on Apple Silicon.
+Thanks to Piotr Sikora. +
+
+ + + +улучшения и исправления кросс-компиляции для Windows.
+Спасибо Piotr Sikora. +
+ +Windows cross-compilation bugfixes and improvements.
+Thanks to Piotr Sikora. +
+
+ + + +неожиданное закрытие соединения при использовании 0-RTT в QUIC.
+Спасибо Владимиру Хомутову. +
+ +unexpected connection closure while using 0-RTT in QUIC.
+Thanks to Vladimir Khomutov. +
+
+ +
+ + From arut at nginx.com Tue Apr 16 14:44:03 2024 From: arut at nginx.com (=?utf-8?q?Roman_Arutyunyan?=) Date: Tue, 16 Apr 2024 14:44:03 +0000 Subject: [nginx] release-1.25.5 tag Message-ID: details: https://hg.nginx.org/nginx/rev/49dce50fad40 branches: changeset: 9239:49dce50fad40 user: Roman Arutyunyan date: Tue Apr 16 18:29:59 2024 +0400 description: release-1.25.5 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 8618e4d900cc -r 49dce50fad40 .hgtags --- a/.hgtags Tue Apr 16 18:27:50 2024 +0400 +++ b/.hgtags Tue Apr 16 18:29:59 2024 +0400 @@ -477,3 +477,4 @@ f8134640e8615448205785cf00b0bc810489b495 1d839f05409d1a50d0f15a2bf36547001f99ae40 release-1.25.2 294a3d07234f8f65d7b0e0b0e2c5b05c12c5da0a release-1.25.3 173a0a7dbce569adbb70257c6ec4f0f6bc585009 release-1.25.4 +8618e4d900cc71082fbe7dc72af087937d64faf5 release-1.25.5 From mux99 at live.be Thu Apr 18 13:57:04 2024 From: mux99 at live.be (=?iso-8859-1?q?Dourov_Maxime?=) Date: Thu, 18 Apr 2024 15:57:04 +0200 Subject: [PATCH 0 of 4] Add MPTCP support Message-ID: Multipath TCP (MPTCP), standardized in RFC8684 [1], is a TCP extension that enables a TCP connection to use different paths. Multipath TCP has been used for several use cases. On smartphones, MPTCP enables seamless handovers between cellular and Wi-Fi networks while preserving established connections. This use-case is what pushed Apple to use MPTCP since 2013 in multiple applications [2]. On dual-stack hosts, Multipath TCP enables the TCP connection to automatically use the best performing path, either IPv4 or IPv6. If one path fails, MPTCP automatically uses the other path. To benefit from MPTCP, both the client and the server have to support it. Multipath TCP is a backward-compatible TCP extension that is enabled by default on recent Linux distributions (Debian, Ubuntu, Redhat, ...). Multipath TCP is included in the Linux kernel since version 5.6 [3]. To use it on Linux, an application must explicitly enable it when creating the socket. No need to change anything else in the application. This series of patches add two functionalities: - First, the new 'protocol' field of the 'ngx_listening_s' allows for the selection of the protocol parameter in the 'socket' system call. The default value is zero. - Second, a new parameter 'mptcp' for the 'listen' directive. It sets the protocol to 'IPPROTO_MPTCP'. For the sake of uniformity, the option is added to the 'http', 'mail' and 'stream' context. Link: https://www.rfc-editor.org/rfc/rfc8684.html [1] Link: https://www.tessares.net/apples-mptcp-story-so-far/ [2] Link: https://www.mptcp.dev [3] From mux99 at live.be Thu Apr 18 13:57:05 2024 From: mux99 at live.be (=?iso-8859-1?q?Dourov_Maxime?=) Date: Thu, 18 Apr 2024 15:57:05 +0200 Subject: [PATCH 1 of 4] Core: added socket protocol In-Reply-To: References: Message-ID: # HG changeset patch # User maxime # Date 1713355365 -7200 # Wed Apr 17 14:02:45 2024 +0200 # Node ID b7cbe9281f9d6911fd40a894ebc4ac2d701d8fa4 # Parent 49dce50fad40bf09db81ca2a35983ecd7b740e43 Core: added socket protocol. This patch updates the creation of listening sockets to use a new field of the `ngx_listening_s` structure. The `protocol` field can be used in conjunction with the `type` to specify the protocol to be used. Modules will then be able to specify a different protocol, e.g. IPPROTO_MPTCP. diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -487,9 +487,20 @@ ngx_open_listening_sockets(ngx_cycle_t * continue; } - s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0); + s = (ngx_socket_t) -1; + if (ls[i].protocol > 0) { + s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, + ls[i].protocol); + /* In case of error, retry with the default protocol */ + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "socket(%d) failed, trying with 0", ls[i].protocol); + } if (s == (ngx_socket_t) -1) { + s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0); + } + + if (s == (ngx_socket_t) -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_socket_n " %V failed", &ls[i].addr_text); return NGX_ERROR; diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -24,6 +24,7 @@ struct ngx_listening_s { ngx_str_t addr_text; int type; + int protocol; int backlog; int rcvbuf; From mux99 at live.be Thu Apr 18 13:57:07 2024 From: mux99 at live.be (=?iso-8859-1?q?Dourov_Maxime?=) Date: Thu, 18 Apr 2024 15:57:07 +0200 Subject: [PATCH 3 of 4] Mail: added MPTCP support In-Reply-To: References: Message-ID: # HG changeset patch # User maxime # Date 1713355424 -7200 # Wed Apr 17 14:03:44 2024 +0200 # Node ID f7ea7c665964b50f1ef6f3964c3fce9596afac20 # Parent 69e3909234d76c6888fba539f9bbbecc9858a7ab Mail: added MPTCP support. Multipath TCP (MPTCP), standardized in RFC8684 [1], is a TCP extension that enables a TCP connection to use different paths. Multipath TCP has been used for several use cases. On smartphones, MPTCP enables seamless handovers between cellular and Wi-Fi networks while preserving established connections. This use-case is what pushed Apple to use MPTCP since 2013 in multiple applications [2]. On dual-stack hosts, Multipath TCP enables the TCP connection to automatically use the best performing path, either IPv4 or IPv6. If one path fails, MPTCP automatically uses the other path. To benefit from MPTCP, both the client and the server have to support it. Multipath TCP is a backward-compatible TCP extension that is enabled by default on recent Linux distributions (Debian, Ubuntu, Redhat, ...). Multipath TCP is included in the Linux kernel since version 5.6 [3]. To use it on Linux, an application must explicitly enable it when creating the socket. No need to change anything else in the application. Even if MPTCP is supported by different OS, only Linux supports the `IPPROTO_MPTCP` protocol, which is why this feature is currently limited to Linux only. This patch adds a new parameter 'mptcp' to the 'listen' directive in the Mail module. Link: https://www.rfc-editor.org/rfc/rfc8684.html [1] Link: https://www.tessares.net/apples-mptcp-story-so-far/ [2] Link: https://www.mptcp.dev [3] diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c +++ b/src/mail/ngx_mail.c @@ -332,6 +332,7 @@ ngx_mail_optimize_servers(ngx_conf_t *cf ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; + ls->protocol = addr[i].opt.protocol; ls->backlog = addr[i].opt.backlog; ls->rcvbuf = addr[i].opt.rcvbuf; ls->sndbuf = addr[i].opt.sndbuf; diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -47,6 +47,7 @@ typedef struct { int tcp_keepintvl; int tcp_keepcnt; #endif + int protocol; int backlog; int rcvbuf; int sndbuf; diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -10,6 +10,10 @@ #include #include +#ifndef IPPROTO_MPTCP +#define IPPROTO_MPTCP 262 +#endif + static void *ngx_mail_core_create_main_conf(ngx_conf_t *cf); static void *ngx_mail_core_create_srv_conf(ngx_conf_t *cf); @@ -468,6 +472,11 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx #endif } + if (ngx_strcmp(value[i].data, "mptcp") == 0) { + ls->protocol = IPPROTO_MPTCP; + continue; + } + if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) { if (ngx_strcmp(&value[i].data[13], "on") == 0) { From mux99 at live.be Thu Apr 18 13:57:08 2024 From: mux99 at live.be (=?iso-8859-1?q?Dourov_Maxime?=) Date: Thu, 18 Apr 2024 15:57:08 +0200 Subject: [PATCH 4 of 4] Stream: added MPTCP support In-Reply-To: References: Message-ID: # HG changeset patch # User maxime # Date 1713355437 -7200 # Wed Apr 17 14:03:57 2024 +0200 # Node ID e2a045fb5e3f6362b9f62cf2353f9db34e031202 # Parent f7ea7c665964b50f1ef6f3964c3fce9596afac20 Stream: added MPTCP support. Multipath TCP (MPTCP), standardized in RFC8684 [1], is a TCP extension that enables a TCP connection to use different paths. Multipath TCP has been used for several use cases. On smartphones, MPTCP enables seamless handovers between cellular and Wi-Fi networks while preserving established connections. This use-case is what pushed Apple to use MPTCP since 2013 in multiple applications [2]. On dual-stack hosts, Multipath TCP enables the TCP connection to automatically use the best performing path, either IPv4 or IPv6. If one path fails, MPTCP automatically uses the other path. To benefit from MPTCP, both the client and the server have to support it. Multipath TCP is a backward-compatible TCP extension that is enabled by default on recent Linux distributions (Debian, Ubuntu, Redhat, ...). Multipath TCP is included in the Linux kernel since version 5.6 [3]. To use it on Linux, an application must explicitly enable it when creating the socket. No need to change anything else in the application. Even if MPTCP is supported by different OS, only Linux supports the `IPPROTO_MPTCP` protocol, which is why this feature is currently limited to Linux only. This patch adds a new parameter 'mptcp' to the 'listen' directive in the Stream module. Link: https://www.rfc-editor.org/rfc/rfc8684.html [1] Link: https://www.tessares.net/apples-mptcp-story-so-far/ [2] Link: https://www.mptcp.dev [3] diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -1010,6 +1010,7 @@ ngx_stream_add_listening(ngx_conf_t *cf, ls->log.handler = ngx_accept_log_error; ls->type = addr->opt.type; + ls->protocol = addr->opt.protocol; ls->backlog = addr->opt.backlog; ls->rcvbuf = addr->opt.rcvbuf; ls->sndbuf = addr->opt.sndbuf; diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -62,6 +62,7 @@ typedef struct { int rcvbuf; int sndbuf; int type; + int protocol; #if (NGX_HAVE_SETFIB) int setfib; #endif diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -9,6 +9,10 @@ #include #include +#ifndef IPPROTO_MPTCP +#define IPPROTO_MPTCP 262 +#endif + static ngx_uint_t ngx_stream_preread_can_peek(ngx_connection_t *c); static ngx_int_t ngx_stream_preread_peek(ngx_stream_session_t *s, @@ -984,6 +988,13 @@ ngx_stream_core_listen(ngx_conf_t *cf, n } #endif +#if (NGX_LINUX) + if (ngx_strcmp(value[i].data, "mptcp") == 0) { + lsopt.protocol = IPPROTO_MPTCP; + continue; + } +#endif + if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) { lsopt.backlog = ngx_atoi(value[i].data + 8, value[i].len - 8); lsopt.set = 1; @@ -1250,6 +1261,12 @@ ngx_stream_core_listen(ngx_conf_t *cf, n if (lsopt.proxy_protocol) { return "\"proxy_protocol\" parameter is incompatible with \"udp\""; } + +#if (NGX_LINUX) + if (lsopt.protocol == IPPROTO_MPTCP) { + return "\"mptcp\" parameter is incompatible with \"udp\""; + } +#endif } for (n = 0; n < u.naddrs; n++) { From mux99 at live.be Thu Apr 18 13:57:06 2024 From: mux99 at live.be (=?iso-8859-1?q?Dourov_Maxime?=) Date: Thu, 18 Apr 2024 15:57:06 +0200 Subject: [PATCH 2 of 4] HTTP: added MPTCP support In-Reply-To: References: Message-ID: # HG changeset patch # User maxime # Date 1713355399 -7200 # Wed Apr 17 14:03:19 2024 +0200 # Node ID 69e3909234d76c6888fba539f9bbbecc9858a7ab # Parent b7cbe9281f9d6911fd40a894ebc4ac2d701d8fa4 HTTP: added MPTCP support. Multipath TCP (MPTCP), standardized in RFC8684 [1], is a TCP extension that enables a TCP connection to use different paths. Multipath TCP has been used for several use cases. On smartphones, MPTCP enables seamless handovers between cellular and Wi-Fi networks while preserving established connections. This use-case is what pushed Apple to use MPTCP since 2013 in multiple applications [2]. On dual-stack hosts, Multipath TCP enables the TCP connection to automatically use the best performing path, either IPv4 or IPv6. If one path fails, MPTCP automatically uses the other path. To benefit from MPTCP, both the client and the server have to support it. Multipath TCP is a backward-compatible TCP extension that is enabled by default on recent Linux distributions (Debian, Ubuntu, Redhat, ...). Multipath TCP is included in the Linux kernel since version 5.6 [3]. To use it on Linux, an application must explicitly enable it when creating the socket. No need to change anything else in the application. Even if MPTCP is supported by different OS, only Linux supports the `IPPROTO_MPTCP` protocol, which is why this feature is currently limited to Linux only. This patch adds a new parameter 'mptcp' to the 'listen' directive in the HTTP module. Link: https://www.rfc-editor.org/rfc/rfc8684.html [1] Link: https://www.tessares.net/apples-mptcp-story-so-far/ [2] Link: https://www.mptcp.dev [3] diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim --- a/contrib/vim/syntax/nginx.vim +++ b/contrib/vim/syntax/nginx.vim @@ -65,7 +65,7 @@ syn match ngxListenComment '#.*$' \ contained \ nextgroup=@ngxListenParams skipwhite skipempty syn keyword ngxListenOptions contained - \ default_server ssl quic proxy_protocol + \ default_server ssl quic proxy_protocol mptcp \ setfib fastopen backlog rcvbuf sndbuf accept_filter deferred bind \ ipv6only reuseport so_keepalive \ nextgroup=@ngxListenParams skipwhite skipempty diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -1845,6 +1845,7 @@ ngx_http_add_listening(ngx_conf_t *cf, n #endif ls->type = addr->opt.type; + ls->protocol = addr->opt.protocol; ls->backlog = addr->opt.backlog; ls->rcvbuf = addr->opt.rcvbuf; ls->sndbuf = addr->opt.sndbuf; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -20,6 +20,10 @@ typedef struct { #define NGX_HTTP_REQUEST_BODY_FILE_ON 1 #define NGX_HTTP_REQUEST_BODY_FILE_CLEAN 2 +#ifndef IPPROTO_MPTCP +#define IPPROTO_MPTCP 262 +#endif + static ngx_int_t ngx_http_core_auth_delay(ngx_http_request_t *r); static void ngx_http_core_auth_delay_handler(ngx_http_request_t *r); @@ -4049,6 +4053,13 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx } #endif +#if (NGX_LINUX) + if (ngx_strcmp(value[n].data, "mptcp") == 0) { + lsopt.protocol = IPPROTO_MPTCP; + continue; + } +#endif + if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) { lsopt.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8); lsopt.set = 1; @@ -4351,6 +4362,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx if (lsopt.proxy_protocol) { return "\"proxy_protocol\" parameter is incompatible with \"quic\""; } +#if (NGX_LINUX) + if (lsopt.protocol == IPPROTO_MPTCP) { + return "\"mptcp\" parameter is incompatible with \"quic\""; + } +#endif } for (n = 0; n < u.naddrs; n++) { diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -88,6 +88,7 @@ typedef struct { int rcvbuf; int sndbuf; int type; + int protocol; #if (NGX_HAVE_SETFIB) int setfib; #endif From pluknet at nginx.com Mon Apr 22 15:00:49 2024 From: pluknet at nginx.com (=?iso-8859-1?q?Sergey_Kandaurov?=) Date: Mon, 22 Apr 2024 19:00:49 +0400 Subject: [PATCH] HTTP/3: fixed handling of malformed request body length Message-ID: <754e32eaca24ad751e2a.1713798049@enoparse.local> # HG changeset patch # User Sergey Kandaurov # Date 1713798017 -14400 # Mon Apr 22 19:00:17 2024 +0400 # Node ID 754e32eaca24ad751e2a94790e1afd55202c1aba # Parent 9f84f2e49c624e82e054a2dcd48723119c44029c HTTP/3: fixed handling of malformed request body length. Previously, a request body larger than declared in Content-Length resulted in a 413 status code, because Content-Length was mistakenly used as the maximum allowed request body, similar to client_max_body_size. Following the HTTP/3 specification, such requests are now rejected with the 400 error as malformed. diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c --- a/src/http/v3/ngx_http_v3_request.c +++ b/src/http/v3/ngx_http_v3_request.c @@ -1575,12 +1575,21 @@ ngx_http_v3_request_body_filter(ngx_http /* rc == NGX_OK */ if (max != -1 && (uint64_t) (max - rb->received) < st->length) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "client intended to send too large " - "body: %O+%ui bytes", - rb->received, st->length); + + if (max == r->headers_in.content_length_n) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client intended to send body data " + "larger than declared"); + + return NGX_HTTP_BAD_REQUEST; - return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; + } else { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "client intended to send too large body: " + "%O+%ui bytes", rb->received, st->length); + + return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; + } } continue; From xeioex at nginx.com Tue Apr 23 01:09:17 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 23 Apr 2024 01:09:17 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/b73f99c7bc54 branches: changeset: 2317:b73f99c7bc54 user: Dmitry Volyntsev date: Mon Apr 22 17:51:24 2024 -0700 description: Version bump. diffstat: src/njs.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 7133f0400019 -r b73f99c7bc54 src/njs.h --- a/src/njs.h Mon Apr 15 16:44:33 2024 -0700 +++ b/src/njs.h Mon Apr 22 17:51:24 2024 -0700 @@ -11,8 +11,8 @@ #include -#define NJS_VERSION "0.8.4" -#define NJS_VERSION_NUMBER 0x000804 +#define NJS_VERSION "0.8.5" +#define NJS_VERSION_NUMBER 0x000805 #include From xeioex at nginx.com Tue Apr 23 01:09:19 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 23 Apr 2024 01:09:19 +0000 Subject: [njs] Modules: improved checking for duplicate js_set variables. Message-ID: details: https://hg.nginx.org/njs/rev/be271e8d0b3b branches: changeset: 2318:be271e8d0b3b user: Dmitry Volyntsev date: Mon Apr 22 17:51:45 2024 -0700 description: Modules: improved checking for duplicate js_set variables. Since 6fb1aca4eeaf (0.8.4) the identical js_set variables introduced as a part of an include file that is shared amongst multiple vhosts are rejected during configuration parsing. The patch ignores duplicate js_set variables when they refer to the same JS function. This fixes #705 issue on Github. diffstat: nginx/ngx_http_js_module.c | 15 ++++++-- nginx/ngx_stream_js_module.c | 15 ++++++-- nginx/t/js_dup_set.t | 74 ++++++++++++++++++++++++++++++++++++++++++++ nginx/t/stream_js_dup_set.t | 72 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 8 deletions(-) diffs (218 lines): diff -r b73f99c7bc54 -r be271e8d0b3b nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Apr 22 17:51:24 2024 -0700 +++ b/nginx/ngx_http_js_module.c Mon Apr 22 17:51:45 2024 -0700 @@ -4732,7 +4732,7 @@ invalid: static char * ngx_http_js_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_str_t *value, *fname; + ngx_str_t *value, *fname, *prev; ngx_http_variable_t *v; value = cf->args->elts; @@ -4759,9 +4759,16 @@ ngx_http_js_set(ngx_conf_t *cf, ngx_comm *fname = value[2]; if (v->get_handler == ngx_http_js_variable_set) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "variable \"%V\" is already declared", &value[1]); - return NGX_CONF_ERROR; + prev = (ngx_str_t *) v->data; + + if (fname->len != prev->len + || ngx_strncmp(fname->data, prev->data, fname->len) != 0) + { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "variable \"%V\" is redeclared with " + "different function name", &value[1]); + return NGX_CONF_ERROR; + } } v->get_handler = ngx_http_js_variable_set; diff -r b73f99c7bc54 -r be271e8d0b3b nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Mon Apr 22 17:51:24 2024 -0700 +++ b/nginx/ngx_stream_js_module.c Mon Apr 22 17:51:45 2024 -0700 @@ -2191,7 +2191,7 @@ invalid: static char * ngx_stream_js_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_str_t *value, *fname; + ngx_str_t *value, *fname, *prev; ngx_stream_variable_t *v; value = cf->args->elts; @@ -2218,9 +2218,16 @@ ngx_stream_js_set(ngx_conf_t *cf, ngx_co *fname = value[2]; if (v->get_handler == ngx_stream_js_variable_set) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "variable \"%V\" is already declared", &value[1]); - return NGX_CONF_ERROR; + prev = (ngx_str_t *) v->data; + + if (fname->len != prev->len + || ngx_strncmp(fname->data, prev->data, fname->len) != 0) + { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "variable \"%V\" is redeclared with " + "different function name", &value[1]); + return NGX_CONF_ERROR; + } } v->get_handler = ngx_stream_js_variable_set; diff -r b73f99c7bc54 -r be271e8d0b3b nginx/t/js_dup_set.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nginx/t/js_dup_set.t Mon Apr 22 17:51:45 2024 -0700 @@ -0,0 +1,74 @@ +#!/usr/bin/perl + +# (C) Dmitry Volyntsev +# (C) Nginx, Inc. + +# Tests for http njs module, duplicate identical js_set directives. + +############################################################################### + +use warnings; +use strict; + +use Test::More; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx; + +############################################################################### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +my $t = Test::Nginx->new()->has(qw/http/) + ->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +http { + %%TEST_GLOBALS_HTTP%% + + js_import test.js; + + server { + listen 127.0.0.1:8080; + server_name localhost; + + location /set1 { + js_set $test test.foo; + return 200 set1:$test; + } + + location /set2 { + js_set $test test.foo; + return 200 set2:$test; + } + } +} + +EOF + +$t->write_file('test.js', <try_run('no njs')->plan(2); + +############################################################################### + +like(http_get('/set1'), qr/set1:42/, '/set1 location'); +like(http_get('/set2'), qr/set2:42/, '/set2 location'); + +############################################################################### diff -r b73f99c7bc54 -r be271e8d0b3b nginx/t/stream_js_dup_set.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nginx/t/stream_js_dup_set.t Mon Apr 22 17:51:45 2024 -0700 @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +# (C) Dmitry Volyntsev +# (C) Nginx, Inc. + +# Tests for stream njs module, duplicate identical js_set directives. + +############################################################################### + +use warnings; +use strict; + +use Test::More; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx; +use Test::Nginx::Stream qw/ stream /; + +############################################################################### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +my $t = Test::Nginx->new()->has(qw/stream stream_return/) + ->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +stream { + %%TEST_GLOBALS_STREAM%% + + js_import test.js; + + server { + listen 127.0.0.1:8081; + js_set $test test.foo; + return 8081:$test; + } + + server { + listen 127.0.0.1:8082; + js_set $test test.foo1; + return 8082:$test; + } +} + +EOF + +$t->write_file('test.js', <try_run('no njs available')->plan(2); + +############################################################################### + +is(stream('127.0.0.1:' . port(8081))->read(), '8081:42', '8081 server'); +is(stream('127.0.0.1:' . port(8082))->read(), '8082:42', '8082 server'); + +############################################################################### From xeioex at nginx.com Tue Apr 23 01:09:21 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 23 Apr 2024 01:09:21 +0000 Subject: [njs] Zlib: fixed inflate(). Message-ID: details: https://hg.nginx.org/njs/rev/d640adf691a7 branches: changeset: 2319:d640adf691a7 user: Dmitry Volyntsev date: Mon Apr 22 17:52:06 2024 -0700 description: Zlib: fixed inflate(). Previously, the function might fail to return the last part of the compressed content. This problem is more visible when output size > 1024 or when chunkSize < the content size. diffstat: external/njs_zlib_module.c | 2 +- src/test/njs_unit_test.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletions(-) diffs (29 lines): diff -r be271e8d0b3b -r d640adf691a7 external/njs_zlib_module.c --- a/external/njs_zlib_module.c Mon Apr 22 17:51:45 2024 -0700 +++ b/external/njs_zlib_module.c Mon Apr 22 17:52:06 2024 -0700 @@ -463,7 +463,7 @@ njs_zlib_ext_inflate(njs_vm_t *vm, njs_v njs_chb_init(&chain, njs_vm_memory_pool(vm)); - while (stream.avail_in > 0) { + while (rc != Z_STREAM_END) { stream.next_out = njs_chb_reserve(&chain, chunk_size); if (njs_slow_path(stream.next_out == NULL)) { njs_vm_memory_error(vm); diff -r be271e8d0b3b -r d640adf691a7 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Apr 22 17:51:45 2024 -0700 +++ b/src/test/njs_unit_test.c Mon Apr 22 17:52:06 2024 -0700 @@ -22352,6 +22352,13 @@ static njs_unit_test_t njs_zlib_test[] njs_str("eJwLd/R2BAAC+gEl,eJw7t/HcpnObAQ/sBIE=") }, { njs_str("const zlib = require('zlib');" + "const buf = 'αβγ'.repeat(56);" + "const enc = zlib.deflateRawSync(buf, {chunkSize:64}).toString('base64');" + "const dec = zlib.inflateRawSync(Buffer.from(enc, 'base64')).toString();" + "buf == dec"), + njs_str("true") }, + + { njs_str("const zlib = require('zlib');" "['WAKA'.repeat(1024), 'αβγ'.repeat(1024)]" ".map(v => [v, zlib.deflateRawSync(v).toString('base64')])" ".every(pair => pair[0] == zlib.inflateRawSync(Buffer.from(pair[1], 'base64')).toString())"), From xeioex at nginx.com Tue Apr 23 01:09:23 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 23 Apr 2024 01:09:23 +0000 Subject: [njs] Zlib: improved tests with zlib-ng. Message-ID: details: https://hg.nginx.org/njs/rev/0cb259f67ade branches: changeset: 2320:0cb259f67ade user: Dmitry Volyntsev date: Mon Apr 22 17:52:14 2024 -0700 description: Zlib: improved tests with zlib-ng. This fixes #704 issue on Github. diffstat: src/test/njs_unit_test.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-) diffs (25 lines): diff -r d640adf691a7 -r 0cb259f67ade src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Apr 22 17:52:06 2024 -0700 +++ b/src/test/njs_unit_test.c Mon Apr 22 17:52:14 2024 -0700 @@ -22319,14 +22319,15 @@ static njs_unit_test_t njs_zlib_test[] njs_str("WAKA,αβγ") }, { njs_str("const zlib = require('zlib');" - "['WAKA', 'αβγ']" - ".map(v => zlib.deflateRawSync(v).toString('base64'))"), - njs_str("C3f0dgQA,O7fx3KZzmwE=") }, + "const enc = ['WAKA', 'αβγ'].map(v => zlib.deflateRawSync(v).toString('base64'));" + "enc.map(v => zlib.inflateRawSync(Buffer.from(v, 'base64')).toString())"), + njs_str("WAKA,αβγ") }, { njs_str("const zlib = require('zlib');" - "['WAKA', 'αβγ']" - ".map(v => zlib.deflateRawSync(v, {dictionary: Buffer.from('WAKA')}).toString('base64'))"), - njs_str("CwdiAA==,O7fx3KZzmwE=") }, + "const enc = ['WAKA', 'αβγ']" + ".map(v => zlib.deflateRawSync(v, {dictionary: Buffer.from('WAKA')}).toString('base64'));" + "enc.map(v => zlib.inflateRawSync(Buffer.from(v, 'base64'), {dictionary: Buffer.from('WAKA')}))"), + njs_str("WAKA,αβγ") }, { njs_str("const zlib = require('zlib');" "['WAKA', 'αβγ']" From xeioex at nginx.com Tue Apr 23 01:59:36 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Tue, 23 Apr 2024 01:59:36 +0000 Subject: [njs] Configure: fixed default path QuickJS discovery typo. Message-ID: details: https://hg.nginx.org/njs/rev/a97a9f3b3cea branches: changeset: 2321:a97a9f3b3cea user: Dmitry Volyntsev date: Mon Apr 22 18:59:03 2024 -0700 description: Configure: fixed default path QuickJS discovery typo. The issue was introduced in 1c8b6b9bc06c (0.8.4). This closes #706 issue on Github. diffstat: auto/quickjs | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff -r 0cb259f67ade -r a97a9f3b3cea auto/quickjs --- a/auto/quickjs Mon Apr 22 17:52:14 2024 -0700 +++ b/auto/quickjs Mon Apr 22 18:59:03 2024 -0700 @@ -40,7 +40,7 @@ if [ $NJS_TRY_QUICKJS = YES ]; then if [ $njs_found = no ]; then njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs.lto" njs_feature_incs="/usr/include/quickjs/" - njs_feature_libs="-L/usr/lib/quickjs/ -lquijs.lto -lm -ldl -lpthread" + njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs.lto -lm -ldl -lpthread" . auto/feature fi @@ -48,7 +48,7 @@ if [ $NJS_TRY_QUICKJS = YES ]; then if [ $njs_found = no ]; then njs_feature="QuickJS library -I/usr/include/quickjs/ -L/usr/lib/quickjs/ -lquickjs" njs_feature_incs="/usr/include/quickjs/" - njs_feature_libs="-L/usr/lib/quickjs/ -lquijs -lm -ldl -lpthread" + njs_feature_libs="-L/usr/lib/quickjs/ -lquickjs -lm -ldl -lpthread" . auto/feature fi From kasei at kasei.im Tue Apr 23 10:02:08 2024 From: kasei at kasei.im (Kasei Wang) Date: Tue, 23 Apr 2024 18:02:08 +0800 Subject: [PATCH]HTTP/2 connection not properly closing during graceful shutdown Message-ID: Hello, I found that there is a slight probability of HTTP/2 connections not properly closing during graceful shutdown, leading to worker processes in shutting down state remaining stuck for an extended period. After investigation, the issue appears to stem from the following: 1. worker processes in shutting down state use ngx_close_idle_connections to close all idle connections, including HTTP/2 connections. 2. For HTTP/2 connections, c->idle is set to true in ngx_http_v2_init. According to the explanation in https://hg.nginx.org/nginx/rev/5e95b9fb33b7, GOAWAY should be sent to all HTTP/2 connections. 3. There might be a time gap between ngx_event_accept and ngx_http_v2_init. For TLS connections, ngx_http_v2_init will be executed after ALPN received, and for plaintext http2 connections, ngx_http_v2_init will be executed after parsing the http2 preface. If ngx_close_idle_connections is executed between ngx_event_accept and ngx_http_v2_init, there's a possibility that c->idle of some connections is set to true AFTER ngx_close_idle_connections, causing those connections to not enter the GOAWAY process and leading to the aforementioned problem. To verify this, I've written a simple HTTP/2 client. This program will wait 15 seconds after TCP connection establishment before starting to send data. The purpose of sleep is to to raise the probability of encountering the issue. You can reproduce the problem by executing "nginx -s reload" during this 15-second wait. If you're interested, you can try my test program () to reproduce the issue. I believe the simplest solution is to set c->close based on ngx_exiting in ngx_http_v2_init. In this way, the connection will send GOAWAY in ngx_http_v2_read_handler. Please confirm if this issue exists, review my analysis and the patch if possible. Thank you very much. # HG changeset patch # User Kasei Wang # Date 1713863474 -28800 # Tue Apr 23 17:11:14 2024 +0800 # Branch help # Node ID e5ba8996973cdd1edd7591a28ee1c145af86c556 # Parent 8618e4d900cc71082fbe7dc72af087937d64faf5 HTTP/2: close http2 connections created during graceful shutdown. diff -r 8618e4d900cc -r e5ba8996973c src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Tue Apr 16 18:27:50 2024 +0400 +++ b/src/http/v2/ngx_http_v2.c Tue Apr 23 17:11:14 2024 +0800 @@ -304,6 +304,10 @@ c->idle = 1; ngx_reusable_connection(c, 0); + if (ngx_exiting) { + c->close = 1; + } + if (c->buffer) { p = c->buffer->pos; end = c->buffer->last; From pluknet at nginx.com Tue Apr 23 13:14:54 2024 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 23 Apr 2024 17:14:54 +0400 Subject: [PATCH] HTTP/3: fixed handling of malformed request body length In-Reply-To: <754e32eaca24ad751e2a.1713798049@enoparse.local> References: <754e32eaca24ad751e2a.1713798049@enoparse.local> Message-ID: <00A1252C-CFF8-4EB2-842E-E15F92C91A86@nginx.com> > On 22 Apr 2024, at 19:00, Sergey Kandaurov wrote: > > # HG changeset patch > # User Sergey Kandaurov > # Date 1713798017 -14400 > # Mon Apr 22 19:00:17 2024 +0400 > # Node ID 754e32eaca24ad751e2a94790e1afd55202c1aba > # Parent 9f84f2e49c624e82e054a2dcd48723119c44029c > HTTP/3: fixed handling of malformed request body length. > > Previously, a request body larger than declared in Content-Length resulted in > a 413 status code, because Content-Length was mistakenly used as the maximum > allowed request body, similar to client_max_body_size. Following the HTTP/3 > specification, such requests are now rejected with the 400 error as malformed. > > diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c > --- a/src/http/v3/ngx_http_v3_request.c > +++ b/src/http/v3/ngx_http_v3_request.c > @@ -1575,12 +1575,21 @@ ngx_http_v3_request_body_filter(ngx_http > /* rc == NGX_OK */ > > if (max != -1 && (uint64_t) (max - rb->received) < st->length) { > - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > - "client intended to send too large " > - "body: %O+%ui bytes", > - rb->received, st->length); > + > + if (max == r->headers_in.content_length_n) { > + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, > + "client intended to send body data " > + "larger than declared"); > + > + return NGX_HTTP_BAD_REQUEST; > > - return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; > + } else { > + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > + "client intended to send too large body: " > + "%O+%ui bytes", rb->received, st->length); > + > + return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; > + } > } > > continue; After more thoughts I replaced "max == r->headers_in.content_length_n" with a more clear check "r->headers_in.content_length_n != -1" (also to make it more similar to the HTTP/2 request body filter). The resulting diff is minimized since both conditions result in return. # HG changeset patch # User Sergey Kandaurov # Date 1713876685 -14400 # Tue Apr 23 16:51:25 2024 +0400 # Node ID c935bfd88ebf05aed181fc03231df8bd95475334 # Parent 9f84f2e49c624e82e054a2dcd48723119c44029c HTTP/3: fixed handling of malformed request body length. Previously, a request body larger than declared in Content-Length resulted in a 413 status code, because Content-Length was mistakenly used as the maximum allowed request body, similar to client_max_body_size. Following the HTTP/3 specification, such requests are now rejected with the 400 error as malformed. diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c --- a/src/http/v3/ngx_http_v3_request.c +++ b/src/http/v3/ngx_http_v3_request.c @@ -1575,6 +1575,15 @@ ngx_http_v3_request_body_filter(ngx_http /* rc == NGX_OK */ if (max != -1 && (uint64_t) (max - rb->received) < st->length) { + + if (r->headers_in.content_length_n != -1) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client intended to send body data " + "larger than declared"); + + return NGX_HTTP_BAD_REQUEST; + } + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client intended to send too large " "body: %O+%ui bytes", -- Sergey Kandaurov From arut at nginx.com Tue Apr 23 13:49:30 2024 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 23 Apr 2024 17:49:30 +0400 Subject: [PATCH] HTTP/3: fixed handling of malformed request body length In-Reply-To: <00A1252C-CFF8-4EB2-842E-E15F92C91A86@nginx.com> References: <754e32eaca24ad751e2a.1713798049@enoparse.local> <00A1252C-CFF8-4EB2-842E-E15F92C91A86@nginx.com> Message-ID: <20240423134930.tuz7mxugbj66emfk@N00W24XTQX> Hi, On Tue, Apr 23, 2024 at 05:14:54PM +0400, Sergey Kandaurov wrote: > > > On 22 Apr 2024, at 19:00, Sergey Kandaurov wrote: > > > > # HG changeset patch > > # User Sergey Kandaurov > > # Date 1713798017 -14400 > > # Mon Apr 22 19:00:17 2024 +0400 > > # Node ID 754e32eaca24ad751e2a94790e1afd55202c1aba > > # Parent 9f84f2e49c624e82e054a2dcd48723119c44029c > > HTTP/3: fixed handling of malformed request body length. > > > > Previously, a request body larger than declared in Content-Length resulted in > > a 413 status code, because Content-Length was mistakenly used as the maximum > > allowed request body, similar to client_max_body_size. Following the HTTP/3 > > specification, such requests are now rejected with the 400 error as malformed. > > > > diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c > > --- a/src/http/v3/ngx_http_v3_request.c > > +++ b/src/http/v3/ngx_http_v3_request.c > > @@ -1575,12 +1575,21 @@ ngx_http_v3_request_body_filter(ngx_http > > /* rc == NGX_OK */ > > > > if (max != -1 && (uint64_t) (max - rb->received) < st->length) { > > - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > > - "client intended to send too large " > > - "body: %O+%ui bytes", > > - rb->received, st->length); > > + > > + if (max == r->headers_in.content_length_n) { > > + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, > > + "client intended to send body data " > > + "larger than declared"); > > + > > + return NGX_HTTP_BAD_REQUEST; > > > > - return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; > > + } else { > > + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > > + "client intended to send too large body: " > > + "%O+%ui bytes", rb->received, st->length); > > + > > + return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; > > + } > > } > > > > continue; > > After more thoughts I replaced "max == r->headers_in.content_length_n" > with a more clear check "r->headers_in.content_length_n != -1" > (also to make it more similar to the HTTP/2 request body filter). > The resulting diff is minimized since both conditions result in return. > > # HG changeset patch > # User Sergey Kandaurov > # Date 1713876685 -14400 > # Tue Apr 23 16:51:25 2024 +0400 > # Node ID c935bfd88ebf05aed181fc03231df8bd95475334 > # Parent 9f84f2e49c624e82e054a2dcd48723119c44029c > HTTP/3: fixed handling of malformed request body length. > > Previously, a request body larger than declared in Content-Length resulted in > a 413 status code, because Content-Length was mistakenly used as the maximum > allowed request body, similar to client_max_body_size. Following the HTTP/3 > specification, such requests are now rejected with the 400 error as malformed. > > diff --git a/src/http/v3/ngx_http_v3_request.c b/src/http/v3/ngx_http_v3_request.c > --- a/src/http/v3/ngx_http_v3_request.c > +++ b/src/http/v3/ngx_http_v3_request.c > @@ -1575,6 +1575,15 @@ ngx_http_v3_request_body_filter(ngx_http > /* rc == NGX_OK */ > if (max != -1 && (uint64_t) (max - rb->received) < st->length) { > + > + if (r->headers_in.content_length_n != -1) { > + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, > + "client intended to send body data " > + "larger than declared"); > + > + return NGX_HTTP_BAD_REQUEST; > + } > + > ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > "client intended to send too large " > "body: %O+%ui bytes", > > > -- > Sergey Kandaurov > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel Looks ok From arut at nginx.com Tue Apr 23 14:41:28 2024 From: arut at nginx.com (=?utf-8?q?Roman_Arutyunyan?=) Date: Tue, 23 Apr 2024 14:41:28 +0000 Subject: [nginx] Stable branch. Message-ID: details: https://hg.nginx.org/nginx/rev/52f427a4c97e branches: stable-1.26 changeset: 9240:52f427a4c97e user: Roman Arutyunyan date: Tue Apr 23 17:31:41 2024 +0400 description: Stable branch. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 49dce50fad40 -r 52f427a4c97e src/core/nginx.h --- a/src/core/nginx.h Tue Apr 16 18:29:59 2024 +0400 +++ b/src/core/nginx.h Tue Apr 23 17:31:41 2024 +0400 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1025005 -#define NGINX_VERSION "1.25.5" +#define nginx_version 1026000 +#define NGINX_VERSION "1.26.0" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From arut at nginx.com Tue Apr 23 14:41:31 2024 From: arut at nginx.com (=?utf-8?q?Roman_Arutyunyan?=) Date: Tue, 23 Apr 2024 14:41:31 +0000 Subject: [nginx] nginx-1.26.0-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/a58202a8c41b branches: stable-1.26 changeset: 9241:a58202a8c41b user: Roman Arutyunyan date: Tue Apr 23 17:40:08 2024 +0400 description: nginx-1.26.0-RELEASE diffstat: docs/xml/nginx/changes.xml | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-) diffs (24 lines): diff -r 52f427a4c97e -r a58202a8c41b docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml Tue Apr 23 17:31:41 2024 +0400 +++ b/docs/xml/nginx/changes.xml Tue Apr 23 17:40:08 2024 +0400 @@ -5,6 +5,20 @@ + + + + +Стабильная ветка 1.26.x. + + +1.26.x stable branch. + + + + + + From arut at nginx.com Tue Apr 23 14:41:34 2024 From: arut at nginx.com (=?utf-8?q?Roman_Arutyunyan?=) Date: Tue, 23 Apr 2024 14:41:34 +0000 Subject: [nginx] release-1.26.0 tag Message-ID: details: https://hg.nginx.org/nginx/rev/cdf74ac25b47 branches: stable-1.26 changeset: 9242:cdf74ac25b47 user: Roman Arutyunyan date: Tue Apr 23 18:04:32 2024 +0400 description: release-1.26.0 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r a58202a8c41b -r cdf74ac25b47 .hgtags --- a/.hgtags Tue Apr 23 17:40:08 2024 +0400 +++ b/.hgtags Tue Apr 23 18:04:32 2024 +0400 @@ -478,3 +478,4 @@ 1d839f05409d1a50d0f15a2bf36547001f99ae40 294a3d07234f8f65d7b0e0b0e2c5b05c12c5da0a release-1.25.3 173a0a7dbce569adbb70257c6ec4f0f6bc585009 release-1.25.4 8618e4d900cc71082fbe7dc72af087937d64faf5 release-1.25.5 +a58202a8c41bf0bd97eef1b946e13105a105520d release-1.26.0 From arut at nginx.com Thu Apr 25 13:06:33 2024 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 25 Apr 2024 17:06:33 +0400 Subject: [PROPOSAL]: Extend list of Stream phases In-Reply-To: References: Message-ID: Hi Andrey, > On 11 Apr 2024, at 3:27 AM, Andrey Kulikov wrote: > > Hello, > > Consider the following test-case: > I, as admin, would like to limit access to certain resources, based on Client TLS certificate content, fields, etc... > > Solution for HTTP: Easy! > There is NGX_HTTP_ACCESS_PHASE phase, where connections have been already accepted, and I have access to all $ssl_client_* variables. > And I control whatever I want, either using the if directive, or by implementing arbitrary sophisticated logic with some custom module. > > Solution for Stream: Simply impossible! > On NGX_STREAM_ACCESS_PHASE only IP-addresses can be checked, as TLS has not taken place yet. > NGX_STREAM_SSL_PHASE seems to be intended to specify certificates/keys for performing TLS handshake. > On NGX_STREAM_PREREAD_PHASE no $ssl_client_* variables available, as TLS handshake has not finished yet. > On NGX_STREAM_CONTENT_PHASE it is too late to do anything, as connection to the destination server was already established. > Hard way: implement a custom stream filter module, which checks access criteria on NGX_STREAM_CONTENT_PHASE. But it looks overcomplicated... > > Proposal: > Extend list of Stream phases at least to following: > > typedef enum { > NGX_STREAM_POST_ACCEPT_PHASE = 0, > NGX_STREAM_PREACCESS_PHASE, > NGX_STREAM_ACCESS_PHASE, > NGX_STREAM_SSL_PHASE, > NGX_STREAM_PREREAD_PHASE, > + NGX_STREAM_PRE_CONTENT_PHASE, // Change name to whatever seems suitable. > NGX_STREAM_CONTENT_PHASE, > NGX_STREAM_LOG_PHASE > } ngx_stream_phases; > > Questions: > Does it look feasible? > Are there any objectives NOT to do anything like this? (binary compatibility, etc...) > If I implement a trivial patch to extend the number of phases, will it be considered for review? While the problem does exist, precontent phase is not the right place for access control anyway. There's another solution. With the introduction of ngx_stream_pass_module, you can terminate TLS in one server and then switch to another server for access control. server { listen 9000 ssl; ... pass 127.0.0.1:9001; } server { listen 127.0.0.1:9001; # access control in access phase ... } ---- Roman Arutyunyan arut at nginx.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From arut at nginx.com Thu Apr 25 14:41:07 2024 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 25 Apr 2024 18:41:07 +0400 Subject: Leaky NGINX Plugin Advice In-Reply-To: References: Message-ID: Hello, As this is a development-related question, a better list for it is nginx-devel at nginx.org . > On 23 Apr 2024, at 1:40 PM, Alex Hussein-Kershaw (HE/HIM) via nginx wrote: > > Hi Folks, > > I've inherited an nginx plugin, written against 0.7.69 that has recently been moved to use nginx 1.24.0 to resolve the need to ship old versions of openssl. > > I've found during performance testing that it's leaking file descriptors. After a few hours running and leaking I hit my configured limit of 100k worker_connections which gets written to logs, and nginx starts "reusing connections". > > The leaked file descriptors don't show up in the output of "ss", they look like this in lsof: > > $ /usr/bin/lsof -p 2875952 | grep protocol | head -2 > nginx 2875952 user 8u sock 0,8 0t0 2222824178 protocol: TCP > nginx 2875952 user 19u sock 0,8 0t0 2266802646 protocol: TCP > > Googling suggests this may be a socket that has been created but never had a "bind" or "connect" call. I've combed through our plugin code, and am confident it's not responsible for making and leaking these sockets. > > I should flag two stinkers which may be responsible: > We have "lingering_timeout" set to an hour, a hack to allow long poll / COMET requests to not be torn down before responding. Stopping load and waiting for an hour does drop some of these leaked fds, but not all. After leaking 17k fds, I stopped my load test and saw it drop to 7k fds which appeared to remain indefinitely. Is this a terrible idea? > Within our plugin, we are incrementing the request count field for the same purpose. I'm not really sure why we need both of these, maybe I'm missing something but I can't get COMET polls to work without. I believe that was inspired by Nchan which does something similar. Should I be able to avoid requests getting torn down via this method without lingering_timeout? > > What could be responsible for these leaked file descriptors and worker connections? I'm unexperienced with nginx so any pointers of where to look are greatly appreciated. Incrementing request counter should be done carefully and can lead to socket leaks. To investigate the issue deeper, you can enable debug logging in nginx and find the leaked socket there by "fd:" prefix. Then track the leaked connection by its connection number (prefixed with '*' in log). > > Many thanks, > Alex > > > _______________________________________________ > nginx mailing list > nginx at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx ---- Roman Arutyunyan arut at nginx.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From arut at nginx.com Fri Apr 26 11:15:42 2024 From: arut at nginx.com (=?iso-8859-1?q?Roman_Arutyunyan?=) Date: Fri, 26 Apr 2024 15:15:42 +0400 Subject: [PATCH] Stream pass: disabled passing from or to udp Message-ID: # HG changeset patch # User Roman Arutyunyan # Date 1714057362 -14400 # Thu Apr 25 19:02:42 2024 +0400 # Branch stable-1.26 # Node ID a60cd9c99efcc1204e6d395104beb39883308c93 # Parent cdf74ac25b47ec928b53aa82ccc1c3d288a2f81c Stream pass: disabled passing from or to udp. Passing from udp was not possible for the most part due to preread buffer restriction. Passing to udp could occasionally work, but the connection would still be bound to the orignial listen rbtree, which prevented it from being deleted on connection closure. Also, passing to a QUIC listen socket is disabled by this change as well. diff --git a/src/stream/ngx_stream_pass_module.c b/src/stream/ngx_stream_pass_module.c --- a/src/stream/ngx_stream_pass_module.c +++ b/src/stream/ngx_stream_pass_module.c @@ -83,6 +83,11 @@ ngx_stream_pass_handler(ngx_stream_sessi c->log->action = "passing connection to port"; + if (c->type == SOCK_DGRAM) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, "cannot pass udp connection"); + goto failed; + } + if (c->buffer && c->buffer->pos != c->buffer->last) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "cannot pass connection with preread data"); @@ -217,6 +222,10 @@ ngx_stream_pass_cleanup(void *data) static ngx_int_t ngx_stream_pass_match(ngx_listening_t *ls, ngx_addr_t *addr) { + if (ls->type == SOCK_DGRAM) { + return NGX_DECLINED; + } + if (!ls->wildcard) { return ngx_cmp_sockaddr(ls->sockaddr, ls->socklen, addr->sockaddr, addr->socklen, 1); From roy at teeuwen.be Sat Apr 27 15:51:12 2024 From: roy at teeuwen.be (Roy Teeuwen) Date: Sat, 27 Apr 2024 17:51:12 +0200 Subject: [PATCH] proxy_cache_lock: Make lock timer configurable In-Reply-To: <8d38e6642e82bb219bb5.1711006239@1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa> References: <8d38e6642e82bb219bb5.1711006239@1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa> Message-ID: Any update on getting this PR merged? I'm also facing the same issue > On 21 Mar 2024, at 08:30, Nejc Lovrencic wrote: > > # HG changeset patch > # User Nejc Lovrencic > # Date 1711005111 -3600 > # Thu Mar 21 08:11:51 2024 +0100 > # Node ID 8d38e6642e82bb219bb5b586f1dcca5222a036e8 > # Parent 89bff782528a91ad123b63b624f798e6fd9c8e68 > proxy_cache_lock: Make lock timer configurable > > Default timer is set to 500ms. This in a worst-case scenario adds 500ms latency to MISS requests. This commit adds proxy_cache_lock_wait_time directive, which makes the timer configurable. > > diff -r 89bff782528a -r 8d38e6642e82 src/http/modules/ngx_http_proxy_module.c > --- a/src/http/modules/ngx_http_proxy_module.c Wed Feb 14 20:03:00 2024 +0400 > +++ b/src/http/modules/ngx_http_proxy_module.c Thu Mar 21 08:11:51 2024 +0100 > @@ -592,6 +592,12 @@ > offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_age), > NULL }, > > + { ngx_string("proxy_cache_lock_wait_time"), > + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, > + ngx_conf_set_msec_slot, > + NGX_HTTP_LOC_CONF_OFFSET, > + offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_wait_time), > + NULL }, > { ngx_string("proxy_cache_revalidate"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, > ngx_conf_set_flag_slot, > @@ -3390,6 +3396,7 @@ > conf->upstream.cache_lock = NGX_CONF_UNSET; > conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; > conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC; > + conf->upstream.cache_lock_wait_time = NGX_CONF_UNSET_MSEC; > conf->upstream.cache_revalidate = NGX_CONF_UNSET; > conf->upstream.cache_convert_head = NGX_CONF_UNSET; > conf->upstream.cache_background_update = NGX_CONF_UNSET; > @@ -3705,6 +3712,9 @@ > ngx_conf_merge_msec_value(conf->upstream.cache_lock_age, > prev->upstream.cache_lock_age, 5000); > > + ngx_conf_merge_msec_value(conf->upstream.cache_lock_wait_time, > + prev->upstream.cache_lock_wait_time, 500); > + > ngx_conf_merge_value(conf->upstream.cache_revalidate, > prev->upstream.cache_revalidate, 0); > > diff -r 89bff782528a -r 8d38e6642e82 src/http/ngx_http_cache.h > --- a/src/http/ngx_http_cache.h Wed Feb 14 20:03:00 2024 +0400 > +++ b/src/http/ngx_http_cache.h Thu Mar 21 08:11:51 2024 +0100 > @@ -103,6 +103,7 @@ > ngx_msec_t lock_timeout; > ngx_msec_t lock_age; > ngx_msec_t lock_time; > + ngx_msec_t lock_wait_time; > ngx_msec_t wait_time; > > ngx_event_t wait_event; > diff -r 89bff782528a -r 8d38e6642e82 src/http/ngx_http_file_cache.c > --- a/src/http/ngx_http_file_cache.c Wed Feb 14 20:03:00 2024 +0400 > +++ b/src/http/ngx_http_file_cache.c Thu Mar 21 08:11:51 2024 +0100 > @@ -452,7 +452,10 @@ > > timer = c->wait_time - now; > > - ngx_add_timer(&c->wait_event, (timer > 500) ? 500 : timer); > + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > + "http file cache lock timer tm:%M lwt:%M", timer, c->lock_wait_time); > + > + ngx_add_timer(&c->wait_event, (timer > c->lock_wait_time) ? c->lock_wait_time : timer); > > r->main->blocked++; > > @@ -531,7 +534,7 @@ > ngx_shmtx_unlock(&cache->shpool->mutex); > > if (wait) { > - ngx_add_timer(&c->wait_event, (timer > 500) ? 500 : timer); > + ngx_add_timer(&c->wait_event, (timer > c->lock_wait_time) ? c->lock_wait_time : timer); > return NGX_AGAIN; > } > > diff -r 89bff782528a -r 8d38e6642e82 src/http/ngx_http_upstream.c > --- a/src/http/ngx_http_upstream.c Wed Feb 14 20:03:00 2024 +0400 > +++ b/src/http/ngx_http_upstream.c Thu Mar 21 08:11:51 2024 +0100 > @@ -894,6 +894,7 @@ > c->lock = u->conf->cache_lock; > c->lock_timeout = u->conf->cache_lock_timeout; > c->lock_age = u->conf->cache_lock_age; > + c->lock_wait_time = u->conf->cache_lock_wait_time; > > u->cache_status = NGX_HTTP_CACHE_MISS; > } > diff -r 89bff782528a -r 8d38e6642e82 src/http/ngx_http_upstream.h > --- a/src/http/ngx_http_upstream.h Wed Feb 14 20:03:00 2024 +0400 > +++ b/src/http/ngx_http_upstream.h Thu Mar 21 08:11:51 2024 +0100 > @@ -204,6 +204,7 @@ > ngx_flag_t cache_lock; > ngx_msec_t cache_lock_timeout; > ngx_msec_t cache_lock_age; > + ngx_msec_t cache_lock_wait_time; > > ngx_flag_t cache_revalidate; > ngx_flag_t cache_convert_head; > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel From xeioex at nginx.com Mon Apr 29 21:24:58 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Mon, 29 Apr 2024 21:24:58 +0000 Subject: [njs] Allowing to use custom allocator in njs_chb_t. Message-ID: details: https://hg.nginx.org/njs/rev/622387b5b612 branches: changeset: 2322:622387b5b612 user: Dmitry Volyntsev date: Fri Apr 26 16:27:52 2024 -0700 description: Allowing to use custom allocator in njs_chb_t. diffstat: external/njs_query_string_module.c | 6 +++--- external/njs_xml_module.c | 2 +- external/njs_zlib_module.c | 4 ++-- nginx/ngx_js_fetch.c | 6 +++--- src/njs_array.c | 2 +- src/njs_chb.c | 21 +++++++++++++++++---- src/njs_chb.h | 27 ++++++++++++++++----------- src/njs_error.c | 2 +- src/njs_function.c | 2 +- src/njs_json.c | 4 ++-- src/njs_regexp.c | 2 +- src/njs_string.c | 8 ++++---- src/njs_typed_array.c | 2 +- src/njs_vm.c | 2 +- src/test/njs_unit_test.c | 2 +- 15 files changed, 55 insertions(+), 37 deletions(-) diffs (347 lines): diff -r a97a9f3b3cea -r 622387b5b612 external/njs_query_string_module.c --- a/external/njs_query_string_module.c Mon Apr 22 18:59:03 2024 -0700 +++ b/external/njs_query_string_module.c Fri Apr 26 16:27:52 2024 -0700 @@ -152,7 +152,7 @@ njs_query_string_decode(njs_vm_t *vm, nj -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; - njs_chb_init(&chain, njs_vm_memory_pool(vm)); + NJS_CHB_MP_INIT(&chain, vm); njs_utf8_decode_init(&ctx); cp = 0; @@ -749,7 +749,7 @@ njs_query_string_stringify(njs_vm_t *vm, encode = njs_value_function(val); } - njs_chb_init(&chain, njs_vm_memory_pool(vm)); + NJS_CHB_MP_INIT(&chain, vm); keys = njs_vm_object_keys(vm, object, njs_value_arg(&value)); if (njs_slow_path(keys == NULL)) { @@ -841,7 +841,7 @@ njs_query_string_escape(njs_vm_t *vm, nj njs_value_string_get(string, &str); - njs_chb_init(&chain, njs_vm_memory_pool(vm)); + NJS_CHB_MP_INIT(&chain, vm); ret = njs_query_string_encode(&chain, &str); if (njs_slow_path(ret != NJS_OK)) { diff -r a97a9f3b3cea -r 622387b5b612 external/njs_xml_module.c --- a/external/njs_xml_module.c Mon Apr 22 18:59:03 2024 -0700 +++ b/external/njs_xml_module.c Fri Apr 26 16:27:52 2024 -0700 @@ -1788,7 +1788,7 @@ njs_xml_ext_canonicalization(njs_vm_t *v } } - njs_chb_init(&chain, njs_vm_memory_pool(vm)); + NJS_CHB_MP_INIT(&chain, vm); buf = xmlOutputBufferCreateIO(njs_xml_buf_write_cb, NULL, &chain, NULL); if (njs_slow_path(buf == NULL)) { diff -r a97a9f3b3cea -r 622387b5b612 external/njs_zlib_module.c --- a/external/njs_zlib_module.c Mon Apr 22 18:59:03 2024 -0700 +++ b/external/njs_zlib_module.c Fri Apr 26 16:27:52 2024 -0700 @@ -320,7 +320,7 @@ njs_zlib_ext_deflate(njs_vm_t *vm, njs_v } } - njs_chb_init(&chain, njs_vm_memory_pool(vm)); + NJS_CHB_MP_INIT(&chain, vm); do { stream.next_out = njs_chb_reserve(&chain, chunk_size); @@ -461,7 +461,7 @@ njs_zlib_ext_inflate(njs_vm_t *vm, njs_v } } - njs_chb_init(&chain, njs_vm_memory_pool(vm)); + NJS_CHB_MP_INIT(&chain, vm); while (rc != Z_STREAM_END) { stream.next_out = njs_chb_reserve(&chain, chunk_size); diff -r a97a9f3b3cea -r 622387b5b612 nginx/ngx_js_fetch.c --- a/nginx/ngx_js_fetch.c Mon Apr 22 18:59:03 2024 -0700 +++ b/nginx/ngx_js_fetch.c Fri Apr 26 16:27:52 2024 -0700 @@ -740,7 +740,7 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value http->header_only = njs_strstr_eq(&request.method, &njs_str_value("HEAD")); - njs_chb_init(&http->chain, njs_vm_memory_pool(vm)); + NJS_CHB_MP_INIT(&http->chain, vm); njs_chb_append(&http->chain, request.method.start, request.method.length); njs_chb_append_literal(&http->chain, " "); @@ -1051,7 +1051,7 @@ ngx_js_ext_response_constructor(njs_vm_t } } - njs_chb_init(&response->chain, njs_vm_memory_pool(vm)); + NJS_CHB_MP_INIT(&response->chain, vm); body = njs_arg(args, nargs, 1); @@ -2468,7 +2468,7 @@ ngx_js_http_process_headers(ngx_js_http_ njs_chb_destroy(&http->chain); - njs_chb_init(&http->response.chain, njs_vm_memory_pool(http->vm)); + NJS_CHB_MP_INIT(&http->response.chain, http->vm); http->process = ngx_js_http_process_body; diff -r a97a9f3b3cea -r 622387b5b612 src/njs_array.c --- a/src/njs_array.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_array.c Fri Apr 26 16:27:52 2024 -0700 @@ -1698,7 +1698,7 @@ njs_array_prototype_join(njs_vm_t *vm, n value = &entry; - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); for (i = 0; i < len; i++) { ret = njs_value_property_i64(vm, this, i, value); diff -r a97a9f3b3cea -r 622387b5b612 src/njs_chb.c --- a/src/njs_chb.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_chb.c Fri Apr 26 16:27:52 2024 -0700 @@ -12,6 +12,19 @@ void +njs_chb_init(njs_chb_t *chain, void *pool, njs_chb_alloc_t alloc, + njs_chb_free_t free) +{ + chain->error = 0; + chain->pool = pool; + chain->alloc = alloc; + chain->free = free; + chain->nodes = NULL; + chain->last = NULL; +} + + +void njs_chb_append0(njs_chb_t *chain, const char *msg, size_t len) { u_char *p; @@ -44,7 +57,7 @@ njs_chb_reserve(njs_chb_t *chain, size_t size = NJS_CHB_MIN_SIZE; } - n = njs_mp_alloc(chain->pool, sizeof(njs_chb_node_t) + size); + n = chain->alloc(chain->pool, sizeof(njs_chb_node_t) + size); if (njs_slow_path(n == NULL)) { chain->error = 1; return NULL; @@ -149,7 +162,7 @@ njs_chb_drop(njs_chb_t *chain, size_t dr if (drop >= size) { njs_chb_destroy(chain); - njs_chb_init(chain, chain->pool); + njs_chb_init(chain, chain->pool, chain->alloc, chain->free); return; } @@ -201,7 +214,7 @@ njs_chb_join(njs_chb_t *chain, njs_str_t return NJS_ERROR; } - start = njs_mp_alloc(chain->pool, size); + start = chain->alloc(chain->pool, size); if (njs_slow_path(start == NULL)) { return NJS_ERROR; } @@ -238,7 +251,7 @@ njs_chb_destroy(njs_chb_t *chain) while (n != NULL) { next = n->next; - njs_mp_free(chain->pool, n); + chain->free(chain->pool, n); n = next; } } diff -r a97a9f3b3cea -r 622387b5b612 src/njs_chb.h --- a/src/njs_chb.h Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_chb.h Fri Apr 26 16:27:52 2024 -0700 @@ -17,14 +17,29 @@ struct njs_chb_node_s { u_char *end; }; +typedef void *(*njs_chb_alloc_t)(void *pool, size_t size); +typedef void (*njs_chb_free_t)(void *pool, void *p); + typedef struct { njs_bool_t error; - njs_mp_t *pool; + + void *pool; + njs_chb_alloc_t alloc; + njs_chb_free_t free; + njs_chb_node_t *nodes; njs_chb_node_t *last; } njs_chb_t; +void njs_chb_init(njs_chb_t *chain, void *pool, njs_chb_alloc_t alloc, + njs_chb_free_t free); +#define NJS_CHB_MP_INIT(chain, vm) \ + njs_chb_init(chain, njs_vm_memory_pool(vm), (njs_chb_alloc_t) njs_mp_alloc,\ + (njs_chb_free_t) njs_mp_free) +#define NJS_CHB_CTX_INIT(chain, ctx) \ + njs_chb_init(chain, ctx, (njs_chb_alloc_t) js_malloc, \ + (njs_chb_free_t) js_free) void njs_chb_append0(njs_chb_t *chain, const char *msg, size_t len); void njs_chb_vsprintf(njs_chb_t *chain, size_t size, const char *fmt, va_list args); @@ -49,16 +64,6 @@ void njs_chb_destroy(njs_chb_t *chain); njs_inline void -njs_chb_init(njs_chb_t *chain, njs_mp_t *pool) -{ - chain->error = 0; - chain->pool = pool; - chain->nodes = NULL; - chain->last = NULL; -} - - -njs_inline void njs_chb_append_str(njs_chb_t *chain, njs_str_t *str) { njs_chb_append0(chain, (const char *) str->start, str->length); diff -r a97a9f3b3cea -r 622387b5b612 src/njs_error.c --- a/src/njs_error.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_error.c Fri Apr 26 16:27:52 2024 -0700 @@ -1069,7 +1069,7 @@ njs_backtrace_to_string(njs_vm_t *vm, nj return NJS_OK; } - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); njs_chb_append_str(&chain, dst); njs_chb_append(&chain, "\n", 1); diff -r a97a9f3b3cea -r 622387b5b612 src/njs_function.c --- a/src/njs_function.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_function.c Fri Apr 26 16:27:52 2024 -0700 @@ -1032,7 +1032,7 @@ njs_function_constructor(njs_vm_t *vm, n goto fail; } - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); if (async) { njs_chb_append_literal(&chain, "(async function("); diff -r a97a9f3b3cea -r 622387b5b612 src/njs_json.c --- a/src/njs_json.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_json.c Fri Apr 26 16:27:52 2024 -0700 @@ -1106,7 +1106,7 @@ njs_json_stringify_iterator(njs_json_str goto memory_error; } - njs_chb_init(&chain, stringify->vm->mem_pool); + NJS_CHB_MP_INIT(&chain, stringify->vm); for ( ;; ) { if (state->index == 0) { @@ -1990,7 +1990,7 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_ value = &exception; } - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); if (!njs_dump_is_recursive(value)) { ret = njs_dump_terminal(stringify, &chain, value, console); diff -r a97a9f3b3cea -r 622387b5b612 src/njs_regexp.c --- a/src/njs_regexp.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_regexp.c Fri Apr 26 16:27:52 2024 -0700 @@ -1398,7 +1398,7 @@ njs_regexp_prototype_symbol_replace(njs_ } } - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); results.separate = 0; results.pointer = 0; diff -r a97a9f3b3cea -r 622387b5b612 src/njs_string.c --- a/src/njs_string.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_string.c Fri Apr 26 16:27:52 2024 -0700 @@ -3081,7 +3081,7 @@ njs_string_get_substitution(njs_vm_t *vm p = rep.start; end = rep.start + rep.length; - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); while (p < end) { r = njs_strlchr(p, end, '$'); @@ -3379,7 +3379,7 @@ njs_string_prototype_replace(njs_vm_t *v return NJS_OK; } - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); p_start = string.start; increment = s.length != 0 ? s.length : 1; @@ -4033,7 +4033,7 @@ njs_string_decode_uri(njs_vm_t *vm, njs_ src = string.start; end = string.start + string.size; - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); njs_utf8_decode_init(&ctx); @@ -4307,7 +4307,7 @@ njs_string_atob(njs_vm_t *vm, njs_value_ len = njs_base64_decoded_length(len, pad); - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); dst = njs_chb_reserve(&chain, len * 2); if (njs_slow_path(dst == NULL)) { diff -r a97a9f3b3cea -r 622387b5b612 src/njs_typed_array.c --- a/src/njs_typed_array.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_typed_array.c Fri Apr 26 16:27:52 2024 -0700 @@ -2143,7 +2143,7 @@ njs_typed_array_prototype_join(njs_vm_t return NJS_ERROR; } - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); length = njs_typed_array_to_chain(vm, &chain, array, separator); size = njs_chb_size(&chain); diff -r a97a9f3b3cea -r 622387b5b612 src/njs_vm.c --- a/src/njs_vm.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/njs_vm.c Fri Apr 26 16:27:52 2024 -0700 @@ -233,7 +233,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st } if (njs_slow_path(vm->options.ast)) { - njs_chb_init(&chain, vm->mem_pool); + NJS_CHB_MP_INIT(&chain, vm); ret = njs_parser_serialize_ast(parser.node, &chain); if (njs_slow_path(ret == NJS_ERROR)) { return ret; diff -r a97a9f3b3cea -r 622387b5b612 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Apr 22 18:59:03 2024 -0700 +++ b/src/test/njs_unit_test.c Fri Apr 26 16:27:52 2024 -0700 @@ -24477,7 +24477,7 @@ njs_chb_test(njs_vm_t *vm, njs_opts_t *o static const njs_str_t expected = njs_str("arg: \"XYZ\" -5"); - njs_chb_init(&chain, njs_vm_memory_pool(vm)); + NJS_CHB_MP_INIT(&chain, vm); p = njs_chb_reserve(&chain, 513); if (p == NULL) { From xeioex at nginx.com Mon Apr 29 21:25:00 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Mon, 29 Apr 2024 21:25:00 +0000 Subject: [njs] Fetch: fixed request Host header when the port is non-standard. Message-ID: details: https://hg.nginx.org/njs/rev/7456fe29ac0a branches: changeset: 2323:7456fe29ac0a user: Dmitry Volyntsev date: Fri Apr 26 16:48:17 2024 -0700 description: Fetch: fixed request Host header when the port is non-standard. This fixes #707 issue on Github. diffstat: nginx/ngx_js_fetch.c | 5 +++ nginx/t/js_fetch_resolver.t | 69 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 7 deletions(-) diffs (122 lines): diff -r 622387b5b612 -r 7456fe29ac0a nginx/ngx_js_fetch.c --- a/nginx/ngx_js_fetch.c Fri Apr 26 16:27:52 2024 -0700 +++ b/nginx/ngx_js_fetch.c Fri Apr 26 16:48:17 2024 -0700 @@ -786,6 +786,11 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value if (!has_host) { njs_chb_append_literal(&http->chain, "Host: "); njs_chb_append(&http->chain, u.host.data, u.host.len); + + if (!u.no_port) { + njs_chb_sprintf(&http->chain, 32, ":%d", u.port); + } + njs_chb_append_literal(&http->chain, CRLF); } diff -r 622387b5b612 -r 7456fe29ac0a nginx/t/js_fetch_resolver.t --- a/nginx/t/js_fetch_resolver.t Fri Apr 26 16:27:52 2024 -0700 +++ b/nginx/t/js_fetch_resolver.t Fri Apr 26 16:48:17 2024 -0700 @@ -65,6 +65,23 @@ http { location /loc { js_content test.loc; } + + location /host { + return 200 8080:$http_host; + } + } + + server { + listen 127.0.0.1:8081; + server_name aaa; + + location /loc { + js_content test.loc; + } + + location /host { + return 200 8081:$http_host; + } } server { @@ -80,19 +97,29 @@ http { EOF my $p0 = port(8080); +my $p1 = port(8081); $t->write_file('test.js', < reply.text()) - .then(body => r.return(200, body)) - .catch(e => r.return(501, e.message)) + try { + let reply = await ngx.fetch(url); + let body = await reply.text(); + r.return(200, body); + + } catch (e) { + r.return(501, e.message); + } } function str(v) { return v ? v : ''}; @@ -109,7 +136,7 @@ my $p0 = port(8080); export default {njs: test_njs, dns, loc}; EOF -$t->try_run('no njs.fetch')->plan(3); +$t->try_run('no njs.fetch')->plan(5); $t->run_daemon(\&dns_daemon, port(8981), $t); $t->waitforfile($t->testdir . '/' . port(8981)); @@ -121,6 +148,34 @@ like(http_get('/dns?domain=many'), qr/ma like(http_get('/dns?domain=unknown'), qr/"unknown" could not be resolved/s, 'fetch dns unknown'); +TODO: { +local $TODO = 'not yet' unless has_version('0.8.5'); + +like(http_get('/dns?domain=aaa&port=p0&loc=host'), qr/8080:aaa:$p0$/s, + 'fetch aaa:8080'); +like(http_get('/dns?domain=aaa&port=p1&loc=host'), qr/8081:aaa:$p1$/s, + 'fetch aaa:8081'); +} + +############################################################################### + +sub has_version { + my $need = shift; + + http_get('/njs') =~ /^([.0-9]+)$/m; + + my @v = split(/\./, $1); + my ($n, $v); + + for $n (split(/\./, $need)) { + $v = shift @v || 0; + return 0 if $n > $v; + return 1 if $v > $n; + } + + return 1; +} + ############################################################################### sub reply_handler { From xeioex at nginx.com Mon Apr 29 21:25:02 2024 From: xeioex at nginx.com (=?utf-8?q?Dmitry_Volyntsev?=) Date: Mon, 29 Apr 2024 21:25:02 +0000 Subject: [njs] Tests: fixed typo in stream_js_dup_set.t introduced in be271e8d0b3b. Message-ID: details: https://hg.nginx.org/njs/rev/18fc657411ca branches: changeset: 2324:18fc657411ca user: Dmitry Volyntsev date: Fri Apr 26 16:48:19 2024 -0700 description: Tests: fixed typo in stream_js_dup_set.t introduced in be271e8d0b3b. Previously, with typo the test was always skipped. diffstat: nginx/t/stream_js_dup_set.t | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 7456fe29ac0a -r 18fc657411ca nginx/t/stream_js_dup_set.t --- a/nginx/t/stream_js_dup_set.t Fri Apr 26 16:48:17 2024 -0700 +++ b/nginx/t/stream_js_dup_set.t Fri Apr 26 16:48:19 2024 -0700 @@ -46,7 +46,7 @@ stream { server { listen 127.0.0.1:8082; - js_set $test test.foo1; + js_set $test test.foo; return 8082:$test; } } From arut at nginx.com Tue Apr 30 15:27:46 2024 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 30 Apr 2024 19:27:46 +0400 Subject: [PATCH]HTTP/2 connection not properly closing during graceful shutdown In-Reply-To: References: Message-ID: <20240430152746.bksaeztpdhlo22uv@N00W24XTQX> Hi, On Tue, Apr 23, 2024 at 06:02:08PM +0800, Kasei Wang wrote: > Hello, > > I found that there is a slight probability of HTTP/2 connections not > properly closing during graceful shutdown, leading to worker processes > in shutting down state remaining stuck for an extended period. After > investigation, the issue appears to stem from the following: > > 1. worker processes in shutting down state use > ngx_close_idle_connections to close all idle connections, including > HTTP/2 connections. > 2. For HTTP/2 connections, c->idle is set to true in ngx_http_v2_init. > According to the explanation in > https://hg.nginx.org/nginx/rev/5e95b9fb33b7, GOAWAY should be sent to > all HTTP/2 connections. > 3. There might be a time gap between ngx_event_accept and > ngx_http_v2_init. For TLS connections, ngx_http_v2_init will be > executed after ALPN received, and for plaintext http2 connections, > ngx_http_v2_init will be executed after parsing the http2 preface. If > ngx_close_idle_connections is executed between ngx_event_accept and > ngx_http_v2_init, there's a possibility that c->idle of some > connections is set to true AFTER ngx_close_idle_connections, causing > those connections to not enter the GOAWAY process and leading to the > aforementioned problem. You're right, the problem does exist. > To verify this, I've written a simple HTTP/2 client. This program will > wait 15 seconds after TCP connection establishment before starting to > send data. The purpose of sleep is to to raise the probability of > encountering the issue. You can reproduce the problem by executing > "nginx -s reload" during this 15-second wait. If you're interested, > you can try my test program > () to > reproduce the issue. > > I believe the simplest solution is to set c->close based on > ngx_exiting in ngx_http_v2_init. In this way, the connection will send > GOAWAY in ngx_http_v2_read_handler. While setting c->close does the trick, I personally don't like abusing its semantics. The flag is used by nginx core to signal the application layer that the connection is being closed. Using it within the application layer is not good, even though this does happen sometimes. > Please confirm if this issue exists, review my analysis and the patch > if possible. Thank you very much. > > # HG changeset patch > # User Kasei Wang > # Date 1713863474 -28800 > # Tue Apr 23 17:11:14 2024 +0800 > # Branch help > # Node ID e5ba8996973cdd1edd7591a28ee1c145af86c556 > # Parent 8618e4d900cc71082fbe7dc72af087937d64faf5 > HTTP/2: close http2 connections created during graceful shutdown. > > diff -r 8618e4d900cc -r e5ba8996973c src/http/v2/ngx_http_v2.c > --- a/src/http/v2/ngx_http_v2.c Tue Apr 16 18:27:50 2024 +0400 > +++ b/src/http/v2/ngx_http_v2.c Tue Apr 23 17:11:14 2024 +0800 > @@ -304,6 +304,10 @@ > c->idle = 1; > ngx_reusable_connection(c, 0); > > + if (ngx_exiting) { > + c->close = 1; > + } > + > if (c->buffer) { > p = c->buffer->pos; > end = c->buffer->last; This solution allows reading and handling the data from c->buffer prior to closing the connection, which we probably don't need. I think it'd be better to just call ngx_http_v2_finalize_connection() at the right moment in ngx_http_v2_init(). -- Roman Arutyunyan