152 changes: 128 additions & 24 deletions auto/lib/pcre/make
Expand Up @@ -3,36 +3,138 @@
# Copyright (C) Nginx, Inc.


case "$NGX_CC_NAME" in
if [ $PCRE_LIBRARY = PCRE2 ]; then

# PCRE2

if [ $NGX_CC_NAME = msvc ]; then

# With PCRE2, it is not possible to compile all sources.
# Since list of source files changes between versions, we
# test files which might not be present.

ngx_pcre_srcs="pcre2_auto_possess.c \
pcre2_chartables.c \
pcre2_compile.c \
pcre2_config.c \
pcre2_context.c \
pcre2_dfa_match.c \
pcre2_error.c \
pcre2_jit_compile.c \
pcre2_maketables.c \
pcre2_match.c \
pcre2_match_data.c \
pcre2_newline.c \
pcre2_ord2utf.c \
pcre2_pattern_info.c \
pcre2_string_utils.c \
pcre2_study.c \
pcre2_substitute.c \
pcre2_substring.c \
pcre2_tables.c \
pcre2_ucd.c \
pcre2_valid_utf.c \
pcre2_xclass.c"

ngx_pcre_test="pcre2_convert.c \
pcre2_extuni.c \
pcre2_find_bracket.c \
pcre2_script_run.c \
pcre2_serialize.c"

for ngx_src in $ngx_pcre_test
do
if [ -f $PCRE/src/$ngx_src ]; then
ngx_pcre_srcs="$ngx_pcre_srcs $ngx_src"
fi
done

ngx_pcre_objs=`echo $ngx_pcre_srcs \
| sed -e "s#\([^ ]*\.\)c#\1$ngx_objext#g"`

ngx_pcre_srcs=`echo $ngx_pcre_srcs \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g"`
ngx_pcre_objs=`echo $ngx_pcre_objs \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g"`

cat << END >> $NGX_MAKEFILE

PCRE_CFLAGS = -O2 -Ob1 -Oi -Gs $LIBC $CPU_OPT
PCRE_FLAGS = -DHAVE_CONFIG_H -DPCRE2_STATIC -DPCRE2_CODE_UNIT_WIDTH=8 \\
-DHAVE_MEMMOVE

PCRE_SRCS = $ngx_pcre_srcs
PCRE_OBJS = $ngx_pcre_objs

$PCRE/src/pcre2.h:
cd $PCRE/src \\
&& copy /y config.h.generic config.h \\
&& copy /y pcre2.h.generic pcre2.h \\
&& copy /y pcre2_chartables.c.dist pcre2_chartables.c

$PCRE/src/pcre2-8.lib: $PCRE/src/pcre2.h $NGX_MAKEFILE
cd $PCRE/src \\
&& cl -nologo -c \$(PCRE_CFLAGS) -I . \$(PCRE_FLAGS) \$(PCRE_SRCS) \\
&& link -lib -out:pcre2-8.lib -verbose:lib \$(PCRE_OBJS)

msvc)
ngx_makefile=makefile.msvc
ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC"
ngx_pcre="PCRE=\"$PCRE\""
;;
END

else

cat << END >> $NGX_MAKEFILE

owc)
ngx_makefile=makefile.owc
ngx_opt="CPU_OPT=\"$CPU_OPT\""
ngx_pcre=`echo PCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
;;
$PCRE/src/pcre2.h: $PCRE/Makefile

$PCRE/Makefile: $NGX_MAKEFILE
cd $PCRE \\
&& if [ -f Makefile ]; then \$(MAKE) distclean; fi \\
&& CC="\$(CC)" CFLAGS="$PCRE_OPT" \\
./configure --disable-shared $PCRE_CONF_OPT

bcc)
ngx_makefile=makefile.bcc
ngx_opt="-DCPU_OPT=\"$CPU_OPT\""
ngx_pcre=`echo \-DPCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
;;
$PCRE/.libs/libpcre2-8.a: $PCRE/Makefile
cd $PCRE \\
&& \$(MAKE) libpcre2-8.la

*)
ngx_makefile=
;;
END

esac
fi


if [ -n "$ngx_makefile" ]; then
else

cat << END >> $NGX_MAKEFILE
# PCRE

case "$NGX_CC_NAME" in

msvc)
ngx_makefile=makefile.msvc
ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC"
ngx_pcre="PCRE=\"$PCRE\""
;;

owc)
ngx_makefile=makefile.owc
ngx_opt="CPU_OPT=\"$CPU_OPT\""
ngx_pcre=`echo PCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
;;

bcc)
ngx_makefile=makefile.bcc
ngx_opt="-DCPU_OPT=\"$CPU_OPT\""
ngx_pcre=`echo \-DPCRE=\"$PCRE\" \
| sed -e "s/\//$ngx_regex_dirsep/g"`
;;

*)
ngx_makefile=
;;

esac


if [ -n "$ngx_makefile" ]; then

cat << END >> $NGX_MAKEFILE

`echo "$PCRE/pcre.lib: $PCRE/pcre.h $NGX_MAKEFILE" \
| sed -e "s/\//$ngx_regex_dirsep/g"`
Expand All @@ -43,9 +145,9 @@ if [ -n "$ngx_makefile" ]; then

END

else
else

cat << END >> $NGX_MAKEFILE
cat << END >> $NGX_MAKEFILE

$PCRE/pcre.h: $PCRE/Makefile

Expand All @@ -61,4 +163,6 @@ $PCRE/.libs/libpcre.a: $PCRE/Makefile

END

fi

fi
18 changes: 10 additions & 8 deletions auto/make
Expand Up @@ -6,9 +6,10 @@
echo "creating $NGX_MAKEFILE"

mkdir -p $NGX_OBJS/src/core $NGX_OBJS/src/event $NGX_OBJS/src/event/modules \
$NGX_OBJS/src/event/quic \
$NGX_OBJS/src/os/unix $NGX_OBJS/src/os/win32 \
$NGX_OBJS/src/http $NGX_OBJS/src/http/v2 $NGX_OBJS/src/http/modules \
$NGX_OBJS/src/http/modules/perl \
$NGX_OBJS/src/http $NGX_OBJS/src/http/v2 $NGX_OBJS/src/http/v3 \
$NGX_OBJS/src/http/modules $NGX_OBJS/src/http/modules/perl \
$NGX_OBJS/src/mail \
$NGX_OBJS/src/stream \
$NGX_OBJS/src/misc
Expand Down Expand Up @@ -313,7 +314,7 @@ $ngx_obj: \$(CORE_DEPS) \$(HTTP_DEPS)$ngx_cont$ngx_src
END

fi
done
done

fi

