Skip to content

http_client_asio based on Botan's TLS implementation #1110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
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
18 changes: 16 additions & 2 deletions Release/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ set(CPPREST_VERSION_REVISION 12)

enable_testing()

set(CPPREST_NO_OPENSSL OFF CACHE BOOL "Exclude OpenSSL. Implies CPPREST_EXCLUDE_WEBSOCKETS and CPPREST_EXCLUDE_LISTENER.")
set(CPPREST_EXCLUDE_LISTENER OFF CACHE BOOL "Exclude listerner functionality.")

if(CPPREST_NO_OPENSSL)
message(STATUS "OpenSSL disabled; disabling websockets and http listener.")
set(CPPREST_HTTP_LISTENER_IMPL none CACHE STRING "Internal use.")
set(CPPREST_EXCLUDE_WEBSOCKETS ON CACHE BOOL "Exclude websockets functionality.")
set(BUILD_SAMPLES OFF CACHE BOOL "Build sample applications.")
endif()

set(WERROR ON CACHE BOOL "Treat Warnings as Errors.")
set(CPPREST_EXCLUDE_WEBSOCKETS OFF CACHE BOOL "Exclude websockets functionality.")
set(CPPREST_EXCLUDE_COMPRESSION OFF CACHE BOOL "Exclude compression functionality.")
Expand Down Expand Up @@ -61,8 +71,12 @@ endif()

include(cmake/cpprest_find_boost.cmake)
include(cmake/cpprest_find_zlib.cmake)
include(cmake/cpprest_find_openssl.cmake)
include(cmake/cpprest_find_websocketpp.cmake)
if(CPPREST_NO_OPENSSL)
include(cmake/cpprest_find_botan.cmake)
else()
include(cmake/cpprest_find_openssl.cmake)
include(cmake/cpprest_find_websocketpp.cmake)
endif()
include(cmake/cpprest_find_brotli.cmake)
include(CheckIncludeFiles)
include(GNUInstallDirs)
Expand Down
90 changes: 90 additions & 0 deletions Release/cmake/cpprest_find_botan.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
function(cpprest_find_botan)
if(TARGET cpprestsdk_botan_internal)
return()
endif()

INCLUDE (FindPackageHandleStandardArgs)

SET (_BOTAN_POSSIBLE_DIRS ${BOTAN_ROOT_DIR})

IF (WIN32)
SET (_BOTAN_POSSIBLE_DIRS ${_BOTAN_POSSIBLE_DIRS} "C:\\usr\\local" "C:\\usr")
ENDIF (WIN32)

# Note: after 1.11.34, botan library moved to semantic versioning (a.k.a. 2.0)
SET (_BOTAN_POSSIBLE_INCLUDE_SUFFIXES include include/botan-1.10 include/botan-1.11 include/botan-2.0 include/botan-2)
SET (_BOTAN_POSSIBLE_LIB_SUFFIXES lib)

FIND_PATH (BOTAN_ROOT_DIR
NAMES botan/botan.h
PATHS ${_BOTAN_POSSIBLE_DIRS}
PATH_SUFFIXES ${_BOTAN_POSSIBLE_INCLUDE_SUFFIXES}
DOC "Botan root directory")

FIND_PATH (BOTAN_INCLUDE_DIR
NAMES botan/botan.h
PATHS ${BOTAN_ROOT_DIR}
PATH_SUFFIXES ${_BOTAN_POSSIBLE_INCLUDE_SUFFIXES}
DOC "Botan include directory")

FIND_LIBRARY (BOTAN_LIBRARY_DEBUG
NAMES botand botand-1.10 botand-1.11 botand-2
PATHS ${_BOTAN_POSSIBLE_DIRS}
PATH_SUFFIXES ${_BOTAN_POSSIBLE_LIB_SUFFIXES}
DOC "Botan debug library")

FIND_LIBRARY (BOTAN_LIBRARY_RELEASE
NAMES botan botan-1.10 botan-1.11 botan-2
PATHS ${_BOTAN_POSSIBLE_DIRS}
PATH_SUFFIXES ${_BOTAN_POSSIBLE_LIB_SUFFIXES}
DOC "Botan release library")

