20 using tcp = asio::ip::tcp;
23 const std::string& cert_file,
24 const std::string& key_file)
25 : server_id_(server_id)
29 asio::ssl::context::tls_server);
33 asio::ssl::context::default_workarounds |
34 asio::ssl::context::no_sslv2 |
35 asio::ssl::context::no_sslv3 |
36 asio::ssl::context::no_tlsv1 |
37 asio::ssl::context::no_tlsv1_1 |
38 asio::ssl::context::single_dh_use);
55 SSL_CTX_set_min_proto_version(native_ctx, TLS1_3_VERSION);
56 SSL_CTX_set_max_proto_version(native_ctx, TLS1_3_VERSION);
59 SSL_CTX_set_ciphersuites(native_ctx,
60 "TLS_AES_256_GCM_SHA384:"
61 "TLS_CHACHA20_POLY1305_SHA256:"
62 "TLS_AES_128_GCM_SHA256");
69 ssl_context_->use_private_key_file(key_file, asio::ssl::context::pem);
71 NETWORK_LOG_INFO(
"[secure_messaging_server] SSL context initialized with TLS 1.3 only, cert: " +
72 cert_file +
", key: " + key_file);
74 catch (
const std::exception& e)
77 std::string(e.what()));
96 if (lifecycle_.is_running())
100 "Server is already running",
101 "secure_messaging_server::start_server");
104 if (!lifecycle_.try_start())
108 "Server is already starting",
109 "secure_messaging_server::start_server");
113 auto result = do_start_impl(port);
116 lifecycle_.mark_stopped();
124 if (!lifecycle_.is_running())
128 "Server is not running",
129 "secure_messaging_server::stop_server");
132 if (!lifecycle_.prepare_stop())
138 auto result = do_stop_impl();
141 lifecycle_.mark_stopped();
148 lifecycle_.wait_for_stop();
167 callbacks_.set<
to_index(callback_index::connection)>(std::move(callback));
172 callbacks_.set<
to_index(callback_index::disconnection)>(std::move(callback));
177 callbacks_.set<
to_index(callback_index::receive)>(std::move(callback));
182 callbacks_.set<
to_index(callback_index::error)>(std::move(callback));
210 std::shared_ptr<session::secure_session> session) ->
void
212 callbacks_.invoke<
to_index(callback_index::connection)>(session);
224 io_context_ = std::make_unique<asio::io_context>();
226 work_guard_ = std::make_unique<asio::executor_work_guard<asio::io_context::executor_type>>(
227 asio::make_work_guard(*io_context_)
229 acceptor_ = std::make_unique<tcp::acceptor>(
230 *io_context_, tcp::endpoint(tcp::v4(), port));
233 cleanup_timer_ = std::make_unique<asio::steady_timer>(*io_context_);
239 start_cleanup_timer();
245 NETWORK_LOG_WARN(
"[secure_messaging_server] network_context not initialized, creating temporary thread pool");
246 thread_pool_ = std::make_shared<integration::basic_thread_pool>(std::thread::hardware_concurrency());
250 io_context_future_ = thread_pool_->
submit(
259 catch (
const std::exception& e)
262 std::string(e.what()));
267 std::to_string(port) +
" (TLS/SSL enabled)");
270 catch (
const std::system_error& e)
273 if (e.code() == asio::error::address_in_use ||
274 e.code() == std::errc::address_in_use)
278 "Failed to bind to port: address already in use",
279 "secure_messaging_server::do_start_impl",
280 "Port: " + std::to_string(port)
283 else if (e.code() == asio::error::access_denied ||
284 e.code() == std::errc::permission_denied)
288 "Failed to bind to port: permission denied",
289 "secure_messaging_server::do_start_impl",
290 "Port: " + std::to_string(port)
296 "Failed to start secure server: " + std::string(e.what()),
297 "secure_messaging_server::do_start_impl",
298 "Port: " + std::to_string(port)
301 catch (
const std::exception& e)
305 "Failed to start secure server: " + std::string(e.what()),
306 "secure_messaging_server::do_start_impl",
307 "Port: " + std::to_string(port)
321 acceptor_->cancel(ec);
322 if (acceptor_->is_open())
324 acceptor_->close(ec);
331 cleanup_timer_->cancel();
338 std::lock_guard<std::mutex> lock(sessions_mutex_);
339 for (
auto& sess : sessions_)
343 sess->stop_session();
362 if (io_context_future_.valid())
365 io_context_future_.wait();
366 }
catch (
const std::exception& e) {
367 NETWORK_LOG_ERROR(
"[secure_messaging_server] Exception while waiting for io_context: " +
368 std::string(e.what()));
374 std::lock_guard<std::mutex> lock(sessions_mutex_);
380 cleanup_timer_.reset();
381 thread_pool_.reset();
387 catch (
const std::exception& e)
391 "Failed to stop secure server: " + std::string(e.what()),
392 "secure_messaging_server::do_stop_impl",
393 "Server ID: " + server_id_
404 auto self = shared_from_this();
405 acceptor_->async_accept(
406 [
this, self](std::error_code ec, tcp::socket sock)
407 { on_accept(ec, std::move(sock)); });
420#if KCENON_WITH_COMMON_SYSTEM
422 connection_errors_.fetch_add(1, std::memory_order_relaxed);
424 monitor_->record_metric(
"connection_errors",
static_cast<double>(connection_errors_.load()));
431 cleanup_dead_sessions();
434 auto new_session = std::make_shared<kcenon::network::session::secure_session>(
435 std::move(socket), *ssl_context_, server_id_);
438 auto self = shared_from_this();
439 auto receive_cb = get_receive_callback();
440 auto disconnection_cb = get_disconnection_callback();
441 auto error_cb = get_error_callback();
445 new_session->set_receive_callback(
446 [
this, self, new_session, receive_cb](
const std::vector<uint8_t>& data)
448 receive_cb(new_session, data);
452 if (disconnection_cb)
454 new_session->set_disconnection_callback(
455 [
this, self, new_session, disconnection_cb](
const std::string& session_id)
457 disconnection_cb(session_id);
463 new_session->set_error_callback(
464 [
this, self, new_session, error_cb](std::error_code err)
466 error_cb(new_session, err);
472 std::lock_guard<std::mutex> lock(sessions_mutex_);
473 sessions_.push_back(new_session);
477 new_session->start_session();
480 invoke_connection_callback(new_session);
482#if KCENON_WITH_COMMON_SYSTEM
485 std::lock_guard<std::mutex> lock(sessions_mutex_);
487 monitor_->record_metric(
"active_connections",
static_cast<double>(sessions_.size()));
498 std::lock_guard<std::mutex> lock(sessions_mutex_);
502 std::remove_if(sessions_.begin(), sessions_.end(),
503 [](
const auto& session) {
504 return session && session->is_stopped();
509 NETWORK_LOG_DEBUG(
"[secure_messaging_server] Cleaned up dead sessions. Active: " +
510 std::to_string(sessions_.size()));
512#if KCENON_WITH_COMMON_SYSTEM
515 monitor_->record_metric(
"active_connections",
static_cast<double>(sessions_.size()));
522 if (!cleanup_timer_ || !is_running())
528 cleanup_timer_->expires_after(std::chrono::seconds(30));
530 auto self = shared_from_this();
531 cleanup_timer_->async_wait(
532 [
this, self](
const std::error_code& ec)
534 if (!ec && is_running())
536 cleanup_dead_sessions();
537 start_cleanup_timer();
543#if KCENON_WITH_COMMON_SYSTEM
544 auto secure_messaging_server::set_monitor(kcenon::common::interfaces::IMonitor* monitor) ->
void
549 auto secure_messaging_server::get_monitor() const ->
kcenon::common::interfaces::IMonitor*
std::shared_ptr< kcenon::network::integration::thread_pool_interface > get_thread_pool()
Get current thread pool.
static network_context & instance()
Get the singleton instance.
std::function< void(const std::string &)> disconnection_callback_t
Callback type for disconnection.
auto on_accept(std::error_code ec, asio::ip::tcp::socket socket) -> void
Handler called when an asynchronous accept finishes.
auto set_connection_callback(connection_callback_t callback) -> void
Sets the callback for new client connections.
auto set_error_callback(error_callback_t callback) -> void
Sets the callback for session errors.
auto server_id() const -> const std::string &
Returns the server identifier.
auto cleanup_dead_sessions() -> void
Removes stopped sessions from the sessions vector.
auto do_stop_impl() -> VoidResult
Secure TCP-specific implementation of server stop.
auto get_connection_callback() const -> connection_callback_t
Gets a copy of the connection callback.
utils::lifecycle_manager lifecycle_
auto get_disconnection_callback() const -> disconnection_callback_t
Gets a copy of the disconnection callback.
secure_messaging_server(std::string_view server_id, const std::string &cert_file, const std::string &key_file)
Constructs a secure_messaging_server with SSL/TLS support.
auto start_cleanup_timer() -> void
Starts a periodic timer that triggers session cleanup.
auto invoke_connection_callback(std::shared_ptr< session::secure_session > session) -> void
Invokes the connection callback with the given session.
~secure_messaging_server() noexcept
Destructor. If the server is still running, stop_server() is invoked.
auto start_server(unsigned short port) -> VoidResult
Starts the server on the specified port.
auto get_error_callback() const -> error_callback_t
Gets a copy of the error callback.
auto stop_server() -> VoidResult
Stops the server and closes all connections.
std::unique_ptr< asio::ssl::context > ssl_context_
std::function< void(std::shared_ptr< session::secure_session >, std::error_code)> error_callback_t
Callback type for errors.
auto get_receive_callback() const -> receive_callback_t
Gets a copy of the receive callback.
auto do_accept() -> void
Initiates an asynchronous accept operation (async_accept).
std::function< void(std::shared_ptr< session::secure_session >)> connection_callback_t
Callback type for new connection.
std::function< void(std::shared_ptr< session::secure_session >, const std::vector< uint8_t > &)> receive_callback_t
Callback type for received data.
auto do_start_impl(unsigned short port) -> VoidResult
Secure TCP-specific implementation of server start.
auto is_running() const noexcept -> bool
Check if the server is currently running.
auto set_disconnection_callback(disconnection_callback_t callback) -> void
Sets the callback for client disconnections.
auto wait_for_stop() -> void
Blocks until stop_server() is called.
auto set_receive_callback(receive_callback_t callback) -> void
Sets the callback for received messages.
virtual std::future< void > submit(std::function< void()> task)=0
Submit a task to the thread pool.
auto get() const -> std::tuple_element_t< Index, std::tuple< CallbackTypes... > >
Gets a callback at the specified index.
auto is_running() const -> bool
Checks if the component is currently running.
struct ssl_ctx_st SSL_CTX
Feature flags for network_system.
Logger system integration interface for network_system.
#define NETWORK_LOG_WARN(msg)
#define NETWORK_LOG_INFO(msg)
#define NETWORK_LOG_ERROR(msg)
#define NETWORK_LOG_DEBUG(msg)
constexpr int internal_error
constexpr int bind_failed
constexpr int server_already_running
constexpr int server_not_started
constexpr auto to_index(E e) noexcept -> std::size_t
Helper to convert enum to std::size_t for callback_manager access.
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
Global context for shared network system resources.
Secure TCP server class with TLS/SSL support.
TLS-secured session wrapper for encrypted communication.