namespace utils { class stream_callbacks: virtual public Botan::TLS::StreamCallbacks { ... ... };
Stream Callbacks are called when tls is handshaking.
std::shared_ptr<Botan::TLS::StreamCallbacks> callbacks = std::make_shared<utils::stream_callbacks>(__log);
Constructor #1 of Botan::TLS::Stream matches parameters:
utils::policy_shared is a class that automatically makes shared-ptr.
utils::policy_shared policy_default{"default"}; utils::policy_shared policy_all{"all"};
Return shared-ptr of Botan::TLS::Policy
std::shared_ptr<Botan::TLS::Policy> policy = policy_default;
Return shared-ptr of Botan::TLS::Policy too.
std::shared_ptr<Botan::TLS::Policy> policy = policy_default.get_shared();
For Server,
std::shared_ptr<Botan::Credentials_Manager> cred_man = std::make_shared<utils::credentials_manager>( cert_fn, key_fn );
For Client,
std::shared_ptr<Botan::Credentials_Manager> cred_man = std::make_shared<utils::credentials_manager>( true, // Use system certificate store. "" );
c++ code, example
#include <iostream> #include <memory> #include <future> #include <sstream> #include <boost/asio.hpp> #include <boost/beast.hpp> #include <ugtls/credentials_manager.hpp> #include <botan/system_rng.h> #include <botan/tls_session_manager_memory.h> #include <ugtls/policy.hpp> #include <botan/asio_stream.h> #include <ugtls/stream_callbacks.hpp> namespace asio = boost::asio; namespace beast = boost::beast; namespace http = beast::http; using std::string_literals::operator""s; namespace net { class server_info { public: const std::string address; const std::uint16_t port; const std::string cert_fn; const std::string key_fn; public: void print() const { std::clog << "COPY:\n"; std::clog << "https://" << address << ":" << port << "\n" << cert_fn << " " << key_fn << std::endl; } }; } // namespace net namespace net { class tls_session: virtual public std::enable_shared_from_this<net::tls_session> { private: std::shared_ptr<net::server_info> __sinfo; private: std::shared_ptr<std::ostringstream> __log; private: std::shared_ptr<Botan::Credentials_Manager> __cred_man; std::shared_ptr<Botan::RNG> __rng; std::shared_ptr<Botan::TLS::Session_Manager> __sess_man; std::shared_ptr<Botan::TLS::Policy> __policy; std::shared_ptr<Botan::TLS::Context> __tls_context; std::shared_ptr<Botan::TLS::StreamCallbacks> __tls_callbacks; Botan::TLS::Stream<beast::tcp_stream> __tls_stream; public: tls_session( //asio::any_io_executor executor__, // socket__ will carray an executor std::shared_ptr<net::server_info> sinfo__, asio::ip::tcp::socket && socket__ ): __sinfo{sinfo__}, __log{std::make_shared<std::ostringstream>()}, __cred_man{ std::make_shared<ugtls::credentials_manager>( __sinfo->cert_fn, __sinfo->key_fn ) }, __rng{std::make_shared<Botan::System_RNG>()}, __sess_man{ std::make_shared<Botan::TLS::Session_Manager_In_Memory>( __rng ) }, __policy{ ugtls::policy_shared{"default"} }, __tls_context{ std::make_shared<Botan::TLS::Context>( __cred_man, __rng, __sess_man, __policy, Botan::TLS::Server_Information{} ) }, __tls_callbacks{ std::make_shared<ugtls::stream_callbacks>( __log ) }, __tls_stream{ __tls_context, __tls_callbacks, std::move(socket__) } { } public: asio::awaitable<void> start() { std::clog << "Session Started!" << std::endl; co_await this->handshake(); co_await this->receive_request(); co_await this->send_response(); co_await this->close(); co_return; } private: asio::awaitable<void> handshake() { *__log << "<h2>[TLS Callbacks]</h2>" << "<pre style=\"border-left:5px solid #000\">" ; // __tls_callbacks are called on handshake. // and message is written to __log __tls_stream.next_layer().expires_after(std::chrono::seconds(10)); auto [ec] = co_await __tls_stream.async_handshake( Botan::TLS::Connection_Side::Server, asio::as_tuple ); *__log << "</pre>"; if (ec) throw std::system_error{ec, "handshake error"}; std::clog << "Handshake OK!" << std::endl; co_return; } private: asio::awaitable<void> receive_request() { http::request<http::string_body> request; beast::flat_buffer buffer; __tls_stream.next_layer().expires_after(std::chrono::seconds(30)); auto [ec, bytes] = co_await http::async_read( __tls_stream, buffer, request, asio::as_tuple ); if (ec && ec != http::error::end_of_stream) throw std::system_error{ ec, "Receive request error" }; std::clog << "Receive request OK" << std::endl; *__log << "<h2>[Received Request]</h2>" << "<pre style=\"border-left:1px solid #000\">" << request << "</pre>"; co_return; } private: asio::awaitable<void> send_response() { http::response<http::string_body> response; response.keep_alive(true); response.version(11); response.set(http::field::server, "c++ web server"); response.set(http::field::content_type, "text/html"); response.body() = "<html><head><title>c++ web server</title></head><body><h1>c++ web server</h1>"s + __log->str() + "</body></html>" ; response.prepare_payload(); __tls_stream.next_layer().expires_after(std::chrono::seconds(20)); auto [ec, bytes] = co_await http::async_write( __tls_stream, response, asio::as_tuple ); std::clog << "Response Status: " << ec << std::endl; co_return; } private: asio::awaitable<void> close() { auto [ec] = co_await __tls_stream.async_shutdown( asio::as_tuple ); std::clog << "TLS Stream closed, " << ec << std::endl; } }; // class tls_session } // namespace net namespace net { class server: virtual public std::enable_shared_from_this<net::server> { private: std::shared_ptr<net::server_info> __sinfo; asio::ip::tcp::acceptor __acceptor; asio::thread_pool __pool{2048u}; public: server( asio::any_io_executor executor__, std::shared_ptr<net::server_info> sinfo__ ): __sinfo{sinfo__}, __acceptor{ executor__, asio::ip::tcp::endpoint{ asio::ip::make_address(__sinfo->address), __sinfo->port } } { } public: asio::awaitable<void> start() { std::clog << "Yoea\n"; co_await this->listen(); co_await this->join(); co_return; } private: asio::awaitable<void> join() { __pool.join(); co_return; } private: asio::awaitable<void> listen() { co_await this->accept(); co_await this->listen(); co_return; } private: asio::awaitable<void> accept() { try { co_await this->do_accept(); } catch (const std::exception & e) { std::cerr << "Session error: " << e.what() << std::endl; } co_return; } private: asio::awaitable<void> do_accept() { auto [ec, socket] = co_await __acceptor.async_accept( asio::as_tuple ); if (ec) throw std::system_error{ec, "accept error"}; std::promise<void> promise; std::future<void> future = promise.get_future(); // Post to the host: use same executor (non-threading) // Post to a thread pool: use different executor (threading) // // Host executor: co_await asio::this_coro::executor; // Thread Pool executor: __pool.get_executor(); // asio::co_spawn( __pool.get_executor(), std::bind( &net::tls_session::start, std::make_shared<net::tls_session>( __sinfo, std::move(socket) ) ), [promise = std::move(promise)] (std::exception_ptr eptr) mutable { if (eptr) { std::clog << "Session Closed: Exception Propagated\n"; promise.set_exception(eptr); } else { std::clog << "Session Closed: No Exception\n"; promise.set_value(); } } ); future.get(); co_return; } }; } // namespace net int main(int argc, char ** argv) { try { if (argc != 5) throw std::runtime_error{ "https-server <address> <port> <cert file> <key file>" }; auto sinfo = std::make_shared<net::server_info>( argv[1], std::stoi(argv[2]), argv[3], argv[4] ); sinfo->print(); asio::thread_pool pool{32u}; std::promise<void> promise; std::future<void> future = promise.get_future(); asio::co_spawn( pool.get_executor(), std::bind( &net::server::start, std::make_shared<net::server>( pool.get_executor(), sinfo ) ), [promise = std::move(promise)] (std::exception_ptr eptr) mutable { if (eptr) promise.set_exception(eptr); else promise.set_value(); } ); future.get(); pool.join(); } catch (const std::exception & e) { std::cerr << "=\n=>\n=\n" << e.what() << std::endl; } }
$ botan keygen --algo=ECDSA --params=secp384r1 --output=server_key.pem $ botan gen_self_signed \ server_key.pem CA --ca --country=WhichCountry --dns=the.example \ --hash=SHA-384 --output=ca.crt $ botan gen_pkcs10 server_key.pem the.domain --output=crt.req $ botan sign_cert ca.crt server_key.pem crt.req --output=server_cert.crt
./bin/gcc-16/debug/cxxstd-26-iso/https-server \ 0.0.0.0 32132 \ ./server_cert.crt ./server_key.pem
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
Mon Sep 14 07:48:19 AM UTC 2026
//////////////////////////////////////////////////////////////////////
+
Powered by:
B2 Build
| boost quickbook
+
+