IF (NOT DEFINED BOTAN_LIBRARIES)
IF (BOTAN_LIBRARY_DEBUG AND BOTAN_LIBRARY_RELEASE)
SET (BOTAN_LIBRARIES
optimized ${BOTAN_LIBRARY_RELEASE}
debug ${BOTAN_LIBRARY_DEBUG})
ELSEIF (BOTAN_LIBRARY_RELEASE)
SET (BOTAN_LIBRARIES ${BOTAN_LIBRARY_RELEASE})
ENDIF (BOTAN_LIBRARY_DEBUG AND BOTAN_LIBRARY_RELEASE)
ENDIF (NOT DEFINED BOTAN_LIBRARIES)

IF (BOTAN_INCLUDE_DIR)
SET (BOTAN_INCLUDE_DIRS ${BOTAN_INCLUDE_DIR})

SET (_BOTAN_VERSION_HEADER ${BOTAN_INCLUDE_DIR}/botan/build.h)

IF (EXISTS ${_BOTAN_VERSION_HEADER})
FILE (STRINGS ${_BOTAN_VERSION_HEADER} _BOTAN_VERSION_TMP REGEX
"#define BOTAN_VERSION_(MAJOR|MINOR|PATCH)[ \t]+[0-9]+")

STRING (REGEX REPLACE
".*#define BOTAN_VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" BOTAN_VERSION_MAJOR
${_BOTAN_VERSION_TMP})
STRING (REGEX REPLACE
".*#define BOTAN_VERSION_MINOR[ \t]+([0-9]+).*" "\\1" BOTAN_VERSION_MINOR
${_BOTAN_VERSION_TMP})
STRING (REGEX REPLACE
".*#define BOTAN_VERSION_PATCH[ \t]+([0-9]+).*" "\\1" BOTAN_VERSION_PATCH
${_BOTAN_VERSION_TMP})

SET (BOTAN_VERSION_COUNT 3)
SET (BOTAN_VERSION
${BOTAN_VERSION_MAJOR}.${BOTAN_VERSION_MINOR}.${BOTAN_VERSION_PATCH})
ENDIF (EXISTS ${_BOTAN_VERSION_HEADER})
ENDIF (BOTAN_INCLUDE_DIR)

MARK_AS_ADVANCED (BOTAN_ROOT_DIR BOTAN_INCLUDE_DIR BOTAN_LIBRARY_DEBUG
BOTAN_LIBRARY_RELEASE)

FIND_PACKAGE_HANDLE_STANDARD_ARGS (Botan REQUIRED_VARS BOTAN_INCLUDE_DIRS
BOTAN_LIBRARIES VERSION_VAR BOTAN_VERSION)

add_library(Botan INTERFACE)
target_include_directories(Botan INTERFACE ${BOTAN_INCLUDE_DIR})
target_link_libraries(Botan INTERFACE ${BOTAN_LIBRARIES})

add_library(cpprestsdk_botan_internal INTERFACE)
target_link_libraries(cpprestsdk_botan_internal INTERFACE "$<BUILD_INTERFACE:${BOTAN_LIBRARY}>")
target_include_directories(cpprestsdk_botan_internal INTERFACE "$<BUILD_INTERFACE:${BOTAN_INCLUDE_DIR}>")
endfunction()
22 changes: 19 additions & 3 deletions Release/include/cpprest/http_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ typedef void* native_handle;
#include "cpprest/oauth2.h"

#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)

#if defined(CPPREST_BOTAN_SSL)
#include <botan/asio_context.h>
#else // CPPREST_BOTAN_SSL

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
Expand All @@ -69,6 +74,9 @@ typedef void* native_handle;
#if defined(__clang__)
#pragma clang diagnostic pop
#endif

#endif // CPPREST_BOTAN_SSL

#endif

/// The web namespace contains functionality common to multiple protocols like HTTP and WebSockets.
Expand All @@ -86,6 +94,12 @@ namespace client
using web::credentials;
using web::web_proxy;

