mirror of
https://github.com/curl/curl.git
synced 2025-09-12 07:02:41 +03:00
msh3: add support for QUIC and HTTP/3 using msh3
Considered experimental, as the other HTTP/3 backends. Closes #8517
This commit is contained in:
parent
7befbe9ce9
commit
37492ebbfa
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -18,6 +18,7 @@
|
|||
.project
|
||||
.settings
|
||||
/.vs
|
||||
/bld/
|
||||
/build/
|
||||
/builds/
|
||||
/stats/
|
||||
|
|
68
CMake/FindMSH3.cmake
Normal file
68
CMake/FindMSH3.cmake
Normal file
|
@ -0,0 +1,68 @@
|
|||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindMSH3
|
||||
----------
|
||||
|
||||
Find the msh3 library
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
``MSH3_FOUND``
|
||||
System has msh3
|
||||
``MSH3_INCLUDE_DIRS``
|
||||
The msh3 include directories.
|
||||
``MSH3_LIBRARIES``
|
||||
The libraries needed to use msh3
|
||||
#]=======================================================================]
|
||||
if(UNIX)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(PC_MSH3 libmsh3)
|
||||
endif()
|
||||
|
||||
find_path(MSH3_INCLUDE_DIR msh3.h
|
||||
HINTS
|
||||
${PC_MSH3_INCLUDEDIR}
|
||||
${PC_MSH3_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(MSH3_LIBRARY NAMES msh3
|
||||
HINTS
|
||||
${PC_MSH3_LIBDIR}
|
||||
${PC_MSH3_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(MSH3
|
||||
REQUIRED_VARS
|
||||
MSH3_LIBRARY
|
||||
MSH3_INCLUDE_DIR
|
||||
)
|
||||
|
||||
if(MSH3_FOUND)
|
||||
set(MSH3_LIBRARIES ${MSH3_LIBRARY})
|
||||
set(MSH3_INCLUDE_DIRS ${MSH3_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(MSH3_INCLUDE_DIRS MSH3_LIBRARIES)
|
|
@ -556,6 +556,16 @@ if(USE_QUICHE)
|
|||
cmake_pop_check_state()
|
||||
endif()
|
||||
|
||||
option(USE_MSH3 "Use msquic library for HTTP/3 support" OFF)
|
||||
if(USE_MSH3)
|
||||
if(USE_NGTCP2 OR USE_QUICHE)
|
||||
message(FATAL_ERROR "Only one HTTP/3 backend can be selected!")
|
||||
endif()
|
||||
set(USE_MSH3 ON)
|
||||
include_directories(${MSH3_INCLUDE_DIRS})
|
||||
list(APPEND CURL_LIBS ${MSH3_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NOT CURL_DISABLE_LDAP)
|
||||
if(WIN32)
|
||||
option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
|
||||
|
|
|
@ -36,6 +36,7 @@ CMAKE_DIST = \
|
|||
CMake/FindGSS.cmake \
|
||||
CMake/FindLibSSH2.cmake \
|
||||
CMake/FindMbedTLS.cmake \
|
||||
CMake/FindMSH3.cmake \
|
||||
CMake/FindNGHTTP2.cmake \
|
||||
CMake/FindNGHTTP3.cmake \
|
||||
CMake/FindNGTCP2.cmake \
|
||||
|
|
77
configure.ac
77
configure.ac
|
@ -170,7 +170,7 @@ curl_verbose_msg="enabled (--disable-verbose)"
|
|||
ssl_backends=
|
||||
curl_h1_msg="enabled (internal)"
|
||||
curl_h2_msg="no (--with-nghttp2, --with-hyper)"
|
||||
curl_h3_msg="no (--with-ngtcp2, --with-quiche)"
|
||||
curl_h3_msg="no (--with-ngtcp2, --with-quiche --with-msh3)"
|
||||
|
||||
enable_altsvc="yes"
|
||||
hsts="yes"
|
||||
|
@ -3036,6 +3036,78 @@ AC_INCLUDES_DEFAULT
|
|||
fi
|
||||
fi
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Check for msh3 (QUIC)
|
||||
dnl **********************************************************************
|
||||
|
||||
OPT_MSH3="no"
|
||||
|
||||
if test "x$disable_http" = "xyes" -o "x$USE_NGTCP" = "x1"; then
|
||||
# without HTTP or with ngtcp2, msh3 is no use
|
||||
OPT_MSH3="no"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(msh3,
|
||||
AS_HELP_STRING([--with-msh3=PATH],[Enable msh3 usage])
|
||||
AS_HELP_STRING([--without-msh3],[Disable msh3 usage]),
|
||||
[OPT_MSH3=$withval])
|
||||
case "$OPT_MSH3" in
|
||||
no)
|
||||
dnl --without-msh3 option used
|
||||
want_msh3="no"
|
||||
;;
|
||||
yes)
|
||||
dnl --with-msh3 option used without path
|
||||
want_msh3="default"
|
||||
want_msh3_path=""
|
||||
;;
|
||||
*)
|
||||
dnl --with-msh3 option used with path
|
||||
want_msh3="yes"
|
||||
want_msh3_path="$withval"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test X"$want_msh3" != Xno; then
|
||||
|
||||
if test "$NGHTTP3_ENABLED" = 1; then
|
||||
AC_MSG_ERROR([--with-msh3 and --with-ngtcp2 are mutually exclusive])
|
||||
fi
|
||||
|
||||
dnl backup the pre-msh3 variables
|
||||
CLEANLDFLAGS="$LDFLAGS"
|
||||
CLEANCPPFLAGS="$CPPFLAGS"
|
||||
CLEANLIBS="$LIBS"
|
||||
|
||||
if test -n "$want_msh3_path"; then
|
||||
LD_MSH3="-L$want_msh3_path/lib"
|
||||
CPP_MSH3="-I$want_msh3_path/include"
|
||||
DIR_MSH3="$want_msh3_path/lib"
|
||||
LDFLAGS="$LDFLAGS $LD_MSH3"
|
||||
CPPFLAGS="$CPPFLAGS $CPP_MSH3"
|
||||
fi
|
||||
LIBS="-lmsh3 $LIBS"
|
||||
|
||||
AC_CHECK_LIB(msh3, MsH3ApiOpen,
|
||||
[
|
||||
AC_CHECK_HEADERS(msh3.h,
|
||||
curl_h3_msg="enabled (msh3)"
|
||||
MSH3_ENABLED=1
|
||||
AC_DEFINE(USE_MSH3, 1, [if msh3 is in use])
|
||||
AC_SUBST(USE_MSH3, [1])
|
||||
CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_MSH3"
|
||||
export CURL_LIBRARY_PATH
|
||||
AC_MSG_NOTICE([Added $DIR_MSH3 to CURL_LIBRARY_PATH]),
|
||||
experimental="$experimental HTTP3"
|
||||
)
|
||||
],
|
||||
dnl not found, revert back to clean variables
|
||||
LDFLAGS=$CLEANLDFLAGS
|
||||
CPPFLAGS=$CLEANCPPFLAGS
|
||||
LIBS=$CLEANLIBS
|
||||
)
|
||||
fi
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Check for zsh completion path
|
||||
dnl **********************************************************************
|
||||
|
@ -4146,7 +4218,8 @@ if test "x$USE_NGHTTP2" = "x1" -o "x$USE_HYPER" = "x1"; then
|
|||
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
|
||||
fi
|
||||
|
||||
if test "x$USE_NGTCP2" = "x1" -o "x$USE_QUICHE" = "x1"; then
|
||||
if test "x$USE_NGTCP2" = "x1" -o "x$USE_QUICHE" = "x1" \
|
||||
-o "x$USE_MSH3" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP3"
|
||||
fi
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ QUIC libraries we are experimenting with:
|
|||
|
||||
[quiche](https://github.com/cloudflare/quiche)
|
||||
|
||||
[msquic](https://github.com/microsoft/msquic) & [msh3](https://github.com/nibanks/msh3)
|
||||
|
||||
## Experimental
|
||||
|
||||
HTTP/3 and QUIC support in curl is considered **EXPERIMENTAL** until further
|
||||
|
@ -136,6 +138,53 @@ Build curl:
|
|||
|
||||
If `make install` results in `Permission denied` error, you will need to prepend it with `sudo`.
|
||||
|
||||
# msh3 (msquic) version
|
||||
|
||||
## Build Linux (with quictls fork of OpenSSL)
|
||||
|
||||
Build msh3:
|
||||
|
||||
% git clone -b v0.1.0 --single-branch --recursive https://github.com/nibanks/msh3
|
||||
% cd msh3 && mkdir build && cd build
|
||||
% cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
|
||||
% cmake --build .
|
||||
% cmake --install .
|
||||
|
||||
Build curl:
|
||||
|
||||
% git clone https://github.com/curl/curl
|
||||
% cd curl
|
||||
% autoreconf -fi
|
||||
% ./configure LDFLAGS="-Wl,-rpath,/usr/local/lib" --with-msh3=/usr/local --with-openssl
|
||||
% make
|
||||
% make install
|
||||
|
||||
Run from `/usr/local/bin/curl`.
|
||||
|
||||
## Build Windows
|
||||
|
||||
Build msh3:
|
||||
|
||||
% git clone -b v0.2.0 --single-branch --recursive https://github.com/nibanks/msh3
|
||||
% cd msh3 && mkdir build && cd build
|
||||
% cmake -G 'Visual Studio 17 2022' -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
|
||||
% cmake --build . --config Release
|
||||
% cmake --install . --config Release
|
||||
|
||||
> **Note** - On Windows, Schannel will be used for TLS support by default. If you with to use (the quictls fork of) OpenSSL, specify the `-DQUIC_TLS=openssl` option to the generate command above. Also note that OpenSSL brings with it an additional set of build dependencies not specified here.
|
||||
|
||||
Build curl (in [Visual Studio Command prompt](../winbuild/README.md#open-a-command-prompt)):
|
||||
|
||||
% git clone https://github.com/curl/curl
|
||||
% cd curl/winbuild
|
||||
% nmake /f Makefile.vc mode=dll WITH_MSH3=dll MSH3_PATH="C:/Program Files/msh3" MACHINE=x64
|
||||
|
||||
Note: If you encouter a build error with `tool_hugehelp.c` being missing, rename `tool_hugehelp.c.cvs` in the same directory to `tool_hugehelp.c` and then run `nmake` again.
|
||||
|
||||
Run in the `C:/Program Files/msh3/lib` directory, copy `curl.exe` to that directory, or copy `msquic.dll` and `msh3.dll` from that directory to the `curl.exe` directory. For example:
|
||||
|
||||
% C:\Program Files\msh3\lib> F:\curl\builds\libcurl-vc-x64-release-dll-ipv6-sspi-schannel-msh3\bin\curl.exe --http3 https://www.google.com
|
||||
|
||||
# `--http3`
|
||||
|
||||
Use HTTP/3 directly:
|
||||
|
|
|
@ -76,11 +76,13 @@ LIB_VTLS_HFILES = \
|
|||
vtls/x509asn1.h
|
||||
|
||||
LIB_VQUIC_CFILES = \
|
||||
vquic/msh3.c \
|
||||
vquic/ngtcp2.c \
|
||||
vquic/quiche.c \
|
||||
vquic/vquic.c
|
||||
|
||||
LIB_VQUIC_HFILES = \
|
||||
vquic/msh3.h \
|
||||
vquic/ngtcp2.h \
|
||||
vquic/quiche.h \
|
||||
vquic/vquic.h
|
||||
|
|
|
@ -54,6 +54,8 @@
|
|||
#define H3VERSION "h3-29"
|
||||
#elif defined(USE_NGTCP2) && !defined(UNITTESTS)
|
||||
#define H3VERSION "h3-29"
|
||||
#elif defined(USE_MSH3) && !defined(UNITTESTS)
|
||||
#define H3VERSION "h3-29"
|
||||
#else
|
||||
#define H3VERSION "h3"
|
||||
#endif
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
@ -371,7 +371,8 @@
|
|||
/* Define if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#define TIME_WITH_SYS_TIME
|
||||
|
||||
/* Define to enable HTTP3 support (experimental, requires NGTCP2 or QUICHE) */
|
||||
/* Define to enable HTTP3 support (experimental, requires NGTCP2, QUICHE or
|
||||
MSH3) */
|
||||
#undef ENABLE_QUIC
|
||||
|
||||
/* Version number of package */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
@ -949,6 +949,9 @@ ${SIZEOF_TIME_T_CODE}
|
|||
/* Define to 1 if you have the quiche_conn_set_qlog_fd function. */
|
||||
#cmakedefine HAVE_QUICHE_CONN_SET_QLOG_FD 1
|
||||
|
||||
/* to enable msh3 */
|
||||
#cmakedefine USE_MSH3 1
|
||||
|
||||
/* if Unix domain sockets are enabled */
|
||||
#cmakedefine USE_UNIX_SOCKETS
|
||||
|
||||
|
|
|
@ -794,7 +794,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
|
|||
#define USE_HTTP2
|
||||
#endif
|
||||
|
||||
#if defined(USE_NGTCP2) || defined(USE_QUICHE)
|
||||
#if defined(USE_NGTCP2) || defined(USE_QUICHE) || defined(USE_MSH3)
|
||||
#define ENABLE_QUIC
|
||||
#endif
|
||||
|
||||
|
|
44
lib/http.h
44
lib/http.h
|
@ -38,6 +38,10 @@ typedef enum {
|
|||
#include <nghttp2/nghttp2.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(ENABLE_QUIC)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
extern const struct Curl_handler Curl_handler_http;
|
||||
|
||||
#ifdef USE_SSL
|
||||
|
@ -163,6 +167,29 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data);
|
|||
struct h3out; /* see ngtcp2 */
|
||||
#endif
|
||||
|
||||
#ifdef USE_MSH3
|
||||
#ifdef _WIN32
|
||||
#define msh3_lock CRITICAL_SECTION
|
||||
#define msh3_lock_initialize(lock) InitializeCriticalSection(lock)
|
||||
#define msh3_lock_uninitialize(lock) DeleteCriticalSection(lock)
|
||||
#define msh3_lock_acquire(lock) EnterCriticalSection(lock)
|
||||
#define msh3_lock_release(lock) LeaveCriticalSection(lock)
|
||||
#else /* !_WIN32 */
|
||||
#include <pthread.h>
|
||||
#define msh3_lock pthread_mutex_t
|
||||
#define msh3_lock_initialize(lock) { \
|
||||
pthread_mutexattr_t attr; \
|
||||
pthread_mutexattr_init(&attr); \
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
|
||||
pthread_mutex_init(lock, &attr); \
|
||||
pthread_mutexattr_destroy(&attr); \
|
||||
}
|
||||
#define msh3_lock_uninitialize(lock) pthread_mutex_destroy(lock)
|
||||
#define msh3_lock_acquire(lock) pthread_mutex_lock(lock)
|
||||
#define msh3_lock_release(lock) pthread_mutex_unlock(lock)
|
||||
#endif /* _WIN32 */
|
||||
#endif /* USE_MSH3 */
|
||||
|
||||
/****************************************************************************
|
||||
* HTTP unique setup
|
||||
***************************************************************************/
|
||||
|
@ -228,11 +255,13 @@ struct HTTP {
|
|||
#endif
|
||||
|
||||
#ifdef ENABLE_QUIC
|
||||
#ifndef USE_MSH3
|
||||
/*********** for HTTP/3 we store stream-local data here *************/
|
||||
int64_t stream3_id; /* stream we are interested in */
|
||||
bool firstheader; /* FALSE until headers arrive */
|
||||
bool firstbody; /* FALSE until body arrives */
|
||||
bool h3req; /* FALSE until request is issued */
|
||||
#endif
|
||||
bool upload_done;
|
||||
#endif
|
||||
#ifdef USE_NGHTTP3
|
||||
|
@ -240,6 +269,21 @@ struct HTTP {
|
|||
struct h3out *h3out; /* per-stream buffers for upload */
|
||||
struct dynbuf overflow; /* excess data received during a single Curl_read */
|
||||
#endif
|
||||
#ifdef USE_MSH3
|
||||
struct MSH3_REQUEST *req;
|
||||
msh3_lock recv_lock;
|
||||
/* Receive Buffer (Headers and Data) */
|
||||
uint8_t* recv_buf;
|
||||
size_t recv_buf_alloc;
|
||||
/* Receive Headers */
|
||||
size_t recv_header_len;
|
||||
bool recv_header_complete;
|
||||
/* Receive Data */
|
||||
size_t recv_data_len;
|
||||
bool recv_data_complete;
|
||||
/* General Receive Error */
|
||||
CURLcode recv_error;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
@ -31,6 +31,9 @@
|
|||
#ifdef USE_QUICHE
|
||||
#include "vquic/quiche.h"
|
||||
#endif
|
||||
#ifdef USE_MSH3
|
||||
#include "vquic/msh3.h"
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
|
||||
|
|
498
lib/vquic/msh3.c
Normal file
498
lib/vquic/msh3.c
Normal file
|
@ -0,0 +1,498 @@
|
|||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifdef USE_MSH3
|
||||
|
||||
#include "urldata.h"
|
||||
#include "curl_printf.h"
|
||||
#include "timeval.h"
|
||||
#include "multiif.h"
|
||||
#include "sendf.h"
|
||||
#include "connect.h"
|
||||
#include "h2h3.h"
|
||||
#include "msh3.h"
|
||||
|
||||
/* #define DEBUG_HTTP3 1 */
|
||||
#ifdef DEBUG_HTTP3
|
||||
#define H3BUGF(x) x
|
||||
#else
|
||||
#define H3BUGF(x) do { } while(0)
|
||||
#endif
|
||||
|
||||
#define MSH3_REQ_INIT_BUF_LEN 8192
|
||||
|
||||
static CURLcode msh3_do_it(struct Curl_easy *data, bool *done);
|
||||
static int msh3_getsock(struct Curl_easy *data,
|
||||
struct connectdata *conn, curl_socket_t *socks);
|
||||
static CURLcode msh3_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool dead_connection);
|
||||
static unsigned int msh3_conncheck(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
unsigned int checks_to_perform);
|
||||
static Curl_recv msh3_stream_recv;
|
||||
static Curl_send msh3_stream_send;
|
||||
static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request,
|
||||
void *IfContext,
|
||||
const MSH3_HEADER *Header);
|
||||
static void MSH3_CALL msh3_data_received(MSH3_REQUEST *Request,
|
||||
void *IfContext, uint32_t Length,
|
||||
const uint8_t *Data);
|
||||
static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext,
|
||||
bool Aborted, uint64_t AbortError);
|
||||
static void MSH3_CALL msh3_shutdown(MSH3_REQUEST *Request, void *IfContext);
|
||||
|
||||
static const struct Curl_handler msh3_curl_handler_http3 = {
|
||||
"HTTPS", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
msh3_do_it, /* do_it */
|
||||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
ZERO_NULL, /* connect_it */
|
||||
ZERO_NULL, /* connecting */
|
||||
ZERO_NULL, /* doing */
|
||||
msh3_getsock, /* proto_getsock */
|
||||
msh3_getsock, /* doing_getsock */
|
||||
ZERO_NULL, /* domore_getsock */
|
||||
msh3_getsock, /* perform_getsock */
|
||||
msh3_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
msh3_conncheck, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_HTTP, /* defport */
|
||||
CURLPROTO_HTTPS, /* protocol */
|
||||
CURLPROTO_HTTP, /* family */
|
||||
PROTOPT_SSL | PROTOPT_STREAM /* flags */
|
||||
};
|
||||
|
||||
static const MSH3_REQUEST_IF msh3_request_if = {
|
||||
msh3_header_received,
|
||||
msh3_data_received,
|
||||
msh3_complete,
|
||||
msh3_shutdown
|
||||
};
|
||||
|
||||
void Curl_quic_ver(char *p, size_t len)
|
||||
{
|
||||
(void)msnprintf(p, len, "msh3/%s", "0.0.1");
|
||||
}
|
||||
|
||||
CURLcode Curl_quic_connect(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
curl_socket_t sockfd,
|
||||
int sockindex,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
struct quicsocket *qs = &conn->hequic[sockindex];
|
||||
bool unsecure = !conn->ssl_config.verifypeer;
|
||||
memset(qs, 0, sizeof(*qs));
|
||||
|
||||
(void)sockfd;
|
||||
(void)addr; /* TODO - Pass address along */
|
||||
(void)addrlen;
|
||||
|
||||
H3BUGF(infof(data, "creating new api/connection"));
|
||||
|
||||
qs->api = MsH3ApiOpen();
|
||||
if(!qs->api) {
|
||||
failf(data, "can't create msh3 api");
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
qs->conn = MsH3ConnectionOpen(qs->api, conn->host.name, unsecure);
|
||||
if(!qs->conn) {
|
||||
failf(data, "can't create msh3 connection");
|
||||
if(qs->api) {
|
||||
MsH3ApiClose(qs->api);
|
||||
}
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_quic_is_connected(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *connected)
|
||||
{
|
||||
struct quicsocket *qs = &conn->hequic[sockindex];
|
||||
MSH3_CONNECTION_STATE state;
|
||||
|
||||
state = MsH3ConnectionGetState(qs->conn, false);
|
||||
if(state == MSH3_CONN_HANDSHAKE_FAILED || state == MSH3_CONN_DISCONNECTED) {
|
||||
failf(data, "failed to connect, state=%u", (uint32_t)state);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(state == MSH3_CONN_CONNECTED) {
|
||||
H3BUGF(infof(data, "connection connected"));
|
||||
*connected = true;
|
||||
conn->quic = qs;
|
||||
conn->recv[sockindex] = msh3_stream_recv;
|
||||
conn->send[sockindex] = msh3_stream_send;
|
||||
conn->handler = &msh3_curl_handler_http3;
|
||||
conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
|
||||
conn->httpversion = 30;
|
||||
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
|
||||
/* TODO - Clean up other happy-eyeballs connection(s)? */
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static int msh3_getsock(struct Curl_easy *data,
|
||||
struct connectdata *conn, curl_socket_t *socks)
|
||||
{
|
||||
struct HTTP *stream = data->req.p.http;
|
||||
int bitmap = GETSOCK_BLANK;
|
||||
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
|
||||
if(stream->recv_error) {
|
||||
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
|
||||
data->state.drain++;
|
||||
}
|
||||
else if(stream->recv_header_len || stream->recv_data_len) {
|
||||
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
|
||||
data->state.drain++;
|
||||
}
|
||||
|
||||
H3BUGF(infof(data, "msh3_getsock %u", (uint32_t)data->state.drain));
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static CURLcode msh3_do_it(struct Curl_easy *data, bool *done)
|
||||
{
|
||||
struct HTTP *stream = data->req.p.http;
|
||||
H3BUGF(infof(data, "msh3_do_it"));
|
||||
stream->recv_buf = malloc(MSH3_REQ_INIT_BUF_LEN);
|
||||
if(!stream->recv_buf) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
stream->req = ZERO_NULL;
|
||||
msh3_lock_initialize(&stream->recv_lock);
|
||||
stream->recv_buf_alloc = MSH3_REQ_INIT_BUF_LEN;
|
||||
stream->recv_header_len = 0;
|
||||
stream->recv_header_complete = false;
|
||||
stream->recv_data_len = 0;
|
||||
stream->recv_data_complete = false;
|
||||
stream->recv_error = CURLE_OK;
|
||||
return Curl_http(data, done);
|
||||
}
|
||||
|
||||
static unsigned int msh3_conncheck(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
unsigned int checks_to_perform)
|
||||
{
|
||||
(void)data;
|
||||
(void)conn;
|
||||
(void)checks_to_perform;
|
||||
H3BUGF(infof(data, "msh3_conncheck"));
|
||||
return CONNRESULT_NONE;
|
||||
}
|
||||
|
||||
static void msh3_cleanup(struct quicsocket *qs, struct HTTP *stream)
|
||||
{
|
||||
if(stream && stream->recv_buf) {
|
||||
free(stream->recv_buf);
|
||||
stream->recv_buf = ZERO_NULL;
|
||||
msh3_lock_uninitialize(&stream->recv_lock);
|
||||
}
|
||||
if(qs->conn) {
|
||||
MsH3ConnectionClose(qs->conn);
|
||||
qs->conn = ZERO_NULL;
|
||||
}
|
||||
if(qs->api) {
|
||||
MsH3ApiClose(qs->api);
|
||||
qs->api = ZERO_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static CURLcode msh3_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn, bool dead_connection)
|
||||
{
|
||||
(void)dead_connection;
|
||||
H3BUGF(infof(data, "disconnecting (msh3)"));
|
||||
msh3_cleanup(conn->quic, data->req.p.http);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
void Curl_quic_disconnect(struct Curl_easy *data, struct connectdata *conn,
|
||||
int tempindex)
|
||||
{
|
||||
if(conn->transport == TRNSPRT_QUIC) {
|
||||
H3BUGF(infof(data, "disconnecting (curl)"));
|
||||
msh3_cleanup(&conn->hequic[tempindex], data->req.p.http);
|
||||
}
|
||||
}
|
||||
|
||||
/* Requires stream->recv_lock to be held */
|
||||
static bool msh3request_ensure_room(struct HTTP *stream, size_t len)
|
||||
{
|
||||
uint8_t *new_recv_buf;
|
||||
const size_t cur_recv_len = stream->recv_header_len + stream->recv_data_len;
|
||||
if(cur_recv_len + len > stream->recv_buf_alloc) {
|
||||
size_t new_recv_buf_alloc_len = stream->recv_buf_alloc;
|
||||
do {
|
||||
new_recv_buf_alloc_len <<= 1; /* TODO - handle overflow */
|
||||
} while(cur_recv_len + len > new_recv_buf_alloc_len);
|
||||
new_recv_buf = malloc(new_recv_buf_alloc_len);
|
||||
if(!new_recv_buf) {
|
||||
return false;
|
||||
}
|
||||
if(cur_recv_len) {
|
||||
memcpy(new_recv_buf, stream->recv_buf, cur_recv_len);
|
||||
}
|
||||
stream->recv_buf_alloc = new_recv_buf_alloc_len;
|
||||
free(stream->recv_buf);
|
||||
stream->recv_buf = new_recv_buf;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request,
|
||||
void *IfContext,
|
||||
const MSH3_HEADER *Header)
|
||||
{
|
||||
struct HTTP *stream = IfContext;
|
||||
size_t total_len;
|
||||
(void)Request;
|
||||
H3BUGF(printf("* msh3_header_received\n"));
|
||||
|
||||
if(stream->recv_header_complete) {
|
||||
H3BUGF(printf("* ignoring header after data\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
msh3_lock_acquire(&stream->recv_lock);
|
||||
|
||||
if((Header->NameLength == 7) &&
|
||||
!strncmp(H2H3_PSEUDO_STATUS, (char *)Header->Name, 7)) {
|
||||
total_len = 9 + Header->ValueLength;
|
||||
if(!msh3request_ensure_room(stream, total_len)) {
|
||||
/* TODO - handle error */
|
||||
goto release_lock;
|
||||
}
|
||||
msnprintf((char *)stream->recv_buf + stream->recv_header_len,
|
||||
stream->recv_buf_alloc - stream->recv_header_len,
|
||||
"HTTP/3 %.*s\n", (int)Header->ValueLength, Header->Value);
|
||||
}
|
||||
else {
|
||||
total_len = Header->NameLength + 4 + Header->ValueLength;
|
||||
if(!msh3request_ensure_room(stream, total_len)) {
|
||||
/* TODO - handle error */
|
||||
goto release_lock;
|
||||
}
|
||||
msnprintf((char *)stream->recv_buf + stream->recv_header_len,
|
||||
stream->recv_buf_alloc - stream->recv_header_len,
|
||||
"%.*s: %.*s\n",
|
||||
(int)Header->NameLength, Header->Name,
|
||||
(int)Header->ValueLength, Header->Value);
|
||||
}
|
||||
|
||||
stream->recv_header_len += total_len - 1; /* don't include null-terminator */
|
||||
|
||||
release_lock:
|
||||
msh3_lock_release(&stream->recv_lock);
|
||||
}
|
||||
|
||||
static void MSH3_CALL msh3_data_received(MSH3_REQUEST *Request,
|
||||
void *IfContext, uint32_t Length,
|
||||
const uint8_t *Data)
|
||||
{
|
||||
struct HTTP *stream = IfContext;
|
||||
size_t cur_recv_len = stream->recv_header_len + stream->recv_data_len;
|
||||
(void)Request;
|
||||
H3BUGF(printf("* msh3_data_received %u. %zu buffered, %zu allocated\n",
|
||||
Length, cur_recv_len, stream->recv_buf_alloc));
|
||||
msh3_lock_acquire(&stream->recv_lock);
|
||||
if(!stream->recv_header_complete) {
|
||||
H3BUGF(printf("* Headers complete!\n"));
|
||||
if(!msh3request_ensure_room(stream, 2)) {
|
||||
/* TODO - handle error */
|
||||
goto release_lock;
|
||||
}
|
||||
stream->recv_buf[stream->recv_header_len++] = '\r';
|
||||
stream->recv_buf[stream->recv_header_len++] = '\n';
|
||||
stream->recv_header_complete = true;
|
||||
cur_recv_len += 2;
|
||||
}
|
||||
if(!msh3request_ensure_room(stream, Length)) {
|
||||
/* TODO - handle error */
|
||||
goto release_lock;
|
||||
}
|
||||
memcpy(stream->recv_buf + cur_recv_len, Data, Length);
|
||||
stream->recv_data_len += (size_t)Length;
|
||||
release_lock:
|
||||
msh3_lock_release(&stream->recv_lock);
|
||||
}
|
||||
|
||||
static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext,
|
||||
bool Aborted, uint64_t AbortError)
|
||||
{
|
||||
struct HTTP *stream = IfContext;
|
||||
(void)Request;
|
||||
(void)AbortError;
|
||||
H3BUGF(printf("* msh3_complete, aborted=%hhu\n", Aborted));
|
||||
msh3_lock_acquire(&stream->recv_lock);
|
||||
if(Aborted) {
|
||||
stream->recv_error = CURLE_HTTP3; /* TODO - how do we pass AbortError? */
|
||||
}
|
||||
stream->recv_header_complete = true;
|
||||
stream->recv_data_complete = true;
|
||||
msh3_lock_release(&stream->recv_lock);
|
||||
}
|
||||
|
||||
static void MSH3_CALL msh3_shutdown(MSH3_REQUEST *Request, void *IfContext)
|
||||
{
|
||||
struct HTTP *stream = IfContext;
|
||||
(void)Request;
|
||||
(void)stream;
|
||||
}
|
||||
|
||||
static_assert(sizeof(MSH3_HEADER) == sizeof(struct h2h3pseudo),
|
||||
"Sizes must match for cast below to work");
|
||||
|
||||
static ssize_t msh3_stream_send(struct Curl_easy *data,
|
||||
int sockindex,
|
||||
const void *mem,
|
||||
size_t len,
|
||||
CURLcode *curlcode)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct HTTP *stream = data->req.p.http;
|
||||
struct quicsocket *qs = conn->quic;
|
||||
struct h2h3req *hreq;
|
||||
|
||||
(void)sockindex;
|
||||
H3BUGF(infof(data, "msh3_stream_send %zu", len));
|
||||
|
||||
if(!stream->req) {
|
||||
*curlcode = Curl_pseudo_headers(data, mem, len, &hreq);
|
||||
if(*curlcode) {
|
||||
failf(data, "Curl_pseudo_headers failed");
|
||||
return -1;
|
||||
}
|
||||
H3BUGF(infof(data, "starting request with %zu headers", hreq->entries));
|
||||
stream->req = MsH3RequestOpen(qs->conn, &msh3_request_if, stream,
|
||||
(MSH3_HEADER*)hreq->header, hreq->entries);
|
||||
Curl_pseudo_free(hreq);
|
||||
if(!stream->req) {
|
||||
failf(data, "request open failed");
|
||||
*curlcode = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
*curlcode = CURLE_OK;
|
||||
return len;
|
||||
}
|
||||
H3BUGF(infof(data, "send %zd body bytes on request %p", len,
|
||||
(void *)stream->req));
|
||||
*curlcode = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t msh3_stream_recv(struct Curl_easy *data,
|
||||
int sockindex,
|
||||
char *buf,
|
||||
size_t buffersize,
|
||||
CURLcode *curlcode)
|
||||
{
|
||||
struct HTTP *stream = data->req.p.http;
|
||||
size_t outsize = 0;
|
||||
(void)sockindex;
|
||||
H3BUGF(infof(data, "msh3_stream_recv %zu", buffersize));
|
||||
|
||||
if(stream->recv_error) {
|
||||
failf(data, "request aborted");
|
||||
*curlcode = stream->recv_error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
msh3_lock_acquire(&stream->recv_lock);
|
||||
|
||||
if(stream->recv_header_len) {
|
||||
outsize = buffersize;
|
||||
if(stream->recv_header_len < outsize) {
|
||||
outsize = stream->recv_header_len;
|
||||
}
|
||||
memcpy(buf, stream->recv_buf, outsize);
|
||||
if(outsize < stream->recv_header_len + stream->recv_data_len) {
|
||||
memmove(stream->recv_buf, stream->recv_buf + outsize,
|
||||
stream->recv_header_len + stream->recv_data_len - outsize);
|
||||
}
|
||||
stream->recv_header_len -= outsize;
|
||||
H3BUGF(infof(data, "returned %zu bytes of headers", outsize));
|
||||
}
|
||||
else if(stream->recv_data_len) {
|
||||
outsize = buffersize;
|
||||
if(stream->recv_data_len < outsize) {
|
||||
outsize = stream->recv_data_len;
|
||||
}
|
||||
memcpy(buf, stream->recv_buf, outsize);
|
||||
if(outsize < stream->recv_data_len) {
|
||||
memmove(stream->recv_buf, stream->recv_buf + outsize,
|
||||
stream->recv_data_len - outsize);
|
||||
}
|
||||
stream->recv_data_len -= outsize;
|
||||
H3BUGF(infof(data, "returned %zu bytes of data", outsize));
|
||||
}
|
||||
else if(stream->recv_data_complete) {
|
||||
H3BUGF(infof(data, "receive complete"));
|
||||
}
|
||||
|
||||
msh3_lock_release(&stream->recv_lock);
|
||||
|
||||
return (ssize_t)outsize;
|
||||
}
|
||||
|
||||
CURLcode Curl_quic_done_sending(struct Curl_easy *data)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
H3BUGF(infof(data, "Curl_quic_done_sending"));
|
||||
if(conn->handler == &msh3_curl_handler_http3) {
|
||||
struct HTTP *stream = data->req.p.http;
|
||||
stream->upload_done = TRUE;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
void Curl_quic_done(struct Curl_easy *data, bool premature)
|
||||
{
|
||||
(void)data;
|
||||
(void)premature;
|
||||
H3BUGF(infof(data, "Curl_quic_done"));
|
||||
}
|
||||
|
||||
bool Curl_quic_data_pending(const struct Curl_easy *data)
|
||||
{
|
||||
struct HTTP *stream = data->req.p.http;
|
||||
H3BUGF(infof((struct Curl_easy *)data, "Curl_quic_data_pending"));
|
||||
return stream->recv_header_len || stream->recv_data_len;
|
||||
}
|
||||
|
||||
#endif /* USE_MSH3 */
|
38
lib/vquic/msh3.h
Normal file
38
lib/vquic/msh3.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef HEADER_CURL_VQUIC_MSH3_H
|
||||
#define HEADER_CURL_VQUIC_MSH3_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifdef USE_MSH3
|
||||
|
||||
#include <msh3.h>
|
||||
|
||||
struct quicsocket {
|
||||
MSH3_API* api;
|
||||
MSH3_CONNECTION* conn;
|
||||
};
|
||||
|
||||
#endif /* USE_MSQUIC */
|
||||
|
||||
#endif /* HEADER_CURL_VQUIC_MSH3_H */
|
|
@ -149,6 +149,23 @@ NGHTTP2 = static
|
|||
USE_NGHTTP2 = false
|
||||
!ENDIF
|
||||
|
||||
!IF "$(ENABLE_MSH3)"=="yes"
|
||||
# compatibility bit, WITH_MSH3 is the correct flag
|
||||
WITH_MSH3 = dll
|
||||
USE_MSH3 = true
|
||||
MSH3 = dll
|
||||
!ELSEIF "$(WITH_MSH3)"=="dll"
|
||||
USE_MSH3 = true
|
||||
MSH3 = dll
|
||||
!ELSEIF "$(WITH_MSH3)"=="static"
|
||||
USE_MSH3 = true
|
||||
MSH3 = static
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF USE_MSH3
|
||||
USE_MSH3 = false
|
||||
!ENDIF
|
||||
|
||||
!IF "$(WITH_MBEDTLS)"=="dll" || "$(WITH_MBEDTLS)"=="static"
|
||||
USE_MBEDTLS = true
|
||||
MBEDTLS = $(WITH_MBEDTLS)
|
||||
|
@ -240,6 +257,10 @@ CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-schannel
|
|||
CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-nghttp2-$(NGHTTP2)
|
||||
!ENDIF
|
||||
|
||||
!IF "$(USE_MSH3)"=="true"
|
||||
CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-msh3
|
||||
!ENDIF
|
||||
|
||||
!MESSAGE configuration name: $(CONFIG_NAME_LIB)
|
||||
|
||||
BUILD_DIR=../builds/$(CONFIG_NAME_LIB)
|
||||
|
@ -261,6 +282,7 @@ $(MODE):
|
|||
@SET CONFIG_NAME_LIB=$(CONFIG_NAME_LIB)
|
||||
@SET MACHINE=$(MACHINE)
|
||||
@SET USE_NGHTTP2=$(USE_NGHTTP2)
|
||||
@SET USE_MSH3=$(USE_MSH3)
|
||||
@SET USE_IDN=$(USE_IDN)
|
||||
@SET USE_IPV6=$(USE_IPV6)
|
||||
@SET USE_SSPI=$(USE_SSPI)
|
||||
|
|
|
@ -164,6 +164,26 @@ NGHTTP2_LIBS = nghttp2.lib
|
|||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
!IFDEF MSH3_PATH
|
||||
MSH3_INC_DIR = $(MSH3_PATH)\include
|
||||
MSH3_LIB_DIR = $(MSH3_PATH)\lib
|
||||
MSH3_LFLAGS = $(MSH3_LFLAGS) "/LIBPATH:$(MSH3_LIB_DIR)"
|
||||
!ELSE
|
||||
MSH3_INC_DIR = $(DEVEL_INCLUDE)
|
||||
MSH3_LIB_DIR = $(DEVEL_LIB)
|
||||
!ENDIF
|
||||
|
||||
!IF "$(WITH_MSH3)"=="dll"
|
||||
MSH3_CFLAGS = /DUSE_MSH3 /I"$(MSH3_INC_DIR)"
|
||||
MSH3_LIBS = msh3.lib
|
||||
!ELSEIF "$(WITH_MSH3)"=="static"
|
||||
MSH3_CFLAGS = /DUSE_MSH3 /DMSH3_STATICLIB /I"$(MSH3_INC_DIR)"
|
||||
!IF EXISTS("$(NGHTTP2_LIB_DIR)\msh3_static.lib")
|
||||
MSH3_LIBS = msh3_static.lib
|
||||
!ELSE
|
||||
MSH3_LIBS = msh3.lib
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
!IFDEF MBEDTLS_PATH
|
||||
MBEDTLS_INC_DIR = $(MBEDTLS_PATH)\include
|
||||
|
@ -492,6 +512,11 @@ CFLAGS = $(CFLAGS) $(NGHTTP2_CFLAGS)
|
|||
LFLAGS = $(LFLAGS) $(NGHTTP2_LFLAGS) $(NGHTTP2_LIBS)
|
||||
!ENDIF
|
||||
|
||||
!IF "$(USE_MSH3)"=="true"
|
||||
CFLAGS = $(CFLAGS) $(MSH3_CFLAGS)
|
||||
LFLAGS = $(LFLAGS) $(MSH3_LFLAGS) $(MSH3_LIBS)
|
||||
!ENDIF
|
||||
|
||||
!IF "$(GEN_PDB)"=="true"
|
||||
CFLAGS = $(CFLAGS) $(CFLAGS_PDB) /Fd"$(LIB_DIROBJ)\$(PDB)"
|
||||
LFLAGS = $(LFLAGS) $(LFLAGS_PDB)
|
||||
|
@ -545,6 +570,7 @@ package: $(TARGET)
|
|||
$(TARGET): $(LIB_OBJS) $(LIB_DIROBJ) $(DIRDIST)
|
||||
@echo Using SSL: $(USE_SSL)
|
||||
@echo Using NGHTTP2: $(USE_NGHTTP2)
|
||||
@echo Using MSH3: $(USE_MSH3)
|
||||
@echo Using c-ares: $(USE_CARES)
|
||||
@echo Using SSH2: $(USE_SSH2)
|
||||
@echo Using SSH: $(USE_SSH)
|
||||
|
|
|
@ -80,6 +80,7 @@ where `<options>` is one or many of:
|
|||
Uncompress them into the deps folder.
|
||||
- `WITH_SSL=<dll/static>` - Enable OpenSSL support, DLL or static
|
||||
- `WITH_NGHTTP2=<dll/static>` - Enable HTTP/2 support, DLL or static
|
||||
- `WITH_MSH3=<dll/static>` - Enable (experimental) HTTP/3 support, DLL or static
|
||||
- `WITH_MBEDTLS=<dll/static>` - Enable mbedTLS support, DLL or static
|
||||
- `WITH_CARES=<dll/static>` - Enable c-ares support, DLL or static
|
||||
- `WITH_ZLIB=<dll/static>` - Enable zlib support, DLL or static
|
||||
|
@ -103,6 +104,7 @@ where `<options>` is one or many of:
|
|||
- `CARES_PATH=<path>` - Custom path for c-ares
|
||||
- `MBEDTLS_PATH=<path>` - Custom path for mbedTLS
|
||||
- `NGHTTP2_PATH=<path>` - Custom path for nghttp2
|
||||
- `MSH3_PATH=<path>` - Custom path for msh3
|
||||
- `SSH2_PATH=<path>` - Custom path for libSSH2
|
||||
- `SSL_PATH=<path>` - Custom path for OpenSSL
|
||||
- `ZLIB_PATH=<path>` - Custom path for zlib
|
||||
|
|
Loading…
Reference in New Issue
Block a user