Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ SET(NGHTTP2_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE STRING "Direct
SET(NGHTTP2_LIBRARIES ${default_nghttp2_libraries} CACHE STRING "NGHTTP2 libraries to link with")
SET(NGHTTP3_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE STRING "Directory with NGHTTP3 include files within nghttp3 subdirectory")
SET(NGHTTP3_LIBRARIES ${default_nghttp3_libraries} CACHE STRING "NGHTTP3 libraries to link with")
SET(NGTCP2_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE STRING "Directory with NGTCP2 include files within ngtcp2 subdirectory")
SET(NGTCP2_LIBRARIES "${CMAKE_INSTALL_PREFIX}/lib/ngtcp2.lib" "${CMAKE_INSTALL_PREFIX}/lib/ngtcp2_crypto_ossl.lib" CACHE STRING "NGTCP2 libraries to link with")
SET(PCRE_CFLAGS "${default_pcre_cflags}" CACHE STRING "PCRE flags for util_pcre.c compilation")
SET(PCRE_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE STRING "Directory with PCRE include files")
SET(PCRE_LIBRARIES ${default_pcre_libraries} CACHE STRING "PCRE libraries to link with")
Expand Down Expand Up @@ -244,6 +246,18 @@ ELSE()
SET(NGHTTP3_FOUND FALSE)
ENDIF()

# See if ngtcp2 exists in a configured or defaulted location
SET(NGTCP2_FOUND TRUE)
IF(EXISTS "${NGTCP2_INCLUDE_DIR}/ngtcp2/ngtcp2_crypto_ossl.h")
FOREACH(onelib ${NGTCP2_LIBRARIES})
IF(NOT EXISTS ${onelib})
SET(NGTCP2_FOUND FALSE)
ENDIF()
ENDFOREACH()
ELSE()
SET(NGTCP2_FOUND FALSE)
ENDIF()

# See if we have Brotli
SET(BROTLI_FOUND TRUE)
IF(EXISTS "${BROTLI_INCLUDE_DIR}/brotli/encode.h")
Expand Down Expand Up @@ -288,6 +302,7 @@ MESSAGE(STATUS "LIBXML2_FOUND ............ : ${LIBXML2_FOUND}")
MESSAGE(STATUS "LUA51_FOUND .............. : ${LUA51_FOUND}")
MESSAGE(STATUS "NGHTTP2_FOUND ............ : ${NGHTTP2_FOUND}")
MESSAGE(STATUS "NGHTTP3_FOUND ............ : ${NGHTTP3_FOUND}")
MESSAGE(STATUS "NGTCP2_FOUND ............. : ${NGTCP2_FOUND}")
MESSAGE(STATUS "OPENSSL_FOUND ............ : ${OPENSSL_FOUND}")
MESSAGE(STATUS "ZLIB_FOUND ............... : ${ZLIB_FOUND}")
MESSAGE(STATUS "BROTLI_FOUND ............. : ${BROTLI_FOUND}")
Expand Down Expand Up @@ -575,9 +590,9 @@ SET(mod_http2_extra_sources
modules/http2/h2_util.c modules/http2/h2_workers.c
modules/http2/h2_ws.c
)
SET(mod_http3_requires NGHTTP3_FOUND)
SET(mod_http3_extra_includes ${NGHTTP3_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/modules/http3/include ${OPENSSL_INCLUDE_DIR})
SET(mod_http3_extra_libs ${NGHTTP3_LIBRARIES} ${OPENSSL_LIBRARIES})
SET(mod_http3_requires NGHTTP3_FOUND NGTCP2_FOUND)
SET(mod_http3_extra_includes ${NGHTTP3_INCLUDE_DIR} ${NGTCP2_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/modules/http3/include ${OPENSSL_INCLUDE_DIR})
SET(mod_http3_extra_libs ${NGHTTP3_LIBRARIES} ${NGTCP2_LIBRARIES} ${OPENSSL_LIBRARIES})
SET(mod_http3_main_source modules/http3/mod_http3.c)
SET(mod_http3_extra_sources
modules/http3/h3_callbacks.c modules/http3/h3_config.c
Expand All @@ -588,7 +603,6 @@ SET(mod_http3_extra_sources
modules/http3/h3_stream.c modules/http3/h3_threads.c
modules/http3/quic/h3q.c modules/http3/quic/h3q_conn.c
modules/http3/quic/h3q_stream.c
modules/http3/quic/detail/h3q_addr.c
modules/http3/quic/detail/h3q_tls.c
)
SET(mod_ldap_extra_defines LDAP_DECLARE_EXPORT)
Expand Down
4 changes: 4 additions & 0 deletions changes-entries/h3_blocked_stream_spin.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*) mod_http3: Fixed an event-thread spin while a client holds its
flow-control window shut: a blocked stream is now blocked again each time
nghttp3 offers it.
[Alexander Gerasimov <codeguard gmail.com>]
4 changes: 4 additions & 0 deletions changes-entries/h3_drain_pending_handshakes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*) mod_http3: Fixed a graceful restart that never ended: a handshake still
pending when the child started to drain did not finish or time out, so
the old child kept its connection count and the port.
[Alexander Gerasimov <codeguard gmail.com>]
5 changes: 5 additions & 0 deletions changes-entries/h3_flow_window_autotune.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*) mod_http3: Added H3MaxWindow (default 6 MiB). Flow-control windows for
client uploads now grow when a client fills them within a few round
trips, up to this cap, so uploads on long, fast paths are no longer held
to a fixed 1 MiB window.
[Alexander Gerasimov <codeguard gmail.com>]
11 changes: 11 additions & 0 deletions changes-entries/h3_memory_cid_map.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*) mod_http3: Less memory per connection. The QUIC connection keeps its
connection IDs in 16 slots of its own, not in an APR pool (8 KB at
least), and makes the CONNECTION_CLOSE buffer only when it closes. The
session and stream allocators keep at most MaxMemFree, as in mod_http2,
so an idle connection gives back its peak memory.
[Alexander Gerasimov <codeguard gmail.com>]

