diff --git a/CMakeLists.txt b/CMakeLists.txt index 579d0365..3f9f7614 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,9 @@ find_package(OpenSSL 1.0.1) find_package(Libev 4.11) find_package(Libcares 1.7.5) find_package(ZLIB 1.2.3) +find_package(Libngtcp2 0.0.0) +find_package(Libngtcp2_crypto_openssl 0.0.0) +find_package(Libnghttp3 0.0.0) if(OPENSSL_FOUND AND LIBEV_FOUND AND ZLIB_FOUND) set(ENABLE_APP_DEFAULT ON) else() @@ -182,9 +185,18 @@ if(HAVE_CUNIT) endif() # openssl (for src) +include(CheckSymbolExists) set(HAVE_OPENSSL ${OPENSSL_FOUND}) if(OPENSSL_FOUND) set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) + cmake_push_check_state() + set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}") + set(CMAKE_REQUIRED_LIBRARIES "${OPENSSL_LIBRARIES}") + check_symbol_exists(SSL_is_quic "openssl/ssl.h" HAVE_SSL_IS_QUIC) + if(NOT HAVE_SSL_IS_QUIC) + message(WARNING "OpenSSL in ${OPENSSL_LIBRARIES} dose not have SSL_is_quic. HTTP/3 support cannot be enabled") + endif() + cmake_pop_check_state() else() set(OPENSSL_INCLUDE_DIRS "") set(OPENSSL_LIBRARIES "") @@ -228,6 +240,12 @@ if(ENABLE_APP AND NOT (ZLIB_FOUND AND OPENSSL_FOUND AND LIBEV_FOUND)) message(FATAL_ERROR "Applications were requested (ENABLE_APP=1) but dependencies are not met.") endif() +# HTTP/3 requires quictls/openssl, libngtcp2, libngtcp2_crypto_openssl +# and libnghttp3. +if(ENABLE_HTTP3 AND NOT (HAVE_SSL_IS_QUIC AND LIBNGTCP2_FOUND AND LIBNGTCP2_CRYPTO_OPENSSL_FOUND AND LIBNGHTTP3_FOUND)) + message(FATAL_ERROR "HTTP/3 was requested (ENABLE_HTTP3=1) but dependencies are not met.") +endif() + # HPACK tools requires jansson if(ENABLE_HPACK_TOOLS AND NOT HAVE_JANSSON) message(FATAL_ERROR "HPACK tools were requested (ENABLE_HPACK_TOOLS=1) but dependencies are not met.") @@ -503,6 +521,9 @@ message(STATUS "summary of build options: Libxml2: ${HAVE_LIBXML2} (LIBS='${LIBXML2_LIBRARIES}') Libev: ${HAVE_LIBEV} (LIBS='${LIBEV_LIBRARIES}') Libc-ares: ${HAVE_LIBCARES} (LIBS='${LIBCARES_LIBRARIES}') + Libngtcp2: ${HAVE_LIBNGTCP2} (LIBS='${LIBNGTCP2_LIBRARIES}') + Libngtcp2_crypto_openssl: ${HAVE_LIBNGTCP2_CRYPTO_OPENSSL} (LIBS='${LIBNGTCP2_CRYPTO_OPENSSL_LIBRARIES}') + Libnghttp3: ${HAVE_LIBNGHTTP3} (LIBS='${LIBNGHTTP3_LIBRARIES}') Libevent(SSL): ${HAVE_LIBEVENT_OPENSSL} (LIBS='${LIBEVENT_OPENSSL_LIBRARIES}') Jansson: ${HAVE_JANSSON} (LIBS='${JANSSON_LIBRARIES}') Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}') @@ -521,6 +542,7 @@ message(STATUS "summary of build options: Examples: ${ENABLE_EXAMPLES} Python bindings:${ENABLE_PYTHON_BINDINGS} Threading: ${ENABLE_THREADS} + HTTP/3(EXPERIMENTAL): ${ENABLE_HTTP3} ") if(ENABLE_LIB_ONLY_DISABLED_OTHERS) message("Only the library will be built. To build other components " diff --git a/CMakeOptions.txt b/CMakeOptions.txt index a8332bf0..754428a2 100644 --- a/CMakeOptions.txt +++ b/CMakeOptions.txt @@ -17,6 +17,7 @@ option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENAB option(ENABLE_STATIC_LIB "Build libnghttp2 in static mode also") option(ENABLE_SHARED_LIB "Build libnghttp2 as a shared library" ON) option(ENABLE_STATIC_CRT "Build libnghttp2 against the MS LIBCMT[d]") +option(ENABLE_HTTP3 "Enable HTTP/3 support" OFF) option(WITH_LIBXML2 "Use libxml2" ${WITH_LIBXML2_DEFAULT}) diff --git a/cmake/FindLibnghttp3.cmake b/cmake/FindLibnghttp3.cmake new file mode 100644 index 00000000..ecd01f6c --- /dev/null +++ b/cmake/FindLibnghttp3.cmake @@ -0,0 +1,41 @@ +# - Try to find libnghttp3 +# Once done this will define +# LIBNGHTTP3_FOUND - System has libnghttp3 +# LIBNGHTTP3_INCLUDE_DIRS - The libnghttp3 include directories +# LIBNGHTTP3_LIBRARIES - The libraries needed to use libnghttp3 + +find_package(PkgConfig QUIET) +pkg_check_modules(PC_LIBNGHTTP3 QUIET libnghttp3) + +find_path(LIBNGHTTP3_INCLUDE_DIR + NAMES nghttp3/nghttp3.h + HINTS ${PC_LIBNGHTTP3_INCLUDE_DIRS} +) +find_library(LIBNGHTTP3_LIBRARY + NAMES nghttp3 + HINTS ${PC_LIBNGHTTP3_LIBRARY_DIRS} +) + +if(LIBNGHTTP3_INCLUDE_DIR) + set(_version_regex "^#define[ \t]+NGHTTP3_VERSION[ \t]+\"([^\"]+)\".*") + file(STRINGS "${LIBNGHTTP3_INCLUDE_DIR}/nghttp3/version.h" + LIBNGHTTP3_VERSION REGEX "${_version_regex}") + string(REGEX REPLACE "${_version_regex}" "\\1" + LIBNGHTTP3_VERSION "${LIBNGHTTP3_VERSION}") + unset(_version_regex) +endif() + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBNGHTTP3_FOUND +# to TRUE if all listed variables are TRUE and the requested version +# matches. +find_package_handle_standard_args(Libnghttp3 REQUIRED_VARS + LIBNGHTTP3_LIBRARY LIBNGHTTP3_INCLUDE_DIR + VERSION_VAR LIBNGHTTP3_VERSION) + +if(LIBNGHTTP3_FOUND) + set(LIBNGHTTP3_LIBRARIES ${LIBNGHTTP3_LIBRARY}) + set(LIBNGHTTP3_INCLUDE_DIRS ${LIBNGHTTP3_INCLUDE_DIR}) +endif() + +mark_as_advanced(LIBNGHTTP3_INCLUDE_DIR LIBNGHTTP3_LIBRARY) diff --git a/cmake/FindLibngtcp2.cmake b/cmake/FindLibngtcp2.cmake new file mode 100644 index 00000000..c6701149 --- /dev/null +++ b/cmake/FindLibngtcp2.cmake @@ -0,0 +1,41 @@ +# - Try to find libngtcp2 +# Once done this will define +# LIBNGTCP2_FOUND - System has libngtcp2 +# LIBNGTCP2_INCLUDE_DIRS - The libngtcp2 include directories +# LIBNGTCP2_LIBRARIES - The libraries needed to use libngtcp2 + +find_package(PkgConfig QUIET) +pkg_check_modules(PC_LIBNGTCP2 QUIET libngtcp2) + +find_path(LIBNGTCP2_INCLUDE_DIR + NAMES ngtcp2/ngtcp2.h + HINTS ${PC_LIBNGTCP2_INCLUDE_DIRS} +) +find_library(LIBNGTCP2_LIBRARY + NAMES ngtcp2 + HINTS ${PC_LIBNGTCP2_LIBRARY_DIRS} +) + +if(LIBNGTCP2_INCLUDE_DIR) + set(_version_regex "^#define[ \t]+NGTCP2_VERSION[ \t]+\"([^\"]+)\".*") + file(STRINGS "${LIBNGTCP2_INCLUDE_DIR}/ngtcp2/version.h" + LIBNGTCP2_VERSION REGEX "${_version_regex}") + string(REGEX REPLACE "${_version_regex}" "\\1" + LIBNGTCP2_VERSION "${LIBNGTCP2_VERSION}") + unset(_version_regex) +endif() + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBNGTCP2_FOUND +# to TRUE if all listed variables are TRUE and the requested version +# matches. +find_package_handle_standard_args(Libngtcp2 REQUIRED_VARS + LIBNGTCP2_LIBRARY LIBNGTCP2_INCLUDE_DIR + VERSION_VAR LIBNGTCP2_VERSION) + +if(LIBNGTCP2_FOUND) + set(LIBNGTCP2_LIBRARIES ${LIBNGTCP2_LIBRARY}) + set(LIBNGTCP2_INCLUDE_DIRS ${LIBNGTCP2_INCLUDE_DIR}) +endif() + +mark_as_advanced(LIBNGTCP2_INCLUDE_DIR LIBNGTCP2_LIBRARY) diff --git a/cmake/FindLibngtcp2_crypto_openssl.cmake b/cmake/FindLibngtcp2_crypto_openssl.cmake new file mode 100644 index 00000000..8df78595 --- /dev/null +++ b/cmake/FindLibngtcp2_crypto_openssl.cmake @@ -0,0 +1,43 @@ +# - Try to find libngtcp2_crypto_openssl +# Once done this will define +# LIBNGTCP2_CRYPTO_OPENSSL_FOUND - System has libngtcp2_crypto_openssl +# LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIRS - The libngtcp2_crypto_openssl include directories +# LIBNGTCP2_CRYPTO_OPENSSL_LIBRARIES - The libraries needed to use libngtcp2_crypto_openssl + +find_package(PkgConfig QUIET) +pkg_check_modules(PC_LIBNGTCP2_CRYPTO_OPENSSL QUIET libngtcp2_crypto_openssl) + +find_path(LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR + NAMES ngtcp2/ngtcp2_crypto_openssl.h + HINTS ${PC_LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIRS} +) +find_library(LIBNGTCP2_CRYPTO_OPENSSL_LIBRARY + NAMES ngtcp2_crypto_openssl + HINTS ${PC_LIBNGTCP2_CRYPTO_OPENSSL_LIBRARY_DIRS} +) + +if(LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR) + set(_version_regex "^#define[ \t]+NGTCP2_VERSION[ \t]+\"([^\"]+)\".*") + file(STRINGS "${LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR}/ngtcp2/version.h" + LIBNGTCP2_CRYPTO_OPENSSL_VERSION REGEX "${_version_regex}") + string(REGEX REPLACE "${_version_regex}" "\\1" + LIBNGTCP2_CRYPTO_OPENSSL_VERSION "${LIBNGTCP2_CRYPTO_OPENSSL_VERSION}") + unset(_version_regex) +endif() + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set +# LIBNGTCP2_CRYPTO_OPENSSL_FOUND to TRUE if all listed variables are +# TRUE and the requested version matches. +find_package_handle_standard_args(Libngtcp2_crypto_openssl REQUIRED_VARS + LIBNGTCP2_CRYPTO_OPENSSL_LIBRARY + LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR + VERSION_VAR LIBNGTCP2_CRYPTO_OPENSSL_VERSION) + +if(LIBNGTCP2_CRYPTO_OPENSSL_FOUND) + set(LIBNGTCP2_CRYPTO_OPENSSL_LIBRARIES ${LIBNGTCP2_CRYPTO_OPENSSL_LIBRARY}) + set(LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIRS ${LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR}) +endif() + +mark_as_advanced(LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR + LIBNGTCP2_CRYPTO_OPENSSL_LIBRARY) diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in index 6c96f70a..290b99e5 100644 --- a/cmakeconfig.h.in +++ b/cmakeconfig.h.in @@ -78,3 +78,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if HTTP/3 is enabled. */ +#cmakedefine ENABLE_HTTP3 1 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8ec64d0e..f65a2925 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,9 @@ include_directories( ${JEMALLOC_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS} ${LIBEV_INCLUDE_DIRS} + ${LIBNGHTTP3_INCLUDE_DIRS} + ${LIBNGTCP2_INCLUDE_DIRS} + ${LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS} ${LIBCARES_INCLUDE_DIRS} ${JANSSON_INCLUDE_DIRS} @@ -27,6 +30,9 @@ link_libraries( ${JEMALLOC_LIBRARIES} ${LIBXML2_LIBRARIES} ${LIBEV_LIBRARIES} + ${LIBNGHTTP3_LIBRARIES} + ${LIBNGTCP2_LIBRARIES} + ${LIBNGTCP2_CRYPTO_OPENSSL_LIBRARIES} ${OPENSSL_LIBRARIES} ${LIBCARES_LIBRARIES} ${JANSSON_LIBRARIES} @@ -67,7 +73,13 @@ if(ENABLE_APP) h2load_http2_session.cc h2load_http1_session.cc ) - + if(ENABLE_HTTP3) + list(APPEND H2LOAD_SOURCES + h2load_http3_session.cc + h2load_quic.cc + quic.cc + ) + endif() # Common libnhttpx sources (used for nghttpx and unit tests) set(NGHTTPX_SRCS @@ -120,6 +132,16 @@ if(ENABLE_APP) shrpx_mruby_module_response.cc ) endif() + if(ENABLE_HTTP3) + list(APPEND NGHTTPX_SRCS + shrpx_quic.cc + shrpx_quic_listener.cc + shrpx_quic_connection_handler.cc + shrpx_http3_upstream.cc + http3.cc + quic.cc + ) + endif() add_library(nghttpx_static STATIC ${NGHTTPX_SRCS}) set_target_properties(nghttpx_static PROPERTIES ARCHIVE_OUTPUT_NAME nghttpx)