Unverified Commit 9aa847f8 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

HTTP3: initial support

USe configure --with-ngtcp2 or --with-quiche

Using either option will enable a HTTP3 build.
Co-authored-by: Alessandro Ghedini
parent f0b7b106
Loading
Loading
Loading
Loading
+159 −0
Original line number Diff line number Diff line
@@ -3341,6 +3341,160 @@ if test X"$want_h2" != Xno; then

fi

dnl **********************************************************************
dnl Check for ngtcp2 (QUIC)
dnl **********************************************************************

OPT_TCP2="yes"
curl_h3_msg="disabled (--with-ngtcp2, --with-quiche)"

if test "x$disable_http" = "xyes"; then
  # without HTTP, ngtcp2 is no use
  OPT_TCP2="no"
fi

AC_ARG_WITH(ngtcp2,
AC_HELP_STRING([--with-ngtcp2=PATH],[Enable ngtcp2 usage])
AC_HELP_STRING([--without-ngtcp2],[Disable ngtcp2 usage]),
  [OPT_TCP2=$withval])
case "$OPT_TCP2" in
  no)
    dnl --without-ngtcp2 option used
    want_tcp2="no"
    ;;
  yes)
    dnl --with-ngtcp2 option used without path
    want_tcp2="default"
    want_tcp2_path=""
    ;;
  *)
    dnl --with-ngtcp2 option used with path
    want_tcp2="yes"
    want_tcp2_path="$withval/lib/pkgconfig"
    ;;
esac

curl_tcp2_msg="disabled (--with-ngtcp2)"
if test X"$want_tcp2" != Xno; then
  dnl backup the pre-ngtcp2 variables
  CLEANLDFLAGS="$LDFLAGS"
  CLEANCPPFLAGS="$CPPFLAGS"
  CLEANLIBS="$LIBS"

  CURL_CHECK_PKGCONFIG(libngtcp2, $want_tcp2_path)

  if test "$PKGCONFIG" != "no" ; then
    LIB_TCP2=`CURL_EXPORT_PCDIR([$want_tcp2_path])
      $PKGCONFIG --libs-only-l libngtcp2`
    AC_MSG_NOTICE([-l is $LIB_TCP2])

    CPP_TCP2=`CURL_EXPORT_PCDIR([$want_tcp2_path]) dnl
      $PKGCONFIG --cflags-only-I libngtcp2`
    AC_MSG_NOTICE([-I is $CPP_TCP2])

    LD_TCP2=`CURL_EXPORT_PCDIR([$want_tcp2_path])
      $PKGCONFIG --libs-only-L libngtcp2`
    AC_MSG_NOTICE([-L is $LD_TCP2])

    LDFLAGS="$LDFLAGS $LD_TCP2"
    CPPFLAGS="$CPPFLAGS $CPP_TCP2"
    LIBS="$LIB_TCP2 $LIBS"

    if test "x$cross_compiling" != "xyes"; then
      DIR_TCP2=`echo $LD_TCP2 | $SED -e 's/-L//'`
    fi
    AC_CHECK_LIB(ngtcp2, ngtcp2_conn_client_new,
      [
       AC_CHECK_HEADERS(ngtcp2/ngtcp2.h,
          curl_h3_msg="enabled (ngtcp2)"
          NGTCP2_ENABLED=1
          AC_DEFINE(USE_NGTCP2, 1, [if ngtcp2 is in use])
          AC_SUBST(USE_NGTCP2, [1])
          CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_TCP2"
          export CURL_LIBRARY_PATH
          AC_MSG_NOTICE([Added $DIR_TCP2 to CURL_LIBRARY_PATH])
       )
      ],
        dnl not found, revert back to clean variables
        LDFLAGS=$CLEANLDFLAGS
        CPPFLAGS=$CLEANCPPFLAGS
        LIBS=$CLEANLIBS
    )

  else
    dnl no ngtcp2 pkg-config found, deal with it
    if test X"$want_tcp2" != Xdefault; then
      dnl To avoid link errors, we do not allow --with-ngtcp2 without
      dnl a pkgconfig file
      AC_MSG_ERROR([--with-ngtcp2 was specified but could not find ngtcp2 pkg-config file.])
    fi
  fi

fi

dnl **********************************************************************
dnl Check for quiche (QUIC)
dnl **********************************************************************

OPT_QUICHE="yes"

if test "x$disable_http" = "xyes" -o "x$USE_NGTCP" = "x1"; then
  # without HTTP or with ngtcp2, quiche is no use
  OPT_QUICHE="no"
fi

AC_ARG_WITH(quiche,
AC_HELP_STRING([--with-quiche=PATH],[Enable quiche usage])
AC_HELP_STRING([--without-quiche],[Disable quiche usage]),
  [OPT_QUICHE=$withval])
case "$OPT_QUICHE" in
  *)
    dnl --with-quiche option used without path
    want_quiche="default"
    want_quiche_path=""
    ;;
  no)
    dnl --without-quiche option used
    want_quiche="no"
    ;;
esac