*) mod_http3: A client can no longer put an Initial DCID that is a CID of
another connection into the CID map. Before, the map could keep a key
that pointed into the pool of a freed connection.
[Alexander Gerasimov <codeguard gmail.com>]
24 changes: 24 additions & 0 deletions changes-entries/h3_mod_ssl_certificate.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
*) mod_http3: Load the HTTP/3 certificate and key in post_config, while
httpd still runs privileged, so a root-only key no longer fails in the
unprivileged child and both mod_ssl and mod_http3 read the same files.
[Alexander Gerasimov <codeguard gmail.com>]

*) mod_http3: A host with "h3" in Protocols now serves HTTP/3 with the
certificate mod_ssl resolved for it (SSLCertificateFile and mod_md
alike), the way mod_http2 rides mod_ssl. H3CertificatePath and
H3CertificateKeyPath are removed; drop them from existing configurations.
[Alexander Gerasimov <codeguard gmail.com>]

*) mod_http3: Select the HTTP/3 certificate by SNI, so each virtual host on
a shared port serves its own certificate instead of the first host's.
Names are matched as httpd matches virtual hosts, wildcard ServerAlias
included. A name that matches no host gets the certificate of the first
virtual host defined, as with mod_ssl.
[Alexander Gerasimov <codeguard gmail.com>]

*) mod_http3: Give every virtual host its own mod_http3 configuration
(AP_MODULE_FLAG_ALWAYS_MERGE). A host without H3 directives used to share
the main server's, so per-host settings such as H3AltSvc and
H3AltSvcMaxAge were silently ignored and hosts could not carry their own
certificate.
[Alexander Gerasimov <codeguard gmail.com>]
14 changes: 14 additions & 0 deletions changes-entries/h3_ngtcp2_early_data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
*) mod_http3: Added H3EarlyData (default off). A resumed client may send its
first request as 0-RTT data and gets the response one round trip sooner.
Only safe methods run before the handshake completes; other methods wait
for it, because 0-RTT data can be replayed (RFC 8470).
[Alexander Gerasimov <codeguard gmail.com>]

