git: cada18903ccc - main - www/nginx-devel: initial support for HTTPv3

From: Sergey A. Osokin <osa_at_FreeBSD.org>
Date: Wed, 05 Jan 2022 16:47:27 UTC
The branch main has been updated by osa:

URL: https://cgit.FreeBSD.org/ports/commit/?id=cada18903ccc63ec77dfb54bf36d8b050682ef69

commit cada18903ccc63ec77dfb54bf36d8b050682ef69
Author:     Sergey A. Osokin <osa@FreeBSD.org>
AuthorDate: 2022-01-05 16:45:15 +0000
Commit:     Sergey A. Osokin <osa@FreeBSD.org>
CommitDate: 2022-01-05 16:47:20 +0000

    www/nginx-devel: initial support for HTTPv3
    
    Bump PORTREVISION.
    
    Based on ideas from:    ashish
---
 www/nginx-devel/Makefile                 |    12 +-
 www/nginx-devel/Makefile.options.desc    |     1 +
 www/nginx-devel/files/extra-patch-httpv3 | 25543 +++++++++++++++++++++++++++++
 3 files changed, 25554 insertions(+), 2 deletions(-)

diff --git a/www/nginx-devel/Makefile b/www/nginx-devel/Makefile
index 9140dbf72c4f..226d737b15b1 100644
--- a/www/nginx-devel/Makefile
+++ b/www/nginx-devel/Makefile
@@ -2,7 +2,7 @@
 
 PORTNAME?=	nginx
 PORTVERSION=	1.21.5
-PORTREVISION=	3
+PORTREVISION=	4
 CATEGORIES=	www
 MASTER_SITES=	https://nginx.org/download/ \
 		LOCAL/osa
@@ -72,7 +72,7 @@ OPTIONS_GROUP_HTTPGRP=	GOOGLE_PERFTOOLS HTTP HTTP_ADDITION HTTP_AUTH_REQ \
 	HTTP_CACHE HTTP_DAV HTTP_DEGRADATION HTTP_FLV HTTP_GUNZIP_FILTER \
 	HTTP_GZIP_STATIC HTTP_IMAGE_FILTER HTTP_MP4 HTTP_PERL \
 	HTTP_RANDOM_INDEX HTTP_REALIP HTTP_SECURE_LINK HTTP_SLICE HTTP_SSL \
-	HTTP_STATUS HTTP_SUB HTTP_XSLT HTTPV2
+	HTTP_STATUS HTTP_SUB HTTP_XSLT HTTPV2 HTTPV3
 
 OPTIONS_GROUP_MAILGRP=	MAIL MAIL_IMAP MAIL_POP3 MAIL_SMTP MAIL_SSL
 
@@ -170,6 +170,14 @@ HTTP_XSLT_USE=			GNOME=libxml2,libxslt
 HTTP_XSLT_VARS=			DSO_BASEMODS+=http_xslt_module
 HTTPV2_IMPLIES=			HTTP_SSL
 HTTPV2_CONFIGURE_ON=		--with-http_v2_module
+HTTPV3_BUILD_DEPENDS=		${LOCALBASE}/bin/bssl:security/boringssl
+HTTPV3_RUN_DEPENDS=		${LOCALBASE}/bin/bssl:security/boringssl
+HTTPV3_CONFIGURE_ON=		--with-ld-opt="-L ${LOCALBASE}/lib -Wl,-rpath,${LOCALBASE}/lib" \
+				--with-http_ssl_module \
+				--build=nginx-quic \
+				--with-stream_quic_module \
+				--with-http_v3_module
+HTTPV3_EXTRA_PATCHES=		${PATCHDIR}/extra-patch-httpv3:-p1
 MAIL_VARS=			DSO_BASEMODS+=mail
 MAIL_IMAP_CONFIGURE_OFF=	--without-mail_imap_module
 MAIL_POP3_CONFIGURE_OFF=	--without-mail_pop3_module
