#pragma once #include #include #include #include #include #include "secsgem/hsms/connection.hpp" #include "secsgem/hsms/header.hpp" namespace secsgem { using hsms::Connection; using hsms::Timers; // Passive (equipment) endpoint: listens for inbound TCP connections and turns // each into a passive HSMS Connection. The connection handler is invoked once // per accepted session so the application can install message/selected handlers // before the session starts. class Server { public: struct Config { uint16_t port = 5000; uint16_t device_id = 0; Timers timers{}; }; using ConnectionHandler = std::function)>; using LogHandler = std::function; Server(asio::io_context& io, Config cfg); void on_connection(ConnectionHandler h) { on_connection_ = std::move(h); } void on_log(LogHandler h) { on_log_ = std::move(h); } void start(); private: void do_accept(); void log(const std::string& msg); asio::io_context& io_; asio::ip::tcp::acceptor acceptor_; Config cfg_; ConnectionHandler on_connection_; LogHandler on_log_; }; // Active (host) endpoint: connects out to a passive peer, retrying every T5 on // failure, and turns the socket into an active HSMS Connection (which initiates // SELECT). The connection handler is invoked once the TCP connection is up. class Client { public: struct Config { std::string host = "127.0.0.1"; uint16_t port = 5000; uint16_t device_id = 0; Timers timers{}; }; using ConnectionHandler = std::function)>; using LogHandler = std::function; Client(asio::io_context& io, Config cfg); void on_connection(ConnectionHandler h) { on_connection_ = std::move(h); } void on_log(LogHandler h) { on_log_ = std::move(h); } void start(); private: void do_connect(); void schedule_retry(); void log(const std::string& msg); asio::io_context& io_; asio::ip::tcp::resolver resolver_; asio::steady_timer retry_timer_; Config cfg_; ConnectionHandler on_connection_; LogHandler on_log_; }; } // namespace secsgem