20 #include <boost/asio/executor_work_guard.hpp>
21 #include <boost/asio/io_context.hpp>
44 std::unique_ptr<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>
work_guard_;
65 explicit Impl(uint16_t port)
78 Impl(uint16_t port, std::shared_ptr<boost::asio::io_context> external_ioc)
94 explicit Impl(std::shared_ptr<interface::Channel> channel)
118 std::lock_guard<std::mutex> lock(
mutex_);
129 std::lock_guard<std::mutex> lock(
mutex_);
131 std::promise<bool> p;
133 return p.get_future();
135 std::promise<bool> p;
136 auto f = p.get_future();
152 auto transport_server = std::dynamic_pointer_cast<transport::TcpServer>(
channel_);
153 if (transport_server) {
155 transport_server->set_unlimited_clients();
163 work_guard_ = std::make_unique<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>(
177 bool should_join =
false;
179 std::unique_lock<std::mutex> lock(
mutex_);
193 auto transport_server = std::dynamic_pointer_cast<transport::TcpServer>(
channel_);
194 if (transport_server) transport_server->request_stop();
218 std::lock_guard<std::mutex> lock(
mutex_);
224 auto transport_server = std::dynamic_pointer_cast<transport::TcpServer>(
channel_);
225 if (transport_server) {
226 transport_server->on_multi_connect([
this](
size_t id,
const std::string& info) {
229 transport_server->on_multi_data([
this](
size_t id,
const std::string& data) {
232 transport_server->on_multi_disconnect([
this](
size_t id) {
253 : impl_(std::make_unique<
Impl>(port, ioc)) {}
265 if (impl_->channel_) {
266 auto transport_server = std::dynamic_pointer_cast<transport::TcpServer>(impl_->channel_);
267 if (transport_server)
return transport_server->broadcast(std::string(data));
273 if (impl_->channel_) {
274 auto transport_server = std::dynamic_pointer_cast<transport::TcpServer>(impl_->channel_);
275 if (transport_server)
return transport_server->send_to_client(client_id, std::string(data));
281 impl_->on_client_connect_ = std::move(h);
285 impl_->on_client_disconnect_ = std::move(h);
289 impl_->on_data_ = std::move(h);
293 impl_->on_error_ = std::move(h);
298 if (!get_impl()->channel_)
return 0;
299 auto transport_server = std::dynamic_pointer_cast<transport::TcpServer>(get_impl()->channel_);
300 return transport_server ? transport_server->get_client_count() : 0;
304 if (!get_impl()->channel_)
return std::vector<size_t>();
305 auto transport_server = std::dynamic_pointer_cast<transport::TcpServer>(get_impl()->channel_);
306 return transport_server ? transport_server->get_connected_clients() : std::vector<size_t>();
310 impl_->auto_manage_ = m;
311 if (impl_->auto_manage_ && !impl_->started_)
start();
316 impl_->port_retry_enabled_ = e;
317 impl_->max_port_retries_ = m;
318 impl_->port_retry_interval_ms_ = i;
323 impl_->idle_timeout_ms_ = ms;
330 impl_->max_clients_ = max;
331 impl_->client_limit_enabled_ =
true;
332 if (impl_->channel_) {
333 auto transport_server = std::dynamic_pointer_cast<transport::TcpServer>(impl_->channel_);
334 if (transport_server) transport_server->set_client_limit(max);
340 impl_->client_limit_enabled_ =
false;
341 if (impl_->channel_) {
342 auto transport_server = std::dynamic_pointer_cast<transport::TcpServer>(impl_->channel_);
343 if (transport_server) transport_server->set_unlimited_clients();
349 impl_->notify_send_failure_ = e;
353 impl_->manage_external_context_ = m;
static std::shared_ptr< interface::Channel > create(const ChannelOptions &options, std::shared_ptr< boost::asio::io_context > external_ioc=nullptr)
Interface for 1:N server communication (e.g., TcpServer)
std::function< void(const ErrorContext &)> ErrorHandler
std::function< void(const ConnectionContext &)> ConnectionHandler
std::function< void(const MessageContext &)> MessageHandler
Modernized TCP Server Wrapper.
bool is_listening() const override
bool send_to(size_t client_id, std::string_view data) override
std::future< bool > start() override
ServerInterface & on_data(MessageHandler handler) override
ServerInterface & on_client_connect(ConnectionHandler handler) override
TcpServer & idle_timeout(int timeout_ms)
bool broadcast(std::string_view data) override
TcpServer & notify_send_failure(bool enable=true)
TcpServer & set_unlimited_clients()
TcpServer & enable_port_retry(bool enable=true, int max_retries=3, int retry_interval_ms=1000)
TcpServer & set_client_limit(size_t max_clients)
TcpServer & auto_manage(bool manage=true)
std::vector< size_t > get_connected_clients() const override
ServerInterface & on_client_disconnect(ConnectionHandler handler) override
TcpServer & set_manage_external_context(bool manage)
size_t get_client_count() const override
ServerInterface & on_error(ErrorHandler handler) override
wrapper::ConnectionContext ConnectionContext
wrapper::ErrorContext ErrorContext
wrapper::MessageContext MessageContext
int port_retry_interval_ms
ConnectionHandler on_client_connect_
ConnectionHandler on_client_disconnect_
bool notify_send_failure_
std::shared_ptr< boost::asio::io_context > external_ioc_
std::atomic< bool > is_listening_
std::shared_ptr< interface::Channel > channel_
std::vector< std::promise< bool > > pending_promises_
std::thread external_thread_
Impl(std::shared_ptr< interface::Channel > channel)
int port_retry_interval_ms_
bool manage_external_context_
std::unique_ptr< boost::asio::executor_work_guard< boost::asio::io_context::executor_type > > work_guard_
bool use_external_context_
std::future< bool > start()
Impl(uint16_t port, std::shared_ptr< boost::asio::io_context > external_ioc)
void setup_internal_handlers()
void fulfill_all(bool value)
bool client_limit_enabled_