#if defined(CPPREST_BOTAN_SSL)
using ssl_context_t = Botan::TLS::Context;
#else
using ssl_context_t = boost::asio::ssl::context;
#endif

/// <summary>
/// HTTP client configuration class, used to set the possible configuration options
/// used to create an http_client instance.
Expand Down Expand Up @@ -334,15 +348,15 @@ class http_client_config
/// </summary>
/// <param name="callback">A user callback allowing for customization of the ssl context at construction
/// time.</param>
void set_ssl_context_callback(const std::function<void(boost::asio::ssl::context&)>& callback)
void set_ssl_context_callback(const std::function<void(ssl_context_t&)>& callback)
{
m_ssl_context_callback = callback;
}

/// <summary>
/// Gets the user's callback to allow for customization of the ssl context.
/// </summary>
const std::function<void(boost::asio::ssl::context&)>& get_ssl_context_callback() const
const std::function<void(ssl_context_t&)>& get_ssl_context_callback() const
{
return m_ssl_context_callback;
}
Expand Down Expand Up @@ -386,7 +400,7 @@ class http_client_config
std::function<void(native_handle)> m_set_user_nativesessionhandle_options;

#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
std::function<void(boost::asio::ssl::context&)> m_ssl_context_callback;
std::function<void(ssl_context_t&)> m_ssl_context_callback;
bool m_tlsext_sni_enabled;
#endif
#if defined(_WIN32) && !defined(__cplusplus_winrt)
Expand All @@ -402,6 +416,8 @@ class http_pipeline;
class http_client
{
public:
using ssl_context = ssl_context_t;

/// <summary>
/// Creates a new http_client connected to specified uri.
/// </summary>
Expand Down
19 changes: 16 additions & 3 deletions Release/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,18 @@ endif()
# Http client component
if(CPPREST_HTTP_CLIENT_IMPL STREQUAL "asio")
cpprest_find_boost()
cpprest_find_openssl()
target_compile_definitions(cpprest PUBLIC -DCPPREST_FORCE_HTTP_CLIENT_ASIO)
if(CPPREST_NO_OPENSSL)
cpprest_find_botan()
set(CPPREST_BOTAN_SSL_FLAG "-DCPPREST_BOTAN_SSL")
set(CPPREST_SSL_LINK_LIB cpprestsdk_botan_internal)
else()
cpprest_find_openssl()
set(CPPREST_BOTAN_SSL_FLAG "")
set(CPPREST_SSL_LINK_LIB cpprestsdk_openssl_internal)
endif()
target_compile_definitions(cpprest PUBLIC ${CPPREST_BOTAN_SSL_FLAG} -DCPPREST_FORCE_HTTP_CLIENT_ASIO)
target_sources(cpprest PRIVATE http/client/http_client_asio.cpp http/client/x509_cert_utilities.cpp)
target_link_libraries(cpprest PUBLIC cpprestsdk_boost_internal cpprestsdk_openssl_internal)
target_link_libraries(cpprest PUBLIC cpprestsdk_boost_internal ${CPPREST_SSL_LINK_LIB})
elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winhttp")
target_link_libraries(cpprest PRIVATE
httpapi.lib
Expand Down Expand Up @@ -248,6 +256,7 @@ if(CPPREST_INSTALL)
set(CPPREST_USES_ZLIB OFF)
set(CPPREST_USES_BROTLI OFF)
set(CPPREST_USES_OPENSSL OFF)
set(CPPREST_USES_BOTAN OFF)

set(CPPREST_TARGETS cpprest)
if(TARGET cpprestsdk_boost_internal)
Expand All @@ -266,6 +275,10 @@ if(CPPREST_INSTALL)
list(APPEND CPPREST_TARGETS cpprestsdk_openssl_internal)
set(CPPREST_USES_OPENSSL ON)
endif()
if(TARGET cpprestsdk_botan_internal)
list(APPEND CPPREST_TARGETS cpprestsdk_botan_internal)
set(CPPREST_USES_BOTAN ON)
endif()
if(TARGET cpprestsdk_websocketpp_internal)
list(APPEND CPPREST_TARGETS cpprestsdk_websocketpp_internal)
endif()
Expand Down
Loading