diff --git a/CMakeLists.txt b/CMakeLists.txt index 7493e07..2bc26cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.5) project(asio_net CXX) option(ASIO_NET_ENABLE_RPC "" ON) +option(ASIO_NET_ENABLE_SSL "" OFF) option(ASIO_NET_BUILD_TEST "" OFF) @@ -17,6 +18,9 @@ add_compile_options(-Wall) add_library(${PROJECT_NAME} INTERFACE) target_include_directories(${PROJECT_NAME} INTERFACE .) +if (ASIO_NET_ENABLE_SSL) + target_compile_definitions(${PROJECT_NAME} INTERFACE -DASIO_NET_ENABLE_SSL) +endif () if (ASIO_NET_ENABLE_RPC) target_include_directories(${PROJECT_NAME} INTERFACE @@ -25,11 +29,17 @@ if (ASIO_NET_ENABLE_RPC) ) endif () +if (ASIO_NET_ENABLE_SSL) + find_package(OpenSSL 1.1.0 REQUIRED) + target_link_libraries(${PROJECT_NAME} INTERFACE OpenSSL::SSL) +endif () + if (ASIO_NET_BUILD_TEST) message(STATUS "ASIO_PATH: $ENV{ASIO_PATH}") include_directories($ENV{ASIO_PATH}) link_libraries(${PROJECT_NAME}) link_libraries(pthread) + add_definitions(-DOPENSSL_PEM_PATH=\"${CMAKE_CURRENT_LIST_DIR}/test/ssl/\") # for github actions/ci if (ASIO_NET_DISABLE_ON_DATA_PRINT) @@ -50,6 +60,10 @@ if (ASIO_NET_BUILD_TEST) add_executable(${PROJECT_NAME}_test_server_discovery test/server_discovery.cpp) add_executable(${PROJECT_NAME}_test_domain_tcp test/domain_tcp.cpp) add_executable(${PROJECT_NAME}_test_domain_udp test/domain_udp.cpp) + if (ASIO_NET_ENABLE_SSL) + add_executable(${PROJECT_NAME}_test_tcp_ssl_c test/tcp_ssl_c.cpp) + add_executable(${PROJECT_NAME}_test_tcp_ssl_s test/tcp_ssl_s.cpp) + endif () if (ASIO_NET_ENABLE_RPC) add_compile_definitions(RPC_CORE_LOG_SHOW_DEBUG) @@ -60,5 +74,8 @@ if (ASIO_NET_BUILD_TEST) add_executable(${PROJECT_NAME}_test_rpc_s test/rpc_s.cpp) add_executable(${PROJECT_NAME}_test_rpc_c test/rpc_c.cpp) add_executable(${PROJECT_NAME}_test_domain_rpc test/domain_rpc.cpp) + if (ASIO_NET_ENABLE_SSL) + add_executable(${PROJECT_NAME}_test_rpc_ssl test/rpc_ssl.cpp) + endif () endif () endif () diff --git a/README.md b/README.md index 80cea4d..1b148b6 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ and [rpc_core](https://github.com/shuai132/rpc_core) * TCP/UDP support, rely on: [asio](http://think-async.com/Asio/) * RPC support, rely on: [rpc_core](https://github.com/shuai132/rpc_core) * Service discovery based on UDP multicast -* Domain socket and rpc support, compatible with IPv6 +* Support IPv6 and SSL (with OpenSSL) +* Domain socket and rpc support * Comprehensive unittests * Automatic reconnection diff --git a/detail/socket_type.hpp b/detail/socket_type.hpp new file mode 100644 index 0000000..079b085 --- /dev/null +++ b/detail/socket_type.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include "asio.hpp" +#include "log.h" +#include "noncopyable.hpp" + +#ifdef ASIO_NET_ENABLE_SSL +#include "asio/ssl.hpp" +#endif + +namespace asio_net { +namespace detail { + +enum class socket_type { + normal, + domain, + ssl, +}; + +template +struct socket_impl; + +template <> +struct socket_impl { + using socket = asio::ip::tcp::socket; + using endpoint = asio::ip::tcp::endpoint; + using resolver = asio::ip::tcp::resolver; + using acceptor = asio::ip::tcp::acceptor; +}; + +template <> +struct socket_impl { + using socket = asio::local::stream_protocol::socket; + using endpoint = asio::local::stream_protocol::endpoint; + using acceptor = asio::local::stream_protocol::acceptor; +}; + +#ifdef ASIO_NET_ENABLE_SSL +template <> +struct socket_impl { + using socket = asio::ssl::stream; + using endpoint = asio::ip::tcp::endpoint; + using resolver = asio::ip::tcp::resolver; + using acceptor = asio::ip::tcp::acceptor; +}; +#endif + +} // namespace detail +} // namespace asio_net diff --git a/detail/tcp_channel_t.hpp b/detail/tcp_channel_t.hpp index 4b63bde..e37645d 100644 --- a/detail/tcp_channel_t.hpp +++ b/detail/tcp_channel_t.hpp @@ -7,18 +7,16 @@ #include "log.h" #include "message.hpp" #include "noncopyable.hpp" +#include "socket_type.hpp" #include "type.h" namespace asio_net { namespace detail { -template +template class tcp_channel_t : private noncopyable { - using socket = typename T::socket; - using endpoint = typename T::endpoint; - public: - tcp_channel_t(socket& socket, const config& config) : socket_(socket), config_(config) { + tcp_channel_t(typename socket_impl::socket& socket, const config& config) : socket_(socket), config_(config) { ASIO_NET_LOGD("tcp_channel: %p", this); } @@ -30,14 +28,18 @@ class tcp_channel_t : private noncopyable { void init_socket() { if (config_.socket_send_buffer_size != UINT32_MAX) { asio::socket_base::send_buffer_size option(config_.socket_send_buffer_size); - socket_.set_option(option); + get_socket().set_option(option); } if (config_.socket_recv_buffer_size != UINT32_MAX) { asio::socket_base::receive_buffer_size option(config_.socket_recv_buffer_size); - socket_.set_option(option); + get_socket().set_option(option); } } + inline auto& get_socket() const { + return socket_.lowest_layer(); + } + public: /** * async send message @@ -60,14 +62,14 @@ class tcp_channel_t : private noncopyable { } bool is_open() const { - return socket_.is_open(); + return get_socket().is_open(); } - endpoint local_endpoint() { + typename socket_impl::endpoint local_endpoint() { return socket_.local_endpoint(); } - endpoint remote_endpoint() { + typename socket_impl::endpoint remote_endpoint() { return socket_.remote_endpoint(); } @@ -187,7 +189,7 @@ class tcp_channel_t : private noncopyable { if (!is_open()) return; asio::error_code ec; - socket_.close(ec); + get_socket().close(ec); if (ec) { ASIO_NET_LOGW("do_close: %s", ec.message().c_str()); } @@ -202,7 +204,7 @@ class tcp_channel_t : private noncopyable { } private: - socket& socket_; + typename socket_impl::socket& socket_; const config& config_; detail::message read_msg_; uint32_t send_buffer_now_ = 0; diff --git a/detail/tcp_client_t.hpp b/detail/tcp_client_t.hpp index 5cd68ae..e3a7595 100644 --- a/detail/tcp_client_t.hpp +++ b/detail/tcp_client_t.hpp @@ -6,17 +6,21 @@ namespace asio_net { namespace detail { -template +template class tcp_client_t : public tcp_channel_t { - using socket = typename T::socket; - using endpoint = typename T::endpoint; - public: explicit tcp_client_t(asio::io_context& io_context, config config = {}) : tcp_channel_t(socket_, config_), io_context_(io_context), socket_(io_context), config_(config) { config_.init(); } +#ifdef ASIO_NET_ENABLE_SSL + explicit tcp_client_t(asio::io_context& io_context, asio::ssl::context& ssl_context, config config = {}) + : tcp_channel_t(socket_, config_), io_context_(io_context), socket_(io_context, ssl_context), config_(config) { + config_.init(); + } +#endif + /** * connect to server * @@ -49,7 +53,7 @@ class tcp_client_t : public tcp_channel_t { void set_reconnect(uint32_t ms) { reconnect_ms_ = ms; - reconnect_timer_ = std::make_unique(socket_.get_executor()); + reconnect_timer_ = std::make_unique(io_context_); } void cancel_reconnect() { @@ -83,30 +87,36 @@ class tcp_client_t : public tcp_channel_t { private: void do_open(const std::string& host, uint16_t port) { - static_assert(std::is_same::value, ""); - auto resolver = std::make_unique(socket_.get_executor()); + static_assert(T == socket_type::normal || T == socket_type::ssl, ""); + auto resolver = std::make_unique::resolver>(io_context_); auto rp = resolver.get(); - rp->async_resolve(typename T::resolver::query(host, std::to_string(port)), - [this, resolver = std::move(resolver)](const std::error_code& ec, const typename T::resolver::results_type& endpoints) { - if (!ec) { - asio::async_connect(socket_, endpoints, [this](const std::error_code& ec, const endpoint&) { - async_connect_handler(ec); - }); - } else { - if (on_open_failed) on_open_failed(ec); - check_reconnect(); - } - }); + rp->async_resolve( + typename socket_impl::resolver::query(host, std::to_string(port)), + [this, resolver = std::move(resolver)](const std::error_code& ec, const typename socket_impl::resolver::results_type& endpoints) { + if (!ec) { + asio::async_connect(tcp_channel_t::get_socket(), endpoints, + [this](const std::error_code& ec, const typename socket_impl::endpoint&) { + async_connect_handler(ec); + }); + } else { + if (on_open_failed) on_open_failed(ec); + check_reconnect(); + } + }); } void do_open(const std::string& endpoint) { - static_assert(std::is_same::value, ""); - socket_.async_connect(typename T::endpoint(endpoint), [this](const std::error_code& ec) { - async_connect_handler(ec); + static_assert(T == socket_type::domain, ""); + socket_.async_connect(typename socket_impl::endpoint(endpoint), [this](const std::error_code& ec) { + async_connect_handler(ec); }); } - void async_connect_handler(const std::error_code& ec) { + template + void async_connect_handler(const std::error_code& ec); + + template <> + void async_connect_handler(const std::error_code& ec) { if (!ec) { this->init_socket(); tcp_channel_t::on_close = [this] { @@ -124,6 +134,39 @@ class tcp_client_t : public tcp_channel_t { } } + template <> + inline void async_connect_handler(const std::error_code& ec) { + async_connect_handler(ec); + } + +#ifdef ASIO_NET_ENABLE_SSL + template <> + void async_connect_handler(const std::error_code& ec) { + if (!ec) { + this->init_socket(); + socket_.async_handshake(asio::ssl::stream_base::client, [this](const std::error_code& error) { + if (!error) { + tcp_channel_t::on_close = [this] { + tcp_client_t::on_close(); + check_reconnect(); + }; + if (on_open) on_open(); + if (reconnect_timer_) { + reconnect_timer_->cancel(); + } + this->do_read_start(); + } else { + if (on_open_failed) on_open_failed(error); + check_reconnect(); + } + }); + } else { + if (on_open_failed) on_open_failed(ec); + check_reconnect(); + } + } +#endif + public: std::function on_open; std::function on_open_failed; @@ -134,7 +177,7 @@ class tcp_client_t : public tcp_channel_t { private: asio::io_context& io_context_; - socket socket_; + typename socket_impl::socket socket_; config config_; std::unique_ptr reconnect_timer_; uint32_t reconnect_ms_ = 0; diff --git a/detail/tcp_server_t.hpp b/detail/tcp_server_t.hpp index 022dd7d..f17a7ab 100644 --- a/detail/tcp_server_t.hpp +++ b/detail/tcp_server_t.hpp @@ -9,9 +9,9 @@ namespace asio_net { namespace detail { -template +template class tcp_session_t : public tcp_channel_t, public std::enable_shared_from_this> { - using socket = typename T::socket; + using socket = typename socket_impl::socket; public: explicit tcp_session_t(socket socket, const config& config) : tcp_channel_t(socket_, config), socket_(std::move(socket)) { @@ -22,21 +22,41 @@ class tcp_session_t : public tcp_channel_t, public std::enable_shared_from_th tcp_channel_t::do_read_start(tcp_session_t::shared_from_this()); } +#ifdef ASIO_NET_ENABLE_SSL + void async_handshake(std::function handle) { + socket_.async_handshake(asio::ssl::stream_base::server, [this, handle = std::move(handle)](const std::error_code& error) { + handle(error); + if (!error) { + this->start(); + } + }); + } +#endif + private: socket socket_; }; -template +template class tcp_server_t { - using socket = typename T::socket; - using endpoint = typename T::endpoint; + using socket = typename socket_impl::socket; + using endpoint = typename socket_impl::endpoint; public: tcp_server_t(asio::io_context& io_context, uint16_t port, config config = {}) - : io_context_(io_context), acceptor_(io_context, endpoint(config.enable_ipv6 ? T::v6() : T::v4(), port)), config_(config) { + : io_context_(io_context), + acceptor_(io_context, endpoint(config.enable_ipv6 ? asio::ip::tcp::v6() : asio::ip::tcp::v4(), port)), + config_(config) { config_.init(); } +#ifdef ASIO_NET_ENABLE_SSL + tcp_server_t(asio::io_context& io_context, uint16_t port, asio::ssl::context& ssl_context, config config = {}) + : io_context_(io_context), ssl_context_(ssl_context), acceptor_(io_context, endpoint(asio::ip::tcp::v4(), port)), config_(config) { + config_.init(); + } +#endif + /** * domain socket * @@ -45,13 +65,13 @@ class tcp_server_t { * @param config */ tcp_server_t(asio::io_context& io_context, const std::string& endpoint, config config = {}) - : io_context_(io_context), acceptor_(io_context, typename T::endpoint(endpoint)), config_(config) { + : io_context_(io_context), acceptor_(io_context, typename socket_impl::endpoint(endpoint)), config_(config) { config_.init(); } public: void start(bool loop = false) { - do_accept(); + do_accept(); if (loop) { io_context_.run(); } @@ -59,24 +79,58 @@ class tcp_server_t { public: std::function>)> on_session; + std::function on_handshake_error; private: - void do_accept() { + template + void do_accept(); + + template <> + void do_accept() { acceptor_.async_accept([this](const std::error_code& ec, socket socket) { if (!ec) { auto session = std::make_shared>(std::move(socket), config_); session->start(); if (on_session) on_session(session); - do_accept(); + do_accept(); + } else { + ASIO_NET_LOGE("do_accept: %s", ec.message().c_str()); + } + }); + } + + template <> + inline void do_accept() { + do_accept(); + } + +#ifdef ASIO_NET_ENABLE_SSL + template <> + void do_accept() { + acceptor_.async_accept([this](const std::error_code& ec, asio::ip::tcp::socket socket) { + if (!ec) { + auto session = std::make_shared>(typename socket_impl::socket(std::move(socket), ssl_context_), config_); + session->async_handshake([this, session](const std::error_code& error) { + if (!error) { + if (on_session) on_session(session); + } else { + if (on_handshake_error) on_handshake_error(error); + } + }); + do_accept(); } else { ASIO_NET_LOGE("do_accept: %s", ec.message().c_str()); } }); } +#endif private: asio::io_context& io_context_; - typename T::acceptor acceptor_; +#ifdef ASIO_NET_ENABLE_SSL + typename std::conditional::type ssl_context_; +#endif + typename socket_impl::acceptor acceptor_; config config_; }; diff --git a/rpc/detail/rpc_client_t.hpp b/rpc/detail/rpc_client_t.hpp index 7ad750f..0b26e27 100644 --- a/rpc/detail/rpc_client_t.hpp +++ b/rpc/detail/rpc_client_t.hpp @@ -2,15 +2,15 @@ #include -#include "rpc_core.hpp" #include "detail/noncopyable.hpp" +#include "rpc_core.hpp" #include "rpc_session.hpp" #include "tcp_client.hpp" namespace asio_net { namespace detail { -template +template class rpc_client_t : noncopyable { public: explicit rpc_client_t(asio::io_context& io_context, uint32_t max_body_size = UINT32_MAX) @@ -34,13 +34,36 @@ class rpc_client_t : noncopyable { }; } +#ifdef ASIO_NET_ENABLE_SSL + explicit rpc_client_t(asio::io_context& io_context, asio::ssl::context& ssl_context, uint32_t max_body_size = UINT32_MAX) + : io_context_(io_context), + client_(std::make_shared>(io_context, ssl_context, config{.auto_pack = true, .max_body_size = max_body_size})) { + client_->on_open = [this]() { + auto session = std::make_shared>(io_context_); + session->init(client_); + + session->on_close = [this] { + client_->on_data = nullptr; + if (on_close) on_close(); + client_->check_reconnect(); + }; + + if (on_open) on_open(session->rpc); + }; + + client_->on_open_failed = [this](const std::error_code& ec) { + if (on_open_failed) on_open_failed(ec); + }; + } +#endif + void open(std::string ip, uint16_t port) { - static_assert(std::is_same::value, ""); + static_assert(T == socket_type::normal || T == socket_type::ssl, ""); client_->open(std::move(ip), port); } void open(std::string endpoint) { - static_assert(std::is_same::value, ""); + static_assert(T == socket_type::domain, ""); client_->open(std::move(endpoint)); } diff --git a/rpc/detail/rpc_server_t.hpp b/rpc/detail/rpc_server_t.hpp index b576bbf..4824488 100644 --- a/rpc/detail/rpc_server_t.hpp +++ b/rpc/detail/rpc_server_t.hpp @@ -9,12 +9,12 @@ namespace asio_net { namespace detail { -template +template class rpc_server_t : noncopyable { public: rpc_server_t(asio::io_context& io_context, uint16_t port, bool enable_ipv6 = false, uint32_t max_body_size = UINT32_MAX) : io_context_(io_context), server_(io_context, port, config{.auto_pack = true, .enable_ipv6 = enable_ipv6, .max_body_size = max_body_size}) { - static_assert(std::is_same::value, ""); + static_assert(T == detail::socket_type::normal, ""); server_.on_session = [this](std::weak_ptr> ws) { auto session = std::make_shared>(io_context_); session->init(std::move(ws)); @@ -24,10 +24,29 @@ class rpc_server_t : noncopyable { }; } +#ifdef ASIO_NET_ENABLE_SSL + rpc_server_t(asio::io_context& io_context, uint16_t port, asio::ssl::context& ssl_context, bool enable_ipv6 = false, + uint32_t max_body_size = UINT32_MAX) + : io_context_(io_context), + server_(io_context, port, ssl_context, config{.auto_pack = true, .enable_ipv6 = enable_ipv6, .max_body_size = max_body_size}) { + static_assert(T == detail::socket_type::ssl, ""); + server_.on_session = [this](std::weak_ptr> ws) { + auto session = std::make_shared>(io_context_); + session->init(std::move(ws)); + if (on_session) { + on_session(session); + } + }; + server_.on_handshake_error = [this](std::error_code ec) { + if (on_handshake_error) on_handshake_error(ec); + }; + } +#endif + rpc_server_t(asio::io_context& io_context, const std::string& endpoint, bool enable_ipv6 = false, uint32_t max_body_size = UINT32_MAX) : io_context_(io_context), server_(io_context, endpoint, config{.auto_pack = true, .enable_ipv6 = enable_ipv6, .max_body_size = max_body_size}) { - static_assert(std::is_same::value, ""); + static_assert(T == detail::socket_type::domain, ""); server_.on_session = [this](std::weak_ptr> ws) { auto session = std::make_shared>(io_context_); session->init(std::move(ws)); @@ -44,6 +63,7 @@ class rpc_server_t : noncopyable { public: std::function>)> on_session; + std::function on_handshake_error; private: asio::io_context& io_context_; diff --git a/rpc/detail/rpc_session_t.hpp b/rpc/detail/rpc_session_t.hpp index c08dfe8..bb4236c 100644 --- a/rpc/detail/rpc_session_t.hpp +++ b/rpc/detail/rpc_session_t.hpp @@ -9,7 +9,7 @@ namespace asio_net { namespace detail { -template +template class rpc_session_t : noncopyable, public std::enable_shared_from_this> { public: explicit rpc_session_t(asio::io_context& io_context) : io_context_(io_context) { diff --git a/rpc/rpc_client.hpp b/rpc/rpc_client.hpp index a52b09a..adcb998 100644 --- a/rpc/rpc_client.hpp +++ b/rpc/rpc_client.hpp @@ -4,7 +4,8 @@ namespace asio_net { -using rpc_client = detail::rpc_client_t; -using domain_rpc_client = detail::rpc_client_t; +using rpc_client = detail::rpc_client_t; +using rpc_client_ssl = detail::rpc_client_t; +using domain_rpc_client = detail::rpc_client_t; } // namespace asio_net diff --git a/rpc/rpc_server.hpp b/rpc/rpc_server.hpp index 31574b2..b1a6668 100644 --- a/rpc/rpc_server.hpp +++ b/rpc/rpc_server.hpp @@ -4,7 +4,8 @@ namespace asio_net { -using rpc_server = detail::rpc_server_t; -using domain_rpc_server = detail::rpc_server_t; +using rpc_server = detail::rpc_server_t; +using rpc_server_ssl = detail::rpc_server_t; +using domain_rpc_server = detail::rpc_server_t; } // namespace asio_net diff --git a/rpc/rpc_session.hpp b/rpc/rpc_session.hpp index f496baa..fba6052 100644 --- a/rpc/rpc_session.hpp +++ b/rpc/rpc_session.hpp @@ -4,7 +4,8 @@ namespace asio_net { -using rpc_session = detail::rpc_session_t; -using domain_rpc_session = detail::rpc_session_t; +using rpc_session = detail::rpc_session_t; +using rpc_session_ssl = detail::rpc_session_t; +using domain_rpc_session = detail::rpc_session_t; } // namespace asio_net diff --git a/tcp_client.hpp b/tcp_client.hpp index 5cbd545..1531ab1 100644 --- a/tcp_client.hpp +++ b/tcp_client.hpp @@ -4,7 +4,8 @@ namespace asio_net { -using tcp_client = detail::tcp_client_t; -using domain_tcp_client = detail::tcp_client_t; +using tcp_client = detail::tcp_client_t; +using tcp_client_ssl = detail::tcp_client_t; +using domain_tcp_client = detail::tcp_client_t; } // namespace asio_net diff --git a/tcp_server.hpp b/tcp_server.hpp index 047c5d9..384a654 100644 --- a/tcp_server.hpp +++ b/tcp_server.hpp @@ -4,10 +4,12 @@ namespace asio_net { -using tcp_session = detail::tcp_session_t; -using tcp_server = detail::tcp_server_t; +using tcp_session = detail::tcp_session_t; +using tcp_session_ssl = detail::tcp_session_t; +using tcp_server = detail::tcp_server_t; +using tcp_server_ssl = detail::tcp_server_t; -using domain_tcp_session = detail::tcp_session_t; -using domain_tcp_server = detail::tcp_server_t; +using domain_tcp_session = detail::tcp_session_t; +using domain_tcp_server = detail::tcp_server_t; } // namespace asio_net diff --git a/test/rpc_reconnect.cpp b/test/rpc_reconnect.cpp index 0cfe6a3..0214823 100644 --- a/test/rpc_reconnect.cpp +++ b/test/rpc_reconnect.cpp @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/test/rpc_ssl.cpp b/test/rpc_ssl.cpp new file mode 100644 index 0000000..021f8b0 --- /dev/null +++ b/test/rpc_ssl.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +#include "assert_def.h" +#include "log.h" +#include "rpc_client.hpp" +#include "rpc_server.hpp" + +using namespace asio_net; + +const uint16_t PORT = 6666; + +int main(int argc, char** argv) { + // test flags + static std::atomic_bool pass_flag_rpc_pass{false}; + static std::atomic_bool pass_flag_session_close{false}; + static std::atomic_bool pass_flag_client_close{false}; + + // server + std::thread([] { + asio::io_context context; + asio::ssl::context ssl_context(asio::ssl::context::sslv23); + { + ssl_context.set_options(asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::single_dh_use); + ssl_context.set_password_callback(std::bind([] { // NOLINT + return "test"; + })); + ssl_context.use_certificate_chain_file(OPENSSL_PEM_PATH "server.pem"); + ssl_context.use_private_key_file(OPENSSL_PEM_PATH "server.pem", asio::ssl::context::pem); + ssl_context.use_tmp_dh_file(OPENSSL_PEM_PATH "dh4096.pem"); + } + static rpc_server_ssl server(context, PORT, ssl_context); // static for test session lifecycle + server.on_session = [](const std::weak_ptr& rs) { + LOG("on_session:"); + auto session = rs.lock(); + session->on_close = [] { + LOG("session on_close:"); + pass_flag_session_close = true; + }; + session->rpc->subscribe("cmd", [](const std::string& data) -> std::string { + LOG("session on cmd: %s", data.c_str()); + ASSERT(data == "hello"); + return "world"; + }); + }; + server.on_handshake_error = [](std::error_code ec) { + LOGE("on_handshake_error: %d, %s", ec.value(), ec.message().c_str()); + }; + server.start(true); + }).detach(); + + // client + std::thread([] { + asio::io_context context; + asio::ssl::context ssl_context(asio::ssl::context::sslv23); + ssl_context.load_verify_file(OPENSSL_PEM_PATH "ca.pem"); + static rpc_client_ssl client(context, ssl_context); // static for test session lifecycle + client.on_open = [&](const std::shared_ptr& rpc) { + LOG("client on_open:"); + rpc->cmd("cmd") + ->msg(std::string("hello")) + ->rsp([&](const std::string& data) { + LOG("cmd rsp: %s", data.c_str()); + if (data == "world") { + pass_flag_rpc_pass = true; + } + client.close(); + }) + ->call(); + }; + client.on_close = [&] { + pass_flag_client_close = true; + LOG("client on_close:"); + client.stop(); + }; + client.open("localhost", PORT); + client.run(); + }).join(); + + ASSERT(pass_flag_rpc_pass); + ASSERT(pass_flag_client_close); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ASSERT(pass_flag_session_close); + LOG("all rpc_session should destroyed before here!!!"); + + return EXIT_SUCCESS; +} diff --git a/test/ssl/ca.pem b/test/ssl/ca.pem new file mode 100644 index 0000000..4580bc1 --- /dev/null +++ b/test/ssl/ca.pem @@ -0,0 +1,50 @@ +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIUX3cVQ47QyJp7SOy0RPzP743W9MwwDQYJKoZIhvcNAQEL +BQAwOzELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5 +MQ0wCwYDVQQKDARhc2lvMB4XDTIxMTExMTIxMTA1MloXDTI2MTExMDIxMTA1Mlow +OzELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5MQ0w +CwYDVQQKDARhc2lvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyURD +LjKxTCkapmWhY0bP1NaaOPzIJTTB0dzREOlmRmBmiHpW7DaRx7qBm6jYDKQ7OCbz +30/j8K4TjHOLIwxzXhXMYTJOcN2giPHNUBvm9oEuDAhYgltArJQnBBEH+3C1hCIv +1+uhTWo0HpGXTeJnvboTZ1YgmbOgr6lMhNiu9QmPX885DxWf6sDq8mRgCDX2x8sk +Ls0HuLSo88Osjx532yEhnrZgexsByhoRD3yrKHV5mWpaunk5BMsP/XMuQHayFmbO +siqnHJoL1znGVH003PcBGmEDmoIUqhLiBi2gWGu1pmckP9loqQUTEn0aLOVclHf4 +slWq344zh4tJCpQMfQIDAQABo1AwTjAdBgNVHQ4EFgQUfiX1CMQrGDi9mIBAg9cg +m0RwLJUwHwYDVR0jBBgwFoAUfiX1CMQrGDi9mIBAg9cgm0RwLJUwDAYDVR0TBAUw +AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAnDnVNSb8z/pNFaZ6YAZ+ukfNT3jjbGm1 +10BOLqJj8s5A8/JkwjaWhky/DuGXDywgEvzXC18aNAxASeqO8h9pAZtszu6NWB4s +h3r+dEQakMacxrZ+jBL/cYLrUv9r3KMPKxaDnplkamqFA/9eNmoV7vDyGtGPZuD6 +oTROtQqqDSrxthCkqnibAfusi7RmlCdvJa0kVK7krKJZAhi8W9f32+lBPv9oq3Ns +dAxnOj/D3UnhNoIt0EdjqUdLo2U39dt5s5Syj2rFUAgfbc02Rwx65kq8AjTRlW/M +KDpGsifwIB8b7wActMUO8c3GptptNVWmFm5+Mmk54P//P3tIAx9KXw== +-----END CERTIFICATE----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIPcVUeQ7ZElgCAggA +MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECGKlFVN6/gIlBIIEyJPeknsA5dvV +WK27AZzs4wM6WrsD6ba+kPJyZTpon5pn4eoTiw4UCvo7C+21G9jCqbIbDrgTWHwH +zu6YrBFTZgRUpdLkLsyUsp4UJrZ8xJ7N/jWlG763CyluFE5oBFLz2Vt/DSDSaWdA +sKdxua/1kvw+KYoDqlObMFIspM5TrndcMnWkOgyvQAvnH0NZXFFBa4QGFrwWDrCo +m12CzMLwaPMrNFBffCTqZnL1AajT+EYqPTi+cQ5mkRpZ2cuzhdug2eki1KkD12ZN +3d8Ehl8bfbLEqRE/HnggleRRt7ia1xkzruqQp14JA2UsrioGMF5nvWgWrbyHfpui +KrCsDwDelrArW/GCki53QBQMuH8Q1YmoNrRZwlG257eA1LiJvmxRyIjKYu0RP+Q8 +EOldycy51VsPVPApUbv9r4IJldrIJiwlmRxxM36uKtFhfojnsWzJORDYI8C37uKi +UEPiD4GSEH6C0lGO94IoZPjl9z/rZ0qZx1VRHl3nxZc0AQvvj9bWMbyRwsgb6wod +P8JSy6uEib9UxuenNHzTd48GcNhJbhOqd4IV0XKhi8W1Kil3mMdc3QAwKaLTx12/ +1GrbMui061uyeM6Rf6Xao0PApDnUNmxcFSTsoarG0yH7Q0WZMgKTDCCGhhtZKlE6 +x7pRsnxiFaIpoh32EVIRI+ZXh2rXBcwa2ew0aEccRXtPFvcmdjevkrHuCggc+M+Y +seFqTHVGWf8eS6o08w095DboD0vFpZXZMRfycTbA7BiE4NYE/uc7v5cH3Ax9l2ef +zG7o9idDt+/RX7OcetxDFw4eQbq7PfjvrfXS1DcRUEyJ04emh7oxlkAUUNsFtabN +T0ggvHxcQWkYRE5oPlkbgpwKpK4LDcApXKFwCDKPur2W5Q7KHRfDLtSvZvYarJum +8j2pGpEis/bdTih29ofNsX6a0Yo5Tlj+9+1c/6/Xi7XvRk/Vbgkoa3iVQ3ckdCuZ +vO7cRYZBBs6W/Ti3hWFzPEX9FfcnSUp9bEnH4ASnmUcp8PDBJYeaI6HqpO3XbkbF +l70eDNakd2cDNjQzkFpBT7HO+HtqU3xNt9K0z2gMB7iTDVFyIzh26joCR2O8tiqS +wUJFkoLPb74GSB7WzE+gb4jXX6n9609PUoR3f896mM34uX3CsY8lA+/0ZGpHnFDA +ToKdmz6WKIAw0E20nyzLuLwPZgj7HLcR7zza4raipe9QxIdyJr5O+jzGt+OjSM9b +K1agibRE5DChqQ+P+ikOc6nG7UNyn+lKSjGEbwuzi8F0iugMgcTc/vYO8OWDNGpd +D1euA5OuVPdfatFa16Fyr4MJJIfE83C4/kSj05fdoyb6pJkOjHhUppVMe+ES5kwl +YI8RES2XVJzUSxnWsIM613YlMgIZ9xgcuIADnO7gaKJ4RQG+9wJ853Uo4+n89K7F +Y6KzihuYAUkbAw1pPo1TODom7A/gB9stqRUSQlZWmIgtnJ8wPjt/we0gzPM8LQzb +ye4KOLjH5iquFc4MU4TtN3gvp9P5R9UFrGeMImS5eMUmBQHckDNdIAtMj7M1wUpR +JVrzDXWDjC21sLn95NtNMPb+FRlt/biTV3IE3ZmX0kbuCRoH7b7hhR41Zpoajwl0 +FqYigB5gnVodGUWuBgDUqA== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/test/ssl/dh4096.pem b/test/ssl/dh4096.pem new file mode 100644 index 0000000..dc2559c --- /dev/null +++ b/test/ssl/dh4096.pem @@ -0,0 +1,25 @@ +-----BEGIN X9.42 DH PARAMETERS----- +MIIELQKCAgEA8eEBgatlTk0QKIwUqHsteHJXzEr0xAW7RLeNid8DdGjTnFw68eV+ +s1YbipEqQVTFG+VZPaof9v0CH2KOdbgWD0KRPC49HB8O/wARFKpy5eJltVe1r07w ++V1Vjciqkh/vGq/yFQsbqwyWJy6AelsbHdSC9Bg9pmu4+pbVGW15zK7PkfjfoO9V +JYbhdqFIPg+9NRRWsl/U9UoyeeIGImI9I4k3fqtv311C6VVErFZylCj7nn45L7IY +GfPcCO5E8FD6EqBv5WnhMNYHMJu9brRvOoAyAyWprqR+aVzHd+DFamDQdsuQjKTk +3+r07znWJfjp6FVTzR5SvjrKg1knK5TibIksoKOlsFZ06bGkFWHjqXNAKhnSpCiU +GJd0qe7pTD+TGQJGWskJpoph+tkICUa+6MyzP9+U6T9hISIY/BpVuWn/iwdLqsvV +s5bg2RjRraww/4Rjm0NyEOTk2MxaLB9gcyu6zcrhX5XRiMgt+jhKwEMwJCEJYkxn +C0yv08A5v6RceFm1jY+8FT0IzRqsWIGV7beNdqtE0B4LBTuN1yQ6x8CKEb6mbIHG +d0XLGppELhD8QUwAr5HiVGTAsS9JlMGgXVkyDtxrVSeS1zHWt77skRQ9UlfJfYMm +5wxHj5QCdQ7ma3oMMZBZutNlkevMzYHIxwqhZstf4ud0j0VMftwZ3GMCggIBAJL7 +cU6/YSxzYDGUcPc6WGT+FAghR0LdhT3Q3Xz1rQRBwSSMPm9NZhyJC3fb+hBl/44X +AHOu1/3dYIWlXPMuHZZdtlt+hkD/sIob16By20Z0p81Kvh3HQglVDJGlFzTmQbTd +CM/EP8eJFiNeMcJB0RgeKyzikRsV4r/acZZM56swTlsRvSDFMh3v9YyYTZbCTwxm +PIVOsxI8uBoWRCzY3yWzjmlZ2u5TR+Z0IVonmNqk6XAKRgxV12YfQVXzzpPZQA9S +GHoD/NQoMdBAi3p4pLEYJ5qMRLYPQbBfSNu5eP9e5uZOiBp/28bVnzEelDGuFupr +lvywkZEVL1KaYtZ/dGkPFXt+A7mNsw5xeDTRjgL4uUJvCNIkjgVEfIrLdUf5IVsU +V8BgunAvgfH+Hy6Tx89v/QGsUWJPhjkSZnXwJ7Ipcsm+Zg0zAZwKDZEQtDLXVPRL +OfCfXMXvlw2u6OHlhSbqO69zZG3dJTlcnjy06n4JYcUim7Mj3Kduige6VWofeEk9 +M/kHrPqNdFE5tHLh2nHcw9yExKHN+l/OUGAvNDfOVS+S+fNSKT0RfC9dMpHLN+Ok +fGuskGzLQAVYF+DYEcnJ++0LEFtd0J381ndSc0iJuH60rKDTqxoRqv7lcdwLFlEV +sQSRoas8s+y+b3FfSu7j0p44qLG9oxZ/WFcWnuUyAiEAjvAD9p3bw8AH0s7dUrX/ +RT1Ge+J/n0tlsgw+LY3zafE= +-----END X9.42 DH PARAMETERS----- diff --git a/test/ssl/server.pem b/test/ssl/server.pem new file mode 100644 index 0000000..a7bcba7 --- /dev/null +++ b/test/ssl/server.pem @@ -0,0 +1,99 @@ +-----BEGIN CERTIFICATE----- +MIIDDjCCAfYCFGGcJXlIeQHiq/qOakbISU5cihPvMA0GCSqGSIb3DQEBCwUAMDsx +CzAJBgNVBAYTAkFVMQwwCgYDVQQIDANOU1cxDzANBgNVBAcMBlN5ZG5leTENMAsG +A1UECgwEYXNpbzAeFw0yMTExMTEyMTExNDRaFw0yNjExMTAyMTExNDRaMEwxCzAJ +BgNVBAYTAkFVMQwwCgYDVQQIDANOU1cxDzANBgNVBAcMBlN5ZG5leTENMAsGA1UE +CgwEYXNpbzEPMA0GA1UECwwGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAu67TzZCFNTZ5c1gKwXfdTH3bP0OB5n6dqXGK6jkPb699dyM4oPtY +2f+OyxJspk8D5pX6HuZ+hLGAsHxfCN+A3RegVZJCR/gXrrMPl/6PfDxtkeFXWy+6 +NAPxqppMj8gbX/czTdNFwgW4J8/RLyH53utjAGQtCRr97EbBOsTSeOmyAxbw4mRt +EvHjacKFcSZzJDlyxCia37791MulZ4lwOZZlke5NzoOqkBIAusQgg7fMWDvH27PD +T+taIyBsYTVJWHf5kMklAlWYXZvNjZp/QGt13lDORg2aSc/P2pE4iLyhbZcpuW+W +nHB7IY1wjDL55/ORCjz3VlNIAMXHP5YQxwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB +AQC3iiwQTgDP4ixulisYIGlJb8iuhxH9G41hm8dF/1qlIfXWxsbjb+g7M5U/3JCb +fwCGoz7uBdj/CKkIb5wx83GVC1yVLbNSvCIS827qxic4GACEYGGAy4Ub5tUCQrLr +JUQTP1WVJcgiKvk7OAcXdA+k/CcNXH153gUPDZz+/BedXe2VbM6LDsqPeSxXfbZN +AWXARAuly7cQk/xkYkPldRRhx4htNCbnkG1qyEqNcYQN1SY9Qhbrm2HkAUntzQ7G +umo4JdbIX6MJ5fYNs+yN/lJB7PiJP8Mz1AtOz4x9JxcLyuB6sapT8Tj53n9g/+m1 +Tqd8lHpWe6oM0sgdWfzdBNir +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,9E0E6B9970E055F1 + +oFvN3t50B2TSeNsRo1vwhVYlMmt0w3MD3Ar75fti4fRhBrWoH4rBPrSouWK4OMDK +CakfVhzJIEvaMav843grS4V+ooAsfnAtiQiQj+5xjZ8PlCuWir5gyjgqeN4zN6ZT +2s/oEy5Kx7Ru5AWMkv+NPW5l3iS3c+Hupfb/auITwECSCCsCBxgNtJ8z0iXjv9Dr +hqvqcI+4F5DSiol3QhitbpQ/k2PKu92AZhPcr9e5HrqeUD7aqfX2q3i+tnJvxC93 +0mvy133bX2ZAGAKMheW/GuzcETfwU80wvmrwHXI9rnuAUaJhrDiIZQ79gubZ0Pcm +w4Y6Z5xxeErb7zKBi+pHKst8MJ7rfSz/N878su6cpESRC/w1paVX7m8/q61kzBkj ++h2qe9DupXBejQkriN+Z858nFtBKbWlFsmAg1FLZonworTUfV2c7S9yzMV/29VOE +T0Bt8BU1Hp+bCjreF4JGbnUJnRQoASpisfUkrD6Ar4GI56Edkkx6hkF0cXdcvfCN +qyhxzcvf/aV1M2kcpBRX9mIfjoFMFNz7uRIxyqPLaDkigwJemoaBo3n9/W5F7N7B +AGNEZ3QhUlc8EyWpGRZRzMevu5wdz1b2+MqItOhPXUo2XcLEj2iFkVDdbj/d9jQH +9ZIe4hQTSf784tAzt2Jp2RHmm22390GB1jdzG/CzbGlAKmaTTEe4FJcd/eLOEZuD +4+iFsEb/bWcCyXkBKkdEoDDMJW8xi5d/1ezJM03nqhvkekDqyhJUJPCbmY1SCX1X +4AO40jJmWQxwj26Pnnncacz4tuecZNqovz+POpKQSIctrQSV4wgf35137KBt7/O7 +EU0N7Qj4xTigyGkEHCZt7BgD8fFrxiP1OkUmFRHEE7Dxiagz6omJV8ien+p9wIgS +QcqkJlgKMwVepjuCuEyvg5oIkAPvp24yhePSJkEvvoDLvM2Kub/CM+UkN8dSgsZk ++ZBE9Oi62AWWow8/ib8Um5DNIEZsq+5CQLeBG7f5kTIBAoA9UceaEgbxzOVUCBcX +L7QsJ3pZ/ei1qx/9tChO/OXa9tleXcjGg7/q/6i6pUyZuqZlt+hk+3HtFmTXIjsM +chbUSMEJ2isv9MDamTtunt9N92A6OxUkAs68kCO/bzotldXMKZVjOohNnML5q/3U +vpsuN8NNwaNHCAM7pjols4V7ebX1lDZFR1hbj+szKMhVKzFfig1lRHafgRrR6H6P +mUK16lKzUbmvwv2IU/3wck+4UNeB/+lRmfAfBasQytnbt+5fwwNkVSrDY2Kxe0nz +2k3eIYST+ygxGuNrW9rnFbBpTJb0OE5cpgun8xxDE91AmL550AcZff+9ulDBhZg1 +eMoKUALlEdDNPffVTH8Iupn0jMnJsjXynztcEVhx4h2aA5X6/2i035uEybCn33qP +J7g30oe2C69BSC0YmkT3MjF6Wrhy+M8dU0dDggRhY6JSS8wESvwGenaPi7SZlbxb +Elmc44bHros1YfGl/xDdhju134/aMBG1GlZlReI+Rwnp9DCp04xiiJb9YKyUNaGY +7BTGWyie/WYYKbX1ZlxqWA9jxow8PM1XYHuanau1/aYT16L7E83HG3qkyuFIlLJh +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIUX3cVQ47QyJp7SOy0RPzP743W9MwwDQYJKoZIhvcNAQEL +BQAwOzELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5 +MQ0wCwYDVQQKDARhc2lvMB4XDTIxMTExMTIxMTA1MloXDTI2MTExMDIxMTA1Mlow +OzELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5MQ0w +CwYDVQQKDARhc2lvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyURD +LjKxTCkapmWhY0bP1NaaOPzIJTTB0dzREOlmRmBmiHpW7DaRx7qBm6jYDKQ7OCbz +30/j8K4TjHOLIwxzXhXMYTJOcN2giPHNUBvm9oEuDAhYgltArJQnBBEH+3C1hCIv +1+uhTWo0HpGXTeJnvboTZ1YgmbOgr6lMhNiu9QmPX885DxWf6sDq8mRgCDX2x8sk +Ls0HuLSo88Osjx532yEhnrZgexsByhoRD3yrKHV5mWpaunk5BMsP/XMuQHayFmbO +siqnHJoL1znGVH003PcBGmEDmoIUqhLiBi2gWGu1pmckP9loqQUTEn0aLOVclHf4 +slWq344zh4tJCpQMfQIDAQABo1AwTjAdBgNVHQ4EFgQUfiX1CMQrGDi9mIBAg9cg +m0RwLJUwHwYDVR0jBBgwFoAUfiX1CMQrGDi9mIBAg9cgm0RwLJUwDAYDVR0TBAUw +AwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAnDnVNSb8z/pNFaZ6YAZ+ukfNT3jjbGm1 +10BOLqJj8s5A8/JkwjaWhky/DuGXDywgEvzXC18aNAxASeqO8h9pAZtszu6NWB4s +h3r+dEQakMacxrZ+jBL/cYLrUv9r3KMPKxaDnplkamqFA/9eNmoV7vDyGtGPZuD6 +oTROtQqqDSrxthCkqnibAfusi7RmlCdvJa0kVK7krKJZAhi8W9f32+lBPv9oq3Ns +dAxnOj/D3UnhNoIt0EdjqUdLo2U39dt5s5Syj2rFUAgfbc02Rwx65kq8AjTRlW/M +KDpGsifwIB8b7wActMUO8c3GptptNVWmFm5+Mmk54P//P3tIAx9KXw== +-----END CERTIFICATE----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIPcVUeQ7ZElgCAggA +MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECGKlFVN6/gIlBIIEyJPeknsA5dvV +WK27AZzs4wM6WrsD6ba+kPJyZTpon5pn4eoTiw4UCvo7C+21G9jCqbIbDrgTWHwH +zu6YrBFTZgRUpdLkLsyUsp4UJrZ8xJ7N/jWlG763CyluFE5oBFLz2Vt/DSDSaWdA +sKdxua/1kvw+KYoDqlObMFIspM5TrndcMnWkOgyvQAvnH0NZXFFBa4QGFrwWDrCo +m12CzMLwaPMrNFBffCTqZnL1AajT+EYqPTi+cQ5mkRpZ2cuzhdug2eki1KkD12ZN +3d8Ehl8bfbLEqRE/HnggleRRt7ia1xkzruqQp14JA2UsrioGMF5nvWgWrbyHfpui +KrCsDwDelrArW/GCki53QBQMuH8Q1YmoNrRZwlG257eA1LiJvmxRyIjKYu0RP+Q8 +EOldycy51VsPVPApUbv9r4IJldrIJiwlmRxxM36uKtFhfojnsWzJORDYI8C37uKi +UEPiD4GSEH6C0lGO94IoZPjl9z/rZ0qZx1VRHl3nxZc0AQvvj9bWMbyRwsgb6wod +P8JSy6uEib9UxuenNHzTd48GcNhJbhOqd4IV0XKhi8W1Kil3mMdc3QAwKaLTx12/ +1GrbMui061uyeM6Rf6Xao0PApDnUNmxcFSTsoarG0yH7Q0WZMgKTDCCGhhtZKlE6 +x7pRsnxiFaIpoh32EVIRI+ZXh2rXBcwa2ew0aEccRXtPFvcmdjevkrHuCggc+M+Y +seFqTHVGWf8eS6o08w095DboD0vFpZXZMRfycTbA7BiE4NYE/uc7v5cH3Ax9l2ef +zG7o9idDt+/RX7OcetxDFw4eQbq7PfjvrfXS1DcRUEyJ04emh7oxlkAUUNsFtabN +T0ggvHxcQWkYRE5oPlkbgpwKpK4LDcApXKFwCDKPur2W5Q7KHRfDLtSvZvYarJum +8j2pGpEis/bdTih29ofNsX6a0Yo5Tlj+9+1c/6/Xi7XvRk/Vbgkoa3iVQ3ckdCuZ +vO7cRYZBBs6W/Ti3hWFzPEX9FfcnSUp9bEnH4ASnmUcp8PDBJYeaI6HqpO3XbkbF +l70eDNakd2cDNjQzkFpBT7HO+HtqU3xNt9K0z2gMB7iTDVFyIzh26joCR2O8tiqS +wUJFkoLPb74GSB7WzE+gb4jXX6n9609PUoR3f896mM34uX3CsY8lA+/0ZGpHnFDA +ToKdmz6WKIAw0E20nyzLuLwPZgj7HLcR7zza4raipe9QxIdyJr5O+jzGt+OjSM9b +K1agibRE5DChqQ+P+ikOc6nG7UNyn+lKSjGEbwuzi8F0iugMgcTc/vYO8OWDNGpd +D1euA5OuVPdfatFa16Fyr4MJJIfE83C4/kSj05fdoyb6pJkOjHhUppVMe+ES5kwl +YI8RES2XVJzUSxnWsIM613YlMgIZ9xgcuIADnO7gaKJ4RQG+9wJ853Uo4+n89K7F +Y6KzihuYAUkbAw1pPo1TODom7A/gB9stqRUSQlZWmIgtnJ8wPjt/we0gzPM8LQzb +ye4KOLjH5iquFc4MU4TtN3gvp9P5R9UFrGeMImS5eMUmBQHckDNdIAtMj7M1wUpR +JVrzDXWDjC21sLn95NtNMPb+FRlt/biTV3IE3ZmX0kbuCRoH7b7hhR41Zpoajwl0 +FqYigB5gnVodGUWuBgDUqA== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/test/tcp_bigdata.cpp b/test/tcp_bigdata.cpp index b1aa0bd..fd65ab4 100644 --- a/test/tcp_bigdata.cpp +++ b/test/tcp_bigdata.cpp @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/test/tcp_reconnect.cpp b/test/tcp_reconnect.cpp index 6505ea4..44238ea 100644 --- a/test/tcp_reconnect.cpp +++ b/test/tcp_reconnect.cpp @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/test/tcp_ssl_c.cpp b/test/tcp_ssl_c.cpp new file mode 100644 index 0000000..96c440c --- /dev/null +++ b/test/tcp_ssl_c.cpp @@ -0,0 +1,30 @@ +#include "log.h" +#include "tcp_client.hpp" + +using namespace asio_net; + +const uint16_t PORT = 6666; + +int main(int argc, char** argv) { + asio::io_context context; + asio::ssl::context ssl_context(asio::ssl::context::sslv23); + ssl_context.load_verify_file(OPENSSL_PEM_PATH "ca.pem"); + tcp_client_ssl client(context, ssl_context); + + client.on_open = [&] { + LOG("client on_open:"); + client.send("hello"); + }; + client.on_data = [](const std::string& data) { + LOG("client on_data: %s", data.c_str()); + }; + client.on_open_failed = [](std::error_code ec) { + LOG("client on_open_failed: %d, %s", ec.value(), ec.message().c_str()); + }; + client.on_close = [] { + LOG("client on_close:"); + }; + client.open("localhost", PORT); + client.run(); + return 0; +} diff --git a/test/tcp_ssl_s.cpp b/test/tcp_ssl_s.cpp new file mode 100644 index 0000000..4769830 --- /dev/null +++ b/test/tcp_ssl_s.cpp @@ -0,0 +1,39 @@ +#include "assert_def.h" +#include "log.h" +#include "tcp_server.hpp" + +using namespace asio_net; + +const uint16_t PORT = 6666; + +int main(int argc, char** argv) { + asio::io_context context; + asio::ssl::context ssl_context(asio::ssl::context::sslv23); + { + ssl_context.set_options(asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::single_dh_use); + ssl_context.set_password_callback(std::bind([] { // NOLINT + return "test"; + })); + ssl_context.use_certificate_chain_file(OPENSSL_PEM_PATH "server.pem"); + ssl_context.use_private_key_file(OPENSSL_PEM_PATH "server.pem", asio::ssl::context::pem); + ssl_context.use_tmp_dh_file(OPENSSL_PEM_PATH "dh4096.pem"); + } + tcp_server_ssl server(context, PORT, ssl_context); + server.on_session = [](const std::weak_ptr& ws) { + LOG("on_session:"); + auto session = ws.lock(); + session->on_close = [] { + LOG("session on_close:"); + }; + session->on_data = [ws](std::string data) { + ASSERT(!ws.expired()); + LOG("session on_data: %zu, %s", data.size(), data.c_str()); + ws.lock()->send(std::move(data)); + }; + }; + server.on_handshake_error = [](std::error_code ec) { + LOGE("on_handshake_error: %d, %s", ec.value(), ec.message().c_str()); + }; + server.start(true); + return 0; +}