mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-07-18 15:32:51 +02:00
Dev/matterhorn server funcs (#1469)
Build on RHEL9 docker image / build (push) Successful in 4m15s
Build on RHEL8 docker image / build (push) Successful in 5m21s
Build and Deploy on local RHEL9 / build (push) Successful in 2m12s
Build and Deploy on local RHEL8 / build (push) Successful in 5m12s
Run Simulator Tests on local RHEL9 / build (push) Successful in 18m55s
Run Simulator Tests on local RHEL8 / build (push) Successful in 22m19s
Build on RHEL9 docker image / build (push) Successful in 4m15s
Build on RHEL8 docker image / build (push) Successful in 5m21s
Build and Deploy on local RHEL9 / build (push) Successful in 2m12s
Build and Deploy on local RHEL8 / build (push) Successful in 5m12s
Run Simulator Tests on local RHEL9 / build (push) Successful in 18m55s
Run Simulator Tests on local RHEL8 / build (push) Successful in 22m19s
* added fetch fmt server library * added first draft of matterhorn * added cpp TCP Interface to slsDetectorServer * 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 * WIP * generated register defs from csv file * oops given in hex * properly added fmt as a dependency * some format changes * WIP * used CRTP for virtual detector * WIP * added udp functions to matterhornserver * fixed build * 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 * added shared memory for aqcuisition status * implemented bus read and write * added Matterhorn data class * modified memory model * added SPI communication * moved memory for Bus communication to BucCommunication class * WIP added HelperFunction for mask conversion * completed HelperFunctions * added tests for MatterHorn Helper Functions * removed shared memory in destructor * fixed SPI communication * moved SharedMemory to slsSupportLib * added toolchain file for cross compilation * fix constructor for HarwareSPICommunication is public * update receiver parameters function * updated mac address * uploaded matterhorn server binary tracked as lfs * small fixes from tests on board * automatically update matterhorn api version when cross compiling binaries * fix bug in SPI read * copy to server_directory/bin when cross compiling * fixed cmake list * update generate_registerdefs.py * fixed copy of server binary * always return error message * add error log when opening dev/mem * code review * fixed eiger, mythen tests for dynamic range * second Review * member function getDerived for better readability * split code into implementation class and actual class doing tcp communication * added slsWarnings and c++17 compiler option * added git lfs to workflow * fix gitea workflows * bug: add extra clock register * implement initial checks * bug: client excpetcs 4 bytes * refactoring directory structure and rename to .hpp * check if detector already set up * missed .h to .hpp * Code Review 3 * use temmplate value for stopserver * use internal CMAKE_CROSSCOMPILING variable * moved boolean stop server flag to DetectorImpl - moving template parameter up * missed a file * replace baseclass:: with this * add Matterhorn server in github workflow * whatever workflow bug- lets see * fixed receiving trim bits changed to int64_t
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
#include "RegisterHelperStructs.hpp"
|
||||
#include "fmt/format.h"
|
||||
#include <cstdint>
|
||||
#include <fcntl.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <sys/mman.h>
|
||||
#include <vector>
|
||||
|
||||
// TODO: maybe should be templated on address type (e.g. uint32_t register or
|
||||
// uint64_t register) for more flexibility?
|
||||
|
||||
namespace sls {
|
||||
|
||||
template <typename IPCores, typename MemoryModel> class BusCommunication {
|
||||
|
||||
using IPCoreEnumType = typename IPCores::ipcore_enum_type;
|
||||
|
||||
public:
|
||||
BusCommunication();
|
||||
|
||||
void mapToMemory();
|
||||
|
||||
uint32_t readRegister(const Register ®ister_) const;
|
||||
void writeRegister(const Register ®ister_, const uint32_t data);
|
||||
|
||||
private:
|
||||
void bus_w(const uint32_t offset, IPCoreEnumType baseadress,
|
||||
const uint32_t data);
|
||||
|
||||
uint32_t bus_r(const uint32_t offset, IPCoreEnumType baseadress) const;
|
||||
|
||||
/// @brief map from id of IP Core to memory model for the register block of
|
||||
/// the IP core
|
||||
std::map<IPCoreEnumType, MemoryModel> ipcoreregisterblocks{};
|
||||
};
|
||||
|
||||
template <typename IPCores, typename MemoryModel>
|
||||
BusCommunication<IPCores, MemoryModel>::BusCommunication() {
|
||||
|
||||
for (const auto &ip_core : IPCores::ipcores) {
|
||||
ipcoreregisterblocks.emplace(ip_core,
|
||||
MemoryModel{static_cast<uint32_t>(ip_core),
|
||||
IPCores::ip_core_block_size});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename IPCores, typename MemoryModel>
|
||||
void BusCommunication<IPCores, MemoryModel>::mapToMemory() {
|
||||
|
||||
for (auto &map_elem : ipcoreregisterblocks) {
|
||||
map_elem.second.mapToMemory();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename IPCores, typename MemoryModel>
|
||||
uint32_t BusCommunication<IPCores, MemoryModel>::readRegister(
|
||||
const Register ®ister_) const {
|
||||
return bus_r(register_.offset_in_bytes, register_.ip_core);
|
||||
}
|
||||
|
||||
template <typename IPCores, typename MemoryModel>
|
||||
void BusCommunication<IPCores, MemoryModel>::writeRegister(
|
||||
const Register ®ister_, const uint32_t data) {
|
||||
bus_w(register_.offset_in_bytes, register_.ip_core, data);
|
||||
}
|
||||
|
||||
template <typename IPCores, typename MemoryModel>
|
||||
uint32_t BusCommunication<IPCores, MemoryModel>::bus_r(
|
||||
const uint32_t offset, const IPCoreEnumType baseadress) const {
|
||||
auto ptr1 = ipcoreregisterblocks.at(baseadress).getMappedMemoryPtr() +
|
||||
offset / (sizeof(uint32_t));
|
||||
return *ptr1;
|
||||
}
|
||||
|
||||
template <typename IPCores, typename MemoryModel>
|
||||
void BusCommunication<IPCores, MemoryModel>::bus_w(
|
||||
const uint32_t offset, const IPCoreEnumType baseadress,
|
||||
const uint32_t data) {
|
||||
auto ptr1 = ipcoreregisterblocks.at(baseadress).getMappedMemoryPtr() +
|
||||
offset / (sizeof(uint32_t));
|
||||
*ptr1 = data;
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
@@ -1,271 +0,0 @@
|
||||
#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{};
|
||||
};
|
||||
|
||||
using ReturnCode = slsDetectorDefs::ReturnCode;
|
||||
|
||||
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,523 @@
|
||||
#pragma once
|
||||
#include "DetectorServerImpl.hpp"
|
||||
#include "TCPInterface.hpp"
|
||||
#include "helpers/Helpers.hpp"
|
||||
#include "helpers/type_traits.hpp"
|
||||
#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 {
|
||||
|
||||
using ReturnCode = slsDetectorDefs::ReturnCode;
|
||||
|
||||
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(
|
||||
std::unique_ptr<
|
||||
DetectorServerImpl<is_stop_server<DerivedDetectorServer>::value>>
|
||||
impl_,
|
||||
uint16_t port = DEFAULT_TCP_CNTRL_PORTNO);
|
||||
|
||||
~DetectorServer() = default;
|
||||
|
||||
protected:
|
||||
/// @brief TCP/IP interface for communication with the client
|
||||
std::unique_ptr<TCPInterface> tcpInterface;
|
||||
|
||||
std::unique_ptr<
|
||||
DetectorServerImpl<is_stop_server<DerivedDetectorServer>::value>>
|
||||
impl;
|
||||
|
||||
auto *getImpl() {
|
||||
return static_cast<typename implementation_type_trait<
|
||||
DerivedDetectorServer>::ImplType *>(impl.get());
|
||||
}
|
||||
|
||||
const auto *getImpl() const {
|
||||
return static_cast<const typename implementation_type_trait<
|
||||
DerivedDetectorServer>::ImplType *>(impl.get());
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief get derived class
|
||||
DerivedDetectorServer *getDerived() {
|
||||
return static_cast<DerivedDetectorServer *>(this);
|
||||
}
|
||||
|
||||
const DerivedDetectorServer *getDerived() const {
|
||||
return static_cast<const DerivedDetectorServer *>(this);
|
||||
}
|
||||
|
||||
ProcessedResult processFunction(const detFuncs function_id,
|
||||
ServerInterface &socket);
|
||||
|
||||
// TODO dont know what this does?
|
||||
ProcessedResult get_update_mode(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult get_source_udp_mac(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult set_source_udp_mac(ServerInterface &socket);
|
||||
|
||||
ProcessedResult get_source_udp_ip(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult set_source_udp_ip(ServerInterface &socket);
|
||||
|
||||
ProcessedResult get_source_udp_port(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult set_destination_udp_mac(ServerInterface &socket);
|
||||
|
||||
ProcessedResult get_destination_udp_mac(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult set_destination_udp_ip(ServerInterface &socket);
|
||||
|
||||
ProcessedResult get_destination_udp_ip(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult set_destination_udp_port(ServerInterface &socket);
|
||||
|
||||
ProcessedResult get_destination_udp_port(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult get_num_frames(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult set_num_frames(ServerInterface &socket);
|
||||
|
||||
ProcessedResult get_num_triggers(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult set_num_triggers(ServerInterface &socket);
|
||||
|
||||
ProcessedResult get_version(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult get_num_udp_interfaces(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult get_detector_type(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult get_receiver_parameters(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult get_run_status(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult initial_checks(ServerInterface &socket) const;
|
||||
|
||||
ProcessedResult
|
||||
set_module_position_and_update_srcudpmac(ServerInterface &socket);
|
||||
};
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
DetectorServer<DerivedDetectorServer>::DetectorServer(
|
||||
std::unique_ptr<
|
||||
DetectorServerImpl<is_stop_server<DerivedDetectorServer>::value>>
|
||||
impl_,
|
||||
uint16_t port)
|
||||
: impl(std::move(impl_)) {
|
||||
validatePortNumber(port);
|
||||
|
||||
std::function<ProcessedResult(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>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::processFunction(
|
||||
const detFuncs function_id, ServerInterface &socket) {
|
||||
|
||||
switch (function_id) {
|
||||
case detFuncs::F_GET_SERVER_VERSION:
|
||||
return get_version(socket);
|
||||
case detFuncs::F_GET_DETECTOR_TYPE:
|
||||
return get_detector_type(socket);
|
||||
case detFuncs::F_INITIAL_CHECKS:
|
||||
return initial_checks(socket);
|
||||
case detFuncs::F_GET_NUM_INTERFACES:
|
||||
return 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);
|
||||
case detFuncs::F_GET_RUN_STATUS:
|
||||
return get_run_status(socket);
|
||||
case detFuncs::F_GET_NUM_FRAMES:
|
||||
return get_num_frames(socket);
|
||||
case detFuncs::F_SET_NUM_FRAMES:
|
||||
return set_num_frames(socket);
|
||||
case detFuncs::F_GET_NUM_TRIGGERS:
|
||||
return get_num_triggers(socket);
|
||||
case detFuncs::F_SET_NUM_TRIGGERS:
|
||||
return set_num_triggers(socket);
|
||||
case detFuncs::F_GET_RECEIVER_PARAMETERS:
|
||||
return get_receiver_parameters(socket);
|
||||
case detFuncs::F_SET_POSITION:
|
||||
return set_module_position_and_update_srcudpmac(socket);
|
||||
default:
|
||||
LOG(logDEBUG) << "Checking specific server functions for function ID: "
|
||||
<< function_id;
|
||||
// process detector specific functions
|
||||
return getDerived()->processFunction(function_id, socket);
|
||||
}
|
||||
|
||||
return return_fail("Function not implemented");
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_update_mode(
|
||||
ServerInterface &socket) const {
|
||||
|
||||
const bool updateMode = impl->get_update_mode();
|
||||
|
||||
// TODO: catch the socket error during Send and add error message to the
|
||||
// ProcessedResult but DatSocket shared with receiver - some refactoring
|
||||
return send_result(socket, static_cast<uint32_t>(updateMode));
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_source_udp_mac(
|
||||
ServerInterface &socket) const {
|
||||
auto srcUdpMac = impl->get_source_udp_mac();
|
||||
|
||||
return send_result(socket, srcUdpMac);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::set_source_udp_mac(
|
||||
ServerInterface &socket) {
|
||||
|
||||
uint64_t newsrcudpMac;
|
||||
|
||||
try {
|
||||
(void)socket.Receive<uint64_t>(newsrcudpMac);
|
||||
} catch (const SocketError &e) {
|
||||
LOG(logERROR) << "Failed to receive new source UDP MAC address: "
|
||||
<< e.what();
|
||||
return return_fail("Failed to receive new source UDP MAC address: " +
|
||||
std::string(e.what()));
|
||||
}
|
||||
|
||||
try {
|
||||
getImpl()->set_source_udp_mac(newsrcudpMac);
|
||||
} catch (const std::exception &e) {
|
||||
LOG(logERROR) << "Failed to set source UDP MAC address: " << e.what();
|
||||
return_fail("Failed to set source UDP MAC address: " +
|
||||
std::string(e.what()));
|
||||
}
|
||||
|
||||
return send_ok(socket);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::set_source_udp_ip(
|
||||
ServerInterface &socket) {
|
||||
|
||||
uint32_t newSrcIp;
|
||||
|
||||
try {
|
||||
(void)socket.Receive(newSrcIp);
|
||||
} catch (const SocketError &e) {
|
||||
auto error_message = "Failed to receive new source UDP IP address: " +
|
||||
std::string(e.what());
|
||||
LOG(logERROR) << error_message;
|
||||
|
||||
return return_fail(error_message);
|
||||
}
|
||||
|
||||
impl->set_source_udp_ip(newSrcIp);
|
||||
return send_ok(socket);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_source_udp_ip(
|
||||
ServerInterface &socket) const {
|
||||
uint32_t src_UdpIp = impl->get_source_udp_ip();
|
||||
return send_result(socket, src_UdpIp);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::set_destination_udp_mac(
|
||||
ServerInterface &socket) {
|
||||
uint64_t newDstMac;
|
||||
|
||||
try {
|
||||
(void)socket.Receive<uint64_t>(newDstMac);
|
||||
} catch (const SocketError &e) {
|
||||
auto error_message =
|
||||
"Failed to receive new destination UDP MAC address: " +
|
||||
std::string(e.what());
|
||||
LOG(logERROR) << error_message;
|
||||
return return_fail(error_message);
|
||||
}
|
||||
|
||||
impl->set_destination_udp_mac(newDstMac);
|
||||
|
||||
return send_ok(socket);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_destination_udp_mac(
|
||||
ServerInterface &socket) const {
|
||||
|
||||
auto dstUdpMac = impl->get_destination_udp_mac();
|
||||
return send_result(socket, dstUdpMac);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::set_destination_udp_ip(
|
||||
ServerInterface &socket) {
|
||||
uint32_t newDstIp;
|
||||
|
||||
try {
|
||||
(void)socket.Receive(newDstIp);
|
||||
} catch (const SocketError &e) {
|
||||
auto error_message =
|
||||
"Failed to receive new destination UDP IP address: " +
|
||||
std::string(e.what());
|
||||
LOG(logERROR) << error_message;
|
||||
return return_fail(error_message);
|
||||
}
|
||||
|
||||
impl->set_destination_udp_ip(newDstIp);
|
||||
|
||||
return send_ok(socket);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_destination_udp_ip(
|
||||
ServerInterface &socket) const {
|
||||
|
||||
uint32_t dstUdpIp = impl->get_destination_udp_ip();
|
||||
return send_result(socket, dstUdpIp);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::set_destination_udp_port(
|
||||
ServerInterface &socket) {
|
||||
uint16_t newDstPort;
|
||||
|
||||
try {
|
||||
(void)socket.Receive(newDstPort);
|
||||
} catch (const SocketError &e) {
|
||||
auto error_message =
|
||||
"Failed to receive new destination UDP port number: " +
|
||||
std::string(e.what());
|
||||
LOG(logERROR) << error_message;
|
||||
return return_fail(error_message);
|
||||
}
|
||||
|
||||
impl->set_destination_udp_port(newDstPort);
|
||||
|
||||
return send_ok(socket);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_destination_udp_port(
|
||||
ServerInterface &socket) const {
|
||||
uint16_t dstUdpPort = impl->get_destination_udp_port();
|
||||
return send_result(socket, dstUdpPort);
|
||||
};
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_num_frames(
|
||||
ServerInterface &socket) const {
|
||||
uint64_t num_frames{};
|
||||
try {
|
||||
num_frames = getImpl()->get_num_frames();
|
||||
} catch (const std::exception &e) {
|
||||
auto error_message =
|
||||
"Failed to get number of frames: " + std::string(e.what());
|
||||
LOG(logERROR) << error_message;
|
||||
return return_fail(error_message);
|
||||
}
|
||||
return send_result(socket, num_frames);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult
|
||||
DetectorServer<DerivedDetectorServer>::set_num_frames(ServerInterface &socket) {
|
||||
int64_t num_frames{};
|
||||
try {
|
||||
(void)socket.Receive(num_frames);
|
||||
} catch (const SocketError &e) {
|
||||
auto error_message =
|
||||
"Failed to receive number of frames: " + std::string(e.what());
|
||||
LOG(logERROR) << error_message;
|
||||
return return_fail(error_message);
|
||||
}
|
||||
try {
|
||||
getImpl()->set_num_frames(num_frames);
|
||||
} catch (const std::exception &e) {
|
||||
auto error_message =
|
||||
"Failed to set number of frames: " + std::string(e.what());
|
||||
LOG(logERROR) << error_message;
|
||||
return return_fail(error_message);
|
||||
}
|
||||
return send_ok(socket);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_num_triggers(
|
||||
ServerInterface &socket) const {
|
||||
uint64_t num_triggers{};
|
||||
try {
|
||||
num_triggers = static_cast<uint64_t>(getImpl()->get_num_triggers());
|
||||
} catch (const std::exception &e) {
|
||||
auto error_message =
|
||||
"Failed to get number of triggers: " + std::string(e.what());
|
||||
LOG(logERROR) << error_message;
|
||||
return return_fail(error_message);
|
||||
}
|
||||
return send_result(socket, num_triggers);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::set_num_triggers(
|
||||
ServerInterface &socket) {
|
||||
int64_t num_triggers{};
|
||||
try {
|
||||
(void)socket.Receive(num_triggers);
|
||||
} catch (const SocketError &e) {
|
||||
auto error_message =
|
||||
"Failed to receive number of triggers: " + std::string(e.what());
|
||||
LOG(logERROR) << error_message;
|
||||
return return_fail(error_message);
|
||||
}
|
||||
try {
|
||||
getImpl()->set_num_triggers(num_triggers);
|
||||
} catch (const std::exception &e) {
|
||||
auto error_message =
|
||||
"Failed to set number of triggers: " + std::string(e.what());
|
||||
LOG(logERROR) << error_message;
|
||||
return return_fail(error_message);
|
||||
}
|
||||
return send_ok(socket);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_version(
|
||||
ServerInterface &socket) const {
|
||||
|
||||
auto version =
|
||||
getImpl()->get_server_version(); // TODO: get Impl from derived server
|
||||
|
||||
char version_cstr[MAX_STR_LENGTH]{};
|
||||
std::snprintf(version_cstr, sizeof(version_cstr), "%s",
|
||||
version.c_str()); // ensures temination
|
||||
LOG(TLogLevel::logDEBUG) << "Server Version: " << version;
|
||||
return send_result(
|
||||
socket,
|
||||
version_cstr); // TODO: check what would be possible return codes!!!
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_num_udp_interfaces(
|
||||
ServerInterface &socket) const {
|
||||
int num_udp_interfaces = getImpl()->get_num_udp_interfaces();
|
||||
|
||||
return send_result(socket, num_udp_interfaces);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_detector_type(
|
||||
ServerInterface &socket) const {
|
||||
uint32_t detectortype = getImpl()->get_detector_type();
|
||||
return send_result(socket, detectortype);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_receiver_parameters(
|
||||
ServerInterface &socket) const {
|
||||
|
||||
slsDetectorDefs::rxParameters rx_params =
|
||||
getImpl()->get_receiver_parameters();
|
||||
|
||||
return send_result(socket, rx_params);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::get_run_status(
|
||||
ServerInterface &socket) const {
|
||||
|
||||
slsDetectorDefs::runStatus status = getImpl()->get_run_status();
|
||||
|
||||
return send_result(socket, status);
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult DetectorServer<DerivedDetectorServer>::initial_checks(
|
||||
ServerInterface &socket) const {
|
||||
auto detectorsetupstatus = getImpl()->get_detector_setup_status();
|
||||
|
||||
// TODO: should there be a time limit?
|
||||
while (detectorsetupstatus.setup_status ==
|
||||
detector_setup_status::NOT_SETUP) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
detectorsetupstatus = getImpl()->get_detector_setup_status();
|
||||
}
|
||||
if (detectorsetupstatus.setup_status ==
|
||||
detector_setup_status::FAILED_SETUP) {
|
||||
return return_fail("Initial checks failed: " +
|
||||
detectorsetupstatus.error_message);
|
||||
} else {
|
||||
return send_result<bool>(socket, true);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DerivedDetectorServer>
|
||||
ProcessedResult
|
||||
DetectorServer<DerivedDetectorServer>::set_module_position_and_update_srcudpmac(
|
||||
ServerInterface &socket) {
|
||||
|
||||
std::array<int, 2> position_info{}; // [num_modules_in_y, module_index]
|
||||
try {
|
||||
(void)socket.Receive(position_info.data(),
|
||||
position_info.size() * sizeof(int));
|
||||
} catch (const SocketError &e) {
|
||||
LOG(logERROR)
|
||||
<< "Failed to receive num modules in y dimension and module index: "
|
||||
<< e.what();
|
||||
return_fail(
|
||||
"Failed to receive num modules in y dimension and module index: " +
|
||||
std::string(e.what()));
|
||||
}
|
||||
|
||||
try {
|
||||
getImpl()->set_module_position_and_update_srcudpmac(position_info);
|
||||
} catch (const std::exception &e) {
|
||||
return_fail("Failed to set module position: " + std::string(e.what()));
|
||||
}
|
||||
|
||||
return send_ok(socket);
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
@@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
#include "sls/SharedMemory.h"
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
|
||||
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{};
|
||||
};
|
||||
|
||||
/// @brief struct to store detector setup status
|
||||
struct detector_setup_status {
|
||||
|
||||
enum SETUP_STATUS : uint8_t {
|
||||
FAILED_SETUP = 0,
|
||||
SUCCESSFUL_SETUP = 1,
|
||||
NOT_SETUP = 2
|
||||
};
|
||||
|
||||
/// @brief true if setupDetector() was successful, false otherwise
|
||||
SETUP_STATUS setup_status{NOT_SETUP};
|
||||
/// @brief error message if setupDetector() failed, empty otherwise
|
||||
std::string error_message{};
|
||||
};
|
||||
|
||||
/// @brief Shared memory structure for stop server to store run status
|
||||
struct acquisitionStatus {
|
||||
|
||||
/* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND ------*/
|
||||
int shmversion;
|
||||
|
||||
bool isValid{true}; // false if freed to block access from python or c++ api
|
||||
|
||||
std::atomic<slsDetectorDefs::runStatus> scanStatus{
|
||||
slsDetectorDefs::runStatus::IDLE}; // idle, running or error
|
||||
std::atomic<bool> scanStop{false};
|
||||
|
||||
// TODO: only neccessary for virtual, maybe have two shared memory
|
||||
// structures, one for virtual
|
||||
std::atomic<slsDetectorDefs::runStatus> status{
|
||||
slsDetectorDefs::runStatus::IDLE};
|
||||
std::atomic<bool> stop{false};
|
||||
};
|
||||
|
||||
template <bool isStopServer> class DetectorServerImpl {
|
||||
|
||||
public:
|
||||
DetectorServerImpl();
|
||||
~DetectorServerImpl();
|
||||
|
||||
bool get_update_mode() const;
|
||||
|
||||
uint64_t get_source_udp_mac() const;
|
||||
|
||||
void set_source_udp_ip(const uint32_t srcip);
|
||||
|
||||
uint32_t get_source_udp_ip() const;
|
||||
|
||||
void set_destination_udp_ip(const uint32_t dstip);
|
||||
|
||||
uint32_t get_destination_udp_ip() const;
|
||||
|
||||
void set_destination_udp_mac(const uint64_t dstmac);
|
||||
|
||||
uint64_t get_destination_udp_mac() const;
|
||||
|
||||
void set_destination_udp_port(const uint16_t dstport);
|
||||
|
||||
uint16_t get_destination_udp_port() const;
|
||||
|
||||
detector_setup_status get_detector_setup_status() const;
|
||||
|
||||
protected:
|
||||
std::array<UDPInfo, 1>
|
||||
udpDetails{}; // TODO: for now only one receiver per module
|
||||
|
||||
/// @brief TODO what is this?
|
||||
bool updateMode{
|
||||
false}; // what should the default be - can update module size etc.
|
||||
|
||||
/// @brief shared mempory with aquisition status
|
||||
mutable SharedMemory<acquisitionStatus> shm{
|
||||
0, 0}; // TODO: is mutable really neccessary?
|
||||
|
||||
/// @brief sets source UDP MAC address in udpDetails and updates udp
|
||||
/// header
|
||||
/// @param srcmac
|
||||
void updateSrcMacAddress(const uint64_t srcmac);
|
||||
|
||||
/// @brief true if setupDetector() was successful, false otherwise
|
||||
detector_setup_status detectorSetupStatus{};
|
||||
|
||||
/// @brief true if the derived server is a stop server, false otherwise
|
||||
static constexpr bool stop_server = isStopServer;
|
||||
|
||||
private:
|
||||
/// @brief creates and maps shared memory
|
||||
void createSharedMemory();
|
||||
};
|
||||
|
||||
} // namespace sls
|
||||
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
#include "fmt/format.h"
|
||||
#include "sls/logger.h"
|
||||
#include "sls/sls_detector_exceptions.h"
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace sls {
|
||||
|
||||
/// @brief class to handle memory mapping and access for hardware IP cores
|
||||
class HardwareMemoryModel {
|
||||
|
||||
public:
|
||||
HardwareMemoryModel(const uint32_t IPcore_base_address,
|
||||
const size_t size_memory_space_);
|
||||
|
||||
~HardwareMemoryModel();
|
||||
|
||||
void mapToMemory();
|
||||
|
||||
void unmapMemory();
|
||||
|
||||
volatile uint32_t *getMappedMemoryPtr() const;
|
||||
|
||||
private:
|
||||
volatile uint32_t *mapped_memory_ptr{nullptr};
|
||||
|
||||
/// @brief offset of the IP core base address in the memory space, used for
|
||||
/// mapping
|
||||
const size_t IPCore_base_address{0};
|
||||
|
||||
/// @brief size mapped memory region [bytes]
|
||||
const size_t size_memory_space{0};
|
||||
};
|
||||
|
||||
/// @brief class to handle memory mapping and access for virtual IP cores (e.g.
|
||||
/// use software implementation of memory)
|
||||
template <typename DataType> class VirtualMemoryModel {
|
||||
|
||||
public:
|
||||
// IPcore_base_address is not used for virtual memory model but kept for
|
||||
// compatibility with HardwareMemoryModel interface
|
||||
VirtualMemoryModel(const uint32_t IPcore_base_address,
|
||||
const size_t size_memory_space_)
|
||||
: size_memory_space(size_memory_space_) {
|
||||
(void)IPcore_base_address; // suppress unused parameter warning
|
||||
}
|
||||
|
||||
~VirtualMemoryModel() = default;
|
||||
|
||||
void mapToMemory() {
|
||||
mapped_memory.resize(
|
||||
size_memory_space /
|
||||
sizeof(DataType)); // TODO: should it be zero initialized?
|
||||
}
|
||||
|
||||
DataType *getMappedMemoryPtr() { return mapped_memory.data(); }
|
||||
|
||||
const DataType *getMappedMemoryPtr() const { return mapped_memory.data(); }
|
||||
|
||||
private:
|
||||
std::vector<DataType> mapped_memory{};
|
||||
|
||||
/// @brief size mapped memory region [bytes]
|
||||
const size_t size_memory_space{0};
|
||||
};
|
||||
|
||||
} // namespace sls
|
||||
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <fmt/format.h>
|
||||
#include <string_view>
|
||||
|
||||
namespace sls {
|
||||
|
||||
enum class IPCore : uint32_t; // forward declaration of IPCore enum class
|
||||
|
||||
/// @brief struct representing 32 bit register
|
||||
struct Register {
|
||||
/// @brief IP core address space
|
||||
const IPCore ip_core{}; // TODO replace by enum type
|
||||
|
||||
/// @brief Offset of the register in bytes from the base address of the IP
|
||||
/// core
|
||||
const uint32_t offset_in_bytes{};
|
||||
};
|
||||
|
||||
struct RegisterField {
|
||||
/// @brief Register to which the field belongs
|
||||
const Register register_{};
|
||||
|
||||
/// @brief Bit position of the least significant bit of the field in the
|
||||
/// register
|
||||
const uint32_t bit_position{};
|
||||
|
||||
/// @brief Bitmask for the field
|
||||
const uint32_t bitmask{};
|
||||
};
|
||||
|
||||
// TODO: maybe static member function of RegisterField?
|
||||
template <typename T>
|
||||
void setRegisterField(uint32_t ®istervalue, const RegisterField ®_field,
|
||||
T field_value) {
|
||||
|
||||
if (field_value > static_cast<T>(reg_field.bitmask)) {
|
||||
throw std::invalid_argument(
|
||||
fmt::format("Value {} cannot fit in field with bitmask {}",
|
||||
field_value, reg_field.bitmask));
|
||||
}
|
||||
// Clear the bits corresponding to the field
|
||||
registervalue &= ~(reg_field.bitmask << reg_field.bit_position);
|
||||
// Set the new value for the field
|
||||
registervalue |= (static_cast<uint32_t>(field_value) & reg_field.bitmask)
|
||||
<< reg_field.bit_position;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T getRegisterField(const uint32_t ®istervalue,
|
||||
const RegisterField ®_field) {
|
||||
// Extract the bits corresponding to the field and shift them to get the
|
||||
// value
|
||||
|
||||
auto field_value =
|
||||
(registervalue >> reg_field.bit_position) & reg_field.bitmask;
|
||||
|
||||
return static_cast<T>(field_value);
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
+32
-7
@@ -10,6 +10,31 @@
|
||||
|
||||
namespace sls {
|
||||
|
||||
using ReturnCode = slsDetectorDefs::ReturnCode;
|
||||
|
||||
struct ProcessedResult {
|
||||
/// @brief return code of the processed command
|
||||
slsDetectorDefs::ReturnCode returnCode{};
|
||||
/// @brief error message to be sent to client in case of failure
|
||||
std::string error_message{};
|
||||
};
|
||||
|
||||
// communication helpers
|
||||
inline ProcessedResult return_fail(std::string_view error_message) {
|
||||
return ProcessedResult{ReturnCode::FAIL,
|
||||
static_cast<std::string>(error_message)};
|
||||
}
|
||||
|
||||
inline ProcessedResult send_ok(ServerInterface &socket) {
|
||||
return ProcessedResult{
|
||||
static_cast<ReturnCode>(socket.Send(ReturnCode::OK))};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline ProcessedResult send_result(ServerInterface &socket, const T &value) {
|
||||
return ProcessedResult{static_cast<ReturnCode>(socket.sendResult(value))};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TCPInterface class handles communication and processing of commands
|
||||
* from Client to Server.
|
||||
@@ -19,9 +44,10 @@ class TCPInterface {
|
||||
public:
|
||||
~TCPInterface();
|
||||
|
||||
TCPInterface(std::function<slsDetectorDefs::ReturnCode(
|
||||
const detFuncs &, ServerInterface &)> &processFunction_,
|
||||
const uint16_t portNumber = DEFAULT_TCP_CNTRL_PORTNO);
|
||||
TCPInterface(
|
||||
std::function<ProcessedResult(const detFuncs &, ServerInterface &)>
|
||||
&processFunction_,
|
||||
const uint16_t portNumber = DEFAULT_TCP_CNTRL_PORTNO);
|
||||
|
||||
/// @brief creates tcp thread
|
||||
void startTCPServer();
|
||||
@@ -40,12 +66,11 @@ class TCPInterface {
|
||||
* @param function_id The ID of the function recived by the server and to
|
||||
* be executed
|
||||
*/
|
||||
slsDetectorDefs::ReturnCode processReceivedData(const detFuncs function_id,
|
||||
ServerInterface &socket);
|
||||
ProcessedResult processReceivedData(const detFuncs function_id,
|
||||
ServerInterface &socket);
|
||||
|
||||
/// @brief map of function IDs and corresponding functions
|
||||
std::function<slsDetectorDefs::ReturnCode(const detFuncs &,
|
||||
ServerInterface &)>
|
||||
std::function<ProcessedResult(const detFuncs &, ServerInterface &)>
|
||||
processFunction;
|
||||
|
||||
/// @brief TCP/IP port number for the detector server
|
||||
@@ -0,0 +1,19 @@
|
||||
/** @file Defs.hpp
|
||||
* @brief this file contains some definitions used in the slsDetectorServer_cpp
|
||||
* project.
|
||||
*/
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace sls {
|
||||
|
||||
/// @brief Individual/Group bit offset in a 48 bit MAC address - 0 indicates
|
||||
/// unicast mac address
|
||||
constexpr uint8_t INDIVIDUAL_GROUP_BIT_OFFSET = 40; // 1000 0000
|
||||
|
||||
/// @brief Universal/Local bit offset in a 48 bit MAC address - 1 indicates
|
||||
/// locally administered mac address, 0 indicates universally administered mac
|
||||
/// address
|
||||
constexpr uint8_t UNIVERSAL_LOCAL_BIT_OFFSET = 41; // 0100 0000
|
||||
|
||||
} // namespace sls
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
#include "Defs.hpp"
|
||||
#include "DetectorServerImpl.hpp"
|
||||
#include "sls/SharedMemory.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace sls {
|
||||
|
||||
constexpr uint64_t mac_mask = 0xffffffffffff0000;
|
||||
constexpr uint8_t offset_row_position_in_mac = 8; // given in bits
|
||||
constexpr uint8_t offset_col_position_in_mac = 0; // given in bits
|
||||
|
||||
/// @brief generates a random locally administered unicast MAC address for the
|
||||
/// source UDP
|
||||
/// @return generated MAC address
|
||||
inline uint64_t generateRandomMacAddress() {
|
||||
uint64_t mac =
|
||||
0xAA0000000000; // locally administered unicast address (0xA: 0b1010) //
|
||||
// TODO maybe 0x02000000000 better?
|
||||
for (int i = 2; i < 5; ++i) {
|
||||
mac |= (static_cast<uint64_t>(std::rand() % 256) << (i * 8));
|
||||
}
|
||||
return mac;
|
||||
}
|
||||
|
||||
/// @brief generates a MAC address based on the module's row and column
|
||||
/// position, last 32 bits of the MAC address are set to module_row and
|
||||
/// module_col
|
||||
/// @param module_row
|
||||
/// @param module_col
|
||||
/// @return generated MAC address
|
||||
inline uint64_t generateMacAddressfromModulePosition(const uint8_t module_row,
|
||||
const uint8_t module_col) {
|
||||
|
||||
uint64_t newSrcMac = generateRandomMacAddress();
|
||||
newSrcMac = (newSrcMac & mac_mask) |
|
||||
(module_row << offset_row_position_in_mac) |
|
||||
(module_col << offset_col_position_in_mac);
|
||||
|
||||
return newSrcMac;
|
||||
}
|
||||
|
||||
/// @brief check that mac is unicast and locally administered
|
||||
/// @param mac
|
||||
/// @return true if mac is valid, false otherwise
|
||||
inline bool isValidMac(const uint64_t mac) {
|
||||
if ((mac << INDIVIDUAL_GROUP_BIT_OFFSET) == 0 &&
|
||||
(mac << UNIVERSAL_LOCAL_BIT_OFFSET) == 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void freeSharedMemory() {
|
||||
SharedMemory<acquisitionStatus> shm(0, -1, "server");
|
||||
|
||||
if (shm.exists()) {
|
||||
shm.removeSharedMemory();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
|
||||
namespace sls {
|
||||
|
||||
// forward declares
|
||||
template <bool isStopServer> class MatterhornServer;
|
||||
|
||||
template <bool isStopServer> class VirtualMatterhornServer;
|
||||
|
||||
template <bool isStopServer> class MatterhornServerImpl;
|
||||
|
||||
template <bool isStopServer> class VirtualMatterhornServerImpl;
|
||||
|
||||
template <typename DerivedServer> class BaseMatterhornServer;
|
||||
|
||||
// type trait to get implementation type
|
||||
|
||||
template <typename DetectorServer> struct implementation_type_trait;
|
||||
|
||||
template <bool isStopServer>
|
||||
struct implementation_type_trait<
|
||||
BaseMatterhornServer<MatterhornServer<isStopServer>>> {
|
||||
using ImplType = MatterhornServerImpl<isStopServer>;
|
||||
};
|
||||
|
||||
template <bool isStopServer>
|
||||
struct implementation_type_trait<
|
||||
BaseMatterhornServer<VirtualMatterhornServer<isStopServer>>> {
|
||||
using ImplType = VirtualMatterhornServerImpl<isStopServer>;
|
||||
};
|
||||
|
||||
// type trait to get stop server flag from Detector Server
|
||||
|
||||
template <typename DetectorServerImpl>
|
||||
struct is_stop_server : std::false_type {};
|
||||
|
||||
template <>
|
||||
struct is_stop_server<VirtualMatterhornServerImpl<true>> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct is_stop_server<MatterhornServerImpl<true>> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct is_stop_server<VirtualMatterhornServer<true>> : std::true_type {};
|
||||
|
||||
template <> struct is_stop_server<MatterhornServer<true>> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct is_stop_server<BaseMatterhornServer<VirtualMatterhornServer<true>>>
|
||||
: std::true_type {};
|
||||
|
||||
template <>
|
||||
struct is_stop_server<BaseMatterhornServer<MatterhornServer<true>>>
|
||||
: std::true_type {};
|
||||
|
||||
} // namespace sls
|
||||
Reference in New Issue
Block a user