mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-05-11 21:45:37 +02:00
Dev/matterhornserver (#1396)
Build and Deploy on local RHEL9 / build (push) Successful in 2m0s
Build on RHEL9 docker image / build (push) Successful in 3m34s
Build on RHEL8 docker image / build (push) Successful in 4m46s
Build and Deploy on local RHEL8 / build (push) Successful in 5m3s
Run Simulator Tests on local RHEL9 / build (push) Successful in 14m43s
Run Simulator Tests on local RHEL8 / build (push) Successful in 18m15s
Build and Deploy on local RHEL9 / build (push) Successful in 2m0s
Build on RHEL9 docker image / build (push) Successful in 3m34s
Build on RHEL8 docker image / build (push) Successful in 4m46s
Build and Deploy on local RHEL8 / build (push) Successful in 5m3s
Run Simulator Tests on local RHEL9 / build (push) Successful in 14m43s
Run Simulator Tests on local RHEL8 / build (push) Successful in 18m15s
* added fetch fmt server library * added first draft of matterhorn * added enum ReturnCode * added cpp TCP Interface to slsDetectorServer * added fmt to workflows * bug: added std::signal for proper handling of ctr+c * added compile option to set log level * WIP * dont use c project settings when building matterhornserver * updated logger * WIP * WIP * linked fmt to slsProjectOptions * solved merge conflict * some refactoring * cleaned up logs * added fmt to workflow * WIP * generated register defs from csv file * oops given in hex * properly added fmt as a dependency * add fmt to conda recipe * some format changes * dont use public headers of fmt * WIP * used CRTP for virtual detector * WIP * added udp functions to matterhornserver * Matterhorn in tostring * warning unused variable from other PR * fixed build * updated cmake * added Server class usable for all detectors * removed stopserver * added some more functions * wrong overload * porper cleanup of matterhorn app * PR Review * refactored directory structure * used pause insetad of sleep --------- Co-authored-by: Dhanya Thattil <dhanya.thattil@psi.ch>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
#include "sls/sls_detector_defs.h"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <getopt.h>
|
||||
#include <string>
|
||||
|
||||
namespace sls {
|
||||
|
||||
struct DetectorServerOptions {
|
||||
// TODO: careful changed for other detectors
|
||||
uint16_t port{DEFAULT_TCP_CNTRL_PORTNO};
|
||||
/// @brief ignore firmware version compatibility
|
||||
bool ignoreFirmwareCompatibility{false};
|
||||
/// @brief safe startup - skip initial detector setup and checks
|
||||
bool safeStartup{false};
|
||||
bool versionRequested{false};
|
||||
bool helpRequested{false};
|
||||
};
|
||||
|
||||
template <typename Server>
|
||||
struct SpecificDetectorServerOptions : DetectorServerOptions {};
|
||||
|
||||
// template specialization
|
||||
// template <>
|
||||
// struct SpecificDetectorServerOptions<BaseMatterhornServer> {};
|
||||
|
||||
// TODO should be a general server specific class or even shared with
|
||||
// CommandLIneOptions in Receiver
|
||||
class CommandLineOptions {
|
||||
|
||||
public:
|
||||
CommandLineOptions() = default;
|
||||
|
||||
~CommandLineOptions() = default;
|
||||
|
||||
DetectorServerOptions parse(int argc, char *argv[]);
|
||||
|
||||
std::string printOptions() const;
|
||||
|
||||
private:
|
||||
std::string getHelpMessage(const std::string &executable) const;
|
||||
|
||||
uint16_t parsePort(const char *optarg) const;
|
||||
|
||||
void parse_deprecated(const int &opt, char *argv[]);
|
||||
|
||||
DetectorServerOptions detectorserveroptions{};
|
||||
|
||||
static constexpr std::array<option, 8> options{
|
||||
{{"help", no_argument, nullptr, 'h'},
|
||||
{"version", no_argument, nullptr, 'v'},
|
||||
{"port", required_argument, nullptr, 'p'},
|
||||
{"ignore_fw_compatibility", no_argument, nullptr,
|
||||
'f'}, // ignore firmware compatibility check
|
||||
{"safe_startup", no_argument, nullptr, 's'}, // safe startup
|
||||
// deprecated options for backward compatibility
|
||||
{"devel", no_argument, nullptr, 'd'}, // safe_startup mode
|
||||
{"update", no_argument, nullptr, 'u'}, // firmware compatibility check
|
||||
|
||||
{nullptr, 0, nullptr, 0}}};
|
||||
|
||||
inline static const char optstring[] = "hvp:fs"
|
||||
"du"; // second part is deprecated
|
||||
};
|
||||
|
||||
} // namespace sls
|
||||
@@ -0,0 +1,269 @@
|
||||
#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 <array>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace sls {
|
||||
|
||||
// TODO move to defs?
|
||||
/// @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{};
|
||||
};
|
||||
|
||||
template <typename DerivedDetectorServer> 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> tcpInterface;
|
||||
|
||||
std::array<UDPInfo, 1>
|
||||
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);
|
||||
|
||||
// TODO dont know what this does?
|
||||
ReturnCode get_update_mode(ServerInterface &socket) const;
|
||||
|
||||
ReturnCode get_source_udp_mac(ServerInterface &socket) const;
|
||||
|
||||
ReturnCode set_source_udp_mac(ServerInterface &socket);
|
||||
|
||||
ReturnCode get_source_udp_ip(ServerInterface &socket) const;
|
||||
|
||||
ReturnCode set_source_udp_ip(ServerInterface &socket);
|
||||
|
||||
ReturnCode get_source_udp_port(ServerInterface &socket) const;
|
||||
|
||||
ReturnCode set_destination_udp_mac(ServerInterface &socket);
|
||||
|
||||
ReturnCode get_destination_udp_mac(ServerInterface &socket) const;
|
||||
|
||||
ReturnCode set_destination_udp_ip(ServerInterface &socket);
|
||||
|
||||
ReturnCode get_destination_udp_ip(ServerInterface &socket) const;
|
||||
|
||||
ReturnCode set_destination_udp_port(ServerInterface &socket);
|
||||
|
||||
ReturnCode get_destination_udp_port(ServerInterface &socket) const;
|
||||
};
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
DetectorServer<DerivedDetectorServer>::DetectorServer(uint16_t port) {
|
||||
validatePortNumber(port);
|
||||
|
||||
udpDetails[0].srcport = DEFAULT_UDP_SRC_PORTNO;
|
||||
udpDetails[0].dstport = DEFAULT_UDP_DST_PORTNO;
|
||||
|
||||
std::function<ReturnCode(const detFuncs &, ServerInterface &)> fn =
|
||||
[this](const detFuncs &function_id, ServerInterface &socket) {
|
||||
return this->processFunction(function_id, socket);
|
||||
};
|
||||
tcpInterface = std::make_unique<TCPInterface>(fn, port);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::processFunction(
|
||||
const detFuncs function_id, ServerInterface &socket) {
|
||||
|
||||
switch (function_id) {
|
||||
case detFuncs::F_GET_SERVER_VERSION:
|
||||
return static_cast<DerivedDetectorServer *>(this)->get_version(socket);
|
||||
case detFuncs::F_GET_DETECTOR_TYPE:
|
||||
return static_cast<DerivedDetectorServer *>(this)->get_detector_type(
|
||||
socket);
|
||||
case detFuncs::F_INITIAL_CHECKS:
|
||||
return static_cast<DerivedDetectorServer *>(this)->initial_checks(
|
||||
socket);
|
||||
case detFuncs::F_GET_NUM_INTERFACES:
|
||||
return static_cast<DerivedDetectorServer *>(this)
|
||||
->get_num_udp_interfaces(socket);
|
||||
case detFuncs::F_GET_UPDATE_MODE:
|
||||
return get_update_mode(socket);
|
||||
case detFuncs::F_SET_SOURCE_UDP_MAC:
|
||||
return set_source_udp_mac(socket);
|
||||
case detFuncs::F_GET_SOURCE_UDP_MAC:
|
||||
return get_source_udp_mac(socket);
|
||||
case detFuncs::F_SET_SOURCE_UDP_IP:
|
||||
return set_source_udp_ip(socket);
|
||||
case detFuncs::F_GET_SOURCE_UDP_IP:
|
||||
return get_source_udp_ip(socket);
|
||||
case detFuncs::F_SET_DEST_UDP_MAC:
|
||||
return set_destination_udp_mac(socket);
|
||||
case detFuncs::F_GET_DEST_UDP_MAC:
|
||||
return get_destination_udp_mac(socket);
|
||||
case detFuncs::F_SET_DEST_UDP_IP:
|
||||
return set_destination_udp_ip(socket);
|
||||
case detFuncs::F_GET_DEST_UDP_IP:
|
||||
return get_destination_udp_ip(socket);
|
||||
case detFuncs::F_SET_DEST_UDP_PORT:
|
||||
return set_destination_udp_port(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<DerivedDetectorServer *>(this)->processFunction(function_id,
|
||||
socket);
|
||||
}
|
||||
|
||||
return ReturnCode::FAIL;
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::get_update_mode(
|
||||
ServerInterface &socket) const {
|
||||
|
||||
return static_cast<ReturnCode>(
|
||||
socket.sendResult(static_cast<int>(updateMode)));
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::set_source_udp_mac(
|
||||
ServerInterface &socket) {
|
||||
uint64_t newsrcudpMac;
|
||||
|
||||
try {
|
||||
int ret = socket.Receive<uint64_t>(newsrcudpMac);
|
||||
} catch (const SocketError &e) {
|
||||
LOG(logERROR) << "Failed to receive new source UDP MAC address: "
|
||||
<< e.what();
|
||||
return ReturnCode::FAIL;
|
||||
}
|
||||
|
||||
udpDetails[0].srcmac = newsrcudpMac;
|
||||
// TODO: configuremac, check unicast address
|
||||
return ReturnCode::OK;
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::get_source_udp_mac(
|
||||
ServerInterface &socket) const {
|
||||
return static_cast<ReturnCode>(socket.sendResult(udpDetails[0].srcmac));
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::set_source_udp_ip(
|
||||
ServerInterface &socket) {
|
||||
uint32_t newSrcIp;
|
||||
|
||||
try {
|
||||
int ret = socket.Receive(newSrcIp);
|
||||
} catch (const SocketError &e) {
|
||||
LOG(logERROR) << "Failed to receive new source UDP IP address: "
|
||||
<< e.what();
|
||||
return ReturnCode::FAIL;
|
||||
}
|
||||
|
||||
udpDetails[0].srcip = newSrcIp;
|
||||
return ReturnCode::OK;
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::get_source_udp_ip(
|
||||
ServerInterface &socket) const {
|
||||
return static_cast<ReturnCode>(socket.sendResult(udpDetails[0].srcip));
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::set_destination_udp_mac(
|
||||
ServerInterface &socket) {
|
||||
uint64_t newDstMac;
|
||||
|
||||
try {
|
||||
int ret = socket.Receive<uint64_t>(newDstMac);
|
||||
} catch (const SocketError &e) {
|
||||
LOG(logERROR) << "Failed to receive new destination UDP MAC address: "
|
||||
<< e.what();
|
||||
return ReturnCode::FAIL;
|
||||
}
|
||||
|
||||
udpDetails[0].dstmac = newDstMac;
|
||||
// TODO: configuremac, check unicast address
|
||||
return ReturnCode::OK;
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::get_destination_udp_mac(
|
||||
ServerInterface &socket) const {
|
||||
return static_cast<ReturnCode>(socket.sendResult(udpDetails[0].dstmac));
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::set_destination_udp_ip(
|
||||
ServerInterface &socket) {
|
||||
uint32_t newDstIp;
|
||||
|
||||
try {
|
||||
int ret = socket.Receive(newDstIp);
|
||||
} catch (const SocketError &e) {
|
||||
LOG(logERROR) << "Failed to receive new destination UDP IP address: "
|
||||
<< e.what();
|
||||
return ReturnCode::FAIL;
|
||||
}
|
||||
|
||||
udpDetails[0].dstip = newDstIp;
|
||||
return ReturnCode::OK;
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::get_destination_udp_ip(
|
||||
ServerInterface &socket) const {
|
||||
return static_cast<ReturnCode>(socket.sendResult(udpDetails[0].dstip));
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::set_destination_udp_port(
|
||||
ServerInterface &socket) {
|
||||
uint16_t newDstPort;
|
||||
|
||||
try {
|
||||
int ret = socket.Receive(newDstPort);
|
||||
} catch (const SocketError &e) {
|
||||
LOG(logERROR) << "Failed to receive new destination UDP port number: "
|
||||
<< e.what();
|
||||
return ReturnCode::FAIL;
|
||||
}
|
||||
|
||||
udpDetails[0].dstport = newDstPort;
|
||||
return ReturnCode::OK;
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ReturnCode DetectorServer<DerivedDetectorServer>::get_destination_udp_port(
|
||||
ServerInterface &socket) const {
|
||||
return static_cast<ReturnCode>(socket.sendResult(udpDetails[0].dstport));
|
||||
};
|
||||
|
||||
} // namespace sls
|
||||
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
#include "sls/ServerSocket.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
#include "sls/sls_detector_funcs.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace sls {
|
||||
|
||||
/**
|
||||
* @brief TCPInterface class handles communication and processing of commands
|
||||
* from Client to Server.
|
||||
*/
|
||||
class TCPInterface {
|
||||
|
||||
public:
|
||||
~TCPInterface();
|
||||
|
||||
TCPInterface(std::function<ReturnCode(const detFuncs &, ServerInterface &)>
|
||||
&processFunction_,
|
||||
const uint16_t portNumber = DEFAULT_TCP_CNTRL_PORTNO);
|
||||
|
||||
/// @brief creates tcp thread
|
||||
void startTCPServer();
|
||||
|
||||
std::atomic<bool> killTcpThread{false};
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief starts the TCP/IP server to listen for client commands and process
|
||||
* them
|
||||
*/
|
||||
void startTCPServerClientConnection();
|
||||
|
||||
/**
|
||||
* @brief decodes the received command and calls the corresponding function
|
||||
* @param function_id The ID of the function recived by the server and to
|
||||
* be executed
|
||||
*/
|
||||
ReturnCode processReceivedData(const detFuncs function_id,
|
||||
ServerInterface &socket);
|
||||
|
||||
/// @brief map of function IDs and corresponding functions
|
||||
std::function<ReturnCode(const detFuncs &, ServerInterface &)>
|
||||
processFunction;
|
||||
|
||||
/// @brief TCP/IP port number for the detector server
|
||||
uint16_t portNumber{};
|
||||
|
||||
/// @brief socket for TCP/IP communication with the client
|
||||
ServerSocket server;
|
||||
|
||||
/// @brief thread for running the TCP/IP server
|
||||
std::unique_ptr<std::thread> tcpThread;
|
||||
};
|
||||
|
||||
} // namespace sls
|
||||
Reference in New Issue
Block a user