17 .Buffer = Buffers::ProcessingToken::EVENT_RATE,
18 .Node = Nodes::ProcessingToken::EVENT_RATE,
19 .Task = Vruta::ProcessingToken::EVENT_DRIVEN
21 , m_io_context(
std::make_unique<asio::io_context>())
41 "Initializing Network Subsystem...");
62 "Network Subsystem initialized with {} backend(s)",
m_backends.size());
69 "Cannot start NetworkSubsystem: not initialized");
79 for (
auto& [transport, backend] :
m_backends) {
84 m_work_guard = std::make_unique<asio::executor_work_guard<asio::io_context::executor_type>>(
87 m_io_thread = std::jthread([
this](
const std::stop_token& token) {
88 while (!token.stop_requested()) {
92 } catch (
const std::exception& e) {
94 "IO context exception: {}", e.what());
99 "Network IO thread exiting");
102 m_running.store(
true);
105 "Network Subsystem started");
108void NetworkSubsystem::pause()
113void NetworkSubsystem::resume()
118void NetworkSubsystem::stop()
120 if (!m_running.load()) {
124 m_running.store(
false);
127 std::shared_lock lock(m_backends_mutex);
128 for (
auto& [transport, backend] : m_backends) {
137 m_work_guard.reset();
138 m_io_context->stop();
140 if (m_io_thread.joinable()) {
141 m_io_thread.request_stop();
145 m_io_context->restart();
148 "Network Subsystem stopped");
151void NetworkSubsystem::shutdown()
156 std::unique_lock lock(m_routing_mutex);
157 m_endpoint_routing.clear();
161 std::unique_lock lock(m_callbacks_mutex);
162 m_endpoint_callbacks.clear();
166 std::unique_lock lock(m_backends_mutex);
167 for (
auto& [transport, backend] : m_backends) {
177 if (m_network_service) {
180 m_network_service.reset();
183 m_ready.store(
false);
186 "Network Subsystem shutdown complete");
189void NetworkSubsystem::wait_until_running()
191 while (!m_running.load(std::memory_order_acquire))
192 std::this_thread::yield();
199bool NetworkSubsystem::add_backend(std::unique_ptr<INetworkBackend> backend)
207 std::unique_lock lock(m_backends_mutex);
209 if (m_backends.contains(transport)) {
211 "Network backend {} already registered", backend->get_name());
215 if (!backend->initialize()) {
217 "Failed to initialize network backend: {}", backend->get_name());
221 backend->set_receive_callback(
222 [
this](uint64_t
id,
const uint8_t* data,
size_t size, std::string_view addr) {
223 on_backend_receive(
id, data, size, addr);
226 backend->set_state_callback(
228 on_backend_state_change(info, prev, curr);
231 if (
auto* tcp =
dynamic_cast<TCPBackend*
>(backend.get())) {
232 tcp->set_endpoint_id_allocator([
this]() -> uint64_t {
233 return m_next_endpoint_id.fetch_add(1);
238 "Added network backend: {}", backend->get_name());
240 m_backends[transport] = std::move(backend);
246 std::shared_lock lock(m_backends_mutex);
247 auto it = m_backends.find(transport);
248 return (it != m_backends.end()) ? it->second.get() :
nullptr;
251std::vector<INetworkBackend*> NetworkSubsystem::get_backends()
const
253 std::shared_lock lock(m_backends_mutex);
254 std::vector<INetworkBackend*> result;
255 result.reserve(m_backends.size());
256 for (
const auto& [transport, backend] : m_backends) {
257 result.push_back(backend.get());
268 auto* backend = get_backend(info.
transport);
271 "No backend for transport {}",
static_cast<int>(info.
transport));
276 ep.
id = m_next_endpoint_id.fetch_add(1);
278 uint64_t backend_id = backend->open_endpoint(ep);
279 if (backend_id == 0) {
284 std::unique_lock lock(m_routing_mutex);
291void NetworkSubsystem::close_endpoint(uint64_t endpoint_id)
293 auto* backend = resolve_backend(endpoint_id);
298 backend->close_endpoint(endpoint_id);
301 std::unique_lock lock(m_routing_mutex);
302 m_endpoint_routing.erase(endpoint_id);
306 std::unique_lock lock(m_callbacks_mutex);
307 m_endpoint_callbacks.erase(endpoint_id);
311bool NetworkSubsystem::send(uint64_t endpoint_id,
const uint8_t* data,
size_t size)
313 auto* backend = resolve_backend(endpoint_id);
317 return backend->send(endpoint_id, data, size);
320bool NetworkSubsystem::send_to(uint64_t endpoint_id,
const uint8_t* data,
size_t size,
321 const std::string& address, uint16_t port)
323 auto* backend = resolve_backend(endpoint_id);
327 return backend->send_to(endpoint_id, data, size, address, port);
330EndpointState NetworkSubsystem::get_endpoint_state(uint64_t endpoint_id)
const
332 auto* backend = resolve_backend(endpoint_id);
334 return EndpointState::CLOSED;
336 return backend->get_endpoint_state(endpoint_id);
339void NetworkSubsystem::set_endpoint_receive_callback(uint64_t endpoint_id,
342 std::unique_lock lock(m_callbacks_mutex);
343 m_endpoint_callbacks[endpoint_id] = std::move(callback);
346std::vector<EndpointInfo> NetworkSubsystem::get_all_endpoints()
const
348 std::shared_lock lock(m_backends_mutex);
349 std::vector<EndpointInfo> result;
350 for (
const auto& [transport, backend] : m_backends) {
351 auto eps = backend->get_endpoints();
352 result.insert(result.end(), eps.begin(), eps.end());
361void NetworkSubsystem::initialize_udp_backend()
363 auto udp = std::make_unique<UDPBackend>(m_config.udp, *m_io_context);
364 add_backend(std::move(udp));
367void NetworkSubsystem::initialize_tcp_backend()
369 auto tcp = std::make_unique<TCPBackend>(m_config.tcp, *m_io_context);
370 add_backend(std::move(tcp));
373void NetworkSubsystem::initialize_shm_backend()
376 "SharedMemory backend not yet implemented");
379void NetworkSubsystem::register_backend_service()
383 auto service = std::make_shared<Registry::Service::NetworkService>();
385 service->open_endpoint = [
this](
const EndpointInfo& info) {
386 return open_endpoint(info);
389 service->close_endpoint = [
this](uint64_t id) {
393 service->send = [
this](uint64_t id,
const uint8_t* data,
size_t size) {
394 return send(
id, data, size);
397 service->send_to = [
this](uint64_t id,
const uint8_t* data,
size_t size,
398 const std::string& addr, uint16_t port) {
399 return send_to(
id, data, size, addr, port);
402 service->get_endpoint_state = [
this](uint64_t id) {
403 return get_endpoint_state(
id);
407 set_endpoint_receive_callback(
id, std::move(cb));
410 service->get_all_endpoints = [
this]() {
411 return get_all_endpoints();
414 m_network_service = service;
417 [service]() ->
void* {
418 return service.get();
426void NetworkSubsystem::on_backend_receive(uint64_t endpoint_id,
const uint8_t* data,
427 size_t size, std::string_view sender_addr)
429 std::shared_lock lock(m_callbacks_mutex);
430 auto it = m_endpoint_callbacks.find(endpoint_id);
431 if (it != m_endpoint_callbacks.end() && it->second) {
432 it->second(endpoint_id, data, size, sender_addr);
436void NetworkSubsystem::on_backend_state_change(
const EndpointInfo& info,
440 "Endpoint {} state: {} -> {}",
441 info.
id,
static_cast<int>(previous),
static_cast<int>(
current));
452 std::shared_lock lock(m_routing_mutex);
453 auto it = m_endpoint_routing.find(endpoint_id);
454 if (it == m_endpoint_routing.end()) {
457 transport = it->second;
460 return get_backend(transport);
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
Abstract interface for network transport backends.
std::unique_ptr< asio::io_context > m_io_context
void shutdown() override
Shutdown and cleanup subsystem resources.
GlobalNetworkConfig m_config
std::shared_mutex m_backends_mutex
void register_backend_service()
void initialize_tcp_backend()
~NetworkSubsystem() override
std::unique_ptr< asio::executor_work_guard< asio::io_context::executor_type > > m_work_guard
void initialize_shm_backend()
void initialize(SubsystemProcessingHandle &handle) override
Initialize with a handle provided by SubsystemManager.
SubsystemProcessingHandle * m_handle
std::atomic< bool > m_ready
void start() override
Start the subsystem's processing/event loops.
NetworkSubsystem(const GlobalNetworkConfig &config)
void register_callbacks() override
Register callback hooks for this domain.
void initialize_udp_backend()
std::unordered_map< NetworkTransport, std::unique_ptr< INetworkBackend > > m_backends
std::atomic< bool > m_running
std::shared_ptr< Registry::Service::NetworkService > m_network_service
Unified interface combining buffer and node processing for subsystems.
Connection-oriented reliable stream transport over TCP via standalone Asio.
static BackendRegistry & instance()
Get the global registry instance.
void unregister_service()
Unregister a service.
EndpointState
Observable connection state for an endpoint.
NetworkTransport
Identifies the transport protocol a backend implements.
std::function< void(uint64_t endpoint_id, const uint8_t *data, size_t size, std::string_view sender_addr)> NetworkReceiveCallback
Callback signature for inbound data on an endpoint.
@ Shutdown
Engine/subsystem shutdown and cleanup.
@ NetworkSubsystem
Network subsystem operations (endpoint management, data routing)
@ Init
Engine/subsystem initialization.
@ Core
Core engine, backend, subsystems.
void stop()
Stop active Portal::Network operations.
bool initialize(Registry::Service::NetworkService *service)
Initialize Portal::Network.
void shutdown()
Shutdown Portal::Network and release all resources.
bool is_initialized()
Return true if Portal::Network has been initialized.
NetworkTransport transport
Describes one logical send/receive endpoint managed by a backend.
SharedMemoryBackendInfo shared_memory
Configuration for the NetworkSubsystem.
Backend network transport service interface.