From e3ff9238a46844432f685ddaf99b69a5a76ca98e Mon Sep 17 00:00:00 2001 From: bugdea1er Date: Thu, 4 Apr 2024 17:32:04 +0300 Subject: [PATCH] Add option to use Boost.Asio --- CMakeLists.txt | 21 +++++++++++----- include/crow/http_connection.h | 33 ++++++++++++++++--------- include/crow/http_request.h | 8 ++++++ include/crow/http_server.h | 28 +++++++++++++++------ include/crow/socket_adaptors.h | 45 +++++++++++++++++++++++++--------- include/crow/task_timer.h | 13 +++++++++- include/crow/websocket.h | 18 +++++++++----- tests/unittest.cpp | 13 +++++++--- 8 files changed, 133 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6944e5e90..f02d9c489 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ option(CROW_BUILD_EXAMPLES "Build the examples in the project" ${CROW_I option(CROW_BUILD_TESTS "Build the tests in the project" ${CROW_IS_MAIN_PROJECT}) option(CROW_AMALGAMATE "Combine all headers into one" OFF) option(CROW_INSTALL "Add install step for Crow" ON ) +option(CROW_USE_BOOST "Use Boost.Asio for Crow" OFF) # Possible values: ssl, compression option(CROW_FEATURES "Enable features extending Crow's abilities" "") @@ -62,12 +63,20 @@ target_include_directories(Crow $ ) -find_package(asio REQUIRED) - -target_link_libraries(Crow - INTERFACE - asio::asio -) +if(CROW_USE_BOOST) + find_package(Boost 1.64 COMPONENTS system date_time REQUIRED) + target_link_libraries(Crow + INTERFACE + Boost::boost Boost::system Boost::date_time + ) + target_compile_definitions(Crow INTERFACE CROW_USE_BOOST) +else() + find_package(asio REQUIRED) + target_link_libraries(Crow + INTERFACE + asio::asio + ) +endif() target_compile_definitions(Crow INTERFACE "") diff --git a/include/crow/http_connection.h b/include/crow/http_connection.h index a6c21875e..64bbf07f4 100644 --- a/include/crow/http_connection.h +++ b/include/crow/http_connection.h @@ -1,32 +1,43 @@ #pragma once + +#ifdef CROW_USE_BOOST +#include +#else #ifndef ASIO_STANDALONE #define ASIO_STANDALONE #endif #include +#endif + #include #include #include -#include #include +#include #include "crow/http_parser_merged.h" #include "crow/common.h" -#include "crow/parser.h" +#include "crow/compression.h" #include "crow/http_response.h" #include "crow/logging.h" -#include "crow/settings.h" -#include "crow/task_timer.h" -#include "crow/middleware_context.h" #include "crow/middleware.h" +#include "crow/middleware_context.h" +#include "crow/parser.h" +#include "crow/settings.h" #include "crow/socket_adaptors.h" -#include "crow/compression.h" +#include "crow/task_timer.h" #include "crow/utility.h" namespace crow { +#ifdef CROW_USE_BOOST + namespace asio = boost::asio; + using error_code = boost::system::error_code; +#else + using error_code = asio::error_code; +#endif using tcp = asio::ip::tcp; - #ifdef CROW_ENABLE_DEBUG static std::atomic connectionCount; #endif @@ -81,7 +92,7 @@ namespace crow void start() { auto self = this->shared_from_this(); - adaptor_.start([self](const asio::error_code& ec) { + adaptor_.start([self](const error_code& ec) { if (!ec) { self->start_deadline(); @@ -474,7 +485,7 @@ namespace crow auto self = this->shared_from_this(); adaptor_.socket().async_read_some( asio::buffer(buffer_), - [self](const asio::error_code& ec, std::size_t bytes_transferred) { + [self](const error_code& ec, std::size_t bytes_transferred) { bool error_while_reading = true; if (!ec) { @@ -517,7 +528,7 @@ namespace crow auto self = this->shared_from_this(); asio::async_write( adaptor_.socket(), buffers_, - [self](const asio::error_code& ec, std::size_t /*bytes_transferred*/) { + [self](const error_code& ec, std::size_t /*bytes_transferred*/) { self->res.clear(); self->res_body_copy_.clear(); if (!self->continue_requested) @@ -548,7 +559,7 @@ namespace crow inline void do_write_sync(std::vector& buffers) { - asio::write(adaptor_.socket(), buffers, [&](asio::error_code ec, std::size_t) { + asio::write(adaptor_.socket(), buffers, [&](error_code ec, std::size_t) { if (!ec) { return false; diff --git a/include/crow/http_request.h b/include/crow/http_request.h index 6be82e7ae..daab8271d 100644 --- a/include/crow/http_request.h +++ b/include/crow/http_request.h @@ -1,9 +1,13 @@ #pragma once +#ifdef CROW_USE_BOOST +#include +#else #ifndef ASIO_STANDALONE #define ASIO_STANDALONE #endif #include +#endif #include "crow/common.h" #include "crow/ci_map.h" @@ -11,6 +15,10 @@ namespace crow { +#ifdef CROW_USE_BOOST + namespace asio = boost::asio; +#endif + /// Find and return the value associated with the key. (returns an empty string if nothing is found) template inline const std::string& get_header_value(const T& headers, const std::string& key) diff --git a/include/crow/http_server.h b/include/crow/http_server.h index c53ce70c7..961776184 100644 --- a/include/crow/http_server.h +++ b/include/crow/http_server.h @@ -1,6 +1,11 @@ #pragma once -#include +#ifdef CROW_USE_BOOST +#include +#ifdef CROW_ENABLE_SSL +#include +#endif +#else #ifndef ASIO_STANDALONE #define ASIO_STANDALONE #endif @@ -8,11 +13,14 @@ #ifdef CROW_ENABLE_SSL #include #endif -#include +#endif + #include +#include +#include #include -#include #include +#include #include "crow/version.h" #include "crow/http_connection.h" @@ -21,6 +29,12 @@ namespace crow { +#ifdef CROW_USE_BOOST + namespace asio = boost::asio; + using error_code = boost::system::error_code; +#else + using error_code = asio::error_code; +#endif using tcp = asio::ip::tcp; template @@ -52,7 +66,7 @@ namespace crow { tick_function_(); tick_timer_.expires_after(std::chrono::milliseconds(tick_interval_.count())); - tick_timer_.async_wait([this](const asio::error_code& ec) { + tick_timer_.async_wait([this](const error_code& ec) { if (ec) return; on_tick(); @@ -128,7 +142,7 @@ namespace crow { tick_timer_.expires_after(std::chrono::milliseconds(tick_interval_.count())); tick_timer_.async_wait( - [this](const asio::error_code& ec) { + [this](const error_code& ec) { if (ec) return; on_tick(); @@ -143,7 +157,7 @@ namespace crow CROW_LOG_INFO << "Call `app.loglevel(crow::LogLevel::Warning)` to hide Info level logs."; signals_.async_wait( - [&](const asio::error_code& /*error*/, int /*signal_number*/) { + [&](const error_code& /*error*/, int /*signal_number*/) { stop(); }); @@ -227,7 +241,7 @@ namespace crow acceptor_.async_accept( p->socket(), - [this, p, &is, service_idx](asio::error_code ec) { + [this, p, &is, service_idx](error_code ec) { if (!ec) { is.post( diff --git a/include/crow/socket_adaptors.h b/include/crow/socket_adaptors.h index 478840ef4..e338750d5 100644 --- a/include/crow/socket_adaptors.h +++ b/include/crow/socket_adaptors.h @@ -1,20 +1,41 @@ #pragma once + +#ifdef CROW_USE_BOOST +#include +#include +#ifdef CROW_ENABLE_SSL +#include +#endif +#if BOOST_VERSION >= 107000 +#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context()) +#else +#define GET_IO_SERVICE(s) ((s).get_io_service()) +#endif +#else #ifndef ASIO_STANDALONE #define ASIO_STANDALONE #endif #include +#include #ifdef CROW_ENABLE_SSL #include #endif -#include "crow/settings.h" -#include #if ASIO_VERSION >= 101300 // 1.13.0 #define GET_IO_SERVICE(s) ((asio::io_context&)(s).get_executor().context()) #else #define GET_IO_SERVICE(s) ((s).get_io_service()) #endif +#endif +#include "crow/settings.h" + namespace crow { +#ifdef CROW_USE_BOOST + namespace asio = boost::asio; + using error_code = boost::system::error_code; +#else + using error_code = asio::error_code; +#endif using tcp = asio::ip::tcp; /// A wrapper for the asio::ip::tcp::socket and asio::ssl::stream @@ -54,32 +75,32 @@ namespace crow void close() { - asio::error_code ec; + error_code ec; socket_.close(ec); } void shutdown_readwrite() { - asio::error_code ec; + error_code ec; socket_.shutdown(asio::socket_base::shutdown_type::shutdown_both, ec); } void shutdown_write() { - asio::error_code ec; + error_code ec; socket_.shutdown(asio::socket_base::shutdown_type::shutdown_send, ec); } void shutdown_read() { - asio::error_code ec; + error_code ec; socket_.shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec); } template void start(F f) { - f(asio::error_code()); + f(error_code()); } tcp::socket socket_; @@ -119,7 +140,7 @@ namespace crow { if (is_open()) { - asio::error_code ec; + error_code ec; raw_socket().close(ec); } } @@ -128,7 +149,7 @@ namespace crow { if (is_open()) { - asio::error_code ec; + error_code ec; raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_both, ec); } } @@ -137,7 +158,7 @@ namespace crow { if (is_open()) { - asio::error_code ec; + error_code ec; raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_send, ec); } } @@ -146,7 +167,7 @@ namespace crow { if (is_open()) { - asio::error_code ec; + error_code ec; raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec); } } @@ -160,7 +181,7 @@ namespace crow void start(F f) { ssl_socket_->async_handshake(asio::ssl::stream_base::server, - [f](const asio::error_code& ec) { + [f](const error_code& ec) { f(ec); }); } diff --git a/include/crow/task_timer.h b/include/crow/task_timer.h index 5ced714fd..15b65b639 100644 --- a/include/crow/task_timer.h +++ b/include/crow/task_timer.h @@ -1,10 +1,15 @@ #pragma once +#ifdef CROW_USE_BOOST +#include +#include +#else #ifndef ASIO_STANDALONE #define ASIO_STANDALONE #endif #include #include +#endif #include #include @@ -15,6 +20,12 @@ namespace crow { +#ifdef CROW_USE_BOOST + namespace asio = boost::asio; + using error_code = boost::system::error_code; +#else + using error_code = asio::error_code; +#endif namespace detail { @@ -112,7 +123,7 @@ namespace crow if (tasks_.empty()) highest_id_ = 0; } - void tick_handler(const asio::error_code& ec) + void tick_handler(const error_code& ec) { if (ec) return; diff --git a/include/crow/websocket.h b/include/crow/websocket.h index c7d8f0638..13027165b 100644 --- a/include/crow/websocket.h +++ b/include/crow/websocket.h @@ -8,6 +8,12 @@ namespace crow { +#ifdef CROW_USE_BOOST + namespace asio = boost::asio; + using error_code = boost::system::error_code; +#else + using error_code = asio::error_code; +#endif namespace websocket { enum class WebSocketReadState @@ -299,7 +305,7 @@ namespace crow //asio::async_read(adaptor_.socket(), asio::buffer(&mini_header_, 1), adaptor_.socket().async_read_some( asio::buffer(&mini_header_, 2), - [this](const asio::error_code& ec, std::size_t + [this](const error_code& ec, std::size_t #ifdef CROW_ENABLE_DEBUG bytes_transferred #endif @@ -367,7 +373,7 @@ namespace crow remaining_length16_ = 0; asio::async_read( adaptor_.socket(), asio::buffer(&remaining_length16_, 2), - [this](const asio::error_code& ec, std::size_t + [this](const error_code& ec, std::size_t #ifdef CROW_ENABLE_DEBUG bytes_transferred #endif @@ -403,7 +409,7 @@ namespace crow { asio::async_read( adaptor_.socket(), asio::buffer(&remaining_length_, 8), - [this](const asio::error_code& ec, std::size_t + [this](const error_code& ec, std::size_t #ifdef CROW_ENABLE_DEBUG bytes_transferred #endif @@ -447,7 +453,7 @@ namespace crow { asio::async_read( adaptor_.socket(), asio::buffer((char*)&mask_, 4), - [this](const asio::error_code& ec, std::size_t + [this](const error_code& ec, std::size_t #ifdef CROW_ENABLE_DEBUG bytes_transferred #endif @@ -489,7 +495,7 @@ namespace crow to_read = remaining_length_; adaptor_.socket().async_read_some( asio::buffer(buffer_, static_cast(to_read)), - [this](const asio::error_code& ec, std::size_t bytes_transferred) { + [this](const error_code& ec, std::size_t bytes_transferred) { is_reading = false; if (!ec) @@ -641,7 +647,7 @@ namespace crow auto watch = std::weak_ptr{anchor_}; asio::async_write( adaptor_.socket(), buffers, - [&, watch](const asio::error_code& ec, std::size_t /*bytes_transferred*/) { + [&, watch](const error_code& ec, std::size_t /*bytes_transferred*/) { if (!ec && !close_connection_) { sending_buffers_.clear(); diff --git a/tests/unittest.cpp b/tests/unittest.cpp index 7e2b4011d..eb65fe1c9 100644 --- a/tests/unittest.cpp +++ b/tests/unittest.cpp @@ -19,6 +19,13 @@ using namespace std; using namespace crow; +#ifdef CROW_USE_BOOST +namespace asio = boost::asio; +using asio_error_code = boost::system::error_code; +#else +using asio_error_code = asio::error_code; +#endif + #define LOCALHOST_ADDRESS "127.0.0.1" TEST_CASE("Rule") @@ -2925,7 +2932,7 @@ TEST_CASE("websocket_max_payload") } } - asio::error_code ec; + asio_error_code ec; c.lowest_layer().shutdown(asio::socket_base::shutdown_type::shutdown_both, ec); app.stop(); @@ -3510,7 +3517,7 @@ TEST_CASE("timeout") asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451)); auto receive_future = async(launch::async, [&]() { - asio::error_code ec; + asio_error_code ec; c.receive(asio::buffer(buf, 2048), 0, ec); return ec; }); @@ -3530,7 +3537,7 @@ TEST_CASE("timeout") size_t received; auto receive_future = async(launch::async, [&]() { - asio::error_code ec; + asio_error_code ec; received = c.receive(asio::buffer(buf, 2048), 0, ec); return ec; });