*) mod_http3: Moved the QUIC transport from the OpenSSL QUIC server to
ngtcp2, with OpenSSL as the TLS backend through its QUIC TLS API. OpenSSL
still drops server-side 0-RTT packets. ngtcp2 >= 1.22.1 is a new build
dependency (--with-ngtcp2). Stream data is no longer copied: nghttp3
releases a buffer when the peer acknowledges it. H3IdleTimeout now always
closes with NO_ERROR; the QUIC idle timer runs 2 seconds longer and
closes silently.
[Alexander Gerasimov <codeguard gmail.com>]
5 changes: 5 additions & 0 deletions changes-entries/h3_parent_socket.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*) mod_http3: On Linux the parent binds the QUIC socket while it still runs
as root, so H3Port 443 works without CAP_NET_BIND_SERVICE. The socket
stays bound across graceful restarts and the children inherit it; one
child at a time serves it.
[Alexander Gerasimov <codeguard gmail.com>]
21 changes: 21 additions & 0 deletions changes-entries/h3_pktinfo_ecn_token_key.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
*) mod_http3: Linux: on a [::] socket, a reply now goes out from the address
the client sent to (IP_PKTINFO, IPV6_PKTINFO). Before, the kernel picked
the source, and on a host with more than one address a client could get
the reply from another address and drop it.
[Alexander Gerasimov <codeguard gmail.com>]

*) mod_http3: Linux: ECN. The module reads the ECN mark of each packet and
gives it to ngtcp2, which reports it back to the client in ACK_ECN
frames, and it puts the mark that ngtcp2 asks for on each packet it
sends.
[Alexander Gerasimov <codeguard gmail.com>]

*) mod_http3: With ListenCoresBucketsRatio and more than one QUIC socket,
the server sends disable_active_migration, so clients do not move a
connection to a new address that another child can get.
[Alexander Gerasimov <codeguard gmail.com>]

*) mod_http3: The parent makes the key for Retry and stateless reset tokens
and keeps it across graceful restarts. A Retry token from a child is now
good in every other child and in the next generation.
[Alexander Gerasimov <codeguard gmail.com>]
6 changes: 6 additions & 0 deletions changes-entries/h3_reuseport_buckets.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*) mod_http3: On Linux, with ListenCoresBucketsRatio, the parent binds one
SO_REUSEPORT QUIC socket per listener bucket and one child serves each,
so more than one child serves HTTP/3. The sockets stay bound when
children start and stop, so the kernel keeps each peer on the same
socket.
[Alexander Gerasimov <codeguard gmail.com>]
3 changes: 3 additions & 0 deletions changes-entries/h3_session_allocator_race.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*) mod_http3: Fixed a heap race that crashed the child: worker threads and
the event thread allocated from one session allocator that had no mutex.
[Alexander Gerasimov <codeguard gmail.com>]
5 changes: 5 additions & 0 deletions changes-entries/h3_udp_gso_gro.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*) mod_http3: Linux: QUIC packets to one peer now go out in one sendmsg with
UDP_SEGMENT (GSO), and reads use UDP_GRO. Without kernel support the
module sends one packet at a time. A stream read now sends the new
flow-control window at once, so a blocked client does not wait.
[Alexander Gerasimov <codeguard gmail.com>]
56 changes: 51 additions & 5 deletions modules/http3/config2.m4
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ h3_threads.lo dnl
h3q.lo dnl
h3q_conn.lo dnl
h3q_stream.lo dnl
h3q_addr.lo dnl
h3q_tls.lo dnl
"

Expand Down Expand Up @@ -158,11 +157,57 @@ AC_DEFUN([APACHE_CHECK_NGHTTP3],[
])