if test X"$want_quiche" != Xno; then
  dnl backup the pre-quiche variables
  CLEANLDFLAGS="$LDFLAGS"
  CLEANCPPFLAGS="$CPPFLAGS"
  CLEANLIBS="$LIBS"

  LIB_QUICHE="-lquiche -ldl -lpthread"
  CPP_QUICHE="-I$OPT_QUICHE/include"
  LD_QUICHE="-L$OPT_QUICHE/target/debug"

  LDFLAGS="$LDFLAGS $LD_QUICHE"
  CPPFLAGS="$CPPFLAGS $CPP_QUICHE"
  LIBS="$LIB_QUICHE $LIBS"

  if test "x$cross_compiling" != "xyes"; then
    DIR_QUICHE=`echo $LD_QUICHE | $SED -e 's/-L//'`
  fi
  AC_CHECK_LIB(quiche, quiche_connect,
    [
     AC_CHECK_HEADERS(quiche.h,
        curl_h3_msg="enabled (quiche)"
        QUICHE_ENABLED=1
        AC_DEFINE(USE_QUICHE, 1, [if quiche is in use])
        AC_SUBST(USE_QUICHE, [1])
        CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_QUICHE"
        export CURL_LIBRARY_PATH
        AC_MSG_NOTICE([Added $DIR_QUICHE to CURL_LIBRARY_PATH]),
     )
    ],
      dnl not found, revert back to clean variables
      LDFLAGS=$CLEANLDFLAGS
      CPPFLAGS=$CLEANCPPFLAGS
      LIBS=$CLEANLIBS
  )
fi

dnl **********************************************************************
dnl Check for zsh completion path
dnl **********************************************************************
@@ -4159,6 +4313,10 @@ if test "x$USE_NGHTTP2" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
fi

if test "x$USE_NGTCP2" = "x1" -o "x$USE_QUICHE" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP3"
fi

if test "x$CURL_WITH_MULTI_SSL" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES MultiSSL"
fi
@@ -4350,6 +4508,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
  PSL:              ${curl_psl_msg}
  Alt-svc:          ${curl_altsvc_msg}
  HTTP2:            ${curl_h2_msg}
  HTTP3:            ${curl_h3_msg}
  Protocols:        ${SUPPORT_PROTOCOLS}
  Features:         ${SUPPORT_FEATURES}
])

docs/HTTP3.md

0 → 100644
+85 −0
Original line number Diff line number Diff line
# HTTP3 (and QUIC)

## Resources

[HTTP/3 Explained](https://daniel.haxx.se/http3-explained/) - the online free
book describing the protocols involved.

[QUIC implementation](https://github.com/curl/curl/wiki/QUIC-implementation) -
the wiki page describing the plan for how to support QUIC and HTTP/3 in curl
and libcurl.

[quicwg.org](https://quicwg.org/) - home of the official protocol drafts

## QUIC libraries

QUIC libraries we're experiementing with:

[ngtcp2](https://github.com/ngtcp2/ngtcp2)

[quiche](https://github.com/ghedo/quiche)

## Experimental!

HTTP/3 and QUIC support in curl is not yet working and this is early days.
Consider all QUIC and HTTP/3 code to be **EXPERIMENTAL** until further notice.

curl does not have HTTP/3 support (yet).

The bleeding edge QUIC work is done in the dedicated
[QUIC](https://github.com/curl/curl/tree/QUIC) branch, but the plan is to
merge as often as possible from there to master. All QUIC related code will
remain being build-time conditionally enabled.

# ngtcp2 version

## Build

1. clone ngtcp2 from git (the draft-17 branch)
2. build and install ngtcp2's custom OpenSSL version (the quic-draft-17 branch)
3. build and install ngtcp2 according to its instructions
4. configure curl with ngtcp2 support: `./configure --with-ngtcp2=<install prefix>`
5. build curl "normally"

## Running

Make sure the custom OpenSSL library is the one used at run-time, as otherwise
you'll just get ld.so linker errors.

## Invoke from command line

    curl --http3-direct https://nghttp2.org:8443/

# quiche version

## build

Build BoringSSL (it needs to be built manually so it can be reused with curl):

     % mkdir -p quiche/deps/boringssl/build
     % cd quiche/deps/boringssl/build
     % cmake -DCMAKE_POSITION_INDEPENDENT_CODE=on ..
     % make -j`nproc`
     % cd ..
     % mkdir .openssl/lib -p
     % cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib
     % ln -s $PWD/include .openssl

Build quiche:

     % cd ../..
     % QUICHE_BSSL_PATH=$PWD/deps/boringssl cargo build

Clone and build curl:

     % cd ..
     % git clone -b quiche https://github.com/ghedo/curl
     % ./buildconf
     % ./configure --with-ssl=$PWD/../quiche/deps/boringssl/.openssl --with-quiche=$PWD/../quiche --enable-debug
     % make -j`nproc`

## Running

Make an HTTP/1.1 request to a QUIC server:

     % src/curl --http3-direct https://cloudflare-quic.com/
+1 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ EXTRA_DIST = \
 HISTORY.md                                     \
 HTTP-COOKIES.md                                \
 HTTP2.md                                       \
 HTTP3.md                                       \
 INSTALL                                        \
 INSTALL.cmake                                  \
 INSTALL.md                                     \
+1 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ DPAGES = \
  http1.0.d					\
  http1.1.d http2.d				\
  http2-prior-knowledge.d			\
  http3-direct.d                                \
  ignore-content-length.d			\
  include.d					\
  insecure.d					\
+14 −0
Original line number Diff line number Diff line
Long: http3-direct
Tags: Versions
Protocols: HTTP
Added: 7.66.0
Mutexed: http1.1 http1.0 http2 http2-prior-knowledge
Requires: HTTP/3
Help: Use HTTP v3
---

Tells curl to use HTTP version 3 directly to the host and port number used in
the URL. A normal HTTP/3 transaction will be done to a host and then get
redirected via Alt-SVc, but this option allows a user to circumvent that when
you know that the target speaks HTTP/3 on the given host and port.
Loading