diff options
Diffstat (limited to '')
55 files changed, 1246 insertions, 246 deletions
@@ -51,3 +51,4 @@ f804aaf7eee10a7d8116820840d6312dd4914a41 1.21.0 e3f504b6082ee97ed0d6c8660890585ef6a5796f 1.21.0-1 331bdadeca30a49dd11b86af99124c2ffeb22d05 1.22.0 86b359acc93fe53f1f21b22abc8d1b40ca26158c 1.22.0-1 +49ee24c03f5749f8a1b69dc1c600ad48517d9d7a 1.23.0 @@ -1,4 +1,44 @@ +Changes with Unit 1.23.0 25 Mar 2021 + + *) Feature: support for multiple certificate bundles on a listener via + the Server Name Indication (SNI) TLS extension. + + *) Feature: "--mandir" ./configure option to specify the directory for + man page installation. + + *) Bugfix: the router process could crash on premature TLS connection + close; the bug had appeared in 1.17.0. + + *) Bugfix: a connection leak occurred on premature TLS connection close; + the bug had appeared in 1.6. + + *) Bugfix: a descriptor and memory leak occurred in the router process + when processing small WebSocket frames from a client; the bug had + appeared in 1.19.0. + + *) Bugfix: a descriptor leak occurred in the router process when + removing or reconfiguring an application; the bug had appeared in + 1.19.0. + + *) Bugfix: persistent storage of certificates might've not worked with + some filesystems in Linux, and all uploaded certificate bundles were + forgotten after restart. + + *) Bugfix: the controller process could crash while requesting + information about a certificate with a non-DNS SAN entry. + + *) Bugfix: the controller process could crash on manipulations with a + certificate containing a SAN and no standard name attributes in + subject or issuer. + + *) Bugfix: the Ruby module didn't respect the user locale for defaults + in the Encoding class. + + *) Bugfix: the PHP 5 module failed to build with thread safety enabled; + the bug had appeared in 1.22.0. + + Changes with Unit 1.22.0 04 Feb 2021 *) Feature: the ServerRequest and ServerResponse objects of Node.js @@ -18,6 +18,7 @@ cat << END default: "$NXT_SBINDIR" --libdir=DIRECTORY set library directory name, default: "$NXT_LIBDIR" --incdir=DIRECTORY set includes directory name, default: "$NXT_INCDIR" + --mandir=DIRECTORY set man pages directory name, default: "$NXT_MANDIR" --modules=DIRECTORY set modules directory name, default: "$NXT_MODULES" --state=DIRECTORY set state directory name, default: "$NXT_STATE" --tmp=DIRECTORY set tmp directory name, default: "$NXT_TMP" @@ -22,10 +22,11 @@ NXT_EXEC_LINK = $NXT_EXEC_LINK $NXT_LD_OPT NXT_SHARED_LOCAL_LINK = $NXT_SHARED_LOCAL_LINK $NXT_LD_OPT NXT_MODULE_LINK = $NXT_MODULE_LINK -all: $NXT_DAEMON +all: $NXT_DAEMON manpage -.PHONY: $NXT_DAEMON +.PHONY: $NXT_DAEMON manpage $NXT_DAEMON: $NXT_BUILD_DIR/$NXT_DAEMON +manpage: $NXT_BUILD_DIR/unitd.8 END @@ -305,6 +306,19 @@ $NXT_BUILD_DIR/$NXT_DAEMON: $NXT_BUILD_DIR/$NXT_LIB_STATIC \\ END +# unitd man page + +cat << END >> $NXT_MAKEFILE + +$NXT_BUILD_DIR/unitd.8: docs/man/unitd.8.in $NXT_BUILD_DIR/nxt_auto_config.h + sed -e "s|%%ERROR_LOG_PATH%%|$NXT_LOG|" \\ + -e "s|%%PID_PATH%%|$NXT_PID|" \\ + -e "s|%%SOCKET_PATH%%|$NXT_CONTROL|" \\ + < docs/man/unitd.8.in > \$@ + +END + + # unit object files. for nxt_src in $NXT_MAKE_SRCS @@ -334,9 +348,9 @@ done cat << END >> $NXT_MAKEFILE -.PHONY: install ${NXT_DAEMON}-install install-check +.PHONY: install ${NXT_DAEMON}-install install-check manpage-install -install: ${NXT_DAEMON}-install +install: ${NXT_DAEMON}-install manpage-install install-check: @test -n "\$(DESTDIR)$NXT_PREFIX" \\ @@ -352,15 +366,22 @@ ${NXT_DAEMON}-install: $NXT_DAEMON install-check install -p $NXT_BUILD_DIR/$NXT_DAEMON \$(DESTDIR)$NXT_SBINDIR/ install -d \$(DESTDIR)$NXT_STATE +manpage-install: manpage install-check + install -d \$(DESTDIR)$NXT_MANDIR/man8 + install -p $NXT_BUILD_DIR/unitd.8 \$(DESTDIR)$NXT_MANDIR/man8/ -.PHONY: uninstall ${NXT_DAEMON}-uninstall +.PHONY: uninstall ${NXT_DAEMON}-uninstall manpage-uninstall -uninstall: ${NXT_DAEMON}-uninstall +uninstall: ${NXT_DAEMON}-uninstall manpage-uninstall ${NXT_DAEMON}-uninstall: rm -f \$(DESTDIR)$NXT_SBINDIR/$NXT_DAEMON @rmdir -p \$(DESTDIR)$NXT_SBINDIR 2>/dev/null || true +manpage-uninstall: + rm -f \$(DESTDIR)$NXT_MANDIR/man8/unitd.8 + @rmdir -p \$(DESTDIR)$NXT_MANDIR/man8 2>/dev/null || true + END cat << END >> $NXT_MAKEFILE diff --git a/auto/modules/java b/auto/modules/java index 60415c35..05b3100c 100644 --- a/auto/modules/java +++ b/auto/modules/java @@ -238,7 +238,7 @@ cat << END > $NXT_JAVA_JARS static const char *nxt_java_system_jars[] = { END -NXT_TOMCAT_VERSION=9.0.39 +NXT_TOMCAT_VERSION=9.0.44 NXT_JAR_VERSION=$NXT_TOMCAT_VERSION @@ -271,7 +271,7 @@ NXT_JAR_NAME=tomcat-util . auto/modules/java_get_jar NXT_JAR_NAME=ecj -NXT_JAR_VERSION=3.23.0 +NXT_JAR_VERSION=3.25.0 NXT_JAR_NAMESPACE=org/eclipse/jdt/ . auto/modules/java_get_jar @@ -284,7 +284,7 @@ static const char *nxt_java_unit_jars[] = { "$NXT_UNIT_JAR", END -NXT_JAR_VERSION=9.4.33.v20201020 +NXT_JAR_VERSION=9.4.38.v20210224 NXT_JAR_NAMESPACE=org/eclipse/jetty/ NXT_JAR_NAME=jetty-util @@ -297,7 +297,7 @@ NXT_JAR_NAME=jetty-http . auto/modules/java_get_jar NXT_JAR_NAME=classgraph -NXT_JAR_VERSION=4.8.90 +NXT_JAR_VERSION=4.8.102 NXT_JAR_NAMESPACE=io/github/classgraph/ . auto/modules/java_get_jar diff --git a/auto/modules/java_jar.sha512 b/auto/modules/java_jar.sha512 index 214cff33..98d27149 100644 --- a/auto/modules/java_jar.sha512 +++ b/auto/modules/java_jar.sha512 @@ -1,14 +1,14 @@ -083f2102a50f2c3a4fc3993d328ddee17707b0529fdcee4868bd3b6901ff20a3d97e9733f83b2e46828469ecc273a1a3a5da26e4ba3d63f725a81b0b9e3e49e6 classgraph-4.8.90.jar -5e63e06eccd76a61249c7c6bd97e5b77dc37335bfdf316d941b00a16bae4f152d4306bac4e45c8422976187b0d77fe30cf7e6f6d4425f7732a3cb0cfa954385b ecj-3.23.0.jar -9abb4ba6802c39526b755429e3f41d641408f91f1c48844cd56cda116fb1479f05f1a3d90c18f30386b07d5593221c1f85ef565da0c6121b6ff005ec7d9c3bd9 jetty-http-9.4.33.v20201020.jar -e60e73ed3fd18e029c8e3cae04eac01d05f985dd0d9059eea620f4f9acac60799706d4b56b5a0f10cc33ff9272afdf11e712c604e31a77fa1afa1f95a57294ce jetty-server-9.4.33.v20201020.jar -35c5ad89d92e77f542d3ce42249f01c478706e2a013c5ab6a9504cf43520e3de90280d82a11389e9909060835421e3caada68e77d86df76a84856be60361d550 jetty-util-9.4.33.v20201020.jar -2d28d12196a7c2d342876d7e63c3a87fd613aadb32afad28d428d5dd9d9d0ebfa8300de3681d885455ac81d215326b11b845346416d5bd12d0e27c1763602caa tomcat-api-9.0.39.jar -661e613ae966e9b1fcc8815823c273fd7a05a6f8d3c469d86ce50650c1f350cbfb624fde8ee86235603078d9c5ccae5dfec8e03e10b5cb1e11109ae6ae4e85bb tomcat-el-api-9.0.39.jar -541d4794e1e15f26d7853cd7841f031e66fd3fc345102871cf58013591c8b57b6ab470d8ac28781c077f25e8d7fc06c19c6444db8e4a28ce4767ddbd907be004 tomcat-jasper-9.0.39.jar -57b916cb87f178604751f52f23f57fbd05da3001c9419602836e25d779727500bc1fceae195d5758aff28393b396751538f2ab7a9390738ebe4d0b4bd17b8ee4 tomcat-jasper-el-9.0.39.jar -d34deeecdecd59e40225ca3ad0ac197fc7f7845f09f551f5f17290ff9971741e62fac4bde16499d585b3d7c5574927c09740c0976dbddacecb19b4772f60c3e3 tomcat-jsp-api-9.0.39.jar -ee43f08f26e1d48c5cd3719e1eeec26e4ef389647a0bcd31435ed85c6c8770ab48fe287c60432aa8821b8fc8fce8ef0977a29b29c8c3b3cb246be53fb0182d1a tomcat-juli-9.0.39.jar -c387931fba85eae7ce030601dbd760cc7c2b0242a670b0c62321a8972e534076a40150044886053b3771099aa57c89057892d4f7fda84f65fa67b9c53dd51400 tomcat-servlet-api-9.0.39.jar -aa0b5ff10cdc686ba1dbc8a35d75aa42196126cbbde0d1ab1b9211ba57987a246bbe825c89a88104a0a60869fcbff4a8067bb247e42b69c887d6b48ee5c4a417 tomcat-util-9.0.39.jar -42c4b698cfb0a1fb154e290ac265c14693a9ef094e54116a324864f5b483f37d7a7decf67f7fe43b546cf1d2f25e9d763adc598a5e92979f756299e981dde43d tomcat-util-scan-9.0.39.jar +5105e9edf0fc6a4a51eb2bb1e2c23bb78a604fe2df3b1e814cf638ce22845a6ae57e75af31db9dd00d5c650403e751659cca8d3bc465fb96525c695188d2055f classgraph-4.8.102.jar +48cee25d195a5c713a962b035ecba633797753474f290c107a0ee96272cd9ae1b6b62b060ef37e0699f6a5af4d4b45e514ef710309f41bdd9440925cf60a111a ecj-3.25.0.jar +3f2a4a5b7f71c6a1317cec29ea12eb04eac68f4cee94c30ffb75fdd36dbc9c622059fb762e27f74f7b7a38eb84966732ba963cc294f5aaf8b7f5f8c9d60c8899 jetty-http-9.4.38.v20210224.jar +cc416b324841e9c259538a3ec678a9d8e07d3bea9b0bb687bc15a759c5065c7de6ea7bbbb15b369b8c6d2023c3294906d8f9cfda28e1b7859283008790581a4d jetty-server-9.4.38.v20210224.jar +efdbeae97c959459c10b05aae62189c535a0935dadf7debf4257257c31a98a4167ca1318daa81dae32161f51117b17468d5fb5a6bb4eea40864ce1265623d684 jetty-util-9.4.38.v20210224.jar +f2534f246c0cec9be576f18d67759b5a997074bb7870cbf7b9469f062ddc6932e5cec45fd439a5beacc8c6248d39dc458af81245a6eb988e294667f2bcd251df tomcat-api-9.0.44.jar +0c8050b04b02a6a1f1384d1a4041594c09868cfeb139978274c5e5797eb95e0668495f489eb61cfe742905e453184edc0ad8a9fd3b2796e960981a20ae4a0334 tomcat-el-api-9.0.44.jar +cc81a06795553f06d3dfe930429fdf47a8e0c1813c554b640d98090cc661c1eb27a91b9a9055bd14d918fc9451073632a635741dd413fd7b4a380d8907862e14 tomcat-jasper-9.0.44.jar +de50107ff31b8c5a7eb97fe86c2fdfa38305be632c8d62329219884dfb6bbe76372b40a67e808263a55b510a41cde639d55e7925d89db06472392519f0410063 tomcat-jasper-el-9.0.44.jar +69a79e58cea950b713f26a94e1db90221c297375a338f010d1332027ef5d93fd262163ec787b06d8cd41a4a31faa81bb4fc83836148eb14a6757591f6fe5f3c6 tomcat-jsp-api-9.0.44.jar +ca036312596dbd92ae43dda79a9a5ad168cf90a12369636fdc6febbedb559b83d5fa22d77629659b588d70990f8a077fd8356be1c56b0227e07688b67dd7c76e tomcat-juli-9.0.44.jar +952c122413805de16de603cfc233785e53b558b39f146b6fa4e11324e26572e4aee76fec2ee69adecc8f4271cd28acb917e1a9e61a908710b3582ab1f76c9706 tomcat-servlet-api-9.0.44.jar +6920bfb2b1ae173d716fedbf4f238003f569a161f277a888c2d53dac0af80ef0480c9ca3be0ede4583716c1b97c1cfa1665439d14274b7d73ec948fd9f952b89 tomcat-util-9.0.44.jar +915304750cbdffc4c9926fcb22eb928d2895cccd8b3f6f13aefb4e5302cccf5f513502b70812630026dd2968712c4c3b1cfe98d37ecf7b349988e7255ddc5b18 tomcat-util-scan-9.0.44.jar diff --git a/auto/modules/nodejs b/auto/modules/nodejs index edaf99ac..b2309143 100644 --- a/auto/modules/nodejs +++ b/auto/modules/nodejs @@ -122,8 +122,11 @@ fi NXT_NODE_TMP=${NXT_BUILD_DIR}/src/${NXT_NODE}/unit-http +NXT_NODE_TMP_G=${NXT_BUILD_DIR}/src/${NXT_NODE}/unit-http-g NXT_NODE_TARBALL=${NXT_BUILD_DIR}/${NXT_NODE}-unit-http.tar.gz -NXT_NODE_VERSION_FILE=${NXT_NODE_TMP}/version.h +NXT_NODE_TARBALL_G=${NXT_BUILD_DIR}/${NXT_NODE}-unit-http-g.tar.gz +NXT_NODE_VERSION_FILE=${NXT_BUILD_DIR}/src/${NXT_NODE}/version.h +NXT_NODE_PACKAGE_FILE=${NXT_BUILD_DIR}/src/${NXT_NODE}/package.json NXT_NODE_EXPORTS="export UNIT_SRC_PATH=${PWD}/src \ && export UNIT_BUILD_PATH=${PWD}/${NXT_BUILD_DIR} \ && export UNIT_LIB_STATIC_PATH=${PWD}/${NXT_BUILD_DIR}/libunit.a" @@ -138,6 +141,7 @@ cat << END >> $NXT_MAKEFILE .PHONY: ${NXT_NODE} .PHONY: ${NXT_NODE}-copy +.PHONY: ${NXT_NODE}-copy-g .PHONY: ${NXT_NODE}-install .PHONY: ${NXT_NODE}-uninstall .PHONY: ${NXT_NODE}-local-check @@ -149,27 +153,37 @@ ${NXT_NODE}: ${NXT_NODE}-copy $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC ${NXT_NODE_EXPORTS} && \\ cd ${NXT_NODE_TMP} && ${NXT_NODE_GYP} configure build clean -${NXT_NODE}-copy: ${NXT_NODE_VERSION_FILE} - mkdir -p ${NXT_BUILD_DIR}/src/ - cp -rp src/nodejs/* ${NXT_BUILD_DIR}/src/${NXT_NODE} +${NXT_NODE}-copy: ${NXT_NODE_VERSION_FILE} ${NXT_NODE_PACKAGE_FILE} + mkdir -p ${NXT_NODE_TMP} + cp -rp src/nodejs/unit-http/* ${NXT_NODE_TMP}/ + cp -p ${NXT_NODE_VERSION_FILE} ${NXT_NODE_PACKAGE_FILE} ${NXT_NODE_TMP}/ + +${NXT_NODE}-copy-g: ${NXT_NODE_VERSION_FILE} ${NXT_NODE_PACKAGE_FILE} + mkdir -p ${NXT_NODE_TMP_G} + cp -rp src/nodejs/unit-http/* ${NXT_NODE_TMP_G}/ + cp -p ${NXT_NODE_VERSION_FILE} ${NXT_NODE_PACKAGE_FILE} ${NXT_NODE_TMP_G}/ + mv ${NXT_NODE_TMP_G}/binding_pub.gyp ${NXT_NODE_TMP_G}/binding.gyp ${NXT_NODE_VERSION_FILE}: ${NXT_VERSION_H} - mkdir -p ${NXT_NODE_TMP} + mkdir -p ${NXT_BUILD_DIR}/src/${NXT_NODE} $echo '#define NXT_NODE_VERNUM \$(NXT_VERNUM)' > $NXT_NODE_VERSION_FILE +${NXT_NODE_PACKAGE_FILE}: ${NXT_VERSION_H} src/nodejs/unit-http/package.json + mkdir -p ${NXT_BUILD_DIR}/src/${NXT_NODE} + sed -e "s|%%VERSION%%|\$(NXT_VERSION)|" \ + src/nodejs/unit-http/package.json > ${NXT_NODE_PACKAGE_FILE} + ${NXT_NODE_TARBALL}: ${NXT_NODE}-copy - sed -e 's/"version"\s*:.*/"version": "\$(NXT_VERSION)",/' \ - ${NXT_NODE_TMP}/package.json > ${NXT_NODE_TMP}/package.json.tmp - mv ${NXT_NODE_TMP}/package.json.tmp ${NXT_NODE_TMP}/package.json tar -zcvf ${NXT_NODE_TARBALL} -C ${NXT_NODE_TMP} . +${NXT_NODE_TARBALL_G}: ${NXT_NODE}-copy-g + tar -zcvf ${NXT_NODE_TARBALL_G} -C ${NXT_NODE_TMP_G} . + install: ${NXT_NODE}-$NXT_NODE_INSTALL -${NXT_NODE}-install: ${NXT_NODE_TARBALL} \ - $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC - ${NXT_NODE_EXPORTS} && \\ - ${NXT_NPM} install -g --unsafe-perm ${PWD}/${NXT_NODE_TARBALL} +${NXT_NODE}-install: ${NXT_NODE_TARBALL_G} libunit-install + ${NXT_NPM} install -g --unsafe-perm ${PWD}/${NXT_NODE_TARBALL_G} ${NXT_NODE}-uninstall: ${NXT_NPM} uninstall -g unit-http diff --git a/auto/options b/auto/options index b6007bc2..572d8a9b 100644 --- a/auto/options +++ b/auto/options @@ -59,6 +59,7 @@ do --sbindir=*) NXT_SBINDIR="$value" ;; --libdir=*) NXT_LIBDIR="$value" ;; --incdir=*) NXT_INCDIR="$value" ;; + --mandir=*) NXT_MANDIR="$value" ;; --modules=*) NXT_MODULES="$value" ;; --state=*) NXT_STATE="$value" ;; --tmp=*) NXT_TMP="$value" ;; @@ -144,6 +145,11 @@ case "$NXT_INCDIR" in *) NXT_INCDIR="$NXT_PREFIX$NXT_INCDIR" ;; esac +case "$NXT_MANDIR" in + /*) ;; + *) NXT_MANDIR="$NXT_PREFIX$NXT_MANDIR" ;; +esac + case "$NXT_MODULES" in /*) ;; *) NXT_MODULES="$NXT_PREFIX$NXT_MODULES" ;; diff --git a/auto/summary b/auto/summary index 833d20c0..84bfbb7f 100644 --- a/auto/summary +++ b/auto/summary @@ -11,6 +11,7 @@ Unit configuration summary: sbin directory: ............ "$NXT_SBINDIR" lib directory: ............. "$NXT_LIBDIR" include directory: ......... "$NXT_INCDIR" + man pages directory: ....... "$NXT_MANDIR" modules directory: ......... "$NXT_MODULES" state directory: ........... "$NXT_STATE" tmp directory: ............. "$NXT_TMP" @@ -35,6 +35,7 @@ NXT_BINDIR="bin" NXT_SBINDIR="sbin" NXT_LIBDIR="lib" NXT_INCDIR="include" +NXT_MANDIR="share/man" NXT_MODULES="modules" NXT_STATE="state" NXT_TMP="tmp" diff --git a/docs/changes.xml b/docs/changes.xml index 4db9cf3e..6c79b560 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -5,6 +5,112 @@ <change_log title="unit"> +<changes apply="unit-php + unit-python unit-python2.7 + unit-python3.4 unit-python3.5 unit-python3.6 unit-python3.7 + unit-python3.8 unit-python3.9 + unit-go + unit-perl + unit-ruby + unit-jsc-common unit-jsc8 unit-jsc10 unit-jsc11 unit-jsc13 + unit-jsc14 unit-jsc15" + ver="1.23.0" rev="1" + date="2021-03-25" time="18:00:00 +0300" + packager="Andrei Belov <defan@nginx.com>"> + +<change> +<para> +NGINX Unit updated to 1.23.0. +</para> +</change> + +</changes> + + +<changes apply="unit" ver="1.23.0" rev="1" + date="2021-03-25" time="18:00:00 +0300" + packager="Andrei Belov <defan@nginx.com>"> + +<change type="feature"> +<para> +support for multiple certificate bundles on a listener via the Server Name +Indication (SNI) TLS extension. +</para> +</change> + +<change type="feature"> +<para> +"--mandir" ./configure option to specify the directory for man page +installation. +</para> +</change> + +<change type="bugfix"> +<para> +the router process could crash on premature TLS connection close; the bug had +appeared in 1.17.0. +</para> +</change> + +<change type="bugfix"> +<para> +a connection leak occurred on premature TLS connection close; the bug had +appeared in 1.6. +</para> +</change> + +<change type="bugfix"> +<para> +a descriptor and memory leak occurred in the router process when processing +small WebSocket frames from a client; the bug had appeared in 1.19.0. +</para> +</change> + +<change type="bugfix"> +<para> +a descriptor leak occurred in the router process when removing or +reconfiguring an application; the bug had appeared in 1.19.0. +</para> +</change> + +<change type="bugfix"> +<para> +persistent storage of certificates might've not worked with some filesystems in +Linux, and all uploaded certificate bundles were forgotten after restart. +</para> +</change> + +<change type="bugfix"> +<para> +the controller process could crash while requesting information about a +certificate with a non-DNS SAN entry. +</para> +</change> + +<change type="bugfix"> +<para> +the controller process could crash on manipulations with a certificate +containing a SAN and no standard name attributes in subject or issuer. +</para> +</change> + +<change type="bugfix"> +<para> +the Ruby module didn't respect the user locale for defaults in the Encoding +class. +</para> +</change> + +<change type="bugfix"> +<para> +the PHP 5 module failed to build with thread safety enabled; the bug had +appeared in 1.22.0. +</para> +</change> + +</changes> + + <changes apply="unit-python3.9" ver="1.22.0" rev="1" date="2021-02-04" time="18:00:00 +0300" packager="Andrei Belov <defan@nginx.com>"> diff --git a/docs/man/unitd.8.in b/docs/man/unitd.8.in new file mode 100644 index 00000000..46182781 --- /dev/null +++ b/docs/man/unitd.8.in @@ -0,0 +1,80 @@ +.\" (C) 2017-2021, NGINX, Inc. +.\" +.Dd March 16, 2021 +.Dt UNITD 8 +.Os +.Sh NAME +.Nm unitd +.Nd "runs the NGINX Unit daemon" +.Sh SYNOPSIS +.Nm +.Op Fl Fl no-daemon +.Op Fl Fl control Ar socket +.Op Fl Fl group Ar name +.Op Fl Fl user Ar name +.Op Fl Fl log Ar file +.Op Fl Fl modules Ar directory +.Op Fl Fl pid Ar file +.Op Fl Fl state Ar directory +.Nm +.Op Fl h | Fl Fl help | v | Fl Fl version +.Sh DESCRIPTION +NGINX Unit is a polyglot app server, a reverse proxy, and a static file server +for UNIX-like systems. +It was built by +.Xr nginx 8 +team members from +scratch to be highly efficient and fully configurable at runtime. +.Sh OPTIONS +.Bl -tag -width indent +.It Fl h , Fl Fl help +Displays a summary of Unit's command-line options and their +compile-time defaults. +.It Fl v , Fl Fl version +Displays Unit's version and the +.Pa ./configure +settings it was built with. +.It Fl Fl no-daemon +Runs Unit in non-daemon mode. +.It Fl Fl control Ar socket +Overrides the control API's socket address in IPv4, IPv6, +or UNIX-domain format. +.It Fl Fl group Ar name , Fl Fl user Ar name +Override group name and user name used to run Unit's non-privileged processes. +.It Fl Fl log Ar file +Overrides the pathname for Unit's log. +.It Fl Fl modules Ar directory +Overrides the directory path for Unit's language modules +.Po Pa *.unit.so +.Pc files . +.It Fl Fl pid Ar file +Overrides the pathname for the PID file of Unit's main process. +.It Fl Fl state Ar directory +Overrides the directory path for Unit's state storage. +.El +.Sh EXIT STATUS +Exit status is 0 on success, or 1 if the daemon encounters an error. +.Sh FILES +.Bl -tag -width indent +.It Pa %%PID_PATH%% +The PID file of Unit's main process. +.It Pa %%ERROR_LOG_PATH%% +A general-purpose log for diagnostics and troubleshooting. +.El +.Sh SOCKETS +.Bl -tag -width indent +.It Pa %%SOCKET_PATH%% +The socket address of Unit's control API. +.El +.Sh AUTHORS +(C) 2017-2021, NGINX, Inc. +.Sh SEE ALSO +.Pp +Website: +.Pa https://unit.nginx.org +.Pp +User mailing list: +.Pa https://mailman.nginx.org/mailman/listinfo/unit +.Pp +GitHub: +.Pa https://github.com/nginx/unit diff --git a/pkg/deb/Makefile b/pkg/deb/Makefile index 16e73b94..8c33fc53 100644 --- a/pkg/deb/Makefile +++ b/pkg/deb/Makefile @@ -227,7 +227,7 @@ endif debuild/unit_$(VERSION).orig.tar.gz: | debuild/$(SRCDIR)/debian cd ../.. && tar -czf pkg/deb/debuild/$(SRCDIR).tar.gz \ --transform "s#^#$(SRCDIR)/#" \ - LICENSE NOTICE CHANGES README configure auto src test version go + LICENSE NOTICE CHANGES README configure auto src test version go docs/man/unitd.8.in mv debuild/$(SRCDIR).tar.gz debuild/unit_$(VERSION).orig.tar.gz cd debuild && tar zxf unit_$(VERSION).orig.tar.gz diff --git a/pkg/deb/debian/rules.in b/pkg/deb/debian/rules.in index aa7921d1..c7a56b6b 100644 --- a/pkg/deb/debian/rules.in +++ b/pkg/deb/debian/rules.in @@ -33,6 +33,8 @@ config.env.%: cp -Pa $(CURDIR)/NOTICE $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/README $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/go $(BUILDDIR_$*)/ + mkdir -p $(BUILDDIR_$*)/docs/man + cp -Pa $(CURDIR)/docs/man/unitd.8.in $(BUILDDIR_$*)/docs/man/ touch $@ configure.unit: config.env.unit @@ -117,7 +119,7 @@ binary-indep: build install dh_testdir dh_testroot dh_installdocs - dh_installchangelogs + dh_installchangelogs dh_link dh_strip --dbg-package=unit-dbg dh_shlibdeps diff --git a/pkg/docker/Dockerfile.go1.15 b/pkg/docker/Dockerfile.go1.15 index 270dc428..45642662 100644 --- a/pkg/docker/Dockerfile.go1.15 +++ b/pkg/docker/Dockerfile.go1.15 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.22.0 \ + && hg up 1.23.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -63,7 +63,7 @@ RUN set -x \ --shell /bin/false \ unit \ && apt update \ - && apt --no-install-recommends --no-install-suggests -y install $(cat /requirements.apt) \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && rm -f /requirements.apt \ && ln -sf /dev/stdout /var/log/unit.log diff --git a/pkg/docker/Dockerfile.jsc11 b/pkg/docker/Dockerfile.jsc11 index cde7c590..4cfc541d 100644 --- a/pkg/docker/Dockerfile.jsc11 +++ b/pkg/docker/Dockerfile.jsc11 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.22.0 \ + && hg up 1.23.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -61,7 +61,7 @@ RUN set -x \ --shell /bin/false \ unit \ && apt update \ - && apt --no-install-recommends --no-install-suggests -y install $(cat /requirements.apt) \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && rm -f /requirements.apt \ && ln -sf /dev/stdout /var/log/unit.log diff --git a/pkg/docker/Dockerfile.minimal b/pkg/docker/Dockerfile.minimal index 91fd79d0..59aaa6a3 100644 --- a/pkg/docker/Dockerfile.minimal +++ b/pkg/docker/Dockerfile.minimal @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.22.0 \ + && hg up 1.23.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -61,7 +61,7 @@ RUN set -x \ --shell /bin/false \ unit \ && apt update \ - && apt --no-install-recommends --no-install-suggests -y install $(cat /requirements.apt) \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && rm -f /requirements.apt \ && ln -sf /dev/stdout /var/log/unit.log diff --git a/pkg/docker/Dockerfile.node15 b/pkg/docker/Dockerfile.node15 index 59b12012..7eddfb26 100644 --- a/pkg/docker/Dockerfile.node15 +++ b/pkg/docker/Dockerfile.node15 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.22.0 \ + && hg up 1.23.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -63,7 +63,7 @@ RUN set -x \ --shell /bin/false \ unit \ && apt update \ - && apt --no-install-recommends --no-install-suggests -y install $(cat /requirements.apt) \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && rm -f /requirements.apt \ && ln -sf /dev/stdout /var/log/unit.log diff --git a/pkg/docker/Dockerfile.perl5.32 b/pkg/docker/Dockerfile.perl5.32 index 589eb989..aa000f63 100644 --- a/pkg/docker/Dockerfile.perl5.32 +++ b/pkg/docker/Dockerfile.perl5.32 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.22.0 \ + && hg up 1.23.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -61,7 +61,7 @@ RUN set -x \ --shell /bin/false \ unit \ && apt update \ - && apt --no-install-recommends --no-install-suggests -y install $(cat /requirements.apt) \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && rm -f /requirements.apt \ && ln -sf /dev/stdout /var/log/unit.log diff --git a/pkg/docker/Dockerfile.php8.0 b/pkg/docker/Dockerfile.php8.0 index c31513d4..4534f9b5 100644 --- a/pkg/docker/Dockerfile.php8.0 +++ b/pkg/docker/Dockerfile.php8.0 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.22.0 \ + && hg up 1.23.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -61,7 +61,7 @@ RUN set -x \ --shell /bin/false \ unit \ && apt update \ - && apt --no-install-recommends --no-install-suggests -y install $(cat /requirements.apt) \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && rm -f /requirements.apt \ && ln -sf /dev/stdout /var/log/unit.log diff --git a/pkg/docker/Dockerfile.python3.9 b/pkg/docker/Dockerfile.python3.9 index 76f50733..e8650d44 100644 --- a/pkg/docker/Dockerfile.python3.9 +++ b/pkg/docker/Dockerfile.python3.9 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.22.0 \ + && hg up 1.23.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -61,7 +61,7 @@ RUN set -x \ --shell /bin/false \ unit \ && apt update \ - && apt --no-install-recommends --no-install-suggests -y install $(cat /requirements.apt) \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && rm -f /requirements.apt \ && ln -sf /dev/stdout /var/log/unit.log diff --git a/pkg/docker/Dockerfile.ruby2.7 b/pkg/docker/Dockerfile.ruby2.7 index aa823756..aa8cdb3f 100644 --- a/pkg/docker/Dockerfile.ruby2.7 +++ b/pkg/docker/Dockerfile.ruby2.7 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.22.0 \ + && hg up 1.23.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -61,7 +61,7 @@ RUN set -x \ --shell /bin/false \ unit \ && apt update \ - && apt --no-install-recommends --no-install-suggests -y install $(cat /requirements.apt) \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && rm -f /requirements.apt \ && ln -sf /dev/stdout /var/log/unit.log diff --git a/pkg/docker/template.Dockerfile b/pkg/docker/template.Dockerfile index d96d7982..55feecc6 100644 --- a/pkg/docker/template.Dockerfile +++ b/pkg/docker/template.Dockerfile @@ -61,7 +61,7 @@ RUN set -x \ --shell /bin/false \ unit \ && apt update \ - && apt --no-install-recommends --no-install-suggests -y install $(cat /requirements.apt) \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ && apt-get clean && rm -rf /var/lib/apt/lists/* \ && rm -f /requirements.apt \ && ln -sf /dev/stdout /var/log/unit.log diff --git a/pkg/rpm/Makefile b/pkg/rpm/Makefile index f0bd0cf9..75327c49 100644 --- a/pkg/rpm/Makefile +++ b/pkg/rpm/Makefile @@ -214,7 +214,7 @@ endif rpmbuild/SOURCES/unit-$(VERSION).tar.gz: cd ../.. && tar -czf pkg/rpm/rpmbuild/SOURCES/unit-$(VERSION).tar.gz \ --transform "s#^#unit-$(VERSION)/#" \ - LICENSE NOTICE CHANGES README configure auto src test version go + LICENSE NOTICE CHANGES README configure auto src test version go docs/man/unitd.8.in unit: check-build-depends-unit rpmbuild/SPECS/unit.spec rpmbuild/SOURCES/unit-$(VERSION).tar.gz @echo "===> Building $@ package" ; \ diff --git a/pkg/rpm/unit.spec.in b/pkg/rpm/unit.spec.in index 08db73e2..3a148b9d 100644 --- a/pkg/rpm/unit.spec.in +++ b/pkg/rpm/unit.spec.in @@ -98,7 +98,7 @@ Library and include files required for NGINX Unit modules development. %install %{__rm} -rf %{buildroot} %{__ln_s} build-nodebug build -DESTDIR=%{buildroot} make unitd-install libunit-install +DESTDIR=%{buildroot} make unitd-install libunit-install manpage-install %{__install} -m755 %{bdir}/build-debug/unitd \ %{buildroot}%{_sbindir}/unitd-debug %{__install} -m644 %{bdir}/build-debug/libunit.a \ @@ -205,6 +205,7 @@ BANNER %dir %{_sharedstatedir}/unit %dir %attr(0700,root,root) %{_localstatedir}/log/unit %config(noreplace) %{_sysconfdir}/logrotate.d/%{name} +%{_mandir}/man8/unitd.8* %files devel %{_libdir}/libunit.a diff --git a/src/nodejs/unit-http/package.json b/src/nodejs/unit-http/package.json index 7ee01346..81f06bd4 100644 --- a/src/nodejs/unit-http/package.json +++ b/src/nodejs/unit-http/package.json @@ -1,6 +1,6 @@ { "name": "unit-http", - "version": "1.0.0", + "version": "%%VERSION%%", "description": "HTTP module for NGINX Unit", "main": "http.js", "files": [ diff --git a/src/nxt_app_log.c b/src/nxt_app_log.c index 0ecd9aac..ae57c2a2 100644 --- a/src/nxt_app_log.c +++ b/src/nxt_app_log.c @@ -19,7 +19,10 @@ static u_char *nxt_log_debug_time(u_char *buf, nxt_realtime_t *now, void nxt_cdecl nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) { - u_char *p, *syslogmsg, *end; + u_char *p, *end; +#if 0 + u_char *syslogmsg; +#endif va_list args; nxt_thread_t *thr; nxt_time_string_t *time_cache; @@ -34,7 +37,9 @@ nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) p = nxt_thread_time_string(thr, time_cache, msg); +#if 0 syslogmsg = p; +#endif #if 0 nxt_fid_t fid; @@ -79,6 +84,7 @@ nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) (void) nxt_write_console(nxt_stderr, msg, p - msg); +#if 0 if (level == NXT_LOG_ALERT) { *(p - nxt_length("\n")) = '\0'; @@ -88,6 +94,7 @@ nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) */ nxt_write_syslog(LOG_ALERT, syslogmsg); } +#endif } diff --git a/src/nxt_cert.c b/src/nxt_cert.c index 9e825d80..3cdb69c1 100644 --- a/src/nxt_cert.c +++ b/src/nxt_cert.c @@ -46,6 +46,8 @@ static int nxt_nxt_cert_pem_suffix(char *pem_str, const char *suffix); static nxt_conf_value_t *nxt_cert_details(nxt_mp_t *mp, nxt_cert_t *cert); static nxt_conf_value_t *nxt_cert_name_details(nxt_mp_t *mp, X509 *x509, nxt_bool_t issuer); +static nxt_conf_value_t *nxt_cert_alt_names_details(nxt_mp_t *mp, + STACK_OF(GENERAL_NAME) *alt_names); static nxt_lvlhsh_t nxt_cert_info; @@ -654,7 +656,6 @@ nxt_cert_name_details(nxt_mp_t *mp, X509 *x509, nxt_bool_t issuer) nxt_str_t str; nxt_int_t ret; nxt_uint_t i, n, count; - GENERAL_NAME *name; nxt_conf_value_t *object, *names; STACK_OF(GENERAL_NAME) *alt_names; u_char buf[256]; @@ -689,12 +690,23 @@ nxt_cert_name_details(nxt_mp_t *mp, X509 *x509, nxt_bool_t issuer) NULL, NULL); if (alt_names != NULL) { + names = nxt_cert_alt_names_details(mp, alt_names); + + sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); + + if (nxt_slow_path(names == NULL)) { + return NULL; + } + count++; + + } else { + names = NULL; } object = nxt_conf_create_object(mp, count); if (nxt_slow_path(object == NULL)) { - goto fail; + return NULL; } for (n = 0, i = 0; n != nxt_nitems(nids) && i != count; n++) { @@ -702,12 +714,12 @@ nxt_cert_name_details(nxt_mp_t *mp, X509 *x509, nxt_bool_t issuer) len = X509_NAME_get_text_by_NID(x509_name, nids[n].nid, (char *) buf, sizeof(buf)); - if (len < 0) { - continue; + if (n == 1 && names != NULL) { + nxt_conf_set_member(object, &alt_names_str, names, i++); } - if (i == 1 && alt_names != NULL) { - i++; + if (len < 0) { + continue; } str.length = len; @@ -716,60 +728,62 @@ nxt_cert_name_details(nxt_mp_t *mp, X509 *x509, nxt_bool_t issuer) ret = nxt_conf_set_member_string_dup(object, mp, &nids[n].name, &str, i++); if (nxt_slow_path(ret != NXT_OK)) { - goto fail; + return NULL; } } - if (alt_names != NULL) { - count = sk_GENERAL_NAME_num(alt_names); - - for (n = 0; n != count; n++) { - name = sk_GENERAL_NAME_value(alt_names, n); + return object; +} - if (name->type != GEN_DNS) { - continue; - } - } - names = nxt_conf_create_array(mp, n); - if (nxt_slow_path(names == NULL)) { - goto fail; - } +static nxt_conf_value_t * +nxt_cert_alt_names_details(nxt_mp_t *mp, STACK_OF(GENERAL_NAME) *alt_names) +{ + nxt_str_t str; + nxt_int_t ret; + nxt_uint_t i, n, count; + GENERAL_NAME *name; + nxt_conf_value_t *array; - for (n = 0, i = 0; n != count; n++) { - name = sk_GENERAL_NAME_value(alt_names, n); + count = sk_GENERAL_NAME_num(alt_names); + n = 0; - if (name->type != GEN_DNS) { - continue; - } + for (i = 0; i != count; i++) { + name = sk_GENERAL_NAME_value(alt_names, i); - str.length = ASN1_STRING_length(name->d.dNSName); -#if OPENSSL_VERSION_NUMBER > 0x10100000L - str.start = (u_char *) ASN1_STRING_get0_data(name->d.dNSName); -#else - str.start = ASN1_STRING_data(name->d.dNSName); -#endif - - ret = nxt_conf_set_element_string_dup(names, mp, i++, &str); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + if (name->type != GEN_DNS) { + continue; } - sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); + n++; + } - nxt_conf_set_member(object, &alt_names_str, names, 1); + array = nxt_conf_create_array(mp, n); + if (nxt_slow_path(array == NULL)) { + return NULL; } - return object; + for (n = 0, i = 0; n != count; n++) { + name = sk_GENERAL_NAME_value(alt_names, n); -fail: + if (name->type != GEN_DNS) { + continue; + } - if (alt_names != NULL) { - sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); + str.length = ASN1_STRING_length(name->d.dNSName); +#if OPENSSL_VERSION_NUMBER > 0x10100000L + str.start = (u_char *) ASN1_STRING_get0_data(name->d.dNSName); +#else + str.start = ASN1_STRING_data(name->d.dNSName); +#endif + + ret = nxt_conf_set_element_string_dup(array, mp, i++, &str); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } } - return NULL; + return array; } @@ -838,7 +852,12 @@ nxt_cert_store_load(nxt_task_t *task, nxt_mp_t *mp) break; } - if (de->d_type != DT_REG) { + nxt_debug(task, "readdir(\"%s\"): \"%s\"", rt->certs.start, de->d_name); + + name.length = nxt_strlen(de->d_name); + name.start = (u_char *) de->d_name; + + if (nxt_str_eq(&name, ".", 1) || nxt_str_eq(&name, "..", 2)) { continue; } @@ -849,9 +868,6 @@ nxt_cert_store_load(nxt_task_t *task, nxt_mp_t *mp) item->fd = -1; - name.length = nxt_strlen(de->d_name); - name.start = (u_char *) de->d_name; - size = rt->certs.length + name.length + 1; if (size > alloc) { diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 67fa3095..8c5d1ec7 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -87,6 +87,8 @@ static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, #if (NXT_TLS) static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); +static nxt_int_t nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value); #endif static nxt_int_t nxt_conf_vldt_action(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); @@ -354,7 +356,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[] = { { .name = nxt_string("certificate"), - .type = NXT_CONF_VLDT_STRING, + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, .validator = nxt_conf_vldt_certificate, }, @@ -1459,10 +1461,10 @@ nxt_conf_vldt_thread_stack_size(nxt_conf_validation_t *vldt, size = nxt_conf_get_number(value); - if (size < PTHREAD_STACK_MIN) { + if (size < NXT_THREAD_STACK_MIN) { return nxt_conf_vldt_error(vldt, "The \"thread_stack_size\" number " "must be equal to or greater than %d.", - PTHREAD_STACK_MIN); + NXT_THREAD_STACK_MIN); } if ((size % nxt_pagesize) != 0) { @@ -1827,9 +1829,34 @@ static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data) { + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + if (nxt_conf_array_elements_count(value) == 0) { + return nxt_conf_vldt_error(vldt, "The \"certificate\" array " + "must contain at least one element."); + } + + return nxt_conf_vldt_array_iterator(vldt, value, + &nxt_conf_vldt_certificate_element); + } + + /* NXT_CONF_STRING */ + + return nxt_conf_vldt_certificate_element(vldt, value); +} + + +static nxt_int_t +nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) +{ nxt_str_t name; nxt_conf_value_t *cert; + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"certificate\" array must " + "contain only string values."); + } + nxt_conf_get_string(value, &name); cert = nxt_cert_info_get(&name); diff --git a/src/nxt_log.c b/src/nxt_log.c index 1c666961..58756816 100644 --- a/src/nxt_log.c +++ b/src/nxt_log.c @@ -66,7 +66,10 @@ nxt_log_set_ctx(nxt_log_t *log, nxt_log_ctx_handler_t handler, void *ctx) void nxt_cdecl nxt_log_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) { - u_char *p, *syslogmsg, *end; + u_char *p, *end; +#if 0 + u_char *syslogmsg; +#endif va_list args; u_char msg[NXT_MAX_ERROR_STR]; @@ -79,7 +82,9 @@ nxt_log_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) *p++ = ' '; } +#if 0 syslogmsg = p; +#endif p = nxt_sprintf(p, end, (log->ident != 0) ? "[%V] *%D " : "[%V] ", &nxt_log_levels[level], log->ident); @@ -100,6 +105,7 @@ nxt_log_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) (void) nxt_write_console(nxt_stderr, msg, p - msg); +#if 0 if (level == NXT_LOG_ALERT) { *(p - nxt_length("\n")) = '\0'; @@ -109,4 +115,5 @@ nxt_log_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) */ nxt_write_syslog(LOG_ALERT, syslogmsg); } +#endif } diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c index 832d1f0d..9b86150f 100644 --- a/src/nxt_openssl.c +++ b/src/nxt_openssl.c @@ -8,17 +8,20 @@ #include <openssl/ssl.h> #include <openssl/conf.h> #include <openssl/err.h> +#include <openssl/rand.h> +#include <openssl/x509v3.h> typedef struct { - SSL *session; - nxt_conn_t *conn; + SSL *session; + nxt_conn_t *conn; - int ssl_error; - uint8_t times; /* 2 bits */ - uint8_t handshake; /* 1 bit */ + int ssl_error; + uint8_t times; /* 2 bits */ + uint8_t handshake; /* 1 bit */ - nxt_buf_mem_t buffer; + nxt_tls_conf_t *conf; + nxt_buf_mem_t buffer; } nxt_openssl_conn_t; @@ -39,8 +42,18 @@ static unsigned long nxt_openssl_thread_id(void); static void nxt_openssl_locks_free(void); #endif static nxt_int_t nxt_openssl_server_init(nxt_task_t *task, - nxt_tls_conf_t *conf); -static nxt_int_t nxt_openssl_chain_file(SSL_CTX *ctx, nxt_fd_t fd); + nxt_tls_conf_t *conf, nxt_mp_t *mp, nxt_bool_t last); +static nxt_int_t nxt_openssl_chain_file(nxt_task_t *task, SSL_CTX *ctx, + nxt_tls_conf_t *conf, nxt_mp_t *mp, nxt_bool_t single); +static nxt_uint_t nxt_openssl_cert_get_names(nxt_task_t *task, X509 *cert, + nxt_tls_conf_t *conf, nxt_mp_t *mp); +static nxt_int_t nxt_openssl_bundle_hash_test(nxt_lvlhsh_query_t *lhq, + void *data); +static nxt_int_t nxt_openssl_bundle_hash_insert(nxt_task_t *task, + nxt_lvlhsh_t *lvlhsh, nxt_tls_bundle_hash_item_t *item, nxt_mp_t * mp); +static nxt_int_t nxt_openssl_servername(SSL *s, int *ad, void *arg); +static nxt_tls_bundle_conf_t *nxt_openssl_find_ctx(nxt_tls_conf_t *conf, + nxt_str_t *sn); static void nxt_openssl_server_free(nxt_task_t *task, nxt_tls_conf_t *conf); static void nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf, nxt_conn_t *c); @@ -244,12 +257,13 @@ nxt_openssl_locks_free(void) static nxt_int_t -nxt_openssl_server_init(nxt_task_t *task, nxt_tls_conf_t *conf) +nxt_openssl_server_init(nxt_task_t *task, nxt_tls_conf_t *conf, + nxt_mp_t *mp, nxt_bool_t last) { - SSL_CTX *ctx; - nxt_fd_t fd; - const char *ciphers, *ca_certificate; - STACK_OF(X509_NAME) *list; + SSL_CTX *ctx; + const char *ciphers, *ca_certificate; + STACK_OF(X509_NAME) *list; + nxt_tls_bundle_conf_t *bundle; ctx = SSL_CTX_new(SSLv23_server_method()); if (ctx == NULL) { @@ -257,8 +271,10 @@ nxt_openssl_server_init(nxt_task_t *task, nxt_tls_conf_t *conf) return NXT_ERROR; } - conf->ctx = ctx; - conf->conn_init = nxt_openssl_conn_init; + bundle = conf->bundle; + nxt_assert(bundle != NULL); + + bundle->ctx = ctx; #ifdef SSL_OP_NO_RENEGOTIATION /* Renegration is not currently supported. */ @@ -286,11 +302,10 @@ nxt_openssl_server_init(nxt_task_t *task, nxt_tls_conf_t *conf) #endif - fd = conf->chain_file; - - if (nxt_openssl_chain_file(ctx, fd) != NXT_OK) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "nxt_openssl_chain_file() failed"); + if (nxt_openssl_chain_file(task, ctx, conf, mp, + last && bundle->next == NULL) + != NXT_OK) + { goto fail; } /* @@ -349,33 +364,51 @@ nxt_openssl_server_init(nxt_task_t *task, nxt_tls_conf_t *conf) SSL_CTX_set_client_CA_list(ctx, list); } + if (last) { + conf->conn_init = nxt_openssl_conn_init; + + if (bundle->next != NULL) { + SSL_CTX_set_tlsext_servername_callback(ctx, nxt_openssl_servername); + } + } + return NXT_OK; fail: SSL_CTX_free(ctx); +#if (OPENSSL_VERSION_NUMBER >= 0x1010100fL \ + && OPENSSL_VERSION_NUMBER < 0x1010101fL) + RAND_keep_random_devices_open(0); +#endif + return NXT_ERROR; } static nxt_int_t -nxt_openssl_chain_file(SSL_CTX *ctx, nxt_fd_t fd) +nxt_openssl_chain_file(nxt_task_t *task, SSL_CTX *ctx, nxt_tls_conf_t *conf, + nxt_mp_t *mp, nxt_bool_t single) { - BIO *bio; - X509 *cert, *ca; - long reason; - EVP_PKEY *key; - nxt_int_t ret; + BIO *bio; + X509 *cert, *ca; + long reason; + EVP_PKEY *key; + nxt_int_t ret; + nxt_tls_bundle_conf_t *bundle; + + ret = NXT_ERROR; + cert = NULL; bio = BIO_new(BIO_s_fd()); if (bio == NULL) { - return NXT_ERROR; + goto end; } - BIO_set_fd(bio, fd, BIO_CLOSE); + bundle = conf->bundle; - ret = NXT_ERROR; + BIO_set_fd(bio, bundle->chain_file, BIO_CLOSE); cert = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); if (cert == NULL) { @@ -386,6 +419,10 @@ nxt_openssl_chain_file(SSL_CTX *ctx, nxt_fd_t fd) goto end; } + if (!single && nxt_openssl_cert_get_names(task, cert, conf, mp) != NXT_OK) { + goto clean; + } + for ( ;; ) { ca = PEM_read_bio_X509(bio, NULL, NULL, NULL); @@ -431,17 +468,324 @@ nxt_openssl_chain_file(SSL_CTX *ctx, nxt_fd_t fd) end: - X509_free(cert); + if (ret != NXT_OK) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, + "nxt_openssl_chain_file() failed"); + } + +clean: + BIO_free(bio); + X509_free(cert); return ret; } +static nxt_uint_t +nxt_openssl_cert_get_names(nxt_task_t *task, X509 *cert, nxt_tls_conf_t *conf, + nxt_mp_t *mp) +{ + int len; + nxt_str_t domain, str; + X509_NAME *x509_name; + nxt_uint_t i, n; + GENERAL_NAME *name; + nxt_tls_bundle_conf_t *bundle; + STACK_OF(GENERAL_NAME) *alt_names; + nxt_tls_bundle_hash_item_t *item; + + bundle = conf->bundle; + + alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + + if (alt_names != NULL) { + n = sk_GENERAL_NAME_num(alt_names); + + for (i = 0; i != n; i++) { + name = sk_GENERAL_NAME_value(alt_names, i); + + if (name->type != GEN_DNS) { + continue; + } + + str.length = ASN1_STRING_length(name->d.dNSName); +#if OPENSSL_VERSION_NUMBER > 0x10100000L + str.start = (u_char *) ASN1_STRING_get0_data(name->d.dNSName); +#else + str.start = ASN1_STRING_data(name->d.dNSName); +#endif + + domain.start = nxt_mp_nget(mp, str.length); + if (nxt_slow_path(domain.start == NULL)) { + goto fail; + } + + domain.length = str.length; + nxt_memcpy_lowcase(domain.start, str.start, str.length); + + item = nxt_mp_get(mp, sizeof(nxt_tls_bundle_hash_item_t)); + if (nxt_slow_path(item == NULL)) { + goto fail; + } + + item->name = domain; + item->bundle = bundle; + + if (nxt_openssl_bundle_hash_insert(task, &conf->bundle_hash, + item, mp) + == NXT_ERROR) + { + goto fail; + } + } + + sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); + + } else { + x509_name = X509_get_subject_name(cert); + len = X509_NAME_get_text_by_NID(x509_name, NID_commonName, + NULL, 0); + if (len <= 0) { + nxt_log(task, NXT_LOG_WARN, "certificate \"%V\" has neither " + "Subject Alternative Name nor Common Name", bundle->name); + return NXT_OK; + } + + domain.start = nxt_mp_nget(mp, len + 1); + if (nxt_slow_path(domain.start == NULL)) { + return NXT_ERROR; + } + + domain.length = X509_NAME_get_text_by_NID(x509_name, NID_commonName, + (char *) domain.start, + len + 1); + nxt_memcpy_lowcase(domain.start, domain.start, domain.length); + + item = nxt_mp_get(mp, sizeof(nxt_tls_bundle_hash_item_t)); + if (nxt_slow_path(item == NULL)) { + return NXT_ERROR; + } + + item->name = domain; + item->bundle = bundle; + + if (nxt_openssl_bundle_hash_insert(task, &conf->bundle_hash, item, + mp) + == NXT_ERROR) + { + return NXT_ERROR; + } + } + + return NXT_OK; + +fail: + + sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); + + return NXT_ERROR; +} + + +static const nxt_lvlhsh_proto_t nxt_openssl_bundle_hash_proto + nxt_aligned(64) = +{ + NXT_LVLHSH_DEFAULT, + nxt_openssl_bundle_hash_test, + nxt_mp_lvlhsh_alloc, + nxt_mp_lvlhsh_free, +}; + + +static nxt_int_t +nxt_openssl_bundle_hash_test(nxt_lvlhsh_query_t *lhq, void *data) +{ + nxt_tls_bundle_hash_item_t *item; + + item = data; + + return nxt_strstr_eq(&lhq->key, &item->name) ? NXT_OK : NXT_DECLINED; +} + + +static nxt_int_t +nxt_openssl_bundle_hash_insert(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, + nxt_tls_bundle_hash_item_t *item, nxt_mp_t *mp) +{ + nxt_str_t str; + nxt_int_t ret; + nxt_lvlhsh_query_t lhq; + nxt_tls_bundle_hash_item_t *old; + + str = item->name; + + if (item->name.start[0] == '*') { + item->name.start++; + item->name.length--; + + if (item->name.length == 0 || item->name.start[0] != '.') { + nxt_log(task, NXT_LOG_WARN, "ignored invalid name \"%V\" " + "in certificate \"%V\": missing \".\" " + "after wildcard symbol", &str, item->bundle->name); + return NXT_OK; + } + } + + lhq.pool = mp; + lhq.key = item->name; + lhq.value = item; + lhq.proto = &nxt_openssl_bundle_hash_proto; + lhq.replace = 0; + lhq.key_hash = nxt_murmur_hash2(item->name.start, item->name.length); + + ret = nxt_lvlhsh_insert(lvlhsh, &lhq); + if (nxt_fast_path(ret == NXT_OK)) { + nxt_debug(task, "name \"%V\" for certificate \"%V\" is inserted", + &str, item->bundle->name); + return NXT_OK; + } + + if (nxt_fast_path(ret == NXT_DECLINED)) { + old = lhq.value; + if (old->bundle != item->bundle) { + nxt_log(task, NXT_LOG_WARN, "ignored duplicate name \"%V\" " + "in certificate \"%V\", identical name appears in \"%V\"", + &str, old->bundle->name, item->bundle->name); + + old->bundle = item->bundle; + } + + return NXT_OK; + } + + return NXT_ERROR; +} + + +static nxt_int_t +nxt_openssl_servername(SSL *s, int *ad, void *arg) +{ + nxt_str_t str; + nxt_uint_t i; + nxt_conn_t *c; + const char *servername; + nxt_tls_conf_t *conf; + nxt_openssl_conn_t *tls; + nxt_tls_bundle_conf_t *bundle; + + c = SSL_get_ex_data(s, nxt_openssl_connection_index); + + if (nxt_slow_path(c == NULL)) { + nxt_thread_log_alert("SSL_get_ex_data() failed"); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); + if (nxt_slow_path(servername == NULL)) { + nxt_log(c->socket.task, NXT_LOG_ALERT, "SSL_get_servername() returned " + "NULL in server name callback"); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + str.length = nxt_strlen(servername); + if (str.length == 0) { + nxt_debug(c->socket.task, "client sent zero-length server name"); + goto done; + } + + if (servername[0] == '.') { + nxt_debug(c->socket.task, "ignored the server name \"%s\": " + "leading \".\"", servername); + goto done; + } + + nxt_debug(c->socket.task, "tls with servername \"%s\"", servername); + + str.start = nxt_mp_nget(c->mem_pool, str.length); + if (nxt_slow_path(str.start == NULL)) { + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + nxt_memcpy_lowcase(str.start, (const u_char *) servername, str.length); + + tls = c->u.tls; + conf = tls->conf; + + bundle = nxt_openssl_find_ctx(conf, &str); + + if (bundle == NULL) { + for (i = 1; i < str.length; i++) { + if (str.start[i] == '.') { + str.start += i; + str.length -= i; + + bundle = nxt_openssl_find_ctx(conf, &str); + break; + } + } + } + + if (bundle != NULL) { + nxt_debug(c->socket.task, "new tls context found for \"%V\": \"%V\" " + "(old: \"%V\")", &str, bundle->name, + conf->bundle->name); + + if (bundle != conf->bundle) { + if (SSL_set_SSL_CTX(s, bundle->ctx) == NULL) { + nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, + "SSL_set_SSL_CTX() failed"); + + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + } + } + +done: + + return SSL_TLSEXT_ERR_OK; +} + + +static nxt_tls_bundle_conf_t * +nxt_openssl_find_ctx(nxt_tls_conf_t *conf, nxt_str_t *sn) +{ + nxt_int_t ret; + nxt_lvlhsh_query_t lhq; + nxt_tls_bundle_hash_item_t *item; + + lhq.key_hash = nxt_murmur_hash2(sn->start, sn->length); + lhq.key = *sn; + lhq.proto = &nxt_openssl_bundle_hash_proto; + + ret = nxt_lvlhsh_find(&conf->bundle_hash, &lhq); + if (ret != NXT_OK) { + return NULL; + } + + item = lhq.value; + + return item->bundle; +} + + static void nxt_openssl_server_free(nxt_task_t *task, nxt_tls_conf_t *conf) { - SSL_CTX_free(conf->ctx); + nxt_tls_bundle_conf_t *bundle; + + bundle = conf->bundle; + nxt_assert(bundle != NULL); + + do { + SSL_CTX_free(bundle->ctx); + bundle = bundle->next; + } while (bundle != NULL); + +#if (OPENSSL_VERSION_NUMBER >= 0x1010100fL \ + && OPENSSL_VERSION_NUMBER < 0x1010101fL) + RAND_keep_random_devices_open(0); +#endif } @@ -463,7 +807,7 @@ nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf, nxt_conn_t *c) c->u.tls = tls; nxt_buf_mem_set_size(&tls->buffer, conf->buffer_size); - ctx = conf->ctx; + ctx = conf->bundle->ctx; s = SSL_new(ctx); if (s == NULL) { @@ -472,6 +816,8 @@ nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf, nxt_conn_t *c) } tls->session = s; + /* To pass TLS config to the nxt_openssl_servername() callback. */ + tls->conf = conf; tls->conn = c; ret = SSL_set_fd(s, c->socket.fd); @@ -493,6 +839,11 @@ nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf, nxt_conn_t *c) c->sendfile = NXT_CONN_SENDFILE_OFF; nxt_openssl_conn_handshake(task, c, c->socket.data); + /* + * TLS configuration might be destroyed after the TLS connection + * is established. + */ + tls->conf = NULL; return; fail: @@ -720,10 +1071,6 @@ nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "openssl conn shutdown fd:%d", c->socket.fd); - if (c->socket.error != 0) { - return; - } - c->read_state = NULL; tls = c->u.tls; diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c index 369e7f32..8fbe7f65 100644 --- a/src/nxt_php_sapi.c +++ b/src/nxt_php_sapi.c @@ -1041,7 +1041,11 @@ nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r) if (r->authorization_field != NXT_UNIT_NONE_FIELD) { f = r->fields + r->authorization_field; +#ifdef NXT_PHP7 php_handle_auth_data(nxt_unit_sptr_get(&f->value)); +#else + php_handle_auth_data(nxt_unit_sptr_get(&f->value) TSRMLS_CC); +#endif } else { SG(request_info).auth_digest = NULL; diff --git a/src/nxt_port_memory.c b/src/nxt_port_memory.c index ae9f079c..bffae8a1 100644 --- a/src/nxt_port_memory.c +++ b/src/nxt_port_memory.c @@ -34,6 +34,10 @@ nxt_port_mmap_handler_use(nxt_port_mmap_handler_t *mmap_handler, int i) mmap_handler->hdr = NULL; } + if (mmap_handler->fd != -1) { + nxt_fd_close(mmap_handler->fd); + } + nxt_free(mmap_handler); } } @@ -238,6 +242,7 @@ nxt_port_incoming_port_mmap(nxt_task_t *task, nxt_process_t *process, } mmap_handler->hdr = hdr; + mmap_handler->fd = -1; if (nxt_slow_path(hdr->src_pid != process->pid || hdr->dst_pid != nxt_pid)) diff --git a/src/nxt_port_socket.c b/src/nxt_port_socket.c index 9d8096b2..3cf2e79a 100644 --- a/src/nxt_port_socket.c +++ b/src/nxt_port_socket.c @@ -6,8 +6,16 @@ #include <nxt_main.h> #include <nxt_port_queue.h> +#include <nxt_port_memory_int.h> +#define NXT_PORT_MAX_ENQUEUE_BUF_SIZE \ + (int) (NXT_PORT_QUEUE_MSG_SIZE - sizeof(nxt_port_msg_t)) + + +static nxt_bool_t nxt_port_can_enqueue_buf(nxt_buf_t *b); +static uint8_t nxt_port_enqueue_buf(nxt_task_t *task, nxt_port_msg_t *pm, + void *qbuf, nxt_buf_t *b); static nxt_int_t nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port, nxt_port_send_msg_t *msg); static nxt_port_send_msg_t *nxt_port_msg_alloc(nxt_port_send_msg_t *m); @@ -151,10 +159,13 @@ nxt_port_socket_write2(nxt_task_t *task, nxt_port_t *port, nxt_uint_t type, nxt_buf_t *b) { int notify; - uint8_t *p; + uint8_t qmsg_size; nxt_int_t res; nxt_port_send_msg_t msg; - uint8_t qmsg[NXT_PORT_QUEUE_MSG_SIZE]; + struct { + nxt_port_msg_t pm; + uint8_t buf[NXT_PORT_MAX_ENQUEUE_BUF_SIZE]; + } qmsg; msg.link.next = NULL; msg.link.prev = NULL; @@ -177,21 +188,31 @@ nxt_port_socket_write2(nxt_task_t *task, nxt_port_t *port, nxt_uint_t type, if (port->queue != NULL && type != _NXT_PORT_MSG_READ_QUEUE) { - if (fd == -1 - && (b == NULL - || nxt_buf_mem_used_size(&b->mem) - <= (int) (NXT_PORT_QUEUE_MSG_SIZE - sizeof(nxt_port_msg_t)))) - { - p = nxt_cpymem(qmsg, &msg.port_msg, sizeof(nxt_port_msg_t)); + if (fd == -1 && nxt_port_can_enqueue_buf(b)) { + qmsg.pm = msg.port_msg; + + qmsg_size = sizeof(qmsg.pm); + if (b != NULL) { - p = nxt_cpymem(p, b->mem.pos, nxt_buf_mem_used_size(&b->mem)); + qmsg_size += nxt_port_enqueue_buf(task, &qmsg.pm, qmsg.buf, b); } - res = nxt_port_queue_send(port->queue, qmsg, p - qmsg, ¬ify); + res = nxt_port_queue_send(port->queue, &qmsg, qmsg_size, ¬ify); nxt_debug(task, "port{%d,%d} %d: enqueue %d notify %d, %d", (int) port->pid, (int) port->id, port->socket.fd, - (int) (p - qmsg), notify, res); + (int) qmsg_size, notify, res); + + if (b != NULL && nxt_fast_path(res == NXT_OK)) { + if (qmsg.pm.mmap) { + b->is_port_mmap_sent = 1; + } + + b->mem.pos = b->mem.free; + + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + b->completion_handler, task, b, b->parent); + } if (notify == 0) { return res; @@ -201,9 +222,9 @@ nxt_port_socket_write2(nxt_task_t *task, nxt_port_t *port, nxt_uint_t type, msg.buf = NULL; } else { - qmsg[0] = _NXT_PORT_MSG_READ_SOCKET; + qmsg.buf[0] = _NXT_PORT_MSG_READ_SOCKET; - res = nxt_port_queue_send(port->queue, qmsg, 1, ¬ify); + res = nxt_port_queue_send(port->queue, qmsg.buf, 1, ¬ify); nxt_debug(task, "port{%d,%d} %d: enqueue 1 notify %d, %d", (int) port->pid, (int) port->id, port->socket.fd, @@ -225,6 +246,56 @@ nxt_port_socket_write2(nxt_task_t *task, nxt_port_t *port, nxt_uint_t type, } +static nxt_bool_t +nxt_port_can_enqueue_buf(nxt_buf_t *b) +{ + if (b == NULL) { + return 1; + } + + if (b->next != NULL) { + return 0; + } + + return (nxt_buf_mem_used_size(&b->mem) <= NXT_PORT_MAX_ENQUEUE_BUF_SIZE + || nxt_buf_is_port_mmap(b)); +} + + +static uint8_t +nxt_port_enqueue_buf(nxt_task_t *task, nxt_port_msg_t *pm, void *qbuf, + nxt_buf_t *b) +{ + ssize_t size; + nxt_port_mmap_msg_t *mm; + nxt_port_mmap_header_t *hdr; + nxt_port_mmap_handler_t *mmap_handler; + + size = nxt_buf_mem_used_size(&b->mem); + + if (size <= NXT_PORT_MAX_ENQUEUE_BUF_SIZE) { + nxt_memcpy(qbuf, b->mem.pos, size); + + return size; + } + + mmap_handler = b->parent; + hdr = mmap_handler->hdr; + mm = qbuf; + + mm->mmap_id = hdr->id; + mm->chunk_id = nxt_port_mmap_chunk_id(hdr, b->mem.pos); + mm->size = nxt_buf_mem_used_size(&b->mem); + + pm->mmap = 1; + + nxt_debug(task, "mmap_msg={%D, %D, %D}", mm->mmap_id, mm->chunk_id, + mm->size); + + return sizeof(nxt_port_mmap_msg_t); +} + + static nxt_int_t nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port, nxt_port_send_msg_t *msg) diff --git a/src/nxt_router.c b/src/nxt_router.c index 03fe2a6c..8524b358 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -51,8 +51,10 @@ typedef struct { typedef struct { + nxt_str_t *name; nxt_socket_conf_t *socket_conf; nxt_router_temp_conf_t *temp_conf; + nxt_bool_t last; } nxt_socket_rpc_t; @@ -116,9 +118,11 @@ static void nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); #if (NXT_TLS) static void nxt_router_tls_rpc_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_router_tlssock_t *tls); + nxt_router_temp_conf_t *tmcf, nxt_router_tlssock_t *tls, nxt_bool_t last); static void nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); +static nxt_int_t nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *value, nxt_socket_conf_t *skcf); #endif static void nxt_router_app_rpc_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_app_t *app); @@ -519,12 +523,11 @@ nxt_router_msg_cancel(nxt_task_t *task, nxt_request_rpc_data_t *req_rpc_data) next = b->next; b->next = NULL; - b->completion_handler = msg_info->completion_handler; - if (b->is_port_mmap_sent) { b->is_port_mmap_sent = cancelled == 0; - b->completion_handler(task, b, b->parent); } + + b->completion_handler(task, b, b->parent); } msg_info->buf = NULL; @@ -944,14 +947,15 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) } #if (NXT_TLS) - qlk = nxt_queue_first(&tmcf->tls); + qlk = nxt_queue_last(&tmcf->tls); - if (qlk != nxt_queue_tail(&tmcf->tls)) { + if (qlk != nxt_queue_head(&tmcf->tls)) { nxt_queue_remove(qlk); tls = nxt_queue_link_data(qlk, nxt_router_tlssock_t, link); - nxt_router_tls_rpc_create(task, tmcf, tls); + nxt_router_tls_rpc_create(task, tmcf, tls, + nxt_queue_is_empty(&tmcf->tls)); return; } #endif @@ -990,7 +994,7 @@ nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) nxt_router_apps_sort(task, router, tmcf); - nxt_router_apps_hash_use(task, rtcf, 1); + nxt_router_apps_hash_use(task, rtcf, 1); nxt_router_engines_post(router, tmcf); @@ -1332,6 +1336,9 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_port_t *port; nxt_router_t *router; nxt_app_joint_t *app_joint; +#if (NXT_TLS) + nxt_conf_value_t *certificate; +#endif nxt_conf_value_t *conf, *http, *value, *websocket; nxt_conf_value_t *applications, *application; nxt_conf_value_t *listeners, *listener; @@ -1343,9 +1350,6 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_router_app_conf_t apcf; nxt_router_access_log_t *access_log; nxt_router_listener_conf_t lscf; -#if (NXT_TLS) - nxt_router_tlssock_t *tls; -#endif static nxt_str_t http_path = nxt_string("/settings/http"); static nxt_str_t applications_path = nxt_string("/applications"); @@ -1729,20 +1733,30 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, } #if (NXT_TLS) - value = nxt_conf_get_path(listener, &certificate_path); + certificate = nxt_conf_get_path(listener, &certificate_path); - if (value != NULL) { - nxt_conf_get_string(value, &name); + if (certificate != NULL) { + if (nxt_conf_type(certificate) == NXT_CONF_ARRAY) { + n = nxt_conf_array_elements_count(certificate); - tls = nxt_mp_get(mp, sizeof(nxt_router_tlssock_t)); - if (nxt_slow_path(tls == NULL)) { - goto fail; - } + for (i = 0; i < n; i++) { + value = nxt_conf_get_array_element(certificate, i); + + nxt_assert(value != NULL); - tls->name = name; - tls->conf = skcf; + ret = nxt_router_conf_tls_insert(tmcf, value, skcf); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + } - nxt_queue_insert_tail(&tmcf->tls, &tls->link); + } else { + /* NXT_CONF_STRING */ + ret = nxt_router_conf_tls_insert(tmcf, certificate, skcf); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + } } #endif @@ -1828,6 +1842,38 @@ fail: } +#if (NXT_TLS) + +static nxt_int_t +nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *value, nxt_socket_conf_t *skcf) +{ + nxt_mp_t *mp; + nxt_str_t str; + nxt_router_tlssock_t *tls; + + mp = tmcf->router_conf->mem_pool; + + tls = nxt_mp_get(mp, sizeof(nxt_router_tlssock_t)); + if (nxt_slow_path(tls == NULL)) { + return NXT_ERROR; + } + + tls->conf = skcf; + nxt_conf_get_string(value, &str); + + if (nxt_slow_path(nxt_str_dup(mp, &tls->name, &str) == NULL)) { + return NXT_ERROR; + } + + nxt_queue_insert_tail(&tmcf->tls, &tls->link); + + return NXT_OK; +} + +#endif + + static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, nxt_conf_value_t *conf) @@ -2383,7 +2429,7 @@ nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, static void nxt_router_tls_rpc_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_router_tlssock_t *tls) + nxt_router_tlssock_t *tls, nxt_bool_t last) { nxt_socket_rpc_t *rpc; @@ -2393,8 +2439,10 @@ nxt_router_tls_rpc_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, return; } + rpc->name = &tls->name; rpc->socket_conf = tls->conf; rpc->temp_conf = tmcf; + rpc->last = last; nxt_cert_store_get(task, &tls->name, tmcf->mem_pool, nxt_router_tls_rpc_handler, rpc); @@ -2405,11 +2453,12 @@ static void nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) { - nxt_mp_t *mp; - nxt_int_t ret; - nxt_tls_conf_t *tlscf; - nxt_socket_rpc_t *rpc; - nxt_router_temp_conf_t *tmcf; + nxt_mp_t *mp; + nxt_int_t ret; + nxt_tls_conf_t *tlscf; + nxt_socket_rpc_t *rpc; + nxt_tls_bundle_conf_t *bundle; + nxt_router_temp_conf_t *tmcf; nxt_debug(task, "tls rpc handler"); @@ -2422,20 +2471,33 @@ nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, mp = tmcf->router_conf->mem_pool; - tlscf = nxt_mp_zget(mp, sizeof(nxt_tls_conf_t)); - if (nxt_slow_path(tlscf == NULL)) { + if (rpc->socket_conf->tls == NULL){ + tlscf = nxt_mp_zget(mp, sizeof(nxt_tls_conf_t)); + if (nxt_slow_path(tlscf == NULL)) { + goto fail; + } + + rpc->socket_conf->tls = tlscf; + + } else { + tlscf = rpc->socket_conf->tls; + } + + bundle = nxt_mp_get(mp, sizeof(nxt_tls_bundle_conf_t)); + if (nxt_slow_path(bundle == NULL)) { goto fail; } - tlscf->chain_file = msg->fd[0]; + bundle->name = rpc->name; + bundle->chain_file = msg->fd[0]; + bundle->next = tlscf->bundle; + tlscf->bundle = bundle; - ret = task->thread->runtime->tls->server_init(task, tlscf); + ret = task->thread->runtime->tls->server_init(task, tlscf, mp, rpc->last); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } - rpc->socket_conf->tls = tlscf; - nxt_work_queue_add(&task->thread->engine->fast_work_queue, nxt_router_conf_apply, task, tmcf, NULL); return; @@ -3726,7 +3788,7 @@ nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) nxt_event_engine_t *engine; nxt_thread_handle_t handle; - handle = (nxt_thread_handle_t) obj; + handle = (nxt_thread_handle_t) (uintptr_t) obj; link = data; nxt_thread_wait(handle); @@ -4050,6 +4112,8 @@ nxt_router_req_headers_ack_handler(nxt_task_t *task, if (b != NULL) { /* First buffer is already sent. Start from second. */ b = b->next; + + req_rpc_data->msg_info.buf->next = NULL; } if (req_rpc_data->msg_info.body_fd != -1 || b != NULL) { @@ -4962,14 +5026,6 @@ nxt_router_app_prepare_request(nxt_task_t *task, port->socket.fd); req_rpc_data->msg_info.buf = buf; - req_rpc_data->msg_info.completion_handler = buf->completion_handler; - - do { - buf->completion_handler = nxt_router_dummy_buf_completion; - buf = buf->next; - } while (buf != NULL); - - buf = req_rpc_data->msg_info.buf; body = req_rpc_data->request->body; diff --git a/src/nxt_router_request.h b/src/nxt_router_request.h index 95044dbb..6e226bae 100644 --- a/src/nxt_router_request.h +++ b/src/nxt_router_request.h @@ -11,7 +11,6 @@ typedef struct { nxt_buf_t *buf; nxt_fd_t body_fd; uint32_t tracking_cookie; - nxt_work_handler_t completion_handler; } nxt_msg_info_t; diff --git a/src/nxt_thread.h b/src/nxt_thread.h index 2ebc331d..d7800cc6 100644 --- a/src/nxt_thread.h +++ b/src/nxt_thread.h @@ -142,6 +142,14 @@ nxt_thread_yield() \ #endif +#if (PTHREAD_STACK_MIN) +#define NXT_THREAD_STACK_MIN PTHREAD_STACK_MIN + +#else +#define NXT_THREAD_STACK_MIN sysconf(_SC_THREAD_STACK_MIN) +#endif + + struct nxt_thread_s { nxt_log_t *log; nxt_log_t main_log; diff --git a/src/nxt_tls.h b/src/nxt_tls.h index d9fcc6a8..c44bfe56 100644 --- a/src/nxt_tls.h +++ b/src/nxt_tls.h @@ -23,28 +23,47 @@ #define NXT_TLS_BUFFER_SIZE 4096 -typedef struct nxt_tls_conf_s nxt_tls_conf_t; - +typedef struct nxt_tls_conf_s nxt_tls_conf_t; +typedef struct nxt_tls_bundle_conf_s nxt_tls_bundle_conf_t; typedef struct { nxt_int_t (*library_init)(nxt_task_t *task); void (*library_free)(nxt_task_t *task); nxt_int_t (*server_init)(nxt_task_t *task, - nxt_tls_conf_t *conf); + nxt_tls_conf_t *conf, nxt_mp_t *mp, + nxt_bool_t last); void (*server_free)(nxt_task_t *task, nxt_tls_conf_t *conf); } nxt_tls_lib_t; -struct nxt_tls_conf_s { +typedef struct { + nxt_tls_bundle_conf_t *bundle; + + nxt_str_t name; +} nxt_tls_bundle_hash_item_t; + + +struct nxt_tls_bundle_conf_s { void *ctx; + + nxt_fd_t chain_file; + nxt_str_t *name; + + nxt_tls_bundle_conf_t *next; +}; + + +struct nxt_tls_conf_s { + nxt_tls_bundle_conf_t *bundle; + nxt_lvlhsh_t bundle_hash; + void (*conn_init)(nxt_task_t *task, nxt_tls_conf_t *conf, nxt_conn_t *c); const nxt_tls_lib_t *lib; - nxt_fd_t chain_file; char *ciphers; char *ca_certificate; diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 2fef17c5..ae4499d8 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -3785,7 +3785,7 @@ nxt_unit_shm_open(nxt_unit_ctx_t *ctx, size_t size) char name[64]; snprintf(name, sizeof(name), NXT_SHM_PREFIX "unit.%d.%p", - lib->pid, (void *) pthread_self()); + lib->pid, (void *) (uintptr_t) pthread_self()); #endif #if (NXT_HAVE_MEMFD_CREATE) diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index 0aad887d..ca14af5b 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -12,6 +12,8 @@ #include NXT_RUBY_MOUNTS_H +#include <locale.h> + #define NXT_RUBY_RACK_API_VERSION_MAJOR 1 #define NXT_RUBY_RACK_API_VERSION_MINOR 3 @@ -200,6 +202,8 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) nxt_ruby_threads = c->threads; + setlocale(LC_CTYPE, ""); + RUBY_INIT_STACK ruby_init(); ruby_options(2, argv); diff --git a/test/conftest.py b/test/conftest.py index b36aabad..20ac6e81 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,9 +1,12 @@ import fcntl +import inspect +import json import os import platform import re import shutil import signal +import socket import stat import subprocess import sys @@ -16,6 +19,8 @@ from unit.check.go import check_go from unit.check.isolation import check_isolation from unit.check.node import check_node from unit.check.tls import check_openssl +from unit.check.regex import check_regex +from unit.http import TestHTTP from unit.option import option from unit.utils import public_dir from unit.utils import waitforfiles @@ -51,10 +56,18 @@ def pytest_addoption(parser): type=str, help="Default user for non-privileged processes of unitd", ) + parser.addoption( + "--restart", + default=False, + action="store_true", + help="Force Unit to restart after every test", + ) unit_instance = {} +unit_log_copy = "unit.log.copy" _processes = [] +http = TestHTTP() def pytest_configure(config): option.config = config.option @@ -64,6 +77,7 @@ def pytest_configure(config): option.save_log = config.option.save_log option.unsafe = config.option.unsafe option.user = config.option.user + option.restart = config.option.restart option.generated_tests = {} option.current_dir = os.path.abspath( @@ -163,6 +177,7 @@ def pytest_sessionstart(session): option.current_dir, unit['temp_dir'], option.test_dir ) option.available['modules']['node'] = check_node(option.current_dir) + option.available['modules']['regex'] = check_regex(unit['unitd']) # remove None values @@ -172,12 +187,17 @@ def pytest_sessionstart(session): check_isolation() + _clear_conf(unit['temp_dir'] + '/control.unit.sock') + unit_stop() _check_alerts() - shutil.rmtree(unit_instance['temp_dir']) + if option.restart: + shutil.rmtree(unit_instance['temp_dir']) + elif option.save_log: + open(unit_instance['temp_dir'] + '/' + unit_log_copy, 'w').close() @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): @@ -241,38 +261,70 @@ def run(request): # stop unit - error = unit_stop() + error_stop_unit = unit_stop() + error_stop_processes = stop_processes() - if error: - _print_log() + # prepare log - assert error is None, 'stop unit' + with open( + unit_instance['log'], 'r', encoding='utf-8', errors='ignore' + ) as f: + log = f.read() - # stop all processes + if not option.restart and option.save_log: + with open(unit_instance['temp_dir'] + '/' + unit_log_copy, 'a') as f: + f.write(log) - error = stop_processes() + # remove unit.log - if error: - _print_log() + if not option.save_log and option.restart: + shutil.rmtree(unit['temp_dir']) - assert error is None, 'stop unit' + # clean temp_dir before the next test - # check unit.log for alerts + if not option.restart: + _clear_conf(unit['temp_dir'] + '/control.unit.sock', log) - _check_alerts() + open(unit['log'], 'w').close() + + for item in os.listdir(unit['temp_dir']): + if item not in [ + 'control.unit.sock', + 'state', + 'unit.pid', + 'unit.log', + unit_log_copy, + ]: + path = os.path.join(unit['temp_dir'], item) + + public_dir(path) + + if os.path.isfile(path) or stat.S_ISSOCK(os.stat(path).st_mode): + os.remove(path) + else: + shutil.rmtree(path) # print unit.log in case of error if hasattr(request.node, 'rep_call') and request.node.rep_call.failed: - _print_log() + _print_log(log) - # remove unit.log + if error_stop_unit or error_stop_processes: + _print_log(log) - if not option.save_log: - shutil.rmtree(unit['temp_dir']) + # check unit.log for errors + + assert error_stop_unit is None, 'stop unit' + assert error_stop_processes is None, 'stop processes' + + _check_alerts(log=log) def unit_run(): global unit_instance + + if not option.restart and 'unitd' in unit_instance: + return unit_instance + build_dir = option.current_dir + '/build' unitd = build_dir + '/unitd' @@ -323,6 +375,12 @@ def unit_run(): def unit_stop(): + if not option.restart: + if inspect.stack()[1].function.startswith('test_'): + pytest.skip('no restart mode') + + return + p = unit_instance['process'] if p.poll() is not None: @@ -345,12 +403,13 @@ def unit_stop(): -def _check_alerts(path=None): +def _check_alerts(path=None, log=None): if path is None: path = unit_instance['log'] - with open(path, 'r', encoding='utf-8', errors='ignore') as f: - log = f.read() + if log is None: + with open(path, 'r', encoding='utf-8', errors='ignore') as f: + log = f.read() found = False @@ -396,6 +455,43 @@ def _print_log(data=None): sys.stdout.write(data) +def _clear_conf(sock, log=None): + def check_success(resp): + if 'success' not in resp: + _print_log(log) + assert 'success' in resp + + resp = http.put( + url='/config', + sock_type='unix', + addr=sock, + body=json.dumps({"listeners": {}, "applications": {}}), + )['body'] + + check_success(resp) + + if 'openssl' not in option.available['modules']: + return + + try: + certs = json.loads(http.get( + url='/certificates', + sock_type='unix', + addr=sock, + )['body']).keys() + + except json.JSONDecodeError: + pytest.fail('Can\'t parse certificates list.') + + for cert in certs: + resp = http.delete( + url='/certificates/' + cert, + sock_type='unix', + addr=sock, + )['body'] + + check_success(resp) + def run_process(target, *args): global _processes @@ -446,5 +542,10 @@ def unit_pid(request): return unit_instance['process'].pid def pytest_sessionfinish(session): + if not option.restart and option.save_log: + print('Path to unit.log:\n' + unit_instance['log'] + '\n') + + option.restart = True + unit_stop() shutil.rmtree(option.cache_dir) diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py index 5770265d..886a160b 100644 --- a/test/test_asgi_application.py +++ b/test/test_asgi_application.py @@ -377,7 +377,7 @@ Connection: close self.get(no_recv=True) assert ( - self.wait_for_record(r'\(5\) Thread: 100') is not None + self.wait_for_record(r'\(5\) Thread: 100', wait=50) is not None ), 'last thread finished' def test_asgi_application_threads(self): diff --git a/test/test_asgi_websockets.py b/test/test_asgi_websockets.py index 6121fcc5..7218d526 100644 --- a/test/test_asgi_websockets.py +++ b/test/test_asgi_websockets.py @@ -30,8 +30,9 @@ class TestASGIWebsockets(TestApplicationPython): self.check_close(sock) - def check_close(self, sock, code=1000, no_close=False): - frame = self.ws.frame_read(sock) + def check_close(self, sock, code=1000, no_close=False, frame=None): + if frame == None: + frame = self.ws.frame_read(sock) assert frame['fin'] == True, 'close fin' assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode' @@ -930,7 +931,14 @@ class TestASGIWebsockets(TestApplicationPython): self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True) - self.check_close(sock, 1002) + + frame = self.ws.frame_read(sock) + + if frame['opcode'] == self.ws.OP_TEXT: + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') + frame = None + + self.check_close(sock, 1002, frame=frame) # 5_16 diff --git a/test/test_java_websockets.py b/test/test_java_websockets.py index 315c496d..df9e0885 100644 --- a/test/test_java_websockets.py +++ b/test/test_java_websockets.py @@ -27,8 +27,9 @@ class TestJavaWebsockets(TestApplicationJava): self.check_close(sock) - def check_close(self, sock, code=1000, no_close=False): - frame = self.ws.frame_read(sock) + def check_close(self, sock, code=1000, no_close=False, frame=None): + if frame == None: + frame = self.ws.frame_read(sock) assert frame['fin'] == True, 'close fin' assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode' @@ -862,7 +863,14 @@ class TestJavaWebsockets(TestApplicationJava): self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True) - self.check_close(sock, 1002) + + frame = self.ws.frame_read(sock) + + if frame['opcode'] == self.ws.OP_TEXT: + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') + frame = None + + self.check_close(sock, 1002, frame=frame) # 5_16 diff --git a/test/test_node_websockets.py b/test/test_node_websockets.py index 4f1e5906..d5f79811 100644 --- a/test/test_node_websockets.py +++ b/test/test_node_websockets.py @@ -27,8 +27,9 @@ class TestNodeWebsockets(TestApplicationNode): self.check_close(sock) - def check_close(self, sock, code=1000, no_close=False): - frame = self.ws.frame_read(sock) + def check_close(self, sock, code=1000, no_close=False, frame=None): + if frame == None: + frame = self.ws.frame_read(sock) assert frame['fin'] == True, 'close fin' assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode' @@ -881,7 +882,14 @@ class TestNodeWebsockets(TestApplicationNode): self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True) - self.check_close(sock, 1002) + + frame = self.ws.frame_read(sock) + + if frame['opcode'] == self.ws.OP_TEXT: + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') + frame = None + + self.check_close(sock, 1002, frame=frame) # 5_16 diff --git a/test/test_proxy.py b/test/test_proxy.py index 2d305e98..7e7c7246 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -482,6 +482,7 @@ Content-Length: 10 check_proxy('http://[:]:7080') check_proxy('http://[::7080') + @pytest.mark.skip('not yet') def test_proxy_loop(self, skip_alert): skip_alert( r'socket.*failed', diff --git a/test/test_python_application.py b/test/test_python_application.py index 709df3ff..41f6f538 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -569,7 +569,7 @@ last line: 987654321 self.get(no_recv=True) assert ( - self.wait_for_record(r'\(5\) Thread: 100') is not None + self.wait_for_record(r'\(5\) Thread: 100', wait=50) is not None ), 'last thread finished' def test_python_application_iter_exception(self): diff --git a/test/test_routing.py b/test/test_routing.py index 4d27cb61..be9a1faf 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -229,6 +229,9 @@ class TestRouting(TestApplicationProto): assert self.get(url='/ABc')['status'] == 404 def test_routes_empty_regex(self): + if not option.available['modules']['regex']: + pytest.skip('requires regex') + self.route_match({"uri":"~"}) assert self.get(url='/')['status'] == 200, 'empty regexp' assert self.get(url='/anything')['status'] == 200, '/anything' @@ -238,6 +241,9 @@ class TestRouting(TestApplicationProto): assert self.get(url='/nothing')['status'] == 404, '/nothing' def test_routes_bad_regex(self): + if not option.available['modules']['regex']: + pytest.skip('requires regex') + assert 'error' in self.route( {"match": {"uri": "~/bl[ah"}, "action": {"return": 200}} ), 'bad regex' @@ -255,6 +261,9 @@ class TestRouting(TestApplicationProto): assert self.get(url='/nothing_z')['status'] == 500, '/nothing_z' def test_routes_match_regex_case_sensitive(self): + if not option.available['modules']['regex']: + pytest.skip('requires regex') + self.route_match({"uri": "~/bl[ah]"}) assert self.get(url='/rlah')['status'] == 404, '/rlah' @@ -263,6 +272,9 @@ class TestRouting(TestApplicationProto): assert self.get(url='/BLAH')['status'] == 404, '/BLAH' def test_routes_match_regex_negative_case_sensitive(self): + if not option.available['modules']['regex']: + pytest.skip('requires regex') + self.route_match({"uri": "!~/bl[ah]"}) assert self.get(url='/rlah')['status'] == 200, '/rlah' diff --git a/test/test_share_fallback.py b/test/test_share_fallback.py index a02cb1a3..46464670 100644 --- a/test/test_share_fallback.py +++ b/test/test_share_fallback.py @@ -1,5 +1,6 @@ import os +import pytest from unit.applications.proto import TestApplicationProto from unit.option import option @@ -27,7 +28,10 @@ class TestStatic(TestApplicationProto): ) def teardown_method(self): - os.chmod(option.temp_dir + '/assets/403', 0o777) + try: + os.chmod(option.temp_dir + '/assets/403', 0o777) + except FileNotFoundError: + pass def action_update(self, conf): assert 'success' in self.conf(conf, 'routes/0/action') @@ -116,6 +120,7 @@ class TestStatic(TestApplicationProto): assert resp['status'] == 200, 'fallback proxy status' assert resp['body'] == '', 'fallback proxy' + @pytest.mark.skip('not yet') def test_fallback_proxy_loop(self, skip_alert): skip_alert( r'open.*/blah/index.html.*failed', diff --git a/test/test_tls.py b/test/test_tls.py index 89c57d07..206ea828 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -199,7 +199,7 @@ class TestTLS(TestApplicationTLS): self.sec_epoch() - self.openssl_date_to_sec_epoch(cert['validity']['since']) ) - < 5 + < 60 ), 'certificate validity since' assert ( self.openssl_date_to_sec_epoch(cert['validity']['until']) diff --git a/test/unit/applications/lang/java.py b/test/unit/applications/lang/java.py index b2e17f23..c9c2095e 100644 --- a/test/unit/applications/lang/java.py +++ b/test/unit/applications/lang/java.py @@ -52,7 +52,7 @@ class TestApplicationJava(TestApplicationProto): os.makedirs(classes_path) classpath = ( - option.current_dir + '/build/tomcat-servlet-api-9.0.39.jar' + option.current_dir + '/build/tomcat-servlet-api-9.0.44.jar' ) ws_jars = glob.glob( diff --git a/test/unit/applications/proto.py b/test/unit/applications/proto.py index af05d071..5c400621 100644 --- a/test/unit/applications/proto.py +++ b/test/unit/applications/proto.py @@ -19,8 +19,8 @@ class TestApplicationProto(TestControl): with open(option.temp_dir + '/' + name, 'r', errors='ignore') as f: return re.search(pattern, f.read()) - def wait_for_record(self, pattern, name='unit.log'): - for i in range(50): + def wait_for_record(self, pattern, name='unit.log', wait=150): + for i in range(wait): found = self.search_in_log(pattern, name) if found is not None: diff --git a/test/unit/check/regex.py b/test/unit/check/regex.py new file mode 100644 index 00000000..734c0150 --- /dev/null +++ b/test/unit/check/regex.py @@ -0,0 +1,13 @@ +import re +import subprocess + + +def check_regex(unitd): + output = subprocess.check_output( + [unitd, '--version'], stderr=subprocess.STDOUT + ) + + if re.search('--no-regex', output.decode()): + return False + + return True diff --git a/test/unit/utils.py b/test/unit/utils.py index 7a0a3fe5..e80fc469 100644 --- a/test/unit/utils.py +++ b/test/unit/utils.py @@ -47,7 +47,7 @@ def waitforsocket(port): except KeyboardInterrupt: raise - pytest.fail('Can\'t connect to the 127.0.0.1:' + port) + pytest.fail('Can\'t connect to the 127.0.0.1:' + str(port)) def findmnt(): @@ -1,5 +1,5 @@ # Copyright (C) NGINX, Inc. -NXT_VERSION=1.22.0 -NXT_VERNUM=12200 +NXT_VERSION=1.23.0 +NXT_VERNUM=12300 |