added cpp TCP Interface to slsDetectorServer

This commit is contained in:
2026-05-29 15:06:18 +02:00
parent eef6be13b7
commit ac3e4b2143
3 changed files with 217 additions and 0 deletions
@@ -0,0 +1,64 @@
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/ClientInterface.cpp
)
add_library(slsServerObject OBJECT
${SOURCES}
)
target_include_directories(slsServerObject PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
target_link_libraries(slsServerObject
PUBLIC
slsProjectOptions
slsSupportStatic
slsDetectorObject
PRIVATE
slsProjectWarnings
)
set(DETECTOR_LIBRARY_TARGETS slsServerObject)
set(PUBLICHEADERS
${CMAKE_CURRENT_SOURCE_DIR}/include/ClientInterface.h
)
#Shared library
if(SLS_BUILD_SHARED_LIBRARIES)
add_library(slsServerShared SHARED $<TARGET_OBJECTS:slsServerObject>)
target_link_libraries(slsServerShared PUBLIC slsServerObject)
set_target_properties(slsServerShared PROPERTIES
VERSION ${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}
SOVERSION ${PACKAGE_VERSION_MAJOR}
LIBRARY_OUTPUT_NAME SlsServer
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
PUBLIC_HEADER "${PUBLICHEADERS}"
)
list(APPEND DETECTOR_LIBRARY_TARGETS slsServerShared)
endif(SLS_BUILD_SHARED_LIBRARIES)
#Static library
add_library(slsServerStatic STATIC $<TARGET_OBJECTS:slsServerObject>)
target_link_libraries(slsServerStatic PUBLIC slsServerObject)
set_target_properties(slsServerStatic PROPERTIES
ARCHIVE_OUTPUT_NAME SlsServerStatic
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
PUBLIC_HEADER "${PUBLICHEADERS}"
)
list(APPEND DETECTOR_LIBRARY_TARGETS slsServerStatic)
if((CMAKE_BUILD_TYPE STREQUAL "Release") AND SLS_LTO_AVAILABLE)
set_property(TARGET ${DETECTOR_LIBRARY_TARGETS} PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
endif()
install(TARGETS ${DETECTOR_LIBRARY_TARGETS}
EXPORT "${TARGETS_EXPORT_NAME}"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sls
)
@@ -0,0 +1,62 @@
#pragma once
#include "sls/ServerSocket.h"
#include "sls/sls_detector_defs.h"
#include "sls/sls_detector_funcs.h"
#include <atomic>
#include <future>
#include <unordered_map>
namespace sls {
/**
* @brief ClientInterface class handles communication and processing of commands
* from Client to Server.
*/
class ClientInterface : private virtual slsDetectorDefs {
protected:
// TODO probably requires std::variant
/// @brief map of function IDs and corresponding functions
std::unordered_map<detFuncs, std::function<ReturnCode(ServerInterface &)>>
functionTable{}; // set in constructor of child process
private:
/// @brief listener thread for TCP/IP communication with the client
std::unique_ptr<std::thread> tcpThread;
/// @brief flag to signal the TCP/IP listener thread to stop
std::atomic<bool> killTcpThread{false};
/// @brief flag to indicate if the receiver is currently locked by a client
bool lockedByClient{false}; // TODO should it be atomic?
uint16_t portNumber{};
/// @brief socket for TCP/IP communication with the client
ServerSocket server;
public:
~ClientInterface();
explicit ClientInterface(
const uint16_t portNumber = DEFAULT_TCP_CNTRL_PORTNO);
// std::string getReceiverVersion();
private:
/// @brief starts the TCP/IP server to listen for client commands
void startTCPServer();
/**
* @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);
bool checkifReceiverLocked();
};
} // namespace sls
@@ -0,0 +1,91 @@
#include "ClientInterface.h"
#include "sls/logger.h"
#include "sls/string_utils.h"
#include <unistd.h>
namespace sls {
ClientInterface::ClientInterface(const uint16_t portNumber)
: portNumber(portNumber), server(portNumber) {
validatePortNumber(portNumber);
// parentThreadId = gettid();
tcpThread =
std::make_unique<std::thread>(&ClientInterface::startTCPServer, this);
}
ClientInterface::~ClientInterface() {
killTcpThread = true;
LOG(logINFO) << "Shutting down TCP Socket on port " << portNumber;
server.shutdown();
LOG(logDEBUG) << "TCP Socket closed on port " << portNumber;
/*
if (receiver) {
receiver->shutDownUDPSockets();
}
*/
tcpThread->join();
}
void ClientInterface::startTCPServer() {
const pid_t tcpThreadId = gettid();
LOG(logINFOBLUE) << "Created [ TCP server Tid: " << tcpThreadId << "]";
LOG(logINFO) << "SLS Receiver starting TCP Server on port " << portNumber
<< '\n';
int function_id{}; // TODO should it be an enum type
while (!killTcpThread) {
LOG(logDEBUG1) << "Start accept loop";
try {
auto socket = server.accept();
try {
// is this to check if I can process a command? or what is that?
if (checkifReceiverLocked()) {
throw SocketError("Receiver locked\n");
}
socket.Receive(function_id);
processReceivedData(static_cast<detFuncs>(function_id), socket);
} catch (const RuntimeError &e) {
// We had an error needs to be sent to client
char mess[MAX_STR_LENGTH]{};
strcpy_safe(mess, e.what());
socket.Send(FAIL);
socket.Send(mess);
}
// TODO handle exiting server if tcp command was to exit server
} catch (const RuntimeError &e) {
LOG(logERROR) << "Accept failed";
}
}
LOG(logINFOBLUE) << "Exiting [ TCP server Tid: " << tcpThreadId << "]";
}
ReturnCode ClientInterface::processReceivedData(const detFuncs function_id,
ServerInterface &socket) {
// TODO: is NUM_DET_FUNCTIONS correct?
if (function_id < 0 || function_id >= NUM_DET_FUNCTIONS) {
throw RuntimeError(UNRECOGNIZED_FNUM_ENUM +
std::to_string(function_id));
}
LOG(logDEBUG1) << "calling function fnum: " << function_id << " ("
<< getFunctionNameFromEnum((enum detFuncs)function_id)
<< ")";
ReturnCode returncode = (functionTable[function_id])(
socket); // how does it pass input arguments?
LOG(logDEBUG1) << "Function "
<< getFunctionNameFromEnum((enum detFuncs)function_id)
<< " finished";
return returncode;
}
bool ClientInterface::checkifReceiverLocked() {
return lockedByClient && server.getThisClient() != server.getLockedBy();
}
} // namespace sls