diff --git a/www/nginx-devel/Makefile.options.desc b/www/nginx-devel/Makefile.options.desc
index 0424d95d8150..b39e871d0a9b 100644
--- a/www/nginx-devel/Makefile.options.desc
+++ b/www/nginx-devel/Makefile.options.desc
@@ -22,6 +22,7 @@ GSSAPI_DESC=			GSSAPI implementation (imply HTTP_AUTH_KRB5)
 HEADERS_MORE_DESC=		3rd party headers_more module
 HTTPGRP_DESC=			Modules that require HTTP module
 HTTPV2_DESC=			Enable HTTP/2 protocol support (SSL req.)
+HTTPV3_DESC=			Enable HTTP/3 protocol support (BoringSSL req.)
 HTTP_ACCEPT_LANGUAGE_DESC=	3rd party accept_language module
 HTTP_ADDITION_DESC=		Enable http_addition module
 HTTP_AUTH_DIGEST_DESC=		3rd party http_authdigest module
diff --git a/www/nginx-devel/files/extra-patch-httpv3 b/www/nginx-devel/files/extra-patch-httpv3
new file mode 100644
index 000000000000..dac679832645
--- /dev/null
+++ b/www/nginx-devel/files/extra-patch-httpv3
@@ -0,0 +1,25543 @@
+diff -r 67408b4a12c0 auto/lib/openssl/conf
+--- a/auto/lib/openssl/conf	Tue Dec 28 18:28:38 2021 +0300
++++ b/auto/lib/openssl/conf	Tue Jan 04 18:14:15 2022 -0500
+@@ -5,12 +5,16 @@
+ 
+ if [ $OPENSSL != NONE ]; then
+ 
++    have=NGX_OPENSSL . auto/have
++    have=NGX_SSL . auto/have
++
++    if [ $USE_OPENSSL_QUIC = YES ]; then
++        have=NGX_QUIC . auto/have
++    fi
++
+     case "$CC" in
+ 
+         cl | bcc32)
+-            have=NGX_OPENSSL . auto/have
+-            have=NGX_SSL . auto/have
+-
+             CFLAGS="$CFLAGS -DNO_SYS_TYPES_H"
+ 
+             CORE_INCS="$CORE_INCS $OPENSSL/openssl/include"
+@@ -33,9 +37,6 @@
+         ;;
+ 
+         *)
+-            have=NGX_OPENSSL . auto/have
+-            have=NGX_SSL . auto/have
+-
+             CORE_INCS="$CORE_INCS $OPENSSL/.openssl/include"
+             CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h"
+             CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a"
+@@ -139,4 +140,28 @@
+         exit 1
+     fi
+ 
++    if [ $USE_OPENSSL_QUIC = YES ]; then
++
++        ngx_feature="OpenSSL QUIC support"
++        ngx_feature_name="NGX_QUIC"
++        ngx_feature_run=no
++        ngx_feature_incs="#include <openssl/ssl.h>"
++        ngx_feature_path=
++        ngx_feature_libs="-lssl -lcrypto $NGX_LIBDL $NGX_LIBPTHREAD"
++        ngx_feature_test="SSL_set_quic_method(NULL, NULL)"
++        . auto/feature
++
++        if [ $ngx_found = no ]; then
++
++cat << END
++
++$0: error: certain modules require OpenSSL QUIC support.
++You can either do not enable the modules, or install the OpenSSL library with
++QUIC support into the system, or build the OpenSSL library with QUIC support
++statically from the source with nginx by using --with-openssl=<path> option.
++
++END
++            exit 1
++        fi
++    fi
+ fi
+diff -r 67408b4a12c0 auto/make
+--- a/auto/make	Tue Dec 28 18:28:38 2021 +0300
++++ b/auto/make	Tue Jan 04 18:14:15 2022 -0500
+@@ -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
+diff -r 67408b4a12c0 auto/modules
+--- a/auto/modules	Tue Dec 28 18:28:38 2021 +0300
++++ b/auto/modules	Tue Jan 04 18:14:15 2022 -0500
+@@ -102,7 +102,7 @@
+     fi
+ 
+ 
+-    if [ $HTTP_V2 = YES ]; then
++    if [ $HTTP_V2 = YES -o $HTTP_V3 = YES ]; then
+         HTTP_SRCS="$HTTP_SRCS $HTTP_HUFF_SRCS"
+     fi
+ 
+@@ -124,6 +124,7 @@
+     #     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
+@@ -156,6 +157,7 @@
+                       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 \
+@@ -217,6 +219,17 @@
+         . 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=
+@@ -426,6 +439,33 @@
+         . auto/module
+     fi
+ 
++    if [ $HTTP_V3 = YES ]; then
++        USE_OPENSSL_QUIC=YES
++        HTTP_SSL=YES
++
++        have=NGX_HTTP_V3 . auto/have
++        have=NGX_HTTP_HEADERS . 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=
+@@ -1035,6 +1075,20 @@
+ 
+     ngx_module_incs=
+ 
++    if [ $STREAM_QUIC = YES ]; then
++        USE_OPENSSL_QUIC=YES
++        have=NGX_STREAM_QUIC . auto/have
++        STREAM_SSL=YES
++
++        ngx_module_name=ngx_stream_quic_module
++        ngx_module_deps=src/stream/ngx_stream_quic_module.h
++        ngx_module_srcs=src/stream/ngx_stream_quic_module.c
++        ngx_module_libs=
++        ngx_module_link=$STREAM_QUIC
++
++        . auto/module
++    fi
++
+     if [ $STREAM_SSL = YES ]; then
+         USE_OPENSSL=YES
+         have=NGX_STREAM_SSL . auto/have
+@@ -1272,6 +1326,60 @@
+ 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"
++    ngx_module_srcs="src/event/quic/ngx_event_quic.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"
++
++    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
+diff -r 67408b4a12c0 auto/options
+--- a/auto/options	Tue Dec 28 18:28:38 2021 +0300
++++ b/auto/options	Tue Jan 04 18:14:15 2022 -0500
+@@ -45,6 +45,8 @@
+ 
+ NGX_FILE_AIO=NO
+ 
++QUIC_BPF=NO
++
+ HTTP=YES
+ 
+ NGX_HTTP_LOG_PATH=
+@@ -59,6 +61,7 @@
+ HTTP_GZIP=YES
+ HTTP_SSL=NO
+ HTTP_V2=NO
++HTTP_V3=NO
+ HTTP_SSI=YES
+ HTTP_REALIP=NO
+ HTTP_XSLT=NO
+@@ -116,6 +119,7 @@
+ 
+ STREAM=NO
+ STREAM_SSL=NO
++STREAM_QUIC=NO
+ STREAM_REALIP=NO
+ STREAM_LIMIT_CONN=YES
+ STREAM_ACCESS=YES
+@@ -149,6 +153,7 @@
+ PCRE2=YES
+ 
+ USE_OPENSSL=NO
++USE_OPENSSL_QUIC=NO
+ OPENSSL=NONE
+ 
+ USE_ZLIB=NO
+@@ -166,6 +171,8 @@
+ NGX_GOOGLE_PERFTOOLS=NO
+ NGX_CPP_TEST=NO
+ 
++SO_COOKIE_FOUND=NO
++
+ NGX_LIBATOMIC=NO
+ 
+ NGX_CPU_CACHE_LINE=
+@@ -211,6 +218,8 @@
+ 
+         --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"
+@@ -228,6 +237,7 @@
+ 
+         --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              ;;
+@@ -314,6 +324,7 @@
+         --with-stream)                   STREAM=YES                 ;;
+         --with-stream=dynamic)           STREAM=DYNAMIC             ;;
+         --with-stream_ssl_module)        STREAM_SSL=YES             ;;
++        --with-stream_quic_module)       STREAM_QUIC=YES            ;;
+         --with-stream_realip_module)     STREAM_REALIP=YES          ;;
+         --with-stream_geoip_module)      STREAM_GEOIP=YES           ;;
+         --with-stream_geoip_module=dynamic)
+@@ -443,8 +454,11 @@
+ 
+   --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
+@@ -533,6 +547,7 @@
+   --with-stream                      enable TCP/UDP proxy module
+   --with-stream=dynamic              enable dynamic TCP/UDP proxy module
+   --with-stream_ssl_module           enable ngx_stream_ssl_module
++  --with-stream_quic_module          enable ngx_stream_quic_module
+   --with-stream_realip_module        enable ngx_stream_realip_module
+   --with-stream_geoip_module         enable ngx_stream_geoip_module
+   --with-stream_geoip_module=dynamic enable dynamic ngx_stream_geoip_module
+diff -r 67408b4a12c0 auto/os/linux
+--- a/auto/os/linux	Tue Dec 28 18:28:38 2021 +0300
++++ b/auto/os/linux	Tue Jan 04 18:14:15 2022 -0500
+@@ -233,3 +233,63 @@
+ 
+ 
+ CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
++
++
++# 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>
++                  #include <stdint.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 <stdint.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
+diff -r 67408b4a12c0 auto/sources
+--- a/auto/sources	Tue Dec 28 18:28:38 2021 +0300
++++ b/auto/sources	Tue Jan 04 18:14:15 2022 -0500
+@@ -83,13 +83,14 @@
+ 
+ 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 \
+diff -r 67408b4a12c0 src/core/nginx.c
+--- a/src/core/nginx.c	Tue Dec 28 18:28:38 2021 +0300
++++ b/src/core/nginx.c	Tue Jan 04 18:14:15 2022 -0500
+@@ -680,6 +680,9 @@
+ 
+     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);
+     }
+ 
+diff -r 67408b4a12c0 src/core/ngx_bpf.c
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/src/core/ngx_bpf.c	Tue Jan 04 18:14:15 2022 -0500
+@@ -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));
++}
+diff -r 67408b4a12c0 src/core/ngx_bpf.h
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/src/core/ngx_bpf.h	Tue Jan 04 18:14:15 2022 -0500
+@@ -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_ */
+diff -r 67408b4a12c0 src/core/ngx_connection.c
+--- a/src/core/ngx_connection.c	Tue Dec 28 18:28:38 2021 +0300
++++ b/src/core/ngx_connection.c	Tue Jan 04 18:14:15 2022 -0500
+@@ -1037,6 +1037,12 @@
+     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) {
+diff -r 67408b4a12c0 src/core/ngx_connection.h
+--- a/src/core/ngx_connection.h	Tue Dec 28 18:28:38 2021 +0300
++++ b/src/core/ngx_connection.h	Tue Jan 04 18:14:15 2022 -0500
+@@ -73,6 +73,7 @@
+     unsigned            reuseport:1;
+     unsigned            add_reuseport:1;
+     unsigned            keepalive:2;
++    unsigned            quic:1;
+ 
+     unsigned            deferred_accept:1;
+     unsigned            delete_deferred:1;
+@@ -147,6 +148,10 @@
+ 
+     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
+diff -r 67408b4a12c0 src/core/ngx_core.h
+--- a/src/core/ngx_core.h	Tue Dec 28 18:28:38 2021 +0300
++++ b/src/core/ngx_core.h	Tue Jan 04 18:14:15 2022 -0500
+@@ -27,6 +27,7 @@
+ 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;
+ 
+@@ -82,6 +83,9 @@
+ #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>
+@@ -91,6 +95,9 @@
+ #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'
+diff -r 67408b4a12c0 src/event/ngx_event.c
+--- a/src/event/ngx_event.c	Tue Dec 28 18:28:38 2021 +0300
++++ b/src/event/ngx_event.c	Tue Jan 04 18:14:15 2022 -0500
+@@ -266,6 +266,18 @@
+ ngx_int_t
+ ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)
+ {
++#if (NGX_QUIC)
++
++    ngx_connection_t  *c;
++
++    c = rev->data;
++
++    if (c->quic) {
++        return ngx_quic_handle_read_event(rev, flags);
++    }
++
++#endif
++
+     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
+ 
+         /* kqueue, epoll */
+@@ -336,9 +348,15 @@
+ {
+     ngx_connection_t  *c;
+ 
++    c = wev->data;
++
++#if (NGX_QUIC)
++    if (c->quic) {
++        return ngx_quic_handle_write_event(wev, lowat);
++    }
++#endif
++
+     if (lowat) {
+-        c = wev->data;
+-
+         if (ngx_send_lowat(c, lowat) == NGX_ERROR) {
+             return NGX_ERROR;
+         }
+@@ -917,6 +935,12 @@
+ {
+     int  sndlowat;
+ 
++#if (NGX_QUIC)
++    if (c->quic) {
++        return NGX_OK;
++    }
++#endif
++
+ #if (NGX_HAVE_LOWAT_EVENT)
+ 
+     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
+diff -r 67408b4a12c0 src/event/ngx_event.h
+--- a/src/event/ngx_event.h	Tue Dec 28 18:28:38 2021 +0300
++++ b/src/event/ngx_event.h	Tue Jan 04 18:14:15 2022 -0500
+@@ -493,12 +493,6 @@
+ 
+ 
+ void ngx_event_accept(ngx_event_t *ev);
+-#if !(NGX_WIN32)
+-void ngx_event_recvmsg(ngx_event_t *ev);
+-void ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp,
+-    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
+-#endif
+-void ngx_delete_udp_connection(void *data);
+ ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle);
+ ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle);
+ u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len);
+@@ -528,6 +522,7 @@
+ 
+ #include <ngx_event_timer.h>
+ #include <ngx_event_posted.h>
++#include <ngx_event_udp.h>
+ 
+ #if (NGX_WIN32)
+ #include <ngx_iocp_module.h>
+diff -r 67408b4a12c0 src/event/ngx_event_openssl.c
+--- a/src/event/ngx_event_openssl.c	Tue Dec 28 18:28:38 2021 +0300
++++ b/src/event/ngx_event_openssl.c	Tue Jan 04 18:14:15 2022 -0500
+@@ -3146,6 +3146,13 @@
+     ngx_err_t   err;
+     ngx_uint_t  tries;
+ 
++#if (NGX_QUIC)
++    if (c->quic) {
++        /* QUIC streams inherit SSL object */
++        return NGX_OK;
++    }
++#endif
++
+     rc = NGX_OK;
+ 
+     ngx_ssl_ocsp_cleanup(c);
+diff -r 67408b4a12c0 src/event/ngx_event_openssl.h
+--- a/src/event/ngx_event_openssl.h	Tue Dec 28 18:28:38 2021 +0300
++++ b/src/event/ngx_event_openssl.h	Tue Jan 04 18:14:15 2022 -0500
+@@ -24,6 +24,14 @@
+ #include <openssl/engine.h>
+ #endif
+ #include <openssl/evp.h>
++#if (NGX_QUIC)
++#ifdef OPENSSL_IS_BORINGSSL
++#include <openssl/hkdf.h>
++#include <openssl/chacha.h>
++#else
++#include <openssl/kdf.h>
++#endif
++#endif
+ #include <openssl/hmac.h>
+ #ifndef OPENSSL_NO_OCSP
+ #include <openssl/ocsp.h>
+diff -r 67408b4a12c0 src/event/ngx_event_udp.c
+--- a/src/event/ngx_event_udp.c	Tue Dec 28 18:28:38 2021 +0300
++++ b/src/event/ngx_event_udp.c	Tue Jan 04 18:14:15 2022 -0500
+@@ -12,52 +12,37 @@
+ 
+ #if !(NGX_WIN32)
+ 
+-struct ngx_udp_connection_s {
+-    ngx_rbtree_node_t   node;
+-    ngx_connection_t   *connection;
+-    ngx_buf_t          *buffer;
+-};
+-
+-
+ static void ngx_close_accepted_udp_connection(ngx_connection_t *c);
+ static ssize_t ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf,
+     size_t size);
+-static ngx_int_t ngx_insert_udp_connection(ngx_connection_t *c);
++static ngx_int_t ngx_create_udp_connection(ngx_connection_t *c);
+ static ngx_connection_t *ngx_lookup_udp_connection(ngx_listening_t *ls,
+-    struct sockaddr *sockaddr, socklen_t socklen,
+-    struct sockaddr *local_sockaddr, socklen_t local_socklen);
++    ngx_str_t *key, struct sockaddr *local_sockaddr, socklen_t local_socklen);
+ 
+ 
+ void
+ ngx_event_recvmsg(ngx_event_t *ev)
+ {
++    size_t             len;
+     ssize_t            n;
++    ngx_str_t          key;
+     ngx_buf_t          buf;
+     ngx_log_t         *log;
+     ngx_err_t          err;
+-    socklen_t          socklen, local_socklen;
++    socklen_t          local_socklen;
+     ngx_event_t       *rev, *wev;
+     struct iovec       iov[1];
+     struct msghdr      msg;
+     ngx_sockaddr_t     sa, lsa;
+-    struct sockaddr   *sockaddr, *local_sockaddr;
++    ngx_udp_dgram_t    dgram;
++    struct sockaddr   *local_sockaddr;
+     ngx_listening_t   *ls;
+     ngx_event_conf_t  *ecf;
+     ngx_connection_t  *c, *lc;
+     static u_char      buffer[65535];
+ 
+-#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
+-
+-#if (NGX_HAVE_IP_RECVDSTADDR)
+-    u_char             msg_control[CMSG_SPACE(sizeof(struct in_addr))];
+-#elif (NGX_HAVE_IP_PKTINFO)
+-    u_char             msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))];
+-#endif
+-
+-#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
+-    u_char             msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+-#endif
+-
++#if (NGX_HAVE_ADDRINFO_CMSG)
++    u_char             msg_control[CMSG_SPACE(sizeof(ngx_addrinfo_t))];
+ #endif
+ 
+     if (ev->timedout) {
+@@ -92,25 +77,13 @@
+         msg.msg_iov = iov;
+         msg.msg_iovlen = 1;
+ 
+-#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
+-
++#if (NGX_HAVE_ADDRINFO_CMSG)
+         if (ls->wildcard) {
++            msg.msg_control = &msg_control;
++            msg.msg_controllen = sizeof(msg_control);
+ 
+-#if (NGX_HAVE_IP_RECVDSTADDR || NGX_HAVE_IP_PKTINFO)
+-            if (ls->sockaddr->sa_family == AF_INET) {
+-                msg.msg_control = &msg_control;
+-                msg.msg_controllen = sizeof(msg_control);
+-            }
+-#endif
+-
+-#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
+-            if (ls->sockaddr->sa_family == AF_INET6) {
+-                msg.msg_control = &msg_control6;
+-                msg.msg_controllen = sizeof(msg_control6);
+-            }
+-#endif
+-        }
+-
++            ngx_memzero(&msg_control, sizeof(msg_control));
++       }
+ #endif
+ 
+         n = recvmsg(lc->fd, &msg, 0);
+@@ -129,7 +102,7 @@
+             return;
+         }
+ 
+-#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
++#if (NGX_HAVE_ADDRINFO_CMSG)
+         if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
+             ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
+                           "recvmsg() truncated data");
+@@ -137,21 +110,21 @@
*** 24632 LINES SKIPPED ***