dnl
dnl APACHE_CHECK_NGTCP2
dnl
dnl Configure for ngtcp2 and its OpenSSL crypto helper, giving preference
dnl to "--with-ngtcp2=<path>" if it was specified.
dnl
AC_DEFUN([APACHE_CHECK_NGTCP2],[
AC_CACHE_CHECK([for ngtcp2], [ac_cv_ngtcp2], [
ac_cv_ngtcp2=no
ap_ngtcp2_base=""
AC_ARG_WITH(ngtcp2, APACHE_HELP_STRING(--with-ngtcp2=PATH, ngtcp2 installation directory), [
if test "x$withval" != "xyes" -a "x$withval" != "x"; then
ap_ngtcp2_base="`cd $withval ; pwd`"
fi
])

saved_CPPFLAGS="$CPPFLAGS"
saved_PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
if test "x$ap_ngtcp2_base" != "x"; then
PKG_CONFIG_PATH="${ap_ngtcp2_base}/lib/pkgconfig:${ap_ngtcp2_base}/lib64/pkgconfig${PKG_CONFIG_PATH+:}${PKG_CONFIG_PATH}"
export PKG_CONFIG_PATH
fi
if test -n "$PKGCONFIG" && $PKGCONFIG --exists libngtcp2 libngtcp2_crypto_ossl; then
ap_ngtcp2_cflags="`$PKGCONFIG --cflags libngtcp2 libngtcp2_crypto_ossl`"
ap_ngtcp2_libs="`$PKGCONFIG --libs libngtcp2 libngtcp2_crypto_ossl`"
elif test "x$ap_ngtcp2_base" != "x"; then
ap_ngtcp2_cflags="-I$ap_ngtcp2_base/include"
ap_ngtcp2_libs="-L$ap_ngtcp2_base/lib -lngtcp2_crypto_ossl -lngtcp2"
else
ap_ngtcp2_cflags=""
ap_ngtcp2_libs="-lngtcp2_crypto_ossl -lngtcp2"
fi
PKG_CONFIG_PATH="$saved_PKG_CONFIG_PATH"

CPPFLAGS="$CPPFLAGS $ap_ngtcp2_cflags"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <ngtcp2/ngtcp2.h>]],[[
#if NGTCP2_VERSION_NUM < 0x011601
#error "ngtcp2 1.22.1 or later is required"
#endif]])],
[ac_cv_ngtcp2=yes
APR_ADDTO(MOD_CFLAGS, [$ap_ngtcp2_cflags])
APR_ADDTO(MOD_LDFLAGS, [$ap_ngtcp2_libs])])
CPPFLAGS="$saved_CPPFLAGS"
])
])

dnl # hook module into the Autoconf mechanism (--enable-http3)
APACHE_MODULE(http3, [HTTP/3 protocol handling in addition to HTTP protocol
handling. Implemented by mod_http3. This module requires a libnghttp3
installation and OpenSSL with QUIC support.
See --with-nghttp3 on how to manage non-standard locations. This module
handling. Implemented by mod_http3. This module requires libnghttp3,
libngtcp2 with its OpenSSL crypto helper, and OpenSSL with the QUIC TLS API.
See --with-nghttp3 and --with-ngtcp2 on how to manage non-standard locations. This module
is usually linked shared and requires loading. ], $http3_objs, , no, [
APACHE_CHECK_OPENSSL
if test "$ac_cv_openssl" = "yes" ; then
Expand All @@ -173,7 +218,8 @@ is usually linked shared and requires loading. ], $http3_objs, , no, [

if test "$enable_http3" != "no" ; then
APACHE_CHECK_NGHTTP3
if test "$ac_cv_nghttp3" = "yes" ; then
APACHE_CHECK_NGTCP2
if test "$ac_cv_nghttp3" = "yes" -a "$ac_cv_ngtcp2" = "yes" ; then
APR_ADDTO(MOD_CFLAGS, [-I\$(top_srcdir)/$modpath_current/include])
if test "x$enable_http3" = "xshared"; then
# The only symbol which needs to be exported is the module
Expand Down
Loading