From ba48329cd43f2fe25b0432d0231ebf3318d91302 Mon Sep 17 00:00:00 2001 From: Alice Date: Mon, 20 Apr 2026 12:25:11 +0200 Subject: [PATCH] added Server class usable for all detectors --- .../include/BaseMatterhornServer.h | 166 +++------------ .../include/MatterhornServer.h | 2 - .../matterhonServer/include/StopServer.h | 14 -- .../include/VirtualMatterhornServer.h | 2 - .../src/VirtualMatterhornServer.cpp | 5 - .../include/DetectorServer.h | 190 ++++++++++++++++++ .../slsDetectorServer/include/TCPInterface.h | 9 +- .../slsDetectorServer/src/TCPInterface.cpp | 17 +- 8 files changed, 225 insertions(+), 180 deletions(-) delete mode 100644 slsDetectorServers/matterhonServer/include/StopServer.h create mode 100644 slsDetectorServers/slsDetectorServer/include/DetectorServer.h diff --git a/slsDetectorServers/matterhonServer/include/BaseMatterhornServer.h b/slsDetectorServers/matterhonServer/include/BaseMatterhornServer.h index 06876bb07..62834a6a5 100644 --- a/slsDetectorServers/matterhonServer/include/BaseMatterhornServer.h +++ b/slsDetectorServers/matterhonServer/include/BaseMatterhornServer.h @@ -1,6 +1,8 @@ #pragma once +#include "DetectorServer.h" #include "TCPInterface.h" #include "communication_funcs.h" +#include "fmt/format.h" #include "sls/logger.h" #include "sls/network_utils.h" #include "sls/sls_detector_defs.h" @@ -14,19 +16,11 @@ namespace sls { -/// @brief struct saving udp details (one UDP port per module) -struct UDPInfo { - uint16_t srcport{}; - uint16_t dstport{}; - uint64_t srcmac{}; - uint64_t dstmac{}; - uint32_t srcip{}; - uint32_t dstip{}; -}; - /// @brief Base class for Matterhorn Server, can be used to implement a virtual /// server for testing and actual server -template class BaseMatterhornServer { +template +class BaseMatterhornServer + : public DetectorServer> { public: /** @@ -36,7 +30,8 @@ template class BaseMatterhornServer { * throws an exception in case of failure * @param port TCP/IP port number */ - explicit BaseMatterhornServer(uint16_t port = DEFAULT_TCP_CNTRL_PORTNO); + explicit BaseMatterhornServer(uint16_t port = DEFAULT_TCP_CNTRL_PORTNO) + : DetectorServer>(port) {} ~BaseMatterhornServer() = default; @@ -46,95 +41,30 @@ template class BaseMatterhornServer { ReturnCode initial_checks(ServerInterface &socket); - ReturnCode get_num_udp_interfaces(ServerInterface &socket); - - ReturnCode get_update_mode(ServerInterface &socket); - - ReturnCode get_source_udp_mac(ServerInterface &socket); - - ReturnCode get_source_udp_ip(ServerInterface &socket); - - ReturnCode get_source_udp_port(ServerInterface &socket); - - ReturnCode get_destination_udp_mac(ServerInterface &socket); - - ReturnCode get_destination_udp_ip(ServerInterface &socket); - - ReturnCode get_destination_udp_port(ServerInterface &socket); - - protected: - size_t num_udp_interfaces() const; - - /// @brief TODO what is this? - bool updateMode{true}; - - /// @brief TCP/IP interface for communication with the client - std::unique_ptr tcpInterface; - std::array - udpDetails{}; // TODO: for now only one receiver per module + /** + * @brief call function corresponding to the function ID received from the + * client and send back the result + * @param function_id the function ID received from the client + * @param socket the socket to send the result back to the client + */ + ReturnCode processFunction(const detFuncs function_id, + ServerInterface &socket); private: static std::string getMatterhornServerVersion(); - - private: - /// @brief map of function IDs and corresponding functions - // maybe load from additional file cleaner - std::unordered_map> - function_table = { - {detFuncs::F_GET_SERVER_VERSION, - [this](ServerInterface &si) { return this->get_version(si); }}, - {detFuncs::F_GET_DETECTOR_TYPE, - [this](ServerInterface &si) { - return this->get_detector_type(si); - }}, - {detFuncs::F_INITIAL_CHECKS, - [this](ServerInterface &si) { - return static_cast(this)->initial_checks(si); - }}, - {detFuncs::F_GET_NUM_INTERFACES, - [this](ServerInterface &si) { - return this->get_num_udp_interfaces(si); - }}, - {detFuncs::F_GET_UPDATE_MODE, - [this](ServerInterface &si) { - return static_cast(this)->get_update_mode(si); - }}, - {detFuncs::F_GET_SOURCE_UDP_MAC, - [this](ServerInterface &si) { - return this->get_source_udp_mac(si); - }}, - - {detFuncs::F_GET_SOURCE_UDP_IP, - [this](ServerInterface &si) { - return this->get_source_udp_ip(si); - }}, - {detFuncs::F_GET_DEST_UDP_MAC, - [this](ServerInterface &si) { - return this->get_destination_udp_mac(si); - }}, - {detFuncs::F_GET_DEST_UDP_IP, - [this](ServerInterface &si) { - return this->get_destination_udp_ip(si); - }}, - {detFuncs::F_GET_DEST_UDP_PORT, [this](ServerInterface &si) { - return this->get_destination_udp_port(si); - }}}; }; template -BaseMatterhornServer::BaseMatterhornServer(uint16_t port) { +ReturnCode +BaseMatterhornServer::processFunction(const detFuncs function_id, + ServerInterface &socket) { - validatePortNumber(port); - - udpDetails[0].srcport = DEFAULT_UDP_SRC_PORTNO; - udpDetails[0].dstport = DEFAULT_UDP_DST_PORTNO; - - // TODO: when do i set the udp mac and ip ? - - tcpInterface = std::make_unique( - function_table, port); // TODO: need a tcp and udp interface - - // need a function to setup detector - e.g. set all registers etc. + switch (function_id) { + default: + throw RuntimeError( + fmt::format("Function {} not implemented", + getFunctionNameFromEnum((enum detFuncs)function_id))); + } } template @@ -162,52 +92,10 @@ std::string BaseMatterhornServer::getMatterhornServerVersion() { } template -size_t BaseMatterhornServer::num_udp_interfaces() const { - return udpDetails.size(); -} +ReturnCode +BaseMatterhornServer::initial_checks(ServerInterface &socket) { -template -ReturnCode BaseMatterhornServer::get_num_udp_interfaces( - ServerInterface &socket) { - int numUDPInterfaces = static_cast(num_udp_interfaces()); - return static_cast(socket.sendResult(numUDPInterfaces)); + return static_cast(this)->initial_checks(socket); } -template -ReturnCode BaseMatterhornServer::get_source_udp_mac( - ServerInterface &socket) { - return static_cast(socket.sendResult(udpDetails[0].srcmac)); -} - -template -ReturnCode BaseMatterhornServer::get_source_udp_ip( - ServerInterface &socket) { - return static_cast(socket.sendResult(udpDetails[0].srcip)); -} - -template -ReturnCode BaseMatterhornServer::get_source_udp_port( - ServerInterface &socket) { - return static_cast( - socket.sendResult(static_cast(udpDetails[0].srcport))); -} - -template -ReturnCode BaseMatterhornServer::get_destination_udp_mac( - ServerInterface &socket) { - return static_cast(socket.sendResult(udpDetails[0].dstmac)); -} - -template -ReturnCode BaseMatterhornServer::get_destination_udp_ip( - ServerInterface &socket) { - return static_cast(socket.sendResult(udpDetails[0].dstip)); -} - -template -ReturnCode BaseMatterhornServer::get_destination_udp_port( - ServerInterface &socket) { - return static_cast(socket.sendResult(udpDetails[0].dstport)); -}; - } // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/matterhonServer/include/MatterhornServer.h b/slsDetectorServers/matterhonServer/include/MatterhornServer.h index 8946d6418..586818b71 100644 --- a/slsDetectorServers/matterhonServer/include/MatterhornServer.h +++ b/slsDetectorServers/matterhonServer/include/MatterhornServer.h @@ -22,8 +22,6 @@ class MatterhornServer : public BaseMatterhornServer { ~MatterhornServer() = default; ReturnCode initial_checks(ServerInterface &socket); - - ReturnCode get_update_mode(ServerInterface &socket); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/matterhonServer/include/StopServer.h b/slsDetectorServers/matterhonServer/include/StopServer.h deleted file mode 100644 index ff314a69f..000000000 --- a/slsDetectorServers/matterhonServer/include/StopServer.h +++ /dev/null @@ -1,14 +0,0 @@ -#include "MatterhornServer.h" -#include - -namespace sls { - -// TODO: should this inherit from MatterhornServer or a base class - depending on virtual or not -class StopServer : public MatterhornServer { - public: - StopServer(uint16_t port); - - ~StopServer() = default; -}; - -} // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/matterhonServer/include/VirtualMatterhornServer.h b/slsDetectorServers/matterhonServer/include/VirtualMatterhornServer.h index 3f2a1c570..61cb31bda 100644 --- a/slsDetectorServers/matterhonServer/include/VirtualMatterhornServer.h +++ b/slsDetectorServers/matterhonServer/include/VirtualMatterhornServer.h @@ -19,8 +19,6 @@ class VirtualMatterhornServer ~VirtualMatterhornServer() = default; ReturnCode initial_checks(ServerInterface &socket); - - ReturnCode get_update_mode(ServerInterface &socket); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/matterhonServer/src/VirtualMatterhornServer.cpp b/slsDetectorServers/matterhonServer/src/VirtualMatterhornServer.cpp index ade3badef..8c82da20c 100644 --- a/slsDetectorServers/matterhonServer/src/VirtualMatterhornServer.cpp +++ b/slsDetectorServers/matterhonServer/src/VirtualMatterhornServer.cpp @@ -21,9 +21,4 @@ ReturnCode VirtualMatterhornServer::initial_checks(ServerInterface &socket) { return static_cast(socket.sendResult(initial_checks_passed)); } -ReturnCode VirtualMatterhornServer::get_update_mode(ServerInterface &socket) { - return static_cast( - socket.sendResult(static_cast(updateMode))); -} - } // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/slsDetectorServer/include/DetectorServer.h b/slsDetectorServers/slsDetectorServer/include/DetectorServer.h new file mode 100644 index 000000000..644bcb440 --- /dev/null +++ b/slsDetectorServers/slsDetectorServer/include/DetectorServer.h @@ -0,0 +1,190 @@ +#pragma once +#include "TCPInterface.h" +#include "communication_funcs.h" +#include "sls/logger.h" +#include "sls/network_utils.h" +#include "sls/sls_detector_defs.h" +#include "sls/versionAPI.h" +#include +#include +#include +#include +#include +#include + +namespace sls { + +// TODO move to defs? +/// @brief struct saving udp details (one UDP port per module) +struct UDPInfo { + uint16_t srcport{}; + uint16_t srcport2{}; + uint16_t dstport{}; + uint16_t dstport2{}; + uint64_t srcmac{}; + uint64_t srcmac2{}; + uint64_t dstmac{}; + uint64_t dstmac2{}; + uint32_t srcip{}; + uint32_t srcip2{}; + uint32_t dstip{}; + uint32_t dstip2{}; +}; + +template class DetectorServer { + + public: + /** + * Constructor + * Creates a detector server. + * Assembles a detector server using TCP and UDP detector interfaces + * throws an exception in case of failure + * @param port TCP/IP port number + */ + explicit DetectorServer(uint16_t port = DEFAULT_TCP_CNTRL_PORTNO); + + protected: + /// @brief TCP/IP interface for communication with the client + std::unique_ptr tcpInterface; + + std::array + udpDetails{}; // TODO: for now only one receiver per module + + /// @brief TODO what is this? + bool updateMode{true}; + + private: + ReturnCode processFunction(const detFuncs function_id, + ServerInterface &socket); + + size_t num_udp_interfaces() const; + + ReturnCode get_num_udp_interfaces(ServerInterface &socket) const; + + // TODO dont know what this does? + ReturnCode get_update_mode(ServerInterface &socket) const; + + ReturnCode get_source_udp_mac(ServerInterface &socket) const; + + ReturnCode get_source_udp_ip(ServerInterface &socket) const; + + ReturnCode get_source_udp_port(ServerInterface &socket) const; + + ReturnCode get_destination_udp_mac(ServerInterface &socket) const; + + ReturnCode get_destination_udp_ip(ServerInterface &socket) const; + + ReturnCode get_destination_udp_port(ServerInterface &socket) const; +}; + +template +DetectorServer::DetectorServer(uint16_t port) { + validatePortNumber(port); + + udpDetails[0].srcport = DEFAULT_UDP_SRC_PORTNO; + udpDetails[0].dstport = DEFAULT_UDP_DST_PORTNO; + + std::function fn = + [this](const detFuncs &function_id, ServerInterface &socket) { + return this->processFunction(function_id, socket); + }; + tcpInterface = std::make_unique(fn, port); +} + +template +ReturnCode DetectorServer::processFunction( + const detFuncs function_id, ServerInterface &socket) { + + switch (function_id) { + case detFuncs::F_GET_SERVER_VERSION: + return static_cast(this)->get_version(socket); + case detFuncs::F_GET_DETECTOR_TYPE: + return static_cast(this)->get_detector_type( + socket); + case detFuncs::F_INITIAL_CHECKS: + return static_cast(this)->initial_checks( + socket); + case detFuncs::F_GET_NUM_INTERFACES: + return static_cast(this) + ->get_num_udp_interfaces(socket); + case detFuncs::F_GET_UPDATE_MODE: + return get_update_mode(socket); + case detFuncs::F_GET_SOURCE_UDP_MAC: + return get_source_udp_mac(socket); + case detFuncs::F_GET_SOURCE_UDP_IP: + return get_source_udp_ip(socket); + case detFuncs::F_GET_DEST_UDP_MAC: + return get_destination_udp_mac(socket); + case detFuncs::F_GET_DEST_UDP_IP: + return get_destination_udp_ip(socket); + case detFuncs::F_GET_DEST_UDP_PORT: + return get_destination_udp_port(socket); + default: + LOG(logDEBUG) << "Checking specific server functions for function ID: " + << function_id; + // process detector specific functions + static_cast(this)->processFunction(function_id, + socket); + } + + return ReturnCode::FAIL; +} + +template +size_t DetectorServer::num_udp_interfaces() const { + return udpDetails.size(); +} + +template +ReturnCode DetectorServer::get_num_udp_interfaces( + ServerInterface &socket) const { + int numUDPInterfaces = static_cast(num_udp_interfaces()); + return static_cast(socket.sendResult(numUDPInterfaces)); +} + +template +ReturnCode DetectorServer::get_update_mode( + ServerInterface &socket) const { + + return static_cast( + socket.sendResult(static_cast(updateMode))); +} + +template +ReturnCode DetectorServer::get_source_udp_mac( + ServerInterface &socket) const { + return static_cast(socket.sendResult(udpDetails[0].srcmac)); +} + +template +ReturnCode DetectorServer::get_source_udp_ip( + ServerInterface &socket) const { + return static_cast(socket.sendResult(udpDetails[0].srcip)); +} + +template +ReturnCode DetectorServer::get_source_udp_port( + ServerInterface &socket) const { + return static_cast( + socket.sendResult(static_cast(udpDetails[0].srcport))); +} + +template +ReturnCode DetectorServer::get_destination_udp_mac( + ServerInterface &socket) const { + return static_cast(socket.sendResult(udpDetails[0].dstmac)); +} + +template +ReturnCode DetectorServer::get_destination_udp_ip( + ServerInterface &socket) const { + return static_cast(socket.sendResult(udpDetails[0].dstip)); +} + +template +ReturnCode DetectorServer::get_destination_udp_port( + ServerInterface &socket) const { + return static_cast(socket.sendResult(udpDetails[0].dstport)); +}; + +} // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/slsDetectorServer/include/TCPInterface.h b/slsDetectorServers/slsDetectorServer/include/TCPInterface.h index 6aa906dac..6efc05367 100644 --- a/slsDetectorServers/slsDetectorServer/include/TCPInterface.h +++ b/slsDetectorServers/slsDetectorServer/include/TCPInterface.h @@ -18,9 +18,8 @@ class TCPInterface { public: ~TCPInterface(); - TCPInterface(std::unordered_map< - detFuncs, std::function> - &functionTable_, + TCPInterface(std::function + &processFunction_, const uint16_t portNumber = DEFAULT_TCP_CNTRL_PORTNO); /// @brief starts the TCP/IP server to listen for client commands @@ -36,8 +35,8 @@ class TCPInterface { ServerInterface &socket); /// @brief map of function IDs and corresponding functions - std::unordered_map> - functionTable{}; + std::function + processFunction; uint16_t portNumber{}; diff --git a/slsDetectorServers/slsDetectorServer/src/TCPInterface.cpp b/slsDetectorServers/slsDetectorServer/src/TCPInterface.cpp index 3d1bc276e..66ca6bc8b 100644 --- a/slsDetectorServers/slsDetectorServer/src/TCPInterface.cpp +++ b/slsDetectorServers/slsDetectorServer/src/TCPInterface.cpp @@ -8,10 +8,10 @@ namespace sls { TCPInterface::TCPInterface( - std::unordered_map> - &functionTable_, + std::function + &processFunction_, const uint16_t portNumber) - : functionTable(functionTable_), portNumber(portNumber), + : processFunction(processFunction_), portNumber(portNumber), server(portNumber) { validatePortNumber(portNumber); } @@ -67,21 +67,12 @@ void TCPInterface::startTCPServer() { ReturnCode TCPInterface::processReceivedData(const detFuncs function_id, ServerInterface &socket) { - // TODO: is NUM_DET_FUNCTIONS correct? LOG(logDEBUG1) << "calling function fnum: " << function_id << " (" << getFunctionNameFromEnum((enum detFuncs)function_id) << ")"; - auto function = functionTable.find(function_id); - if (function == functionTable.end()) { - throw RuntimeError( - fmt::format("Function {} not found not implemented", - getFunctionNameFromEnum((enum detFuncs)function_id))); - } - - ReturnCode returncode = - function->second(socket); // how does it pass input arguments? + ReturnCode returncode = processFunction(function_id, socket); LOG(logDEBUG1) << "Function " << getFunctionNameFromEnum((enum detFuncs)function_id)