Expand Down Expand Up @@ -343,7 +344,7 @@ $ngx_obj: \$(CORE_DEPS) \$(MAIL_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX

END
done
done

fi

Expand Down Expand Up @@ -373,7 +374,7 @@ $ngx_obj: \$(CORE_DEPS) \$(STREAM_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX

END
done
done

fi

Expand All @@ -399,7 +400,7 @@ $ngx_obj: \$(CORE_DEPS) $ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX

END
done
done

fi

Expand Down Expand Up @@ -431,7 +432,7 @@ $ngx_obj: \$(ADDON_DEPS)$ngx_cont$ngx_src
$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX

END
done
done

fi

Expand Down Expand Up @@ -502,6 +503,7 @@ fi
for ngx_module in $DYNAMIC_MODULES
do
eval ngx_module_srcs="\$${ngx_module}_SRCS"
eval ngx_module_shrd="\$${ngx_module}_SHRD"
eval eval ngx_module_libs="\\\"\$${ngx_module}_LIBS\\\""

eval ngx_module_modules="\$${ngx_module}_MODULES"
Expand Down Expand Up @@ -567,7 +569,7 @@ END
| sed -e "s/\(.*\.\)c/\1$ngx_objext/"`

ngx_module_objs=
for ngx_src in $ngx_module_srcs
for ngx_src in $ngx_module_srcs $ngx_module_shrd
do
case "$ngx_src" in
src/*)
Expand Down
44 changes: 42 additions & 2 deletions auto/module
Expand Up @@ -17,7 +17,6 @@ if [ "$ngx_module_link" = DYNAMIC ]; then
done

DYNAMIC_MODULES="$DYNAMIC_MODULES $ngx_module"
eval ${ngx_module}_SRCS=\"$ngx_module_srcs\"

eval ${ngx_module}_MODULES=\"$ngx_module_name\"

Expand All @@ -31,6 +30,30 @@ if [ "$ngx_module_link" = DYNAMIC ]; then
eval ${ngx_module}_ORDER=\"$ngx_module_order\"
fi

srcs=
shrd=
for src in $ngx_module_srcs
do
found=no
for old in $DYNAMIC_MODULES_SRCS
do
if [ $src = $old ]; then
found=yes
break
fi
done

if [ $found = no ]; then
srcs="$srcs $src"
else
shrd="$shrd $src"
fi
done
eval ${ngx_module}_SRCS=\"$srcs\"
eval ${ngx_module}_SHRD=\"$shrd\"

DYNAMIC_MODULES_SRCS="$DYNAMIC_MODULES_SRCS $srcs"

if test -n "$ngx_module_incs"; then
CORE_INCS="$CORE_INCS $ngx_module_incs"
fi
Expand Down Expand Up @@ -107,7 +130,24 @@ elif [ "$ngx_module_link" = ADDON ]; then
eval ${ngx_module_type}_MODULES=\"\$${ngx_module_type}_MODULES \
$ngx_module_name\"

NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_module_srcs"
srcs=
for src in $ngx_module_srcs
do
found=no
for old in $NGX_ADDON_SRCS
do
if [ $src = $old ]; then
found=yes
break
fi
done

if [ $found = no ]; then
srcs="$srcs $src"
fi
done

NGX_ADDON_SRCS="$NGX_ADDON_SRCS $srcs"

if test -n "$ngx_module_incs"; then
eval ${ngx_var}_INCS=\"\$${ngx_var}_INCS $ngx_module_incs\"
Expand Down
120 changes: 117 additions & 3 deletions auto/modules
Expand Up @@ -102,6 +102,11 @@ if [ $HTTP = YES ]; then
fi


if [ $HTTP_V2 = YES -o $HTTP_V3 = YES ]; then
HTTP_SRCS="$HTTP_SRCS $HTTP_HUFF_SRCS"
fi


# the module order is important
# ngx_http_static_module
# ngx_http_gzip_static_module
Expand All @@ -119,6 +124,7 @@ if [ $HTTP = YES ]; then
# ngx_http_header_filter
# ngx_http_chunked_filter
# ngx_http_v2_filter
# ngx_http_v3_filter
# ngx_http_range_header_filter
# ngx_http_gzip_filter
# ngx_http_postpone_filter
Expand Down Expand Up @@ -151,6 +157,7 @@ if [ $HTTP = YES ]; then
ngx_http_header_filter_module \
ngx_http_chunked_filter_module \
ngx_http_v2_filter_module \
ngx_http_v3_filter_module \
ngx_http_range_header_filter_module \
ngx_http_gzip_filter_module \
ngx_http_postpone_filter_module \
Expand Down Expand Up @@ -212,6 +219,17 @@ if [ $HTTP = YES ]; then
. auto/module
fi

if [ $HTTP_V3 = YES ]; then
ngx_module_name=ngx_http_v3_filter_module
ngx_module_incs=
ngx_module_deps=
ngx_module_srcs=src/http/v3/ngx_http_v3_filter_module.c
ngx_module_libs=
ngx_module_link=$HTTP_V3

. auto/module
fi

if :; then
ngx_module_name=ngx_http_range_header_filter_module
ngx_module_incs=
Expand Down Expand Up @@ -405,7 +423,6 @@ if [ $HTTP = YES ]; then

if [ $HTTP_V2 = YES ]; then
have=NGX_HTTP_V2 . auto/have
have=NGX_HTTP_HEADERS . auto/have

ngx_module_name=ngx_http_v2_module
ngx_module_incs=src/http/v2
Expand All @@ -414,15 +431,39 @@ if [ $HTTP = YES ]; then
ngx_module_srcs="src/http/v2/ngx_http_v2.c \
src/http/v2/ngx_http_v2_table.c \
src/http/v2/ngx_http_v2_encode.c \
src/http/v2/ngx_http_v2_huff_decode.c \
src/http/v2/ngx_http_v2_huff_encode.c \
src/http/v2/ngx_http_v2_module.c"
ngx_module_libs=
ngx_module_link=$HTTP_V2

. auto/module
fi

if [ $HTTP_V3 = YES ]; then
USE_OPENSSL_QUIC=YES
HTTP_SSL=YES

have=NGX_HTTP_V3 . auto/have

ngx_module_name=ngx_http_v3_module
ngx_module_incs=src/http/v3
ngx_module_deps="src/http/v3/ngx_http_v3.h \
src/http/v3/ngx_http_v3_encode.h \
src/http/v3/ngx_http_v3_parse.h \
src/http/v3/ngx_http_v3_table.h \
src/http/v3/ngx_http_v3_uni.h"
ngx_module_srcs="src/http/v3/ngx_http_v3.c \
src/http/v3/ngx_http_v3_encode.c \
src/http/v3/ngx_http_v3_parse.c \
src/http/v3/ngx_http_v3_table.c \
src/http/v3/ngx_http_v3_uni.c \
src/http/v3/ngx_http_v3_request.c \
src/http/v3/ngx_http_v3_module.c"
ngx_module_libs=
ngx_module_link=$HTTP_V3

. auto/module
fi

if :; then
ngx_module_name=ngx_http_static_module
ngx_module_incs=
Expand Down Expand Up @@ -985,6 +1026,12 @@ if [ $MAIL != NO ]; then
ngx_module_srcs=src/mail/ngx_mail_proxy_module.c

. auto/module

ngx_module_name=ngx_mail_realip_module
ngx_module_deps=
ngx_module_srcs=src/mail/ngx_mail_realip_module.c

. auto/module
fi


Expand Down Expand Up @@ -1119,6 +1166,16 @@ if [ $STREAM != NO ]; then
. auto/module
fi

if [ $STREAM_SET = YES ]; then
ngx_module_name=ngx_stream_set_module
ngx_module_deps=
ngx_module_srcs=src/stream/ngx_stream_set_module.c
ngx_module_libs=
ngx_module_link=$STREAM_SET

. auto/module
fi

if [ $STREAM_UPSTREAM_HASH = YES ]; then
ngx_module_name=ngx_stream_upstream_hash_module
ngx_module_deps=
Expand Down Expand Up @@ -1253,6 +1310,63 @@ if [ $USE_OPENSSL = YES ]; then
fi


if [ $USE_OPENSSL_QUIC = YES ]; then
ngx_module_type=CORE
ngx_module_name=ngx_quic_module
ngx_module_incs=
ngx_module_deps="src/event/quic/ngx_event_quic.h \
src/event/quic/ngx_event_quic_transport.h \
src/event/quic/ngx_event_quic_protection.h \
src/event/quic/ngx_event_quic_connection.h \
src/event/quic/ngx_event_quic_frames.h \
src/event/quic/ngx_event_quic_connid.h \
src/event/quic/ngx_event_quic_migration.h \
src/event/quic/ngx_event_quic_streams.h \
src/event/quic/ngx_event_quic_ssl.h \
src/event/quic/ngx_event_quic_tokens.h \
src/event/quic/ngx_event_quic_ack.h \
src/event/quic/ngx_event_quic_output.h \
src/event/quic/ngx_event_quic_socket.h \
src/event/quic/ngx_event_quic_openssl_compat.h"
ngx_module_srcs="src/event/quic/ngx_event_quic.c \
src/event/quic/ngx_event_quic_udp.c \
src/event/quic/ngx_event_quic_transport.c \
src/event/quic/ngx_event_quic_protection.c \
src/event/quic/ngx_event_quic_frames.c \
src/event/quic/ngx_event_quic_connid.c \
src/event/quic/ngx_event_quic_migration.c \
src/event/quic/ngx_event_quic_streams.c \
src/event/quic/ngx_event_quic_ssl.c \
src/event/quic/ngx_event_quic_tokens.c \
src/event/quic/ngx_event_quic_ack.c \
src/event/quic/ngx_event_quic_output.c \
src/event/quic/ngx_event_quic_socket.c \
src/event/quic/ngx_event_quic_openssl_compat.c"

ngx_module_libs=
ngx_module_link=YES
ngx_module_order=

. auto/module

if [ $QUIC_BPF = YES -a $SO_COOKIE_FOUND = YES ]; then
ngx_module_type=CORE
ngx_module_name=ngx_quic_bpf_module
ngx_module_incs=
ngx_module_deps=
ngx_module_srcs="src/event/quic/ngx_event_quic_bpf.c \
src/event/quic/ngx_event_quic_bpf_code.c"
ngx_module_libs=
ngx_module_link=YES
ngx_module_order=

. auto/module

have=NGX_QUIC_BPF . auto/have
fi
fi


if [ $USE_PCRE = YES ]; then
ngx_module_type=CORE
ngx_module_name=ngx_regex_module
Expand Down
20 changes: 20 additions & 0 deletions auto/options
Expand Up @@ -45,6 +45,8 @@ USE_THREADS=NO

NGX_FILE_AIO=NO

QUIC_BPF=NO

HTTP=YES

NGX_HTTP_LOG_PATH=
Expand All @@ -59,6 +61,7 @@ HTTP_CHARSET=YES
HTTP_GZIP=YES
HTTP_SSL=NO
HTTP_V2=NO
HTTP_V3=NO
HTTP_SSI=YES
HTTP_REALIP=NO
HTTP_XSLT=NO
Expand Down Expand Up @@ -124,15 +127,18 @@ STREAM_GEOIP=NO
STREAM_MAP=YES
STREAM_SPLIT_CLIENTS=YES
STREAM_RETURN=YES
STREAM_SET=YES
STREAM_UPSTREAM_HASH=YES
STREAM_UPSTREAM_LEAST_CONN=YES
STREAM_UPSTREAM_RANDOM=YES
STREAM_UPSTREAM_ZONE=YES
STREAM_SSL_PREREAD=NO

DYNAMIC_MODULES=
DYNAMIC_MODULES_SRCS=

NGX_ADDONS=
NGX_ADDON_SRCS=
NGX_ADDON_DEPS=
DYNAMIC_ADDONS=

Expand All @@ -143,8 +149,10 @@ PCRE=NONE
PCRE_OPT=
PCRE_CONF_OPT=
PCRE_JIT=NO
PCRE2=YES

USE_OPENSSL=NO
USE_OPENSSL_QUIC=NO
OPENSSL=NONE

USE_ZLIB=NO
Expand All @@ -162,6 +170,8 @@ USE_GEOIP=NO
NGX_GOOGLE_PERFTOOLS=NO
NGX_CPP_TEST=NO

SO_COOKIE_FOUND=NO

NGX_LIBATOMIC=NO

NGX_CPU_CACHE_LINE=
Expand Down Expand Up @@ -207,6 +217,8 @@ do

--with-file-aio) NGX_FILE_AIO=YES ;;

--without-quic_bpf_module) QUIC_BPF=NONE ;;

--with-ipv6)
NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG
$0: warning: the \"--with-ipv6\" option is deprecated"
Expand All @@ -224,6 +236,7 @@ $0: warning: the \"--with-ipv6\" option is deprecated"

--with-http_ssl_module) HTTP_SSL=YES ;;
--with-http_v2_module) HTTP_V2=YES ;;
--with-http_v3_module) HTTP_V3=YES ;;
--with-http_realip_module) HTTP_REALIP=YES ;;
--with-http_addition_module) HTTP_ADDITION=YES ;;
--with-http_xslt_module) HTTP_XSLT=YES ;;
Expand Down Expand Up @@ -324,6 +337,7 @@ use the \"--with-mail_ssl_module\" option instead"
--without-stream_split_clients_module)
STREAM_SPLIT_CLIENTS=NO ;;
--without-stream_return_module) STREAM_RETURN=NO ;;
--without-stream_set_module) STREAM_SET=NO ;;
--without-stream_upstream_hash_module)
STREAM_UPSTREAM_HASH=NO ;;
--without-stream_upstream_least_conn_module)
Expand Down Expand Up @@ -353,6 +367,7 @@ use the \"--with-mail_ssl_module\" option instead"
--with-pcre=*) PCRE="$value" ;;
--with-pcre-opt=*) PCRE_OPT="$value" ;;
--with-pcre-jit) PCRE_JIT=YES ;;
--without-pcre2) PCRE2=DISABLED ;;

--with-openssl=*) OPENSSL="$value" ;;
--with-openssl-opt=*) OPENSSL_OPT="$value" ;;
Expand Down Expand Up @@ -437,8 +452,11 @@ cat << END

--with-file-aio enable file AIO support

--without-quic_bpf_module disable ngx_quic_bpf_module

--with-http_ssl_module enable ngx_http_ssl_module
--with-http_v2_module enable ngx_http_v2_module
--with-http_v3_module enable ngx_http_v3_module
--with-http_realip_module enable ngx_http_realip_module
--with-http_addition_module enable ngx_http_addition_module
--with-http_xslt_module enable ngx_http_xslt_module
Expand Down Expand Up @@ -538,6 +556,7 @@ cat << END
--without-stream_split_clients_module
disable ngx_stream_split_clients_module
--without-stream_return_module disable ngx_stream_return_module
--without-stream_set_module disable ngx_stream_set_module
--without-stream_upstream_hash_module
disable ngx_stream_upstream_hash_module
--without-stream_upstream_least_conn_module
Expand Down Expand Up @@ -568,6 +587,7 @@ cat << END
--with-pcre=DIR set path to PCRE library sources
--with-pcre-opt=OPTIONS set additional build options for PCRE
--with-pcre-jit build PCRE with JIT compilation support
--without-pcre2 do not use PCRE2 library

--with-zlib=DIR set path to zlib library sources
--with-zlib-opt=OPTIONS set additional build options for zlib
Expand Down
2 changes: 1 addition & 1 deletion auto/os/conf
Expand Up @@ -110,7 +110,7 @@ case "$NGX_MACHINE" in
NGX_MACH_CACHE_LINE=64
;;

aarch64 )
aarch64 | arm64)
have=NGX_ALIGNMENT value=16 . auto/define
NGX_MACH_CACHE_LINE=64
;;
Expand Down
8 changes: 3 additions & 5 deletions auto/os/freebsd
Expand Up @@ -44,12 +44,10 @@ if [ $osreldate -gt 300007 ]; then
CORE_SRCS="$CORE_SRCS $FREEBSD_SENDFILE_SRCS"
fi

if [ $NGX_FILE_AIO = YES ]; then
if [ $osreldate -gt 502103 ]; then
echo " + sendfile()'s SF_NODISKIO found"
if [ $osreldate -gt 1100093 ]; then
echo " + sendfile()'s SF_NODISKIO found"

have=NGX_HAVE_AIO_SENDFILE . auto/have
fi
have=NGX_HAVE_SENDFILE_NODISKIO . auto/have
fi

# POSIX semaphores
Expand Down
84 changes: 84 additions & 0 deletions auto/os/linux
Expand Up @@ -86,6 +86,31 @@ if [ $ngx_found = yes ]; then
ee.data.ptr = NULL;
epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)"
. auto/feature


# eventfd()

ngx_feature="eventfd()"
ngx_feature_name="NGX_HAVE_EVENTFD"
ngx_feature_run=no
ngx_feature_incs="#include <sys/eventfd.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="(void) eventfd(0, 0)"
. auto/feature

if [ $ngx_found = yes ]; then
have=NGX_HAVE_SYS_EVENTFD_H . auto/have
fi


if [ $ngx_found = no ]; then

ngx_feature="eventfd() (SYS_eventfd)"
ngx_feature_incs="#include <sys/syscall.h>"
ngx_feature_test="(void) SYS_eventfd"
. auto/feature
fi
fi


Expand Down Expand Up @@ -207,4 +232,63 @@ ngx_feature_test="struct crypt_data cd;
ngx_include="sys/vfs.h"; . auto/include


# BPF sockhash

ngx_feature="BPF sockhash"
ngx_feature_name="NGX_HAVE_BPF"
ngx_feature_run=no
ngx_feature_incs="#include <linux/bpf.h>
#include <sys/syscall.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="union bpf_attr attr = { 0 };

attr.map_flags = 0;
attr.map_type = BPF_MAP_TYPE_SOCKHASH;

syscall(__NR_bpf, 0, &attr, 0);"
. auto/feature

if [ $ngx_found = yes ]; then
CORE_SRCS="$CORE_SRCS src/core/ngx_bpf.c"
CORE_DEPS="$CORE_DEPS src/core/ngx_bpf.h"

if [ $QUIC_BPF != NONE ]; then
QUIC_BPF=YES
fi
fi


ngx_feature="SO_COOKIE"
ngx_feature_name="NGX_HAVE_SO_COOKIE"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
$NGX_INCLUDE_INTTYPES_H"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="socklen_t optlen = sizeof(uint64_t);
uint64_t cookie;
getsockopt(0, SOL_SOCKET, SO_COOKIE, &cookie, &optlen)"
. auto/feature

if [ $ngx_found = yes ]; then
SO_COOKIE_FOUND=YES
fi


# UDP segmentation offloading

ngx_feature="UDP_SEGMENT"
ngx_feature_name="NGX_HAVE_UDP_SEGMENT"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
#include <netinet/udp.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="socklen_t optlen = sizeof(int);
int val;
getsockopt(0, SOL_UDP, UDP_SEGMENT, &val, &optlen)"
. auto/feature


CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
8 changes: 6 additions & 2 deletions auto/sources
Expand Up @@ -83,13 +83,14 @@ CORE_SRCS="src/core/nginx.c \

EVENT_MODULES="ngx_events_module ngx_event_core_module"

EVENT_INCS="src/event src/event/modules"
EVENT_INCS="src/event src/event/modules src/event/quic"

EVENT_DEPS="src/event/ngx_event.h \
src/event/ngx_event_timer.h \
src/event/ngx_event_posted.h \
src/event/ngx_event_connect.h \
src/event/ngx_event_pipe.h"
src/event/ngx_event_pipe.h \
src/event/ngx_event_udp.h"

EVENT_SRCS="src/event/ngx_event.c \
src/event/ngx_event_timer.c \
Expand Down Expand Up @@ -255,3 +256,6 @@ NGX_WIN32_RC="src/os/win32/nginx.rc"


HTTP_FILE_CACHE_SRCS=src/http/ngx_http_file_cache.c

HTTP_HUFF_SRCS="src/http/ngx_http_huff_decode.c
src/http/ngx_http_huff_encode.c"
4 changes: 2 additions & 2 deletions auto/summary
Expand Up @@ -16,9 +16,9 @@ if [ $USE_PCRE = DISABLED ]; then

else
case $PCRE in
YES) echo " + using system PCRE library" ;;
YES) echo " + using system $PCRE_LIBRARY library" ;;
NONE) echo " + PCRE library is not used" ;;
*) echo " + using PCRE library: $PCRE" ;;
*) echo " + using $PCRE_LIBRARY library: $PCRE" ;;
esac
fi

Expand Down
111 changes: 62 additions & 49 deletions auto/unix
Expand Up @@ -448,6 +448,54 @@ ngx_feature_test="setsockopt(0, IPPROTO_IPV6, IPV6_RECVPKTINFO, NULL, 0)"
. auto/feature


# IP packet fragmentation

ngx_feature="IP_MTU_DISCOVER"
ngx_feature_name="NGX_HAVE_IP_MTU_DISCOVER"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
#include <netinet/in.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="(void) IP_PMTUDISC_DO;
setsockopt(0, IPPROTO_IP, IP_MTU_DISCOVER, NULL, 0)"
. auto/feature


ngx_feature="IPV6_MTU_DISCOVER"
ngx_feature_name="NGX_HAVE_IPV6_MTU_DISCOVER"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
#include <netinet/in.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="(void) IPV6_PMTUDISC_DO;
setsockopt(0, IPPROTO_IPV6, IPV6_MTU_DISCOVER, NULL, 0)"
. auto/feature


ngx_feature="IP_DONTFRAG"
ngx_feature_name="NGX_HAVE_IP_DONTFRAG"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
#include <netinet/in.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_DONTFRAG, NULL, 0)"
. auto/feature


ngx_feature="IPV6_DONTFRAG"
ngx_feature_name="NGX_HAVE_IPV6_DONTFRAG"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
#include <netinet/in.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_IP, IPV6_DONTFRAG, NULL, 0)"
. auto/feature


ngx_feature="TCP_DEFER_ACCEPT"
ngx_feature_name="NGX_HAVE_DEFERRED_ACCEPT"
ngx_feature_run=no
Expand Down Expand Up @@ -582,29 +630,6 @@ Currently file AIO is supported on FreeBSD 4.3+ and Linux 2.6.22+ only
END
exit 1
fi

else

ngx_feature="eventfd()"
ngx_feature_name="NGX_HAVE_EVENTFD"
ngx_feature_run=no
ngx_feature_incs="#include <sys/eventfd.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="(void) eventfd(0, 0)"
. auto/feature

if [ $ngx_found = yes ]; then
have=NGX_HAVE_SYS_EVENTFD_H . auto/have
fi

if [ $ngx_found = no ]; then

ngx_feature="eventfd() (SYS_eventfd)"
ngx_feature_incs="#include <sys/syscall.h>"
ngx_feature_test="(void) SYS_eventfd"
. auto/feature
fi
fi


Expand Down Expand Up @@ -727,56 +752,44 @@ ngx_feature_test="char buf[1]; struct iovec vec[1]; ssize_t n;
. auto/feature


ngx_feature="sys_nerr"
ngx_feature_name="NGX_SYS_NERR"
ngx_feature_run=value
ngx_feature_incs='#include <errno.h>
#include <stdio.h>'
# strerrordesc_np(), introduced in glibc 2.32

ngx_feature="strerrordesc_np()"
ngx_feature_name="NGX_HAVE_STRERRORDESC_NP"
ngx_feature_run=no
ngx_feature_incs='#include <string.h>'
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test='printf("%d", sys_nerr);'
ngx_feature_test="char *p; p = strerrordesc_np(0);
if (p == NULL) return 1"
. auto/feature


if [ $ngx_found = no ]; then

# Cygiwn defines _sys_nerr
ngx_feature="_sys_nerr"
ngx_feature="sys_nerr"
ngx_feature_name="NGX_SYS_NERR"
ngx_feature_run=value
ngx_feature_incs='#include <errno.h>
#include <stdio.h>'
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test='printf("%d", _sys_nerr);'
ngx_feature_test='printf("%d", sys_nerr);'
. auto/feature
fi


if [ $ngx_found = no ]; then

# Solaris has no sys_nerr
ngx_feature='maximum errno'
ngx_feature_name=NGX_SYS_NERR
# Cygiwn defines _sys_nerr
ngx_feature="_sys_nerr"
ngx_feature_name="NGX_SYS_NERR"
ngx_feature_run=value
ngx_feature_incs='#include <errno.h>
#include <string.h>
#include <stdio.h>'
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test='int n;
char *p;
for (n = 1; n < 1000; n++) {
errno = 0;
p = strerror(n);
if (errno == EINVAL
|| p == NULL
|| strncmp(p, "Unknown error", 13) == 0)
{
break;
}
}
printf("%d", n);'
ngx_feature_test='printf("%d", _sys_nerr);'
. auto/feature
fi

Expand Down
2 changes: 2 additions & 0 deletions conf/mime.types
Expand Up @@ -15,6 +15,7 @@ types {
text/vnd.wap.wml wml;
text/x-component htc;

image/avif avif;
image/png png;
image/svg+xml svg svgz;
image/tiff tif tiff;
Expand Down Expand Up @@ -51,6 +52,7 @@ types {
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx;
application/vnd.wap.wmlc wmlc;
application/wasm wasm;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
Expand Down
1,209 changes: 425 additions & 784 deletions contrib/vim/syntax/nginx.vim

Large diffs are not rendered by default.

8 changes: 3 additions & 5 deletions docs/html/50x.html
Expand Up @@ -3,11 +3,9 @@
<head>
<title>Error</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
Expand Down
8 changes: 3 additions & 5 deletions docs/html/index.html
Expand Up @@ -3,11 +3,9 @@
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
Expand Down
13 changes: 10 additions & 3 deletions docs/man/nginx.8
Expand Up @@ -25,7 +25,7 @@
.\" SUCH DAMAGE.
.\"
.\"
.Dd December 5, 2019
.Dd November 5, 2020
.Dt NGINX 8
.Os
.Sh NAME
Expand All @@ -35,6 +35,7 @@
.Nm
.Op Fl ?hqTtVv
.Op Fl c Ar file
.Op Fl e Ar file
.Op Fl g Ar directives
.Op Fl p Ar prefix
.Op Fl s Ar signal
Expand All @@ -54,6 +55,12 @@ Print help.
.It Fl c Ar file
Use an alternative configuration
.Ar file .
.It Fl e Ar file
Use an alternative error log
.Ar file .
Special value
.Cm stderr
indicates that the standard error output should be used.
.It Fl g Ar directives
Set global configuration directives.
See
Expand Down Expand Up @@ -198,10 +205,10 @@ Development of
started in 2002, with the first public release on October 4, 2004.
.Sh AUTHORS
.An -nosplit
.An Igor Sysoev Aq igor@sysoev.ru .
.An Igor Sysoev Aq Mt igor@sysoev.ru .
.Pp
This manual page was originally written by
.An Sergey A. Osokin Aq osa@FreeBSD.org.ru
.An Sergey A. Osokin Aq Mt osa@FreeBSD.org.ru
as a result of compiling many
.Nm
documents from all over the world.
4 changes: 2 additions & 2 deletions docs/text/LICENSE
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2019 Igor Sysoev
* Copyright (C) 2011-2019 Nginx, Inc.
* Copyright (C) 2002-2021 Igor Sysoev
* Copyright (C) 2011-2023 Nginx, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down
2,027 changes: 2,027 additions & 0 deletions docs/xml/nginx/changes.xml

Large diffs are not rendered by default.

16 changes: 6 additions & 10 deletions misc/GNUmakefile
Expand Up @@ -6,21 +6,15 @@ TEMP = tmp

CC = cl
OBJS = objs.msvc8
OPENSSL = openssl-1.1.1f
ZLIB = zlib-1.2.11
PCRE = pcre-8.44
OPENSSL = openssl-3.0.11
ZLIB = zlib-1.3
PCRE = pcre2-10.39


release: export

mv $(TEMP)/$(NGINX)/auto/configure $(TEMP)/$(NGINX)

# delete incomplete sources
rm $(TEMP)/$(NGINX)/src/event/ngx_event_acceptex.c
rm $(TEMP)/$(NGINX)/src/event/ngx_event_connectex.c
rm $(TEMP)/$(NGINX)/src/event/modules/ngx_iocp_module.*
rm -r $(TEMP)/$(NGINX)/src/os/win32

mv $(TEMP)/$(NGINX)/docs/text/LICENSE $(TEMP)/$(NGINX)
mv $(TEMP)/$(NGINX)/docs/text/README $(TEMP)/$(NGINX)
mv $(TEMP)/$(NGINX)/docs/html $(TEMP)/$(NGINX)
Expand Down Expand Up @@ -81,6 +75,8 @@ win32:
--with-http_slice_module \
--with-mail \
--with-stream \
--with-stream_realip_module \
--with-stream_ssl_preread_module \
--with-openssl=$(OBJS)/lib/$(OPENSSL) \
--with-openssl-opt="no-asm no-tests -D_WIN32_WINNT=0x0501" \
--with-http_ssl_module \
Expand Down Expand Up @@ -109,7 +105,7 @@ zip: export
$(MAKE) -f docs/GNUmakefile changes
mv $(TEMP)/$(NGINX)/CHANGES* $(TEMP)/$(NGINX)/docs/

cp -p $(OBJS)/lib/$(OPENSSL)/LICENSE \
cp -p $(OBJS)/lib/$(OPENSSL)/LICENSE.txt \
$(TEMP)/$(NGINX)/docs/OpenSSL.LICENSE

cp -p $(OBJS)/lib/$(PCRE)/LICENCE \
Expand Down
98 changes: 92 additions & 6 deletions src/core/nginx.c
Expand Up @@ -13,6 +13,7 @@
static void ngx_show_version_info(void);
static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
static void ngx_cleanup_environment(void *data);
static void ngx_cleanup_environment_variable(void *data);
static ngx_int_t ngx_get_options(int argc, char *const *argv);
static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
Expand Down Expand Up @@ -183,6 +184,7 @@ static ngx_uint_t ngx_show_help;
static ngx_uint_t ngx_show_version;
static ngx_uint_t ngx_show_configure;
static u_char *ngx_prefix;
static u_char *ngx_error_log;
static u_char *ngx_conf_file;
static u_char *ngx_conf_params;
static char *ngx_signal;
Expand Down Expand Up @@ -230,7 +232,7 @@ main(int argc, char *const *argv)
ngx_pid = ngx_getpid();
ngx_parent = ngx_getppid();

log = ngx_log_init(ngx_prefix);
log = ngx_log_init(ngx_prefix, ngx_error_log);
if (log == NULL) {
return 1;
}
Expand Down Expand Up @@ -393,9 +395,9 @@ ngx_show_version_info(void)

if (ngx_show_help) {
ngx_write_stderr(
"Usage: nginx [-?hvVtTq] [-s signal] [-c filename] "
"[-p prefix] [-g directives]" NGX_LINEFEED
NGX_LINEFEED
"Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]" NGX_LINEFEED
" [-e filename] [-c filename] [-g directives]"
NGX_LINEFEED NGX_LINEFEED
"Options:" NGX_LINEFEED
" -?,-h : this help" NGX_LINEFEED
" -v : show version and exit" NGX_LINEFEED
Expand All @@ -413,6 +415,12 @@ ngx_show_version_info(void)
NGX_LINEFEED
#else
" -p prefix : set prefix path (default: NONE)" NGX_LINEFEED
#endif
" -e filename : set error log file (default: "
#ifdef NGX_ERROR_LOG_STDERR
"stderr)" NGX_LINEFEED
#else
NGX_ERROR_LOG_PATH ")" NGX_LINEFEED
#endif
" -c filename : set configuration file (default: " NGX_CONF_PATH
")" NGX_LINEFEED
Expand Down Expand Up @@ -492,6 +500,7 @@ ngx_add_inherited_sockets(ngx_cycle_t *cycle)
ngx_memzero(ls, sizeof(ngx_listening_t));

ls->fd = (ngx_socket_t) s;
ls->inherited = 1;
}
}

Expand All @@ -510,7 +519,8 @@ ngx_add_inherited_sockets(ngx_cycle_t *cycle)
char **
ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
{
char **p, **env;
char **p, **env, *str;
size_t len;
ngx_str_t *var;
ngx_uint_t i, n;
ngx_core_conf_t *ccf;
Expand Down Expand Up @@ -592,7 +602,31 @@ ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
for (i = 0; i < ccf->env.nelts; i++) {

if (var[i].data[var[i].len] == '=') {
env[n++] = (char *) var[i].data;

if (last) {
env[n++] = (char *) var[i].data;
continue;
}

cln = ngx_pool_cleanup_add(cycle->pool, 0);
if (cln == NULL) {
return NULL;
}

len = ngx_strlen(var[i].data) + 1;

str = ngx_alloc(len, cycle->log);
if (str == NULL) {
return NULL;
}

ngx_memcpy(str, var[i].data, len);

cln->handler = ngx_cleanup_environment_variable;
cln->data = str;

env[n++] = str;

continue;
}

Expand Down Expand Up @@ -637,6 +671,29 @@ ngx_cleanup_environment(void *data)
}


static void
ngx_cleanup_environment_variable(void *data)
{
char *var = data;

char **p;

for (p = environ; *p; p++) {

/*
* if an environment variable is still used, as it happens on exit,
* the only option is to leak it
*/

if (*p == var) {
return;
}
}

ngx_free(var);
}


ngx_pid_t
ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
{
Expand Down Expand Up @@ -672,6 +729,9 @@ ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)

ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
if (ls[i].ignore) {
continue;
}
p = ngx_sprintf(p, "%ud;", ls[i].fd);
}

Expand Down Expand Up @@ -799,6 +859,24 @@ ngx_get_options(int argc, char *const *argv)
ngx_log_stderr(0, "option \"-p\" requires directory name");
return NGX_ERROR;

case 'e':
if (*p) {
ngx_error_log = p;

} else if (argv[++i]) {
ngx_error_log = (u_char *) argv[i];

} else {
ngx_log_stderr(0, "option \"-e\" requires file name");
return NGX_ERROR;
}

if (ngx_strcmp(ngx_error_log, "stderr") == 0) {
ngx_error_log = (u_char *) "";
}

goto next;

case 'c':
if (*p) {
ngx_conf_file = p;
Expand Down Expand Up @@ -991,6 +1069,14 @@ ngx_process_options(ngx_cycle_t *cycle)
}
}

if (ngx_error_log) {
cycle->error_log.len = ngx_strlen(ngx_error_log);
cycle->error_log.data = ngx_error_log;

} else {
ngx_str_set(&cycle->error_log, NGX_ERROR_LOG_PATH);
}

if (ngx_conf_params) {
cycle->conf_param.len = ngx_strlen(ngx_conf_params);
cycle->conf_param.data = ngx_conf_params;
Expand Down
4 changes: 2 additions & 2 deletions src/core/nginx.h
Expand Up @@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_


#define nginx_version 1017010
#define NGINX_VERSION "1.17.10"
#define nginx_version 1025003
#define NGINX_VERSION "1.25.3"
#define NGINX_VER "nginx/" NGINX_VERSION

#ifdef NGX_BUILD
Expand Down
143 changes: 143 additions & 0 deletions src/core/ngx_bpf.c
@@ -0,0 +1,143 @@

/*
* Copyright (C) Nginx, Inc.
*/


#include <ngx_config.h>
#include <ngx_core.h>

#define NGX_BPF_LOGBUF_SIZE (16 * 1024)


static ngx_inline int
ngx_bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size)
{
return syscall(__NR_bpf, cmd, attr, size);
}


void
ngx_bpf_program_link(ngx_bpf_program_t *program, const char *symbol, int fd)
{
ngx_uint_t i;
ngx_bpf_reloc_t *rl;

rl = program->relocs;

for (i = 0; i < program->nrelocs; i++) {
if (ngx_strcmp(rl[i].name, symbol) == 0) {
program->ins[rl[i].offset].src_reg = 1;
program->ins[rl[i].offset].imm = fd;
}
}
}


int
ngx_bpf_load_program(ngx_log_t *log, ngx_bpf_program_t *program)
{
int fd;
union bpf_attr attr;
#if (NGX_DEBUG)
char buf[NGX_BPF_LOGBUF_SIZE];
#endif

ngx_memzero(&attr, sizeof(union bpf_attr));

attr.license = (uintptr_t) program->license;
attr.prog_type = program->type;
attr.insns = (uintptr_t) program->ins;
attr.insn_cnt = program->nins;

#if (NGX_DEBUG)
/* for verifier errors */
attr.log_buf = (uintptr_t) buf;
attr.log_size = NGX_BPF_LOGBUF_SIZE;
attr.log_level = 1;
#endif

fd = ngx_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
if (fd < 0) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
"failed to load BPF program");

ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
"bpf verifier: %s", buf);

return -1;
}

return fd;
}


int
ngx_bpf_map_create(ngx_log_t *log, enum bpf_map_type type, int key_size,
int value_size, int max_entries, uint32_t map_flags)
{
int fd;
union bpf_attr attr;

ngx_memzero(&attr, sizeof(union bpf_attr));

attr.map_type = type;
attr.key_size = key_size;
attr.value_size = value_size;
attr.max_entries = max_entries;
attr.map_flags = map_flags;

fd = ngx_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
if (fd < 0) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
"failed to create BPF map");
return NGX_ERROR;
}

return fd;
}


int
ngx_bpf_map_update(int fd, const void *key, const void *value, uint64_t flags)
{
union bpf_attr attr;

ngx_memzero(&attr, sizeof(union bpf_attr));

attr.map_fd = fd;
attr.key = (uintptr_t) key;
attr.value = (uintptr_t) value;
attr.flags = flags;

return ngx_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
}


int
ngx_bpf_map_delete(int fd, const void *key)
{
union bpf_attr attr;

ngx_memzero(&attr, sizeof(union bpf_attr));

attr.map_fd = fd;
attr.key = (uintptr_t) key;

return ngx_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
}


int
ngx_bpf_map_lookup(int fd, const void *key, void *value)
{
union bpf_attr attr;

ngx_memzero(&attr, sizeof(union bpf_attr));

attr.map_fd = fd;
attr.key = (uintptr_t) key;
attr.value = (uintptr_t) value;

return ngx_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
}
43 changes: 43 additions & 0 deletions src/core/ngx_bpf.h
@@ -0,0 +1,43 @@

/*
* Copyright (C) Nginx, Inc.
*/


#ifndef _NGX_BPF_H_INCLUDED_
#define _NGX_BPF_H_INCLUDED_


#include <ngx_config.h>
#include <ngx_core.h>

#include <linux/bpf.h>


typedef struct {
char *name;
int offset;
} ngx_bpf_reloc_t;

typedef struct {
char *license;
enum bpf_prog_type type;
struct bpf_insn *ins;
size_t nins;
ngx_bpf_reloc_t *relocs;
size_t nrelocs;
} ngx_bpf_program_t;


void ngx_bpf_program_link(ngx_bpf_program_t *program, const char *symbol,
int fd);
int ngx_bpf_load_program(ngx_log_t *log, ngx_bpf_program_t *program);

int ngx_bpf_map_create(ngx_log_t *log, enum bpf_map_type type, int key_size,
int value_size, int max_entries, uint32_t map_flags);
int ngx_bpf_map_update(int fd, const void *key, const void *value,
uint64_t flags);
int ngx_bpf_map_delete(int fd, const void *key);
int ngx_bpf_map_lookup(int fd, const void *key, void *value);

#endif /* _NGX_BPF_H_INCLUDED_ */
8 changes: 4 additions & 4 deletions src/core/ngx_buf.c
Expand Up @@ -203,16 +203,16 @@ ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free, ngx_chain_t **busy,
while (*busy) {
cl = *busy;

if (ngx_buf_size(cl->buf) != 0) {
break;
}

if (cl->buf->tag != tag) {
*busy = cl->next;
ngx_free_chain(p, cl);
continue;
}

if (ngx_buf_size(cl->buf) != 0) {
break;
}

cl->buf->pos = cl->buf->start;
cl->buf->last = cl->buf->start;

Expand Down
23 changes: 10 additions & 13 deletions src/core/ngx_buf.h
Expand Up @@ -90,9 +90,6 @@ struct ngx_output_chain_ctx_s {

#if (NGX_HAVE_FILE_AIO || NGX_COMPAT)
ngx_output_chain_aio_pt aio_handler;
#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
ssize_t (*aio_preload)(ngx_buf_t *file);
#endif
#endif

#if (NGX_THREADS || NGX_COMPAT)
Expand Down Expand Up @@ -125,20 +122,20 @@ typedef struct {
#define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR


#define ngx_buf_in_memory(b) (b->temporary || b->memory || b->mmap)
#define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !b->in_file)
#define ngx_buf_in_memory(b) ((b)->temporary || (b)->memory || (b)->mmap)
#define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !(b)->in_file)

#define ngx_buf_special(b) \
((b->flush || b->last_buf || b->sync) \
&& !ngx_buf_in_memory(b) && !b->in_file)
(((b)->flush || (b)->last_buf || (b)->sync) \
&& !ngx_buf_in_memory(b) && !(b)->in_file)

#define ngx_buf_sync_only(b) \
(b->sync \
&& !ngx_buf_in_memory(b) && !b->in_file && !b->flush && !b->last_buf)
((b)->sync && !ngx_buf_in_memory(b) \
&& !(b)->in_file && !(b)->flush && !(b)->last_buf)

#define ngx_buf_size(b) \
(ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): \
(b->file_last - b->file_pos))
(ngx_buf_in_memory(b) ? (off_t) ((b)->last - (b)->pos): \
((b)->file_last - (b)->file_pos))

ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);
ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
Expand All @@ -149,8 +146,8 @@ ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);

ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool);
#define ngx_free_chain(pool, cl) \
cl->next = pool->chain; \
pool->chain = cl
(cl)->next = (pool)->chain; \
(pool)->chain = (cl)



Expand Down
6 changes: 3 additions & 3 deletions src/core/ngx_conf_file.c
Expand Up @@ -544,8 +544,8 @@ ngx_conf_read_token(ngx_conf_t *cf)
}

ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected end of file, "
"expecting \";\" or \"}\"");
"unexpected end of file, "
"expecting \";\" or \"}\"");
return NGX_ERROR;
}

Expand Down Expand Up @@ -1137,7 +1137,7 @@ ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)

a = (ngx_array_t **) (p + cmd->offset);

if (*a == NULL) {
if (*a == NGX_CONF_UNSET_PTR || *a == NULL) {
*a = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t));
if (*a == NULL) {
return NGX_CONF_ERROR;
Expand Down
151 changes: 133 additions & 18 deletions src/core/ngx_connection.c
Expand Up @@ -495,21 +495,24 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
return NGX_ERROR;
}

if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(const void *) &reuseaddr, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
"setsockopt(SO_REUSEADDR) %V failed",
&ls[i].addr_text);
if (ls[i].type != SOCK_DGRAM || !ngx_test_config) {

if (ngx_close_socket(s) == -1) {
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(const void *) &reuseaddr, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
"setsockopt(SO_REUSEADDR) %V failed",
&ls[i].addr_text);
}

return NGX_ERROR;
if (ngx_close_socket(s) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
&ls[i].addr_text);
}

return NGX_ERROR;
}
}

#if (NGX_HAVE_REUSEPORT)
Expand Down Expand Up @@ -657,7 +660,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
/*
* on OpenVZ after suspend/resume EADDRINUSE
* may be returned by listen() instead of bind(), see
* https://bugzilla.openvz.org/show_bug.cgi?id=2470
* https://bugs.openvz.org/browse/OVZ-5587
*/

if (err != NGX_EADDRINUSE || !ngx_test_config) {
Expand Down Expand Up @@ -1010,6 +1013,78 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
}
}

#endif

#if (NGX_HAVE_IP_MTU_DISCOVER)

if (ls[i].quic && ls[i].sockaddr->sa_family == AF_INET) {
value = IP_PMTUDISC_DO;

if (setsockopt(ls[i].fd, IPPROTO_IP, IP_MTU_DISCOVER,
(const void *) &value, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(IP_MTU_DISCOVER) "
"for %V failed, ignored",
&ls[i].addr_text);
}
}

#elif (NGX_HAVE_IP_DONTFRAG)

if (ls[i].quic && ls[i].sockaddr->sa_family == AF_INET) {
value = 1;

if (setsockopt(ls[i].fd, IPPROTO_IP, IP_DONTFRAG,
(const void *) &value, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(IP_DONTFRAG) "
"for %V failed, ignored",
&ls[i].addr_text);
}
}

#endif

#if (NGX_HAVE_INET6)

#if (NGX_HAVE_IPV6_MTU_DISCOVER)

if (ls[i].quic && ls[i].sockaddr->sa_family == AF_INET6) {
value = IPV6_PMTUDISC_DO;

if (setsockopt(ls[i].fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
(const void *) &value, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(IPV6_MTU_DISCOVER) "
"for %V failed, ignored",
&ls[i].addr_text);
}
}

#elif (NGX_HAVE_IP_DONTFRAG)

if (ls[i].quic && ls[i].sockaddr->sa_family == AF_INET6) {
value = 1;

if (setsockopt(ls[i].fd, IPPROTO_IPV6, IPV6_DONTFRAG,
(const void *) &value, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(IPV6_DONTFRAG) "
"for %V failed, ignored",
&ls[i].addr_text);
}
}

#endif

#endif
}

Expand All @@ -1034,6 +1109,12 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {

#if (NGX_QUIC)
if (ls[i].quic) {
continue;
}
#endif

c = ls[i].connection;

if (c) {
Expand Down Expand Up @@ -1070,7 +1151,8 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)

if (ls[i].sockaddr->sa_family == AF_UNIX
&& ngx_process <= NGX_PROCESS_MASTER
&& ngx_new_binary == 0)
&& ngx_new_binary == 0
&& (!ls[i].inherited || ngx_getppid() != ngx_parent))
{
u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;

Expand Down Expand Up @@ -1106,12 +1188,9 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
return NULL;
}

c = ngx_cycle->free_connections;
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);

if (c == NULL) {
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
c = ngx_cycle->free_connections;
}
c = ngx_cycle->free_connections;

if (c == NULL) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
Expand Down Expand Up @@ -1297,6 +1376,22 @@ ngx_drain_connections(ngx_cycle_t *cycle)
ngx_queue_t *q;
ngx_connection_t *c;

if (cycle->free_connection_n > cycle->connection_n / 16
|| cycle->reusable_connections_n == 0)
{
return;
}

if (cycle->connections_reuse_time != ngx_time()) {
cycle->connections_reuse_time = ngx_time();

ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
"%ui worker_connections are not enough, "
"reusing connections",
cycle->connection_n);
}

c = NULL;
n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1);

for (i = 0; i < n; i++) {
Expand All @@ -1313,6 +1408,21 @@ ngx_drain_connections(ngx_cycle_t *cycle)
c->close = 1;
c->read->handler(c->read);
}

if (cycle->free_connection_n == 0 && c && c->reusable) {

/*
* if no connections were freed, try to reuse the last
* connection again: this should free it as long as
* previous reuse moved it to lingering close
*/

ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
"reusing connection again");

c->close = 1;
c->read->handler(c->read);
}
}


Expand Down Expand Up @@ -1473,6 +1583,10 @@ ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
}
#endif

if (err == NGX_EMSGSIZE && c->log_error == NGX_ERROR_IGNORE_EMSGSIZE) {
return 0;
}

if (err == 0
|| err == NGX_ECONNRESET
#if (NGX_WIN32)
Expand All @@ -1490,6 +1604,7 @@ ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
{
switch (c->log_error) {

case NGX_ERROR_IGNORE_EMSGSIZE:
case NGX_ERROR_IGNORE_EINVAL:
case NGX_ERROR_IGNORE_ECONNRESET:
case NGX_ERROR_INFO:
Expand Down
15 changes: 11 additions & 4 deletions src/core/ngx_connection.h
Expand Up @@ -45,8 +45,6 @@ struct ngx_listening_s {
size_t pool_size;
/* should be here because of the AcceptEx() preread */
size_t post_accept_buffer_size;
/* should be here because of the deferred accept */
ngx_msec_t post_accept_timeout;

ngx_listening_t *previous;
ngx_connection_t *connection;
Expand Down Expand Up @@ -75,6 +73,7 @@ struct ngx_listening_s {
unsigned reuseport:1;
unsigned add_reuseport:1;
unsigned keepalive:2;
unsigned quic:1;

unsigned deferred_accept:1;
unsigned delete_deferred:1;
Expand All @@ -98,7 +97,8 @@ typedef enum {
NGX_ERROR_ERR,
NGX_ERROR_INFO,
NGX_ERROR_IGNORE_ECONNRESET,
NGX_ERROR_IGNORE_EINVAL
NGX_ERROR_IGNORE_EINVAL,
NGX_ERROR_IGNORE_EMSGSIZE
} ngx_connection_log_error_e;


Expand Down Expand Up @@ -149,6 +149,10 @@ struct ngx_connection_s {

ngx_proxy_protocol_t *proxy_protocol;

#if (NGX_QUIC || NGX_COMPAT)
ngx_quic_stream_t *quic;
#endif

#if (NGX_SSL || NGX_COMPAT)
ngx_ssl_connection_t *ssl;
#endif
Expand All @@ -164,6 +168,7 @@ struct ngx_connection_s {

ngx_atomic_uint_t number;

ngx_msec_t start_time;
ngx_uint_t requests;

unsigned buffered:8;
Expand All @@ -173,6 +178,7 @@ struct ngx_connection_s {
unsigned timedout:1;
unsigned error:1;
unsigned destroyed:1;
unsigned pipeline:1;

unsigned idle:1;
unsigned reusable:1;
Expand All @@ -185,8 +191,9 @@ struct ngx_connection_s {
unsigned tcp_nopush:2; /* ngx_connection_tcp_nopush_e */

unsigned need_last_buf:1;
unsigned need_flush_buf:1;

#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
#if (NGX_HAVE_SENDFILE_NODISKIO || NGX_COMPAT)
unsigned busy_count:2;
#endif

Expand Down
7 changes: 7 additions & 0 deletions src/core/ngx_core.h
Expand Up @@ -27,6 +27,7 @@ typedef struct ngx_connection_s ngx_connection_t;
typedef struct ngx_thread_task_s ngx_thread_task_t;
typedef struct ngx_ssl_s ngx_ssl_t;
typedef struct ngx_proxy_protocol_s ngx_proxy_protocol_t;
typedef struct ngx_quic_stream_s ngx_quic_stream_t;
typedef struct ngx_ssl_connection_s ngx_ssl_connection_t;
typedef struct ngx_udp_connection_s ngx_udp_connection_t;

Expand Down Expand Up @@ -82,6 +83,9 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
#include <ngx_resolver.h>
#if (NGX_OPENSSL)
#include <ngx_event_openssl.h>
#if (NGX_QUIC)
#include <ngx_event_quic.h>
#endif
#endif
#include <ngx_process_cycle.h>
#include <ngx_conf_file.h>
Expand All @@ -91,6 +95,9 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
#include <ngx_connection.h>
#include <ngx_syslog.h>
#include <ngx_proxy_protocol.h>
#if (NGX_HAVE_BPF)
#include <ngx_bpf.h>
#endif


#define LF (u_char) '\n'
Expand Down
17 changes: 15 additions & 2 deletions src/core/ngx_cycle.c
Expand Up @@ -96,6 +96,15 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
return NULL;
}

cycle->error_log.len = old_cycle->error_log.len;
cycle->error_log.data = ngx_pnalloc(pool, old_cycle->error_log.len + 1);
if (cycle->error_log.data == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
ngx_cpystrn(cycle->error_log.data, old_cycle->error_log.data,
old_cycle->error_log.len + 1);

cycle->conf_file.len = old_cycle->conf_file.len;
cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1);
if (cycle->conf_file.data == NULL) {
Expand Down Expand Up @@ -520,6 +529,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
== NGX_OK)
{
nls[n].fd = ls[i].fd;
nls[n].inherited = ls[i].inherited;
nls[n].previous = &ls[i];
ls[i].remain = 1;

Expand Down Expand Up @@ -1008,6 +1018,7 @@ ngx_int_t
ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
{
size_t len;
ngx_int_t rc;
ngx_uint_t create;
ngx_file_t file;
u_char pid[NGX_INT64_LEN + 2];
Expand All @@ -1032,11 +1043,13 @@ ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
return NGX_ERROR;
}

rc = NGX_OK;

if (!ngx_test_config) {
len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid;

if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
return NGX_ERROR;
rc = NGX_ERROR;
}
}

Expand All @@ -1045,7 +1058,7 @@ ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
ngx_close_file_n " \"%s\" failed", file.name.data);
}

return NGX_OK;
return rc;
}


Expand Down
2 changes: 2 additions & 0 deletions src/core/ngx_cycle.h
Expand Up @@ -55,6 +55,7 @@ struct ngx_cycle_s {

ngx_queue_t reusable_connections_queue;
ngx_uint_t reusable_connections_n;
time_t connections_reuse_time;

ngx_array_t listening;
ngx_array_t paths;
Expand All @@ -79,6 +80,7 @@ struct ngx_cycle_s {
ngx_str_t conf_param;
ngx_str_t conf_prefix;
ngx_str_t prefix;
ngx_str_t error_log;
ngx_str_t lock_file;
ngx_str_t hostname;
};
Expand Down
4 changes: 4 additions & 0 deletions src/core/ngx_hash.c
Expand Up @@ -274,6 +274,10 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
}

for (n = 0; n < nelts; n++) {
if (names[n].key.data == NULL) {
continue;
}

if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
{
ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
Expand Down
7 changes: 5 additions & 2 deletions src/core/ngx_hash.h
Expand Up @@ -89,12 +89,15 @@ typedef struct {
} ngx_hash_keys_arrays_t;


typedef struct {
typedef struct ngx_table_elt_s ngx_table_elt_t;

struct ngx_table_elt_s {
ngx_uint_t hash;
ngx_str_t key;
ngx_str_t value;
u_char *lowcase_key;
} ngx_table_elt_t;
ngx_table_elt_t *next;
};


void *ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len);
Expand Down
19 changes: 8 additions & 11 deletions src/core/ngx_log.c
Expand Up @@ -315,21 +315,19 @@ ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err)


ngx_log_t *
ngx_log_init(u_char *prefix)
ngx_log_init(u_char *prefix, u_char *error_log)
{
u_char *p, *name;
size_t nlen, plen;

ngx_log.file = &ngx_log_file;
ngx_log.log_level = NGX_LOG_NOTICE;

name = (u_char *) NGX_ERROR_LOG_PATH;

/*
* we use ngx_strlen() here since BCC warns about
* condition is always false and unreachable code
*/
if (error_log == NULL) {
error_log = (u_char *) NGX_ERROR_LOG_PATH;
}

name = error_log;
nlen = ngx_strlen(name);

if (nlen == 0) {
Expand Down Expand Up @@ -369,7 +367,7 @@ ngx_log_init(u_char *prefix)
*p++ = '/';
}

ngx_cpystrn(p, (u_char *) NGX_ERROR_LOG_PATH, nlen + 1);
ngx_cpystrn(p, error_log, nlen + 1);

p = name;
}
Expand Down Expand Up @@ -403,8 +401,7 @@ ngx_log_init(u_char *prefix)
ngx_int_t
ngx_log_open_default(ngx_cycle_t *cycle)
{
ngx_log_t *log;
static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH);
ngx_log_t *log;

if (ngx_log_get_file_log(&cycle->new_log) != NULL) {
return NGX_OK;
Expand All @@ -425,7 +422,7 @@ ngx_log_open_default(ngx_cycle_t *cycle)

log->log_level = NGX_LOG_ERR;

log->file = ngx_conf_open_file(cycle, &error_log);
log->file = ngx_conf_open_file(cycle, &cycle->error_log);
if (log->file == NULL) {
return NGX_ERROR;
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/ngx_log.h
Expand Up @@ -228,7 +228,7 @@ void ngx_cdecl ngx_log_debug_core(ngx_log_t *log, ngx_err_t err,

/*********************************/

ngx_log_t *ngx_log_init(u_char *prefix);
ngx_log_t *ngx_log_init(u_char *prefix, u_char *error_log);
void ngx_cdecl ngx_log_abort(ngx_err_t err, const char *fmt, ...);
void ngx_cdecl ngx_log_stderr(ngx_err_t err, const char *fmt, ...);
u_char *ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err);
Expand Down
7 changes: 6 additions & 1 deletion src/core/ngx_module.h
Expand Up @@ -41,7 +41,7 @@
#define NGX_MODULE_SIGNATURE_3 "0"
#endif

#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT)
#if (NGX_HAVE_SENDFILE_NODISKIO || NGX_COMPAT)
#define NGX_MODULE_SIGNATURE_4 "1"
#else
#define NGX_MODULE_SIGNATURE_4 "0"
Expand Down Expand Up @@ -107,7 +107,12 @@
#endif

#define NGX_MODULE_SIGNATURE_17 "0"

#if (NGX_QUIC || NGX_COMPAT)
#define NGX_MODULE_SIGNATURE_18 "1"
#else
#define NGX_MODULE_SIGNATURE_18 "0"
#endif

#if (NGX_HAVE_OPENAT)
#define NGX_MODULE_SIGNATURE_19 "1"
Expand Down
53 changes: 17 additions & 36 deletions src/core/ngx_output_chain.c
Expand Up @@ -29,10 +29,6 @@

static ngx_inline ngx_int_t
ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf);
#if (NGX_HAVE_AIO_SENDFILE)
static ngx_int_t ngx_output_chain_aio_setup(ngx_output_chain_ctx_t *ctx,
ngx_file_t *file);
#endif
static ngx_int_t ngx_output_chain_add_copy(ngx_pool_t *pool,
ngx_chain_t **chain, ngx_chain_t *in);
static ngx_int_t ngx_output_chain_align_file_buf(ngx_output_chain_ctx_t *ctx,
Expand Down Expand Up @@ -260,10 +256,6 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
}
#endif

if (buf->in_file && buf->file->directio) {
return 0;
}

sendfile = ctx->sendfile;

#if (NGX_SENDFILE_LIMIT)
Expand All @@ -272,6 +264,19 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
sendfile = 0;
}

#endif

#if !(NGX_HAVE_SENDFILE_NODISKIO)

/*
* With DIRECTIO, disable sendfile() unless sendfile(SF_NOCACHE)
* is available.
*/

if (buf->in_file && buf->file->directio) {
sendfile = 0;
}

#endif

if (!sendfile) {
Expand All @@ -283,12 +288,6 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
buf->in_file = 0;
}

#if (NGX_HAVE_AIO_SENDFILE)
if (ctx->aio_preload && buf->in_file) {
(void) ngx_output_chain_aio_setup(ctx, buf->file);
}
#endif

if (ctx->need_in_memory && !ngx_buf_in_memory(buf)) {
return 0;
}
Expand All @@ -301,28 +300,6 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
}


#if (NGX_HAVE_AIO_SENDFILE)

static ngx_int_t
ngx_output_chain_aio_setup(ngx_output_chain_ctx_t *ctx, ngx_file_t *file)
{
ngx_event_aio_t *aio;

if (file->aio == NULL && ngx_file_aio_init(file, ctx->pool) != NGX_OK) {
return NGX_ERROR;
}

aio = file->aio;

aio->data = ctx->filter_ctx;
aio->preload_handler = ctx->aio_preload;

return NGX_OK;
}

#endif


static ngx_int_t
ngx_output_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain,
ngx_chain_t *in)
Expand Down Expand Up @@ -803,6 +780,10 @@ ngx_chain_writer(void *data, ngx_chain_t *in)
return NGX_ERROR;
}

if (chain && c->write->ready) {
ngx_post_event(c->write, &ngx_posted_next_events);
}

for (cl = ctx->out; cl && cl != chain; /* void */) {
ln = cl;
cl = cl->next;
Expand Down
212 changes: 202 additions & 10 deletions src/core/ngx_proxy_protocol.c
Expand Up @@ -13,7 +13,15 @@
#define NGX_PROXY_PROTOCOL_AF_INET6 2


#define ngx_proxy_protocol_parse_uint16(p) ((p)[0] << 8 | (p)[1])
#define ngx_proxy_protocol_parse_uint16(p) \
( ((uint16_t) (p)[0] << 8) \
+ ( (p)[1]) )

#define ngx_proxy_protocol_parse_uint32(p) \
( ((uint32_t) (p)[0] << 24) \
+ ( (p)[1] << 16) \
+ ( (p)[2] << 8) \
+ ( (p)[3]) )


typedef struct {
Expand All @@ -40,12 +48,52 @@ typedef struct {
} ngx_proxy_protocol_inet6_addrs_t;


typedef struct {
u_char type;
u_char len[2];
} ngx_proxy_protocol_tlv_t;


typedef struct {
u_char client;
u_char verify[4];
} ngx_proxy_protocol_tlv_ssl_t;


typedef struct {
ngx_str_t name;
ngx_uint_t type;
} ngx_proxy_protocol_tlv_entry_t;


static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p,
u_char *last, ngx_str_t *addr);
static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last,
in_port_t *port, u_char sep);
static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
u_char *last);
static ngx_int_t ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c,
ngx_str_t *tlvs, ngx_uint_t type, ngx_str_t *value);


static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_entries[] = {
{ ngx_string("alpn"), 0x01 },
{ ngx_string("authority"), 0x02 },
{ ngx_string("unique_id"), 0x05 },
{ ngx_string("ssl"), 0x20 },
{ ngx_string("netns"), 0x30 },
{ ngx_null_string, 0x00 }
};


static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_ssl_entries[] = {
{ ngx_string("version"), 0x21 },
{ ngx_string("cn"), 0x22 },
{ ngx_string("cipher"), 0x23 },
{ ngx_string("sig_alg"), 0x24 },
{ ngx_string("key_alg"), 0x25 },
{ ngx_null_string, 0x00 }
};


u_char *
Expand All @@ -61,7 +109,7 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
len = last - buf;

if (len >= sizeof(ngx_proxy_protocol_header_t)
&& memcmp(p, signature, sizeof(signature) - 1) == 0)
&& ngx_memcmp(p, signature, sizeof(signature) - 1) == 0)
{
return ngx_proxy_protocol_v2_read(c, buf, last);
}
Expand Down Expand Up @@ -139,8 +187,14 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)

invalid:

for (p = buf; p < last; p++) {
if (*p == CR || *p == LF) {
break;
}
}

ngx_log_error(NGX_LOG_ERR, c->log, 0,
"broken header: \"%*s\"", (size_t) (last - buf), buf);
"broken header: \"%*s\"", (size_t) (p - buf), buf);

return NULL;
}
Expand Down Expand Up @@ -227,7 +281,9 @@ ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
{
ngx_uint_t port, lport;

if (last - buf < NGX_PROXY_PROTOCOL_MAX_HEADER) {
if (last - buf < NGX_PROXY_PROTOCOL_V1_MAX_HEADER) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"too small buffer for PROXY protocol");
return NULL;
}

Expand Down Expand Up @@ -340,11 +396,11 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)

src_sockaddr.sockaddr_in.sin_family = AF_INET;
src_sockaddr.sockaddr_in.sin_port = 0;
memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
ngx_memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);

dst_sockaddr.sockaddr_in.sin_family = AF_INET;
dst_sockaddr.sockaddr_in.sin_port = 0;
memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);
ngx_memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);

pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port);
pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port);
Expand All @@ -367,11 +423,11 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)

src_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
src_sockaddr.sockaddr_in6.sin6_port = 0;
memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
ngx_memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);

dst_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
dst_sockaddr.sockaddr_in6.sin6_port = 0;
memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);
ngx_memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);

pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port);
Expand Down Expand Up @@ -412,11 +468,147 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
&pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);

if (buf < end) {
ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 %z bytes of tlv ignored", end - buf);
pp->tlvs.data = ngx_pnalloc(c->pool, end - buf);
if (pp->tlvs.data == NULL) {
return NULL;
}

ngx_memcpy(pp->tlvs.data, buf, end - buf);
pp->tlvs.len = end - buf;
}

c->proxy_protocol = pp;

return end;
}


ngx_int_t
ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name,
ngx_str_t *value)
{
u_char *p;
size_t n;
uint32_t verify;
ngx_str_t ssl, *tlvs;
ngx_int_t rc, type;
ngx_proxy_protocol_tlv_ssl_t *tlv_ssl;
ngx_proxy_protocol_tlv_entry_t *te;

if (c->proxy_protocol == NULL) {
return NGX_DECLINED;
}

ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 get tlv \"%V\"", name);

te = ngx_proxy_protocol_tlv_entries;
tlvs = &c->proxy_protocol->tlvs;

p = name->data;
n = name->len;

if (n >= 4 && p[0] == 's' && p[1] == 's' && p[2] == 'l' && p[3] == '_') {

rc = ngx_proxy_protocol_lookup_tlv(c, tlvs, 0x20, &ssl);
if (rc != NGX_OK) {
return rc;
}

if (ssl.len < sizeof(ngx_proxy_protocol_tlv_ssl_t)) {
return NGX_ERROR;
}

p += 4;
n -= 4;

if (n == 6 && ngx_strncmp(p, "verify", 6) == 0) {

tlv_ssl = (ngx_proxy_protocol_tlv_ssl_t *) ssl.data;
verify = ngx_proxy_protocol_parse_uint32(tlv_ssl->verify);

value->data = ngx_pnalloc(c->pool, NGX_INT32_LEN);
if (value->data == NULL) {
return NGX_ERROR;
}

value->len = ngx_sprintf(value->data, "%uD", verify)
- value->data;
return NGX_OK;
}

ssl.data += sizeof(ngx_proxy_protocol_tlv_ssl_t);
ssl.len -= sizeof(ngx_proxy_protocol_tlv_ssl_t);

te = ngx_proxy_protocol_tlv_ssl_entries;
tlvs = &ssl;
}

if (n >= 2 && p[0] == '0' && p[1] == 'x') {

type = ngx_hextoi(p + 2, n - 2);
if (type == NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"invalid PROXY protocol TLV \"%V\"", name);
return NGX_ERROR;
}

return ngx_proxy_protocol_lookup_tlv(c, tlvs, type, value);
}

for ( /* void */ ; te->type; te++) {
if (te->name.len == n && ngx_strncmp(te->name.data, p, n) == 0) {
return ngx_proxy_protocol_lookup_tlv(c, tlvs, te->type, value);
}
}

ngx_log_error(NGX_LOG_ERR, c->log, 0,
"unknown PROXY protocol TLV \"%V\"", name);

return NGX_DECLINED;
}


static ngx_int_t
ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c, ngx_str_t *tlvs,
ngx_uint_t type, ngx_str_t *value)
{
u_char *p;
size_t n, len;
ngx_proxy_protocol_tlv_t *tlv;

ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
"PROXY protocol v2 lookup tlv:%02xi", type);

p = tlvs->data;
n = tlvs->len;

while (n) {
if (n < sizeof(ngx_proxy_protocol_tlv_t)) {
ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV");
return NGX_ERROR;
}

tlv = (ngx_proxy_protocol_tlv_t *) p;
len = ngx_proxy_protocol_parse_uint16(tlv->len);

p += sizeof(ngx_proxy_protocol_tlv_t);
n -= sizeof(ngx_proxy_protocol_tlv_t);

if (n < len) {
ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV");
return NGX_ERROR;
}

if (tlv->type == type) {
value->data = p;
value->len = len;
return NGX_OK;
}

p += len;
n -= len;
}

return NGX_DECLINED;
}
6 changes: 5 additions & 1 deletion src/core/ngx_proxy_protocol.h
Expand Up @@ -13,21 +13,25 @@
#include <ngx_core.h>


#define NGX_PROXY_PROTOCOL_MAX_HEADER 107
#define NGX_PROXY_PROTOCOL_V1_MAX_HEADER 107
#define NGX_PROXY_PROTOCOL_MAX_HEADER 4096


struct ngx_proxy_protocol_s {
ngx_str_t src_addr;
ngx_str_t dst_addr;
in_port_t src_port;
in_port_t dst_port;
ngx_str_t tlvs;
};


u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,
u_char *last);
u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf,
u_char *last);
ngx_int_t ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name,
ngx_str_t *value);


#endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */
52 changes: 39 additions & 13 deletions src/core/ngx_queue.c
Expand Up @@ -9,6 +9,10 @@
#include <ngx_core.h>


static void ngx_queue_merge(ngx_queue_t *queue, ngx_queue_t *tail,
ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *));


/*
* find the middle queue element if the queue has odd number of elements
* or the first element of the queue's second part otherwise
Expand Down Expand Up @@ -45,36 +49,58 @@ ngx_queue_middle(ngx_queue_t *queue)
}


/* the stable insertion sort */
/* the stable merge sort */

void
ngx_queue_sort(ngx_queue_t *queue,
ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *))
{
ngx_queue_t *q, *prev, *next;
ngx_queue_t *q, tail;

q = ngx_queue_head(queue);

if (q == ngx_queue_last(queue)) {
return;
}

for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) {
q = ngx_queue_middle(queue);

ngx_queue_split(queue, q, &tail);

ngx_queue_sort(queue, cmp);
ngx_queue_sort(&tail, cmp);

ngx_queue_merge(queue, &tail, cmp);
}


prev = ngx_queue_prev(q);
next = ngx_queue_next(q);
static void
ngx_queue_merge(ngx_queue_t *queue, ngx_queue_t *tail,
ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *))
{
ngx_queue_t *q1, *q2;

ngx_queue_remove(q);
q1 = ngx_queue_head(queue);
q2 = ngx_queue_head(tail);

do {
if (cmp(prev, q) <= 0) {
break;
}
for ( ;; ) {
if (q1 == ngx_queue_sentinel(queue)) {
ngx_queue_add(queue, tail);
break;
}

prev = ngx_queue_prev(prev);
if (q2 == ngx_queue_sentinel(tail)) {
break;
}

if (cmp(q1, q2) <= 0) {
q1 = ngx_queue_next(q1);
continue;
}

} while (prev != ngx_queue_sentinel(queue));
ngx_queue_remove(q2);
ngx_queue_insert_before(q1, q2);

ngx_queue_insert_after(prev, q);
q2 = ngx_queue_head(tail);
}
}
3 changes: 3 additions & 0 deletions src/core/ngx_queue.h
Expand Up @@ -47,6 +47,9 @@ struct ngx_queue_s {
(h)->prev = x


#define ngx_queue_insert_before ngx_queue_insert_tail


#define ngx_queue_head(h) \
(h)->next

Expand Down
3 changes: 3 additions & 0 deletions src/core/ngx_rbtree.h
Expand Up @@ -47,6 +47,9 @@ struct ngx_rbtree_s {
(tree)->sentinel = s; \
(tree)->insert = i

#define ngx_rbtree_data(node, type, link) \
(type *) ((u_char *) (node) - offsetof(type, link))


void ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node);
void ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node);
Expand Down
475 changes: 422 additions & 53 deletions src/core/ngx_regex.c

Large diffs are not rendered by default.

34 changes: 26 additions & 8 deletions src/core/ngx_regex.h
Expand Up @@ -12,24 +12,38 @@
#include <ngx_config.h>
#include <ngx_core.h>

#include <pcre.h>

#if (NGX_PCRE2)

#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>

#define NGX_REGEX_NO_MATCHED PCRE2_ERROR_NOMATCH /* -1 */

#define NGX_REGEX_NO_MATCHED PCRE_ERROR_NOMATCH /* -1 */
typedef pcre2_code ngx_regex_t;

#define NGX_REGEX_CASELESS PCRE_CASELESS
#else

#include <pcre.h>

#define NGX_REGEX_NO_MATCHED PCRE_ERROR_NOMATCH /* -1 */

typedef struct {
pcre *code;
pcre_extra *extra;
} ngx_regex_t;

#endif


#define NGX_REGEX_CASELESS 0x00000001
#define NGX_REGEX_MULTILINE 0x00000002


typedef struct {
ngx_str_t pattern;
ngx_pool_t *pool;
ngx_int_t options;
ngx_uint_t options;

ngx_regex_t *regex;
int captures;
Expand All @@ -49,10 +63,14 @@ typedef struct {
void ngx_regex_init(void);
ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc);

#define ngx_regex_exec(re, s, captures, size) \
pcre_exec(re->code, re->extra, (const char *) (s)->data, (s)->len, 0, 0, \
captures, size)
#define ngx_regex_exec_n "pcre_exec()"
ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures,
ngx_uint_t size);

#if (NGX_PCRE2)
#define ngx_regex_exec_n "pcre2_match()"
#else
#define ngx_regex_exec_n "pcre_exec()"
#endif

ngx_int_t ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log);

Expand Down