From d625642abcc481b73c06a42c0b87fa614d36294b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 21 Mar 2021 00:30:33 +0100 Subject: [PATCH 1/6] created common OSAL stuff to unify UDP code --- osal/common/CMakeLists.txt | 19 +++++-- osal/common/TcpIpBase.cpp | 52 +++++++++++++++++++ osal/common/TcpIpBase.h | 49 +++++++++++++++++ .../TcpTmTcServer.cpp} | 42 +++++++-------- .../TcpTmTcServer.h} | 10 ++-- .../UdpTcPollingTask.cpp} | 41 +++++++++------ .../UdpTcPollingTask.h} | 12 +++-- .../UdpTmTcBridge.cpp} | 50 +++++++++++------- .../UdpTmTcBridge.h} | 13 ++--- osal/common/tcpipCommon.h | 3 +- osal/{windows => common}/tcpipHelpers.h | 2 +- osal/windows/CMakeLists.txt | 8 --- osal/windows/tcpipHelpers.cpp | 2 +- 13 files changed, 214 insertions(+), 89 deletions(-) create mode 100644 osal/common/TcpIpBase.cpp create mode 100644 osal/common/TcpIpBase.h rename osal/{windows/TcWinTcpServer.cpp => common/TcpTmTcServer.cpp} (73%) rename osal/{windows/TcWinTcpServer.h => common/TcpTmTcServer.h} (84%) rename osal/{windows/TcWinUdpPollingTask.cpp => common/UdpTcPollingTask.cpp} (75%) rename osal/{windows/TcWinUdpPollingTask.h => common/UdpTcPollingTask.h} (88%) rename osal/{windows/TmTcWinUdpBridge.cpp => common/UdpTmTcBridge.cpp} (77%) rename osal/{windows/TmTcWinUdpBridge.h => common/UdpTmTcBridge.h} (82%) rename osal/{windows => common}/tcpipHelpers.h (89%) diff --git a/osal/common/CMakeLists.txt b/osal/common/CMakeLists.txt index b77985fb..af76484d 100644 --- a/osal/common/CMakeLists.txt +++ b/osal/common/CMakeLists.txt @@ -1,3 +1,16 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE - tcpipCommon.cpp -) +if(DEFINED WIN32 OR DEFINED UNIX) + target_sources(${LIB_FSFW_NAME} PRIVATE + tcpipCommon.cpp + TcpIpBase.cpp + UdpTcPollingTask.cpp + UdpTmTcBridge.cpp + TcpTmTcServer.cpp + ) +endif() + +if(WIN32) + target_link_libraries(${LIB_FSFW_NAME} PRIVATE + wsock32 + ws2_32 + ) +endif() \ No newline at end of file diff --git a/osal/common/TcpIpBase.cpp b/osal/common/TcpIpBase.cpp new file mode 100644 index 00000000..03de81b1 --- /dev/null +++ b/osal/common/TcpIpBase.cpp @@ -0,0 +1,52 @@ +#include "TcpIpBase.h" + +#ifdef __unix__ + +#include + +#endif + +TcpIpBase::TcpIpBase() { + closeSocket(serverSocket); +} + +TcpIpBase::~TcpIpBase() { +#ifdef _WIN32 + WSACleanup(); +#endif +} + + +int TcpIpBase::closeSocket(socket_t socket) { +#ifdef _WIN32 + return closesocket(socket); +#elif defined(__unix__) + return close(socket) +#endif +} + +int TcpIpBase::getLastSocketError() { +#ifdef _WIN32 + return WSAGetLastError(); +#elif defined(__unix__) + return errno; +#endif +} + +ReturnValue_t TcpIpBase::initialize() { +#ifdef _WIN32 + /* Initiates Winsock DLL. */ + WSAData wsaData; + WORD wVersionRequested = MAKEWORD(2, 2); + int err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + /* Tell the user that we could not find a usable Winsock DLL. */ +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: WSAStartup failed with error: " << + err << std::endl; +#endif + return HasReturnvaluesIF::RETURN_FAILED; + } +#endif + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/osal/common/TcpIpBase.h b/osal/common/TcpIpBase.h new file mode 100644 index 00000000..8da217bc --- /dev/null +++ b/osal/common/TcpIpBase.h @@ -0,0 +1,49 @@ +#ifndef FSFW_OSAL_COMMON_TCPIPIF_H_ +#define FSFW_OSAL_COMMON_TCPIPIF_H_ + +#include + +#ifdef _WIN32 + +#include + +#elif defined(__unix__) + + +#endif + +class TcpIpBase { +protected: + +#ifdef _WIN32 + static constexpr int SHUT_RECV = SD_RECEIVE; + static constexpr int SHUT_SEND = SD_SEND; + static constexpr int SHUT_BOTH = SD_BOTH; + + using socket_t = SOCKET; +#elif defined(__unix__) + using socket_t = int; + + static constexpr int INVALID_SOCKET = -1; + static constexpr int SOCKET_ERROR = -1; + + static constexpr int SHUT_RECV = SHUT_RD; + static constexpr int SHUT_SEND = SHUT_WR; + static constexpr int SHUT_BOTH = SHUT_RDWR; +#endif + + TcpIpBase(); + virtual ~TcpIpBase(); + + ReturnValue_t initialize(); + + int closeSocket(socket_t socket); + + int getLastSocketError(); + + socket_t serverSocket = 0; + +}; + + +#endif /* FSFW_OSAL_COMMON_TCPIPIF_H_ */ diff --git a/osal/windows/TcWinTcpServer.cpp b/osal/common/TcpTmTcServer.cpp similarity index 73% rename from osal/windows/TcWinTcpServer.cpp rename to osal/common/TcpTmTcServer.cpp index f68edfba..320b937d 100644 --- a/osal/windows/TcWinTcpServer.cpp +++ b/osal/common/TcpTmTcServer.cpp @@ -1,14 +1,16 @@ -#include "TcWinTcpServer.h" +#include "TcpTmTcServer.h" #include "tcpipHelpers.h" #include "../../serviceinterface/ServiceInterface.h" +#ifdef _WIN32 #include #include +#endif -const std::string TcWinTcpServer::DEFAULT_TCP_SERVER_PORT = "7301"; -const std::string TcWinTcpServer::DEFAULT_TCP_CLIENT_PORT = "7302"; +const std::string TcpTmTcServer::DEFAULT_TCP_SERVER_PORT = "7301"; +const std::string TcpTmTcServer::DEFAULT_TCP_CLIENT_PORT = "7302"; -TcWinTcpServer::TcWinTcpServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge, +TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge, std::string customTcpServerPort): SystemObject(objectId), tcpPort(customTcpServerPort) { if(tcpPort == "") { @@ -16,23 +18,17 @@ TcWinTcpServer::TcWinTcpServer(object_id_t objectId, object_id_t tmtcUnixUdpBrid } } -ReturnValue_t TcWinTcpServer::initialize() { +ReturnValue_t TcpTmTcServer::initialize() { using namespace tcpip; + + ReturnValue_t result = TcpIpBase::initialize(); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + int retval = 0; struct addrinfo *addrResult = nullptr; - struct addrinfo hints; - /* Initiates Winsock DLL. */ - WSAData wsaData; - WORD wVersionRequested = MAKEWORD(2, 2); - int err = WSAStartup(wVersionRequested, &wsaData); - if (err != 0) { - /* Tell the user that we could not find a usable Winsock DLL. */ -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: WSAStartup failed with error: " << - err << std::endl; -#endif - return HasReturnvaluesIF::RETURN_FAILED; - } + struct addrinfo hints = { 0 }; ZeroMemory(&hints, sizeof (hints)); hints.ai_family = AF_INET; @@ -43,7 +39,7 @@ ReturnValue_t TcWinTcpServer::initialize() { retval = getaddrinfo(nullptr, tcpPort.c_str(), &hints, &addrResult); if (retval != 0) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TcWinTcpServer::TcWinTcpServer: Retrieving address info failed!" << + sif::warning << "TcWinTcpServer::TcpTmTcServer: Retrieving address info failed!" << std::endl; #endif handleError(Protocol::TCP, ErrorSources::GETADDRINFO_CALL); @@ -65,7 +61,7 @@ ReturnValue_t TcWinTcpServer::initialize() { retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast(addrResult->ai_addrlen)); if(retval == SOCKET_ERROR) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TcWinTcpServer::TcWinTcpServer: Binding socket failed!" << + sif::warning << "TcWinTcpServer::TcpTmTcServer: Binding socket failed!" << std::endl; #endif freeaddrinfo(addrResult); @@ -77,12 +73,12 @@ ReturnValue_t TcWinTcpServer::initialize() { } -TcWinTcpServer::~TcWinTcpServer() { +TcpTmTcServer::~TcpTmTcServer() { closesocket(listenerTcpSocket); WSACleanup(); } -ReturnValue_t TcWinTcpServer::performOperation(uint8_t opCode) { +ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { using namespace tcpip; /* If a connection is accepted, the corresponding socket will be assigned to the new socket */ SOCKET clientSocket; @@ -110,7 +106,7 @@ ReturnValue_t TcWinTcpServer::performOperation(uint8_t opCode) { receptionBuffer.size(), 0); if(retval > 0) { #if FSFW_TCP_RCV_WIRETAPPING_ENABLED == 1 - sif::info << "TcWinTcpServer::performOperation: Received " << retval << " bytes." + sif::info << "TcpTmTcServer::performOperation: Received " << retval << " bytes." std::endl; #endif handleError(Protocol::TCP, ErrorSources::RECV_CALL, 500); diff --git a/osal/windows/TcWinTcpServer.h b/osal/common/TcpTmTcServer.h similarity index 84% rename from osal/windows/TcWinTcpServer.h rename to osal/common/TcpTmTcServer.h index bd9f3576..ff6eb610 100644 --- a/osal/windows/TcWinTcpServer.h +++ b/osal/common/TcpTmTcServer.h @@ -1,6 +1,7 @@ #ifndef FSFW_OSAL_WINDOWS_TCWINTCPSERVER_H_ #define FSFW_OSAL_WINDOWS_TCWINTCPSERVER_H_ +#include "TcpIpBase.h" #include "../../objectmanager/SystemObject.h" #include "../../tasks/ExecutableObjectIF.h" @@ -15,17 +16,18 @@ * @details * Based on: https://docs.microsoft.com/en-us/windows/win32/winsock/complete-server-code */ -class TcWinTcpServer: +class TcpTmTcServer: public SystemObject, + public TcpIpBase, public ExecutableObjectIF { public: /* The ports chosen here should not be used by any other process. */ static const std::string DEFAULT_TCP_SERVER_PORT; static const std::string DEFAULT_TCP_CLIENT_PORT; - TcWinTcpServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge, + TcpTmTcServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge, std::string customTcpServerPort = ""); - virtual~ TcWinTcpServer(); + virtual~ TcpTmTcServer(); ReturnValue_t initialize() override; ReturnValue_t performOperation(uint8_t opCode) override; @@ -33,7 +35,7 @@ public: private: std::string tcpPort; - SOCKET listenerTcpSocket = 0; + socket_t listenerTcpSocket = 0; struct sockaddr_in tcpAddress; int tcpAddrLen = sizeof(tcpAddress); int currentBacklog = 3; diff --git a/osal/windows/TcWinUdpPollingTask.cpp b/osal/common/UdpTcPollingTask.cpp similarity index 75% rename from osal/windows/TcWinUdpPollingTask.cpp rename to osal/common/UdpTcPollingTask.cpp index 980404f9..506f1c98 100644 --- a/osal/windows/TcWinUdpPollingTask.cpp +++ b/osal/common/UdpTcPollingTask.cpp @@ -1,4 +1,4 @@ -#include "TcWinUdpPollingTask.h" +#include "UdpTcPollingTask.h" #include "tcpipHelpers.h" #include "../../globalfunctions/arrayprinter.h" #include "../../serviceinterface/ServiceInterfaceStream.h" @@ -8,7 +8,7 @@ //! Debugging preprocessor define. #define FSFW_UDP_RCV_WIRETAPPING_ENABLED 0 -TcWinUdpPollingTask::TcWinUdpPollingTask(object_id_t objectId, +UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, size_t frameSize, double timeoutSeconds): SystemObject(objectId), tmtcBridgeId(tmtcUnixUdpBridge) { @@ -32,9 +32,9 @@ TcWinUdpPollingTask::TcWinUdpPollingTask(object_id_t objectId, } } -TcWinUdpPollingTask::~TcWinUdpPollingTask() {} +UdpTcPollingTask::~UdpTcPollingTask() {} -ReturnValue_t TcWinUdpPollingTask::performOperation(uint8_t opCode) { +ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) { /* Sender Address is cached here. */ struct sockaddr_in senderAddress; int senderAddressSize = sizeof(senderAddress); @@ -52,13 +52,13 @@ ReturnValue_t TcWinUdpPollingTask::performOperation(uint8_t opCode) { if(bytesReceived == SOCKET_ERROR) { /* Handle error */ #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcWinUdpPollingTask::performOperation: Reception error." << std::endl; + sif::error << "UdpTcPollingTask::performOperation: Reception error." << std::endl; #endif tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 1000); continue; } #if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 - sif::debug << "TcWinUdpPollingTask::performOperation: " << bytesReceived << + sif::debug << "UdpTcPollingTask::performOperation: " << bytesReceived << " bytes received" << std::endl; #endif @@ -72,7 +72,7 @@ ReturnValue_t TcWinUdpPollingTask::performOperation(uint8_t opCode) { } -ReturnValue_t TcWinUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) { +ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) { store_address_t storeId; #if FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 @@ -83,7 +83,7 @@ ReturnValue_t TcWinUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) { if (result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning<< "TcWinUdpPollingTask::transferPusToSoftwareBus: Data storage failed." << + sif::warning<< "UdpTcPollingTask::transferPusToSoftwareBus: Data storage failed." << std::endl; sif::warning << "Packet size: " << bytesRead << std::endl; #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ @@ -97,7 +97,7 @@ ReturnValue_t TcWinUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) { if (result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TcWinUdpPollingTask::handleSuccessfullTcRead: " + sif::warning << "UdpTcPollingTask::handleSuccessfullTcRead: " " Sending message to queue failed" << std::endl; #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ @@ -106,37 +106,44 @@ ReturnValue_t TcWinUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) { return result; } -ReturnValue_t TcWinUdpPollingTask::initialize() { +ReturnValue_t UdpTcPollingTask::initialize() { tcStore = objectManager->get(objects::TC_STORE); if (tcStore == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcWinUdpPollingTask::initialize: TC store uninitialized!" << std::endl; + sif::error << "UdpTcPollingTask::initialize: TC store uninitialized!" << std::endl; #endif return ObjectManagerIF::CHILD_INIT_FAILED; } - tmtcBridge = objectManager->get(tmtcBridgeId); + tmtcBridge = objectManager->get(tmtcBridgeId); if(tmtcBridge == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcWinUdpPollingTask::initialize: Invalid TMTC bridge object!" << + sif::error << "UdpTcPollingTask::initialize: Invalid TMTC bridge object!" << std::endl; #endif return ObjectManagerIF::CHILD_INIT_FAILED; } + + ReturnValue_t result = TcpIpBase::initialize(); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t TcWinUdpPollingTask::initializeAfterTaskCreation() { +ReturnValue_t UdpTcPollingTask::initializeAfterTaskCreation() { /* Initialize the destination after task creation. This ensures that the destination has already been set in the TMTC bridge. */ targetTcDestination = tmtcBridge->getRequestQueue(); /* The server socket is set up in the bridge intialization. Calling this function here - ensures that it is set up properly in any case*/ + ensures that it is set up regardless of which class was initialized first */ serverUdpSocket = tmtcBridge->serverSocket; return HasReturnvaluesIF::RETURN_OK; } -void TcWinUdpPollingTask::setTimeout(double timeoutSeconds) { +void UdpTcPollingTask::setTimeout(double timeoutSeconds) { +#ifdef _WIN32 DWORD timeoutMs = timeoutSeconds * 1000.0; int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast(&timeoutMs), sizeof(DWORD)); @@ -146,4 +153,6 @@ void TcWinUdpPollingTask::setTimeout(double timeoutSeconds) { "receive timeout failed with " << strerror(errno) << std::endl; #endif } +#elif defined(__unix__) +#endif } diff --git a/osal/windows/TcWinUdpPollingTask.h b/osal/common/UdpTcPollingTask.h similarity index 88% rename from osal/windows/TcWinUdpPollingTask.h rename to osal/common/UdpTcPollingTask.h index 35e3a701..6b11cc5a 100644 --- a/osal/windows/TcWinUdpPollingTask.h +++ b/osal/common/UdpTcPollingTask.h @@ -1,7 +1,7 @@ #ifndef FSFW_OSAL_WINDOWS_TCSOCKETPOLLINGTASK_H_ #define FSFW_OSAL_WINDOWS_TCSOCKETPOLLINGTASK_H_ -#include "TmTcWinUdpBridge.h" +#include "UdpTmTcBridge.h" #include "../../objectmanager/SystemObject.h" #include "../../tasks/ExecutableObjectIF.h" #include "../../storagemanager/StorageManagerIF.h" @@ -17,7 +17,9 @@ * This class caches the IP address of the sender. It is assumed there * is only one sender for now. */ -class TcWinUdpPollingTask: public SystemObject, +class UdpTcPollingTask: + public TcpIpBase, + public SystemObject, public ExecutableObjectIF { friend class TmTcWinUdpBridge; public: @@ -25,9 +27,9 @@ public: //! 0.5 default milliseconds timeout for now. static constexpr timeval DEFAULT_TIMEOUT = {0, 500}; - TcWinUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, + UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, size_t frameSize = 0, double timeoutSeconds = -1); - virtual~ TcWinUdpPollingTask(); + virtual~ UdpTcPollingTask(); /** * Turn on optional timeout for UDP polling. In the default mode, @@ -46,7 +48,7 @@ protected: private: //! TMTC bridge is cached. object_id_t tmtcBridgeId = objects::NO_OBJECT; - TmTcWinUdpBridge* tmtcBridge = nullptr; + UdpTmTcBridge* tmtcBridge = nullptr; MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; //! See: https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recvfrom diff --git a/osal/windows/TmTcWinUdpBridge.cpp b/osal/common/UdpTmTcBridge.cpp similarity index 77% rename from osal/windows/TmTcWinUdpBridge.cpp rename to osal/common/UdpTmTcBridge.cpp index 8755c84a..be586745 100644 --- a/osal/windows/TmTcWinUdpBridge.cpp +++ b/osal/common/UdpTmTcBridge.cpp @@ -1,16 +1,24 @@ -#include "TmTcWinUdpBridge.h" #include "tcpipHelpers.h" #include #include +#include + +#ifdef _WIN32 #include +#elif defined(__unix__) + +#include + +#endif + //! Debugging preprocessor define. #define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0 -const std::string TmTcWinUdpBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_UDP_SERVER_PORT; +const std::string UdpTmTcBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; -TmTcWinUdpBridge::TmTcWinUdpBridge(object_id_t objectId, object_id_t tcDestination, +UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort): TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { if(udpServerPort == "") { @@ -24,16 +32,18 @@ TmTcWinUdpBridge::TmTcWinUdpBridge(object_id_t objectId, object_id_t tcDestinati communicationLinkUp = false; } -ReturnValue_t TmTcWinUdpBridge::initialize() { +ReturnValue_t UdpTmTcBridge::initialize() { ReturnValue_t result = TmTcBridge::initialize(); if(result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TmTcWinUdpBridge::initialize: TmTcBridge initialization failed!" + sif::error << "TmTcUdpBridge::initialize: TmTcBridge initialization failed!" << std::endl; #endif return result; } + +#ifdef _WIN32 /* Initiates Winsock DLL. */ WSAData wsaData; WORD wVersionRequested = MAKEWORD(2, 2); @@ -42,26 +52,28 @@ ReturnValue_t TmTcWinUdpBridge::initialize() { /* Tell the user that we could not find a usable */ /* Winsock DLL. */ #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: WSAStartup failed with error: " << + sif::error << "TmTcUdpBridge::TmTcUdpBridge: WSAStartup failed with error: " << err << std::endl; #else - sif::printError("TmTcWinUdpBridge::TmTcWinUdpBridge: WSAStartup failed with error: %d\n", + sif::printError("TmTcUdpBridge::TmTcUdpBridge: WSAStartup failed with error: %d\n", err); #endif return HasReturnvaluesIF::RETURN_FAILED; } +#endif struct addrinfo *addrResult = nullptr; - struct addrinfo hints; + struct addrinfo hints = { 0 }; - ZeroMemory(&hints, sizeof (hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; +#ifdef _WIN32 /* See: https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo for information about AI_PASSIVE. */ hints.ai_flags = AI_PASSIVE; +#endif /* Set up UDP socket: https://en.wikipedia.org/wiki/Getaddrinfo @@ -70,7 +82,7 @@ ReturnValue_t TmTcWinUdpBridge::initialize() { int retval = getaddrinfo(nullptr, udpServerPort.c_str(), &hints, &addrResult); if (retval != 0) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Retrieving address info failed!" << + sif::warning << "TmTcUdpBridge::TmTcUdpBridge: Retrieving address info failed!" << std::endl; #endif return HasReturnvaluesIF::RETURN_FAILED; @@ -79,7 +91,7 @@ ReturnValue_t TmTcWinUdpBridge::initialize() { serverSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol); if(serverSocket == INVALID_SOCKET) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not open UDP socket!" << + sif::warning << "TmTcUdpBridge::TmTcUdpBridge: Could not open UDP socket!" << std::endl; #endif freeaddrinfo(addrResult); @@ -90,7 +102,7 @@ ReturnValue_t TmTcWinUdpBridge::initialize() { retval = bind(serverSocket, addrResult->ai_addr, static_cast(addrResult->ai_addrlen)); if(retval != 0) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not bind " + sif::error << "TmTcUdpBridge::TmTcUdpBridge: Could not bind " "local port (" << udpServerPort << ") to server socket!" << std::endl; #endif freeaddrinfo(addrResult); @@ -100,15 +112,13 @@ ReturnValue_t TmTcWinUdpBridge::initialize() { return HasReturnvaluesIF::RETURN_OK; } -TmTcWinUdpBridge::~TmTcWinUdpBridge() { +UdpTmTcBridge::~UdpTmTcBridge() { if(mutex != nullptr) { MutexFactory::instance()->deleteMutex(mutex); } - closesocket(serverSocket); - WSACleanup(); } -ReturnValue_t TmTcWinUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { +ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) { int flags = 0; /* The target address can be set by different threads so this lock ensures thread-safety */ @@ -130,18 +140,18 @@ ReturnValue_t TmTcWinUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { ); if(bytesSent == SOCKET_ERROR) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TmTcWinUdpBridge::sendTm: Send operation failed." << std::endl; + sif::warning << "TmTcUdpBridge::sendTm: Send operation failed." << std::endl; #endif tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL); } #if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 - sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were" + sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent << " bytes were" " sent." << std::endl; #endif return HasReturnvaluesIF::RETURN_OK; } -void TmTcWinUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) { +void UdpTmTcBridge::checkAndSetClientAddress(sockaddr_in& newAddress) { /* The target address can be set by different threads so this lock ensures thread-safety */ MutexGuard lock(mutex, timeoutType, mutexTimeoutMs); @@ -159,7 +169,7 @@ void TmTcWinUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) { clientAddressLen = sizeof(clientAddress); } -void TmTcWinUdpBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, +void UdpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs) { this->timeoutType = timeoutType; this->mutexTimeoutMs = timeoutMs; diff --git a/osal/windows/TmTcWinUdpBridge.h b/osal/common/UdpTmTcBridge.h similarity index 82% rename from osal/windows/TmTcWinUdpBridge.h rename to osal/common/UdpTmTcBridge.h index c2f7d6aa..fcf2baec 100644 --- a/osal/windows/TmTcWinUdpBridge.h +++ b/osal/common/UdpTmTcBridge.h @@ -1,20 +1,22 @@ #ifndef FSFW_OSAL_WINDOWS_TMTCWINUDPBRIDGE_H_ #define FSFW_OSAL_WINDOWS_TMTCWINUDPBRIDGE_H_ +#include "TcpIpBase.h" #include "../../tmtcservices/TmTcBridge.h" #include -#include -class TmTcWinUdpBridge: public TmTcBridge { - friend class TcWinUdpPollingTask; +class UdpTmTcBridge: + public TmTcBridge, + public TcpIpBase { + friend class UdpTcPollingTask; public: /* The ports chosen here should not be used by any other process. */ static const std::string DEFAULT_UDP_SERVER_PORT; - TmTcWinUdpBridge(object_id_t objectId, object_id_t tcDestination, + UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort = ""); - virtual~ TmTcWinUdpBridge(); + virtual~ UdpTmTcBridge(); /** * Set properties of internal mutex. @@ -29,7 +31,6 @@ protected: virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; private: - SOCKET serverSocket = 0; std::string udpServerPort; struct sockaddr_in clientAddress; diff --git a/osal/common/tcpipCommon.h b/osal/common/tcpipCommon.h index 9b38c9fb..dc5ada52 100644 --- a/osal/common/tcpipCommon.h +++ b/osal/common/tcpipCommon.h @@ -6,8 +6,7 @@ namespace tcpip { -const char* const DEFAULT_UDP_SERVER_PORT = "7301"; -const char* const DEFAULT_TCP_SERVER_PORT = "7303"; +const char* const DEFAULT_SERVER_PORT = "7301"; enum class Protocol { UDP, diff --git a/osal/windows/tcpipHelpers.h b/osal/common/tcpipHelpers.h similarity index 89% rename from osal/windows/tcpipHelpers.h rename to osal/common/tcpipHelpers.h index 01f009b9..9764a93f 100644 --- a/osal/windows/tcpipHelpers.h +++ b/osal/common/tcpipHelpers.h @@ -2,7 +2,7 @@ #define FSFW_OSAL_WINDOWS_TCPIPHELPERS_H_ #include "../../timemanager/clockDefinitions.h" -#include "../common/tcpipCommon.h" +#include "tcpipCommon.h" namespace tcpip { diff --git a/osal/windows/CMakeLists.txt b/osal/windows/CMakeLists.txt index a2b31688..1bb39b37 100644 --- a/osal/windows/CMakeLists.txt +++ b/osal/windows/CMakeLists.txt @@ -1,11 +1,3 @@ target_sources(${LIB_FSFW_NAME} PRIVATE - TcWinUdpPollingTask.cpp - TmTcWinUdpBridge.cpp - TcWinTcpServer.cpp tcpipHelpers.cpp ) - -target_link_libraries(${LIB_FSFW_NAME} PRIVATE - wsock32 - ws2_32 -) \ No newline at end of file diff --git a/osal/windows/tcpipHelpers.cpp b/osal/windows/tcpipHelpers.cpp index ef07f5ca..03278a92 100644 --- a/osal/windows/tcpipHelpers.cpp +++ b/osal/windows/tcpipHelpers.cpp @@ -1,4 +1,4 @@ -#include "tcpipHelpers.h" +#include "../common/tcpipHelpers.h" #include #include "../../tasks/TaskFactory.h" From 86577f4b80aa8566a5212edd2712e804b279d638 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 21 Mar 2021 12:51:28 +0100 Subject: [PATCH 2/6] fixed for linux --- osal/common/TcpIpBase.cpp | 3 +- osal/common/TcpIpBase.h | 1 + osal/common/TcpTmTcServer.cpp | 20 +- osal/common/TcpTmTcServer.h | 6 +- osal/common/UdpTcPollingTask.cpp | 19 +- osal/common/UdpTcPollingTask.h | 4 - osal/common/UdpTmTcBridge.cpp | 8 +- osal/common/UdpTmTcBridge.h | 10 +- osal/linux/CMakeLists.txt | 2 - osal/linux/TcUnixUdpPollingTask.cpp | 304 ++++++++++++------------- osal/linux/TcUnixUdpPollingTask.h | 134 +++++------ osal/linux/TmTcUnixUdpBridge.cpp | 334 ++++++++++++++-------------- osal/linux/TmTcUnixUdpBridge.h | 106 ++++----- 13 files changed, 484 insertions(+), 467 deletions(-) diff --git a/osal/common/TcpIpBase.cpp b/osal/common/TcpIpBase.cpp index 03de81b1..35524743 100644 --- a/osal/common/TcpIpBase.cpp +++ b/osal/common/TcpIpBase.cpp @@ -2,6 +2,7 @@ #ifdef __unix__ +#include #include #endif @@ -21,7 +22,7 @@ int TcpIpBase::closeSocket(socket_t socket) { #ifdef _WIN32 return closesocket(socket); #elif defined(__unix__) - return close(socket) + return close(socket); #endif } diff --git a/osal/common/TcpIpBase.h b/osal/common/TcpIpBase.h index 8da217bc..652d791a 100644 --- a/osal/common/TcpIpBase.h +++ b/osal/common/TcpIpBase.h @@ -9,6 +9,7 @@ #elif defined(__unix__) +#include #endif diff --git a/osal/common/TcpTmTcServer.cpp b/osal/common/TcpTmTcServer.cpp index 320b937d..2da5da95 100644 --- a/osal/common/TcpTmTcServer.cpp +++ b/osal/common/TcpTmTcServer.cpp @@ -5,6 +5,11 @@ #ifdef _WIN32 #include #include + +#elif defined(__unix__) + +#include + #endif const std::string TcpTmTcServer::DEFAULT_TCP_SERVER_PORT = "7301"; @@ -30,7 +35,6 @@ ReturnValue_t TcpTmTcServer::initialize() { struct addrinfo *addrResult = nullptr; struct addrinfo hints = { 0 }; - ZeroMemory(&hints, sizeof (hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; @@ -74,16 +78,15 @@ ReturnValue_t TcpTmTcServer::initialize() { TcpTmTcServer::~TcpTmTcServer() { - closesocket(listenerTcpSocket); - WSACleanup(); + closeSocket(listenerTcpSocket); } ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { using namespace tcpip; /* If a connection is accepted, the corresponding socket will be assigned to the new socket */ - SOCKET clientSocket; - sockaddr_in clientSockAddr; - int connectorSockAddrLen = 0; + socket_t clientSocket; + sockaddr clientSockAddr; + socklen_t connectorSockAddrLen = 0; int retval = 0; /* Listen for connection requests permanently for lifetime of program */ @@ -94,8 +97,7 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { continue; } - clientSocket = accept(listenerTcpSocket, reinterpret_cast(&clientSockAddr), - &connectorSockAddrLen); + clientSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen); if(clientSocket == INVALID_SOCKET) { handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500); @@ -119,7 +121,7 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { } /* Done, shut down connection */ - retval = shutdown(clientSocket, SD_SEND); + retval = shutdown(clientSocket, SHUT_SEND); } return HasReturnvaluesIF::RETURN_OK; } diff --git a/osal/common/TcpTmTcServer.h b/osal/common/TcpTmTcServer.h index ff6eb610..4dcc77a2 100644 --- a/osal/common/TcpTmTcServer.h +++ b/osal/common/TcpTmTcServer.h @@ -5,6 +5,10 @@ #include "../../objectmanager/SystemObject.h" #include "../../tasks/ExecutableObjectIF.h" +#ifdef __unix__ +#include +#endif + #include #include @@ -36,7 +40,7 @@ private: std::string tcpPort; socket_t listenerTcpSocket = 0; - struct sockaddr_in tcpAddress; + struct sockaddr tcpAddress; int tcpAddrLen = sizeof(tcpAddress); int currentBacklog = 3; diff --git a/osal/common/UdpTcPollingTask.cpp b/osal/common/UdpTcPollingTask.cpp index 506f1c98..3d51e118 100644 --- a/osal/common/UdpTcPollingTask.cpp +++ b/osal/common/UdpTcPollingTask.cpp @@ -3,8 +3,17 @@ #include "../../globalfunctions/arrayprinter.h" #include "../../serviceinterface/ServiceInterfaceStream.h" +#ifdef _WIN32 + #include +#else + +#include +#include + +#endif + //! Debugging preprocessor define. #define FSFW_UDP_RCV_WIRETAPPING_ENABLED 0 @@ -36,17 +45,17 @@ UdpTcPollingTask::~UdpTcPollingTask() {} ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) { /* Sender Address is cached here. */ - struct sockaddr_in senderAddress; - int senderAddressSize = sizeof(senderAddress); + struct sockaddr senderAddress; + socklen_t senderAddressSize = sizeof(senderAddress); /* Poll for new UDP datagrams in permanent loop. */ while(true) { int bytesReceived = recvfrom( - serverUdpSocket, + this->serverSocket, reinterpret_cast(receptionBuffer.data()), frameSize, receptionFlags, - reinterpret_cast(&senderAddress), + &senderAddress, &senderAddressSize ); if(bytesReceived == SOCKET_ERROR) { @@ -138,7 +147,7 @@ ReturnValue_t UdpTcPollingTask::initializeAfterTaskCreation() { targetTcDestination = tmtcBridge->getRequestQueue(); /* The server socket is set up in the bridge intialization. Calling this function here ensures that it is set up regardless of which class was initialized first */ - serverUdpSocket = tmtcBridge->serverSocket; + this->serverSocket = tmtcBridge->serverSocket; return HasReturnvaluesIF::RETURN_OK; } diff --git a/osal/common/UdpTcPollingTask.h b/osal/common/UdpTcPollingTask.h index 6b11cc5a..4df62b94 100644 --- a/osal/common/UdpTcPollingTask.h +++ b/osal/common/UdpTcPollingTask.h @@ -54,10 +54,6 @@ private: //! See: https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recvfrom int receptionFlags = 0; - //! Server socket, which is member of TMTC bridge. - //! Will be cached shortly after SW intialization. - SOCKET serverUdpSocket = 0; - std::vector receptionBuffer; size_t frameSize = 0; diff --git a/osal/common/UdpTmTcBridge.cpp b/osal/common/UdpTmTcBridge.cpp index be586745..a8975c0e 100644 --- a/osal/common/UdpTmTcBridge.cpp +++ b/osal/common/UdpTmTcBridge.cpp @@ -5,11 +5,13 @@ #include #ifdef _WIN32 + #include #elif defined(__unix__) -#include +#include +#include #endif @@ -135,7 +137,7 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) { reinterpret_cast(data), dataLen, flags, - reinterpret_cast(&clientAddress), + &clientAddress, clientAddressLen ); if(bytesSent == SOCKET_ERROR) { @@ -151,7 +153,7 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) { return HasReturnvaluesIF::RETURN_OK; } -void UdpTmTcBridge::checkAndSetClientAddress(sockaddr_in& newAddress) { +void UdpTmTcBridge::checkAndSetClientAddress(sockaddr& newAddress) { /* The target address can be set by different threads so this lock ensures thread-safety */ MutexGuard lock(mutex, timeoutType, mutexTimeoutMs); diff --git a/osal/common/UdpTmTcBridge.h b/osal/common/UdpTmTcBridge.h index fcf2baec..afc8ee98 100644 --- a/osal/common/UdpTmTcBridge.h +++ b/osal/common/UdpTmTcBridge.h @@ -4,6 +4,10 @@ #include "TcpIpBase.h" #include "../../tmtcservices/TmTcBridge.h" +#ifdef __unix__ +#include +#endif + #include class UdpTmTcBridge: @@ -25,7 +29,7 @@ public: ReturnValue_t initialize() override; - void checkAndSetClientAddress(sockaddr_in& clientAddress); + void checkAndSetClientAddress(sockaddr& clientAddress); protected: virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; @@ -33,8 +37,8 @@ protected: private: std::string udpServerPort; - struct sockaddr_in clientAddress; - int clientAddressLen = 0; + struct sockaddr clientAddress; + socklen_t clientAddressLen = 0; //! Access to the client address is mutex protected as it is set by another task. MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; diff --git a/osal/linux/CMakeLists.txt b/osal/linux/CMakeLists.txt index 6c377844..332fe2f4 100644 --- a/osal/linux/CMakeLists.txt +++ b/osal/linux/CMakeLists.txt @@ -13,8 +13,6 @@ target_sources(${LIB_FSFW_NAME} QueueFactory.cpp SemaphoreFactory.cpp TaskFactory.cpp - TcUnixUdpPollingTask.cpp - TmTcUnixUdpBridge.cpp Timer.cpp tcpipHelpers.cpp ) diff --git a/osal/linux/TcUnixUdpPollingTask.cpp b/osal/linux/TcUnixUdpPollingTask.cpp index 37dadb76..ec3687b9 100644 --- a/osal/linux/TcUnixUdpPollingTask.cpp +++ b/osal/linux/TcUnixUdpPollingTask.cpp @@ -1,152 +1,152 @@ -#include "TcUnixUdpPollingTask.h" -#include "tcpipHelpers.h" - -#include "../../globalfunctions/arrayprinter.h" - -#define FSFW_UDP_RCV_WIRETAPPING_ENABLED 0 - -TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId, - object_id_t tmtcUnixUdpBridge, size_t frameSize, - double timeoutSeconds): SystemObject(objectId), - tmtcBridgeId(tmtcUnixUdpBridge) { - - if(frameSize > 0) { - this->frameSize = frameSize; - } - else { - this->frameSize = DEFAULT_MAX_FRAME_SIZE; - } - - /* Set up reception buffer with specified frame size. - For now, it is assumed that only one frame is held in the buffer! */ - receptionBuffer.reserve(this->frameSize); - receptionBuffer.resize(this->frameSize); - - if(timeoutSeconds == -1) { - receptionTimeout = DEFAULT_TIMEOUT; - } - else { - receptionTimeout = timevalOperations::toTimeval(timeoutSeconds); - } -} - -TcUnixUdpPollingTask::~TcUnixUdpPollingTask() {} - -ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) { - /* Sender Address is cached here. */ - struct sockaddr_in senderAddress; - socklen_t senderAddressSize = sizeof(senderAddress); - - /* Poll for new UDP datagrams in permanent loop. */ - while(true) { - ssize_t bytesReceived = recvfrom( - serverUdpSocket, - receptionBuffer.data(), - frameSize, - receptionFlags, - reinterpret_cast(&senderAddress), - &senderAddressSize - ); - if(bytesReceived < 0) { - /* Handle error */ -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcSocketPollingTask::performOperation: Reception error." << std::endl; -#endif - tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 500); - continue; - } -#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 - sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived - << " bytes received" << std::endl; -#endif - - ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); - if(result != HasReturnvaluesIF::RETURN_FAILED) { - - } - tmtcBridge->checkAndSetClientAddress(senderAddress); - } - return HasReturnvaluesIF::RETURN_OK; -} - - -ReturnValue_t TcUnixUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) { - store_address_t storeId; - -#if FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 - arrayprinter::print(receptionBuffer.data(), bytesRead); -#endif - - ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRead); - if (result != HasReturnvaluesIF::RETURN_OK) { -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcUnixUdpPollingTask::handleSuccessfullTcRead: Data " - "storage failed" << std::endl; - sif::error << "Packet size: " << bytesRead << std::endl; -#else -#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ -#endif /* FSFW_VERBOSE_LEVEL >= 1 */ - return HasReturnvaluesIF::RETURN_FAILED; - } - - TmTcMessage message(storeId); - - result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); - if (result != HasReturnvaluesIF::RETURN_OK) { -#if FSFW_VERBOSE_LEVEL >= 1 -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcUnixUdpPollingTask::handleSuccessfullTcRead: Sending message to queue " - "failed" << std::endl; -#else -#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ -#endif /* FSFW_VERBOSE_LEVEL >= 1 */ - tcStore->deleteData(storeId); - } - return result; -} - -ReturnValue_t TcUnixUdpPollingTask::initialize() { - tcStore = objectManager->get(objects::TC_STORE); - if (tcStore == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcSerialPollingTask::initialize: TC Store uninitialized!" - << std::endl; -#endif - return ObjectManagerIF::CHILD_INIT_FAILED; - } - - tmtcBridge = objectManager->get(tmtcBridgeId); - if(tmtcBridge == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid" - " TMTC bridge object!" << std::endl; -#endif - return ObjectManagerIF::CHILD_INIT_FAILED; - } - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t TcUnixUdpPollingTask::initializeAfterTaskCreation() { - /* Initialize the destination after task creation. This ensures - that the destination has already been set in the TMTC bridge. */ - targetTcDestination = tmtcBridge->getRequestQueue(); - /* The server socket is set up in the bridge intialization. Calling this function here - ensures that it is set up properly in any case*/ - serverUdpSocket = tmtcBridge->serverSocket; - return HasReturnvaluesIF::RETURN_OK; -} - -void TcUnixUdpPollingTask::setTimeout(double timeoutSeconds) { - timeval tval; - tval = timevalOperations::toTimeval(timeoutSeconds); - int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO, - &tval, sizeof(receptionTimeout)); - if(result == -1) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting " - "receive timeout failed with " << strerror(errno) << std::endl; -#endif - } -} +//#include "TcUnixUdpPollingTask.h" +//#include "tcpipHelpers.h" +// +//#include "../../globalfunctions/arrayprinter.h" +// +//#define FSFW_UDP_RCV_WIRETAPPING_ENABLED 0 +// +//TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId, +// object_id_t tmtcUnixUdpBridge, size_t frameSize, +// double timeoutSeconds): SystemObject(objectId), +// tmtcBridgeId(tmtcUnixUdpBridge) { +// +// if(frameSize > 0) { +// this->frameSize = frameSize; +// } +// else { +// this->frameSize = DEFAULT_MAX_FRAME_SIZE; +// } +// +// /* Set up reception buffer with specified frame size. +// For now, it is assumed that only one frame is held in the buffer! */ +// receptionBuffer.reserve(this->frameSize); +// receptionBuffer.resize(this->frameSize); +// +// if(timeoutSeconds == -1) { +// receptionTimeout = DEFAULT_TIMEOUT; +// } +// else { +// receptionTimeout = timevalOperations::toTimeval(timeoutSeconds); +// } +//} +// +//TcUnixUdpPollingTask::~TcUnixUdpPollingTask() {} +// +//ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) { +// /* Sender Address is cached here. */ +// struct sockaddr_in senderAddress; +// socklen_t senderAddressSize = sizeof(senderAddress); +// +// /* Poll for new UDP datagrams in permanent loop. */ +// while(true) { +// ssize_t bytesReceived = recvfrom( +// serverUdpSocket, +// receptionBuffer.data(), +// frameSize, +// receptionFlags, +// reinterpret_cast(&senderAddress), +// &senderAddressSize +// ); +// if(bytesReceived < 0) { +// /* Handle error */ +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::error << "TcSocketPollingTask::performOperation: Reception error." << std::endl; +//#endif +// tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 500); +// continue; +// } +//#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 +// sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived +// << " bytes received" << std::endl; +//#endif +// +// ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); +// if(result != HasReturnvaluesIF::RETURN_FAILED) { +// +// } +// tmtcBridge->checkAndSetClientAddress(senderAddress); +// } +// return HasReturnvaluesIF::RETURN_OK; +//} +// +// +//ReturnValue_t TcUnixUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) { +// store_address_t storeId; +// +//#if FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 +// arrayprinter::print(receptionBuffer.data(), bytesRead); +//#endif +// +// ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRead); +// if (result != HasReturnvaluesIF::RETURN_OK) { +//#if FSFW_VERBOSE_LEVEL >= 1 +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::error << "TcUnixUdpPollingTask::handleSuccessfullTcRead: Data " +// "storage failed" << std::endl; +// sif::error << "Packet size: " << bytesRead << std::endl; +//#else +//#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ +//#endif /* FSFW_VERBOSE_LEVEL >= 1 */ +// return HasReturnvaluesIF::RETURN_FAILED; +// } +// +// TmTcMessage message(storeId); +// +// result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); +// if (result != HasReturnvaluesIF::RETURN_OK) { +//#if FSFW_VERBOSE_LEVEL >= 1 +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::error << "TcUnixUdpPollingTask::handleSuccessfullTcRead: Sending message to queue " +// "failed" << std::endl; +//#else +//#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ +//#endif /* FSFW_VERBOSE_LEVEL >= 1 */ +// tcStore->deleteData(storeId); +// } +// return result; +//} +// +//ReturnValue_t TcUnixUdpPollingTask::initialize() { +// tcStore = objectManager->get(objects::TC_STORE); +// if (tcStore == nullptr) { +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::error << "TcSerialPollingTask::initialize: TC Store uninitialized!" +// << std::endl; +//#endif +// return ObjectManagerIF::CHILD_INIT_FAILED; +// } +// +// tmtcBridge = objectManager->get(tmtcBridgeId); +// if(tmtcBridge == nullptr) { +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid" +// " TMTC bridge object!" << std::endl; +//#endif +// return ObjectManagerIF::CHILD_INIT_FAILED; +// } +// +// return HasReturnvaluesIF::RETURN_OK; +//} +// +//ReturnValue_t TcUnixUdpPollingTask::initializeAfterTaskCreation() { +// /* Initialize the destination after task creation. This ensures +// that the destination has already been set in the TMTC bridge. */ +// targetTcDestination = tmtcBridge->getRequestQueue(); +// /* The server socket is set up in the bridge intialization. Calling this function here +// ensures that it is set up properly in any case*/ +// serverUdpSocket = tmtcBridge->serverSocket; +// return HasReturnvaluesIF::RETURN_OK; +//} +// +//void TcUnixUdpPollingTask::setTimeout(double timeoutSeconds) { +// timeval tval; +// tval = timevalOperations::toTimeval(timeoutSeconds); +// int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO, +// &tval, sizeof(receptionTimeout)); +// if(result == -1) { +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting " +// "receive timeout failed with " << strerror(errno) << std::endl; +//#endif +// } +//} diff --git a/osal/linux/TcUnixUdpPollingTask.h b/osal/linux/TcUnixUdpPollingTask.h index 39ee0914..1040d1a2 100644 --- a/osal/linux/TcUnixUdpPollingTask.h +++ b/osal/linux/TcUnixUdpPollingTask.h @@ -1,67 +1,67 @@ -#ifndef FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ -#define FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ - -#include "../../objectmanager/SystemObject.h" -#include "../../osal/linux/TmTcUnixUdpBridge.h" -#include "../../tasks/ExecutableObjectIF.h" - -#include -#include - -/** - * @brief This class can be used to implement the polling of a Unix socket, - * using UDP for now. - * @details - * The task will be blocked while the specified number of bytes has not been - * received, so TC reception is handled inside a separate task. - * This class caches the IP address of the sender. It is assumed there - * is only one sender for now. - */ -class TcUnixUdpPollingTask: public SystemObject, - public ExecutableObjectIF { - friend class TmTcUnixUdpBridge; -public: - static constexpr size_t DEFAULT_MAX_FRAME_SIZE = 2048; - //! 0.5 default milliseconds timeout for now. - static constexpr timeval DEFAULT_TIMEOUT = {.tv_sec = 0, .tv_usec = 500}; - - TcUnixUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, - size_t frameSize = 0, double timeoutSeconds = -1); - virtual~ TcUnixUdpPollingTask(); - - /** - * Turn on optional timeout for UDP polling. In the default mode, - * the receive function will block until a packet is received. - * @param timeoutSeconds - */ - void setTimeout(double timeoutSeconds); - - virtual ReturnValue_t performOperation(uint8_t opCode) override; - virtual ReturnValue_t initialize() override; - virtual ReturnValue_t initializeAfterTaskCreation() override; - -protected: - StorageManagerIF* tcStore = nullptr; - -private: - //! TMTC bridge is cached. - object_id_t tmtcBridgeId = objects::NO_OBJECT; - TmTcUnixUdpBridge* tmtcBridge = nullptr; - MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; - - //! Reception flags: https://linux.die.net/man/2/recvfrom. - int receptionFlags = 0; - - //! Server socket, which is member of TMTC bridge and is assigned in - //! constructor - int serverUdpSocket = 0; - - std::vector receptionBuffer; - - size_t frameSize = 0; - timeval receptionTimeout; - - ReturnValue_t handleSuccessfullTcRead(size_t bytesRead); -}; - -#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */ +//#ifndef FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ +//#define FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ +// +//#include "../../objectmanager/SystemObject.h" +//#include "../../osal/linux/TmTcUnixUdpBridge.h" +//#include "../../tasks/ExecutableObjectIF.h" +// +//#include +//#include +// +///** +// * @brief This class can be used to implement the polling of a Unix socket, +// * using UDP for now. +// * @details +// * The task will be blocked while the specified number of bytes has not been +// * received, so TC reception is handled inside a separate task. +// * This class caches the IP address of the sender. It is assumed there +// * is only one sender for now. +// */ +//class TcUnixUdpPollingTask: public SystemObject, +// public ExecutableObjectIF { +// friend class TmTcUnixUdpBridge; +//public: +// static constexpr size_t DEFAULT_MAX_FRAME_SIZE = 2048; +// //! 0.5 default milliseconds timeout for now. +// static constexpr timeval DEFAULT_TIMEOUT = {.tv_sec = 0, .tv_usec = 500}; +// +// TcUnixUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, +// size_t frameSize = 0, double timeoutSeconds = -1); +// virtual~ TcUnixUdpPollingTask(); +// +// /** +// * Turn on optional timeout for UDP polling. In the default mode, +// * the receive function will block until a packet is received. +// * @param timeoutSeconds +// */ +// void setTimeout(double timeoutSeconds); +// +// virtual ReturnValue_t performOperation(uint8_t opCode) override; +// virtual ReturnValue_t initialize() override; +// virtual ReturnValue_t initializeAfterTaskCreation() override; +// +//protected: +// StorageManagerIF* tcStore = nullptr; +// +//private: +// //! TMTC bridge is cached. +// object_id_t tmtcBridgeId = objects::NO_OBJECT; +// TmTcUnixUdpBridge* tmtcBridge = nullptr; +// MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; +// +// //! Reception flags: https://linux.die.net/man/2/recvfrom. +// int receptionFlags = 0; +// +// //! Server socket, which is member of TMTC bridge and is assigned in +// //! constructor +// int serverUdpSocket = 0; +// +// std::vector receptionBuffer; +// +// size_t frameSize = 0; +// timeval receptionTimeout; +// +// ReturnValue_t handleSuccessfullTcRead(size_t bytesRead); +//}; +// +//#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */ diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp index fa7913ea..c0cd6877 100644 --- a/osal/linux/TmTcUnixUdpBridge.cpp +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -1,167 +1,167 @@ -#include "TmTcUnixUdpBridge.h" -#include "tcpipHelpers.h" -#include "../../serviceinterface/ServiceInterface.h" -#include "../../ipc/MutexGuard.h" - -#include -#include -#include - -#include - -//! Debugging preprocessor define. -#define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0 - -const std::string TmTcUnixUdpBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_UDP_SERVER_PORT; - -TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, - object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort): - TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { - if(udpServerPort == "") { - this->udpServerPort = DEFAULT_UDP_SERVER_PORT; - } - else { - this->udpServerPort = udpServerPort; - } - - mutex = MutexFactory::instance()->createMutex(); - communicationLinkUp = false; -} - -ReturnValue_t TmTcUnixUdpBridge::initialize() { - using namespace tcpip; - - ReturnValue_t result = TmTcBridge::initialize(); - if(result != HasReturnvaluesIF::RETURN_OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TmTcUnixUdpBridge::initialize: TmTcBridge initialization failed!" - << std::endl; -#endif - return result; - } - - struct addrinfo *addrResult = nullptr; - struct addrinfo hints; - - std::memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_protocol = IPPROTO_UDP; - hints.ai_flags = AI_PASSIVE; - - /* Set up UDP socket: - https://man7.org/linux/man-pages/man3/getaddrinfo.3.html - Passing nullptr as the first parameter and specifying AI_PASSIVE in hints will cause - getaddrinfo to assign the address 0.0.0.0 (any address) */ - int retval = getaddrinfo(nullptr, udpServerPort.c_str(), &hints, &addrResult); - if (retval != 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Retrieving address info failed!" << - std::endl; -#endif - return HasReturnvaluesIF::RETURN_FAILED; - } - - /* Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html */ - serverSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol); - if(serverSocket < 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open UDP socket!" << - std::endl; -#else - sif::printError("TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open UDP socket!\n"); -#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ - freeaddrinfo(addrResult); - handleError(Protocol::UDP, ErrorSources::SOCKET_CALL); - return HasReturnvaluesIF::RETURN_FAILED; - } - - retval = bind(serverSocket, addrResult->ai_addr, static_cast(addrResult->ai_addrlen)); - if(retval != 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not bind " - "local port (" << udpServerPort << ") to server socket!" << std::endl; -#endif - freeaddrinfo(addrResult); - handleError(Protocol::UDP, ErrorSources::BIND_CALL); - return HasReturnvaluesIF::RETURN_FAILED; - } - - return HasReturnvaluesIF::RETURN_OK; -} - -TmTcUnixUdpBridge::~TmTcUnixUdpBridge() { - if(mutex != nullptr) { - MutexFactory::instance()->deleteMutex(mutex); - } - close(serverSocket); -} - -ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { - int flags = 0; - - /* The target address can be set by different threads so this lock ensures thread-safety */ - MutexGuard lock(mutex, timeoutType, mutexTimeoutMs); - - if(ipAddrAnySet){ - clientAddress.sin_addr.s_addr = htons(INADDR_ANY); - clientAddressLen = sizeof(clientAddress); - } - -#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 - char ipAddress [15]; - sif::debug << "IP Address Sender: "<< - inet_ntop(AF_INET,&clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; -#endif - - ssize_t bytesSent = sendto( - serverSocket, - data, - dataLen, - flags, - reinterpret_cast(&clientAddress), - clientAddressLen - ); - if(bytesSent < 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TmTcUnixUdpBridge::sendTm: Send operation failed." << std::endl; -#endif - tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL); - } - -#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 - sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were" - " sent." << std::endl; -#endif - - return HasReturnvaluesIF::RETURN_OK; -} - -void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) { - /* The target address can be set by different threads so this lock ensures thread-safety */ - MutexGuard lock(mutex, timeoutType, mutexTimeoutMs); - -#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 - char ipAddress [15]; - sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, - &newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; - sif::debug << "IP Address Old: " << inet_ntop(AF_INET, - &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; -#endif - registerCommConnect(); - - /* Set new IP address to reply to. */ - clientAddress = newAddress; - clientAddressLen = sizeof(clientAddress); -} - -void TmTcUnixUdpBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, - dur_millis_t timeoutMs) { - this->timeoutType = timeoutType; - this->mutexTimeoutMs = timeoutMs; -} - -void TmTcUnixUdpBridge::setClientAddressToAny(bool ipAddrAnySet){ - this->ipAddrAnySet = ipAddrAnySet; -} - +//#include "TmTcUnixUdpBridge.h" +//#include "tcpipHelpers.h" +//#include "../../serviceinterface/ServiceInterface.h" +//#include "../../ipc/MutexGuard.h" +// +//#include +//#include +//#include +// +//#include +// +////! Debugging preprocessor define. +//#define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0 +// +//const std::string TmTcUnixUdpBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_UDP_SERVER_PORT; +// +//TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, +// object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort): +// TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { +// if(udpServerPort == "") { +// this->udpServerPort = DEFAULT_UDP_SERVER_PORT; +// } +// else { +// this->udpServerPort = udpServerPort; +// } +// +// mutex = MutexFactory::instance()->createMutex(); +// communicationLinkUp = false; +//} +// +//ReturnValue_t TmTcUnixUdpBridge::initialize() { +// using namespace tcpip; +// +// ReturnValue_t result = TmTcBridge::initialize(); +// if(result != HasReturnvaluesIF::RETURN_OK) { +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::error << "TmTcUnixUdpBridge::initialize: TmTcBridge initialization failed!" +// << std::endl; +//#endif +// return result; +// } +// +// struct addrinfo *addrResult = nullptr; +// struct addrinfo hints; +// +// std::memset(&hints, 0, sizeof(hints)); +// hints.ai_family = AF_INET; +// hints.ai_socktype = SOCK_DGRAM; +// hints.ai_protocol = IPPROTO_UDP; +// hints.ai_flags = AI_PASSIVE; +// +// /* Set up UDP socket: +// https://man7.org/linux/man-pages/man3/getaddrinfo.3.html +// Passing nullptr as the first parameter and specifying AI_PASSIVE in hints will cause +// getaddrinfo to assign the address 0.0.0.0 (any address) */ +// int retval = getaddrinfo(nullptr, udpServerPort.c_str(), &hints, &addrResult); +// if (retval != 0) { +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Retrieving address info failed!" << +// std::endl; +//#endif +// return HasReturnvaluesIF::RETURN_FAILED; +// } +// +// /* Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html */ +// serverSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol); +// if(serverSocket < 0) { +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open UDP socket!" << +// std::endl; +//#else +// sif::printError("TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open UDP socket!\n"); +//#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ +// freeaddrinfo(addrResult); +// handleError(Protocol::UDP, ErrorSources::SOCKET_CALL); +// return HasReturnvaluesIF::RETURN_FAILED; +// } +// +// retval = bind(serverSocket, addrResult->ai_addr, static_cast(addrResult->ai_addrlen)); +// if(retval != 0) { +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not bind " +// "local port (" << udpServerPort << ") to server socket!" << std::endl; +//#endif +// freeaddrinfo(addrResult); +// handleError(Protocol::UDP, ErrorSources::BIND_CALL); +// return HasReturnvaluesIF::RETURN_FAILED; +// } +// +// return HasReturnvaluesIF::RETURN_OK; +//} +// +//TmTcUnixUdpBridge::~TmTcUnixUdpBridge() { +// if(mutex != nullptr) { +// MutexFactory::instance()->deleteMutex(mutex); +// } +// close(serverSocket); +//} +// +//ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { +// int flags = 0; +// +// /* The target address can be set by different threads so this lock ensures thread-safety */ +// MutexGuard lock(mutex, timeoutType, mutexTimeoutMs); +// +// if(ipAddrAnySet){ +// clientAddress.sin_addr.s_addr = htons(INADDR_ANY); +// clientAddressLen = sizeof(clientAddress); +// } +// +//#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 +// char ipAddress [15]; +// sif::debug << "IP Address Sender: "<< +// inet_ntop(AF_INET,&clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; +//#endif +// +// ssize_t bytesSent = sendto( +// serverSocket, +// data, +// dataLen, +// flags, +// reinterpret_cast(&clientAddress), +// clientAddressLen +// ); +// if(bytesSent < 0) { +//#if FSFW_CPP_OSTREAM_ENABLED == 1 +// sif::warning << "TmTcUnixUdpBridge::sendTm: Send operation failed." << std::endl; +//#endif +// tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL); +// } +// +//#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 +// sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were" +// " sent." << std::endl; +//#endif +// +// return HasReturnvaluesIF::RETURN_OK; +//} +// +//void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) { +// /* The target address can be set by different threads so this lock ensures thread-safety */ +// MutexGuard lock(mutex, timeoutType, mutexTimeoutMs); +// +//#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 +// char ipAddress [15]; +// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, +// &newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; +// sif::debug << "IP Address Old: " << inet_ntop(AF_INET, +// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; +//#endif +// registerCommConnect(); +// +// /* Set new IP address to reply to. */ +// clientAddress = newAddress; +// clientAddressLen = sizeof(clientAddress); +//} +// +//void TmTcUnixUdpBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, +// dur_millis_t timeoutMs) { +// this->timeoutType = timeoutType; +// this->mutexTimeoutMs = timeoutMs; +//} +// +//void TmTcUnixUdpBridge::setClientAddressToAny(bool ipAddrAnySet){ +// this->ipAddrAnySet = ipAddrAnySet; +//} +// diff --git a/osal/linux/TmTcUnixUdpBridge.h b/osal/linux/TmTcUnixUdpBridge.h index 3ab2118c..b4b00950 100644 --- a/osal/linux/TmTcUnixUdpBridge.h +++ b/osal/linux/TmTcUnixUdpBridge.h @@ -1,53 +1,53 @@ -#ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ -#define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ - -#include "../../tmtcservices/AcceptsTelecommandsIF.h" -#include "../../tmtcservices/TmTcBridge.h" -#include -#include -#include - -class TmTcUnixUdpBridge: - public TmTcBridge { - friend class TcUnixUdpPollingTask; -public: - - /* The ports chosen here should not be used by any other process. - List of used ports on Linux: /etc/services */ - static const std::string DEFAULT_UDP_SERVER_PORT; - - TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, - object_id_t tmStoreId, object_id_t tcStoreId, - std::string serverPort = ""); - virtual~ TmTcUnixUdpBridge(); - - /** - * Set properties of internal mutex. - */ - void setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs); - - ReturnValue_t initialize() override; - - void checkAndSetClientAddress(sockaddr_in& clientAddress); - - void setClientAddressToAny(bool ipAddrAnySet); - -protected: - virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; - -private: - int serverSocket = 0; - std::string udpServerPort; - - struct sockaddr_in clientAddress; - socklen_t clientAddressLen = 0; - - bool ipAddrAnySet = false; - - //! Access to the client address is mutex protected as it is set by another task. - MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; - dur_millis_t mutexTimeoutMs = 20; - MutexIF* mutex; -}; - -#endif /* FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ */ +//#ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ +//#define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ +// +//#include "../../tmtcservices/AcceptsTelecommandsIF.h" +//#include "../../tmtcservices/TmTcBridge.h" +//#include +//#include +//#include +// +//class TmTcUnixUdpBridge: +// public TmTcBridge { +// friend class TcUnixUdpPollingTask; +//public: +// +// /* The ports chosen here should not be used by any other process. +// List of used ports on Linux: /etc/services */ +// static const std::string DEFAULT_UDP_SERVER_PORT; +// +// TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, +// object_id_t tmStoreId, object_id_t tcStoreId, +// std::string serverPort = ""); +// virtual~ TmTcUnixUdpBridge(); +// +// /** +// * Set properties of internal mutex. +// */ +// void setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs); +// +// ReturnValue_t initialize() override; +// +// void checkAndSetClientAddress(sockaddr_in& clientAddress); +// +// void setClientAddressToAny(bool ipAddrAnySet); +// +//protected: +// virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; +// +//private: +// int serverSocket = 0; +// std::string udpServerPort; +// +// struct sockaddr_in clientAddress; +// socklen_t clientAddressLen = 0; +// +// bool ipAddrAnySet = false; +// +// //! Access to the client address is mutex protected as it is set by another task. +// MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; +// dur_millis_t mutexTimeoutMs = 20; +// MutexIF* mutex; +//}; +// +//#endif /* FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ */ From b5a14bb9dfbb57dbfcc89c8fab19a244c5396598 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 21 Mar 2021 13:02:14 +0100 Subject: [PATCH 3/6] deleted old linux code --- osal/common/UdpTcPollingTask.cpp | 172 +++++++++++++++------------- osal/common/UdpTcPollingTask.h | 4 +- osal/common/UdpTmTcBridge.cpp | 14 ++- osal/linux/TcUnixUdpPollingTask.cpp | 152 ------------------------ osal/linux/TcUnixUdpPollingTask.h | 67 ----------- osal/linux/TmTcUnixUdpBridge.cpp | 167 --------------------------- osal/linux/TmTcUnixUdpBridge.h | 53 --------- osal/linux/tcpipHelpers.cpp | 2 +- osal/linux/tcpipHelpers.h | 14 --- 9 files changed, 102 insertions(+), 543 deletions(-) delete mode 100644 osal/linux/TcUnixUdpPollingTask.cpp delete mode 100644 osal/linux/TcUnixUdpPollingTask.h delete mode 100644 osal/linux/TmTcUnixUdpBridge.cpp delete mode 100644 osal/linux/TmTcUnixUdpBridge.h delete mode 100644 osal/linux/tcpipHelpers.h diff --git a/osal/common/UdpTcPollingTask.cpp b/osal/common/UdpTcPollingTask.cpp index 3d51e118..bace593f 100644 --- a/osal/common/UdpTcPollingTask.cpp +++ b/osal/common/UdpTcPollingTask.cpp @@ -18,27 +18,27 @@ #define FSFW_UDP_RCV_WIRETAPPING_ENABLED 0 UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, - object_id_t tmtcUnixUdpBridge, size_t frameSize, - double timeoutSeconds): SystemObject(objectId), - tmtcBridgeId(tmtcUnixUdpBridge) { - if(frameSize > 0) { - this->frameSize = frameSize; - } - else { - this->frameSize = DEFAULT_MAX_FRAME_SIZE; - } + object_id_t tmtcUnixUdpBridge, size_t maxRecvSize, + double timeoutSeconds): SystemObject(objectId), + tmtcBridgeId(tmtcUnixUdpBridge) { + if(frameSize > 0) { + this->frameSize = frameSize; + } + else { + this->frameSize = DEFAULT_MAX_RECV_SIZE; + } - /* Set up reception buffer with specified frame size. + /* Set up reception buffer with specified frame size. For now, it is assumed that only one frame is held in the buffer! */ - receptionBuffer.reserve(this->frameSize); - receptionBuffer.resize(this->frameSize); + receptionBuffer.reserve(this->frameSize); + receptionBuffer.resize(this->frameSize); - if(timeoutSeconds == -1) { - receptionTimeout = DEFAULT_TIMEOUT; - } - else { - receptionTimeout = timevalOperations::toTimeval(timeoutSeconds); - } + if(timeoutSeconds == -1) { + receptionTimeout = DEFAULT_TIMEOUT; + } + else { + receptionTimeout = timevalOperations::toTimeval(timeoutSeconds); + } } UdpTcPollingTask::~UdpTcPollingTask() {} @@ -48,120 +48,130 @@ ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) { struct sockaddr senderAddress; socklen_t senderAddressSize = sizeof(senderAddress); - /* Poll for new UDP datagrams in permanent loop. */ - while(true) { - int bytesReceived = recvfrom( - this->serverSocket, - reinterpret_cast(receptionBuffer.data()), - frameSize, - receptionFlags, - &senderAddress, - &senderAddressSize - ); - if(bytesReceived == SOCKET_ERROR) { - /* Handle error */ + /* Poll for new UDP datagrams in permanent loop. */ + while(true) { + int bytesReceived = recvfrom( + this->serverSocket, + reinterpret_cast(receptionBuffer.data()), + frameSize, + receptionFlags, + &senderAddress, + &senderAddressSize + ); + if(bytesReceived == SOCKET_ERROR) { + /* Handle error */ #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "UdpTcPollingTask::performOperation: Reception error." << std::endl; + sif::error << "UdpTcPollingTask::performOperation: Reception error." << std::endl; #endif - tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 1000); - continue; - } + tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 1000); + continue; + } #if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 - sif::debug << "UdpTcPollingTask::performOperation: " << bytesReceived << - " bytes received" << std::endl; + sif::debug << "UdpTcPollingTask::performOperation: " << bytesReceived << + " bytes received" << std::endl; #endif - ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); - if(result != HasReturnvaluesIF::RETURN_FAILED) { + ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); + if(result != HasReturnvaluesIF::RETURN_FAILED) { - } - tmtcBridge->checkAndSetClientAddress(senderAddress); - } - return HasReturnvaluesIF::RETURN_OK; + } + tmtcBridge->checkAndSetClientAddress(senderAddress); + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) { - store_address_t storeId; + store_address_t storeId; #if FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 arrayprinter::print(receptionBuffer.data(), bytesRead); #endif - ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRead); - if (result != HasReturnvaluesIF::RETURN_OK) { + ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRead); + if (result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning<< "UdpTcPollingTask::transferPusToSoftwareBus: Data storage failed." << - std::endl; - sif::warning << "Packet size: " << bytesRead << std::endl; + sif::warning<< "UdpTcPollingTask::transferPusToSoftwareBus: Data storage failed." << + std::endl; + sif::warning << "Packet size: " << bytesRead << std::endl; #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - return HasReturnvaluesIF::RETURN_FAILED; - } + return HasReturnvaluesIF::RETURN_FAILED; + } - TmTcMessage message(storeId); + TmTcMessage message(storeId); - result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); - if (result != HasReturnvaluesIF::RETURN_OK) { + result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); + if (result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "UdpTcPollingTask::handleSuccessfullTcRead: " - " Sending message to queue failed" << std::endl; + sif::warning << "UdpTcPollingTask::handleSuccessfullTcRead: " + " Sending message to queue failed" << std::endl; #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - tcStore->deleteData(storeId); - } - return result; + tcStore->deleteData(storeId); + } + return result; } ReturnValue_t UdpTcPollingTask::initialize() { - tcStore = objectManager->get(objects::TC_STORE); - if (tcStore == nullptr) { + tcStore = objectManager->get(objects::TC_STORE); + if (tcStore == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "UdpTcPollingTask::initialize: TC store uninitialized!" << std::endl; + sif::error << "UdpTcPollingTask::initialize: TC store uninitialized!" << std::endl; #endif - return ObjectManagerIF::CHILD_INIT_FAILED; - } + return ObjectManagerIF::CHILD_INIT_FAILED; + } - tmtcBridge = objectManager->get(tmtcBridgeId); - if(tmtcBridge == nullptr) { + tmtcBridge = objectManager->get(tmtcBridgeId); + if(tmtcBridge == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "UdpTcPollingTask::initialize: Invalid TMTC bridge object!" << - std::endl; + sif::error << "UdpTcPollingTask::initialize: Invalid TMTC bridge object!" << + std::endl; #endif - return ObjectManagerIF::CHILD_INIT_FAILED; - } + return ObjectManagerIF::CHILD_INIT_FAILED; + } ReturnValue_t result = TcpIpBase::initialize(); if(result != HasReturnvaluesIF::RETURN_OK) { return result; } - return HasReturnvaluesIF::RETURN_OK; + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t UdpTcPollingTask::initializeAfterTaskCreation() { - /* Initialize the destination after task creation. This ensures + /* Initialize the destination after task creation. This ensures that the destination has already been set in the TMTC bridge. */ - targetTcDestination = tmtcBridge->getRequestQueue(); - /* The server socket is set up in the bridge intialization. Calling this function here + targetTcDestination = tmtcBridge->getRequestQueue(); + /* The server socket is set up in the bridge intialization. Calling this function here ensures that it is set up regardless of which class was initialized first */ this->serverSocket = tmtcBridge->serverSocket; - return HasReturnvaluesIF::RETURN_OK; + return HasReturnvaluesIF::RETURN_OK; } void UdpTcPollingTask::setTimeout(double timeoutSeconds) { #ifdef _WIN32 - DWORD timeoutMs = timeoutSeconds * 1000.0; - int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO, - reinterpret_cast(&timeoutMs), sizeof(DWORD)); - if(result == -1) { + DWORD timeoutMs = timeoutSeconds * 1000.0; + int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO, + reinterpret_cast(&timeoutMs), sizeof(DWORD)); + if(result == -1) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TcWinUdpPollingTask::TcSocketPollingTask: Setting " - "receive timeout failed with " << strerror(errno) << std::endl; + sif::error << "TcWinUdpPollingTask::TcSocketPollingTask: Setting " + "receive timeout failed with " << strerror(errno) << std::endl; #endif - } + } #elif defined(__unix__) + timeval tval; + tval = timevalOperations::toTimeval(timeoutSeconds); + int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, + &tval, sizeof(receptionTimeout)); + if(result == -1) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting " + "receive timeout failed with " << strerror(errno) << std::endl; +#endif + } #endif } diff --git a/osal/common/UdpTcPollingTask.h b/osal/common/UdpTcPollingTask.h index 4df62b94..ae1c4c44 100644 --- a/osal/common/UdpTcPollingTask.h +++ b/osal/common/UdpTcPollingTask.h @@ -23,12 +23,12 @@ class UdpTcPollingTask: public ExecutableObjectIF { friend class TmTcWinUdpBridge; public: - static constexpr size_t DEFAULT_MAX_FRAME_SIZE = 2048; + static constexpr size_t DEFAULT_MAX_RECV_SIZE = 1500; //! 0.5 default milliseconds timeout for now. static constexpr timeval DEFAULT_TIMEOUT = {0, 500}; UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, - size_t frameSize = 0, double timeoutSeconds = -1); + size_t maxRecvSize = 0, double timeoutSeconds = -1); virtual~ UdpTcPollingTask(); /** diff --git a/osal/common/UdpTmTcBridge.cpp b/osal/common/UdpTmTcBridge.cpp index a8975c0e..ae74e94b 100644 --- a/osal/common/UdpTmTcBridge.cpp +++ b/osal/common/UdpTmTcBridge.cpp @@ -70,12 +70,14 @@ ReturnValue_t UdpTmTcBridge::initialize() { hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; -#ifdef _WIN32 - /* See: - https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo - for information about AI_PASSIVE. */ - hints.ai_flags = AI_PASSIVE; -#endif +//#ifdef _WIN32 +// /* See: +// https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo +// and +// +// for information about AI_PASSIVE. */ +// hints.ai_flags = AI_PASSIVE; +//#endif /* Set up UDP socket: https://en.wikipedia.org/wiki/Getaddrinfo diff --git a/osal/linux/TcUnixUdpPollingTask.cpp b/osal/linux/TcUnixUdpPollingTask.cpp deleted file mode 100644 index ec3687b9..00000000 --- a/osal/linux/TcUnixUdpPollingTask.cpp +++ /dev/null @@ -1,152 +0,0 @@ -//#include "TcUnixUdpPollingTask.h" -//#include "tcpipHelpers.h" -// -//#include "../../globalfunctions/arrayprinter.h" -// -//#define FSFW_UDP_RCV_WIRETAPPING_ENABLED 0 -// -//TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId, -// object_id_t tmtcUnixUdpBridge, size_t frameSize, -// double timeoutSeconds): SystemObject(objectId), -// tmtcBridgeId(tmtcUnixUdpBridge) { -// -// if(frameSize > 0) { -// this->frameSize = frameSize; -// } -// else { -// this->frameSize = DEFAULT_MAX_FRAME_SIZE; -// } -// -// /* Set up reception buffer with specified frame size. -// For now, it is assumed that only one frame is held in the buffer! */ -// receptionBuffer.reserve(this->frameSize); -// receptionBuffer.resize(this->frameSize); -// -// if(timeoutSeconds == -1) { -// receptionTimeout = DEFAULT_TIMEOUT; -// } -// else { -// receptionTimeout = timevalOperations::toTimeval(timeoutSeconds); -// } -//} -// -//TcUnixUdpPollingTask::~TcUnixUdpPollingTask() {} -// -//ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) { -// /* Sender Address is cached here. */ -// struct sockaddr_in senderAddress; -// socklen_t senderAddressSize = sizeof(senderAddress); -// -// /* Poll for new UDP datagrams in permanent loop. */ -// while(true) { -// ssize_t bytesReceived = recvfrom( -// serverUdpSocket, -// receptionBuffer.data(), -// frameSize, -// receptionFlags, -// reinterpret_cast(&senderAddress), -// &senderAddressSize -// ); -// if(bytesReceived < 0) { -// /* Handle error */ -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::error << "TcSocketPollingTask::performOperation: Reception error." << std::endl; -//#endif -// tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 500); -// continue; -// } -//#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 -// sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived -// << " bytes received" << std::endl; -//#endif -// -// ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); -// if(result != HasReturnvaluesIF::RETURN_FAILED) { -// -// } -// tmtcBridge->checkAndSetClientAddress(senderAddress); -// } -// return HasReturnvaluesIF::RETURN_OK; -//} -// -// -//ReturnValue_t TcUnixUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) { -// store_address_t storeId; -// -//#if FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 -// arrayprinter::print(receptionBuffer.data(), bytesRead); -//#endif -// -// ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRead); -// if (result != HasReturnvaluesIF::RETURN_OK) { -//#if FSFW_VERBOSE_LEVEL >= 1 -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::error << "TcUnixUdpPollingTask::handleSuccessfullTcRead: Data " -// "storage failed" << std::endl; -// sif::error << "Packet size: " << bytesRead << std::endl; -//#else -//#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ -//#endif /* FSFW_VERBOSE_LEVEL >= 1 */ -// return HasReturnvaluesIF::RETURN_FAILED; -// } -// -// TmTcMessage message(storeId); -// -// result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message); -// if (result != HasReturnvaluesIF::RETURN_OK) { -//#if FSFW_VERBOSE_LEVEL >= 1 -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::error << "TcUnixUdpPollingTask::handleSuccessfullTcRead: Sending message to queue " -// "failed" << std::endl; -//#else -//#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ -//#endif /* FSFW_VERBOSE_LEVEL >= 1 */ -// tcStore->deleteData(storeId); -// } -// return result; -//} -// -//ReturnValue_t TcUnixUdpPollingTask::initialize() { -// tcStore = objectManager->get(objects::TC_STORE); -// if (tcStore == nullptr) { -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::error << "TcSerialPollingTask::initialize: TC Store uninitialized!" -// << std::endl; -//#endif -// return ObjectManagerIF::CHILD_INIT_FAILED; -// } -// -// tmtcBridge = objectManager->get(tmtcBridgeId); -// if(tmtcBridge == nullptr) { -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid" -// " TMTC bridge object!" << std::endl; -//#endif -// return ObjectManagerIF::CHILD_INIT_FAILED; -// } -// -// return HasReturnvaluesIF::RETURN_OK; -//} -// -//ReturnValue_t TcUnixUdpPollingTask::initializeAfterTaskCreation() { -// /* Initialize the destination after task creation. This ensures -// that the destination has already been set in the TMTC bridge. */ -// targetTcDestination = tmtcBridge->getRequestQueue(); -// /* The server socket is set up in the bridge intialization. Calling this function here -// ensures that it is set up properly in any case*/ -// serverUdpSocket = tmtcBridge->serverSocket; -// return HasReturnvaluesIF::RETURN_OK; -//} -// -//void TcUnixUdpPollingTask::setTimeout(double timeoutSeconds) { -// timeval tval; -// tval = timevalOperations::toTimeval(timeoutSeconds); -// int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO, -// &tval, sizeof(receptionTimeout)); -// if(result == -1) { -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting " -// "receive timeout failed with " << strerror(errno) << std::endl; -//#endif -// } -//} diff --git a/osal/linux/TcUnixUdpPollingTask.h b/osal/linux/TcUnixUdpPollingTask.h deleted file mode 100644 index 1040d1a2..00000000 --- a/osal/linux/TcUnixUdpPollingTask.h +++ /dev/null @@ -1,67 +0,0 @@ -//#ifndef FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ -//#define FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ -// -//#include "../../objectmanager/SystemObject.h" -//#include "../../osal/linux/TmTcUnixUdpBridge.h" -//#include "../../tasks/ExecutableObjectIF.h" -// -//#include -//#include -// -///** -// * @brief This class can be used to implement the polling of a Unix socket, -// * using UDP for now. -// * @details -// * The task will be blocked while the specified number of bytes has not been -// * received, so TC reception is handled inside a separate task. -// * This class caches the IP address of the sender. It is assumed there -// * is only one sender for now. -// */ -//class TcUnixUdpPollingTask: public SystemObject, -// public ExecutableObjectIF { -// friend class TmTcUnixUdpBridge; -//public: -// static constexpr size_t DEFAULT_MAX_FRAME_SIZE = 2048; -// //! 0.5 default milliseconds timeout for now. -// static constexpr timeval DEFAULT_TIMEOUT = {.tv_sec = 0, .tv_usec = 500}; -// -// TcUnixUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, -// size_t frameSize = 0, double timeoutSeconds = -1); -// virtual~ TcUnixUdpPollingTask(); -// -// /** -// * Turn on optional timeout for UDP polling. In the default mode, -// * the receive function will block until a packet is received. -// * @param timeoutSeconds -// */ -// void setTimeout(double timeoutSeconds); -// -// virtual ReturnValue_t performOperation(uint8_t opCode) override; -// virtual ReturnValue_t initialize() override; -// virtual ReturnValue_t initializeAfterTaskCreation() override; -// -//protected: -// StorageManagerIF* tcStore = nullptr; -// -//private: -// //! TMTC bridge is cached. -// object_id_t tmtcBridgeId = objects::NO_OBJECT; -// TmTcUnixUdpBridge* tmtcBridge = nullptr; -// MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; -// -// //! Reception flags: https://linux.die.net/man/2/recvfrom. -// int receptionFlags = 0; -// -// //! Server socket, which is member of TMTC bridge and is assigned in -// //! constructor -// int serverUdpSocket = 0; -// -// std::vector receptionBuffer; -// -// size_t frameSize = 0; -// timeval receptionTimeout; -// -// ReturnValue_t handleSuccessfullTcRead(size_t bytesRead); -//}; -// -//#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */ diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp deleted file mode 100644 index c0cd6877..00000000 --- a/osal/linux/TmTcUnixUdpBridge.cpp +++ /dev/null @@ -1,167 +0,0 @@ -//#include "TmTcUnixUdpBridge.h" -//#include "tcpipHelpers.h" -//#include "../../serviceinterface/ServiceInterface.h" -//#include "../../ipc/MutexGuard.h" -// -//#include -//#include -//#include -// -//#include -// -////! Debugging preprocessor define. -//#define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0 -// -//const std::string TmTcUnixUdpBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_UDP_SERVER_PORT; -// -//TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, -// object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort): -// TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { -// if(udpServerPort == "") { -// this->udpServerPort = DEFAULT_UDP_SERVER_PORT; -// } -// else { -// this->udpServerPort = udpServerPort; -// } -// -// mutex = MutexFactory::instance()->createMutex(); -// communicationLinkUp = false; -//} -// -//ReturnValue_t TmTcUnixUdpBridge::initialize() { -// using namespace tcpip; -// -// ReturnValue_t result = TmTcBridge::initialize(); -// if(result != HasReturnvaluesIF::RETURN_OK) { -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::error << "TmTcUnixUdpBridge::initialize: TmTcBridge initialization failed!" -// << std::endl; -//#endif -// return result; -// } -// -// struct addrinfo *addrResult = nullptr; -// struct addrinfo hints; -// -// std::memset(&hints, 0, sizeof(hints)); -// hints.ai_family = AF_INET; -// hints.ai_socktype = SOCK_DGRAM; -// hints.ai_protocol = IPPROTO_UDP; -// hints.ai_flags = AI_PASSIVE; -// -// /* Set up UDP socket: -// https://man7.org/linux/man-pages/man3/getaddrinfo.3.html -// Passing nullptr as the first parameter and specifying AI_PASSIVE in hints will cause -// getaddrinfo to assign the address 0.0.0.0 (any address) */ -// int retval = getaddrinfo(nullptr, udpServerPort.c_str(), &hints, &addrResult); -// if (retval != 0) { -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Retrieving address info failed!" << -// std::endl; -//#endif -// return HasReturnvaluesIF::RETURN_FAILED; -// } -// -// /* Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html */ -// serverSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol); -// if(serverSocket < 0) { -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open UDP socket!" << -// std::endl; -//#else -// sif::printError("TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open UDP socket!\n"); -//#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ -// freeaddrinfo(addrResult); -// handleError(Protocol::UDP, ErrorSources::SOCKET_CALL); -// return HasReturnvaluesIF::RETURN_FAILED; -// } -// -// retval = bind(serverSocket, addrResult->ai_addr, static_cast(addrResult->ai_addrlen)); -// if(retval != 0) { -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not bind " -// "local port (" << udpServerPort << ") to server socket!" << std::endl; -//#endif -// freeaddrinfo(addrResult); -// handleError(Protocol::UDP, ErrorSources::BIND_CALL); -// return HasReturnvaluesIF::RETURN_FAILED; -// } -// -// return HasReturnvaluesIF::RETURN_OK; -//} -// -//TmTcUnixUdpBridge::~TmTcUnixUdpBridge() { -// if(mutex != nullptr) { -// MutexFactory::instance()->deleteMutex(mutex); -// } -// close(serverSocket); -//} -// -//ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { -// int flags = 0; -// -// /* The target address can be set by different threads so this lock ensures thread-safety */ -// MutexGuard lock(mutex, timeoutType, mutexTimeoutMs); -// -// if(ipAddrAnySet){ -// clientAddress.sin_addr.s_addr = htons(INADDR_ANY); -// clientAddressLen = sizeof(clientAddress); -// } -// -//#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 -// char ipAddress [15]; -// sif::debug << "IP Address Sender: "<< -// inet_ntop(AF_INET,&clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; -//#endif -// -// ssize_t bytesSent = sendto( -// serverSocket, -// data, -// dataLen, -// flags, -// reinterpret_cast(&clientAddress), -// clientAddressLen -// ); -// if(bytesSent < 0) { -//#if FSFW_CPP_OSTREAM_ENABLED == 1 -// sif::warning << "TmTcUnixUdpBridge::sendTm: Send operation failed." << std::endl; -//#endif -// tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL); -// } -// -//#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 -// sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were" -// " sent." << std::endl; -//#endif -// -// return HasReturnvaluesIF::RETURN_OK; -//} -// -//void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) { -// /* The target address can be set by different threads so this lock ensures thread-safety */ -// MutexGuard lock(mutex, timeoutType, mutexTimeoutMs); -// -//#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 -// char ipAddress [15]; -// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, -// &newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; -// sif::debug << "IP Address Old: " << inet_ntop(AF_INET, -// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; -//#endif -// registerCommConnect(); -// -// /* Set new IP address to reply to. */ -// clientAddress = newAddress; -// clientAddressLen = sizeof(clientAddress); -//} -// -//void TmTcUnixUdpBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, -// dur_millis_t timeoutMs) { -// this->timeoutType = timeoutType; -// this->mutexTimeoutMs = timeoutMs; -//} -// -//void TmTcUnixUdpBridge::setClientAddressToAny(bool ipAddrAnySet){ -// this->ipAddrAnySet = ipAddrAnySet; -//} -// diff --git a/osal/linux/TmTcUnixUdpBridge.h b/osal/linux/TmTcUnixUdpBridge.h deleted file mode 100644 index b4b00950..00000000 --- a/osal/linux/TmTcUnixUdpBridge.h +++ /dev/null @@ -1,53 +0,0 @@ -//#ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ -//#define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ -// -//#include "../../tmtcservices/AcceptsTelecommandsIF.h" -//#include "../../tmtcservices/TmTcBridge.h" -//#include -//#include -//#include -// -//class TmTcUnixUdpBridge: -// public TmTcBridge { -// friend class TcUnixUdpPollingTask; -//public: -// -// /* The ports chosen here should not be used by any other process. -// List of used ports on Linux: /etc/services */ -// static const std::string DEFAULT_UDP_SERVER_PORT; -// -// TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination, -// object_id_t tmStoreId, object_id_t tcStoreId, -// std::string serverPort = ""); -// virtual~ TmTcUnixUdpBridge(); -// -// /** -// * Set properties of internal mutex. -// */ -// void setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs); -// -// ReturnValue_t initialize() override; -// -// void checkAndSetClientAddress(sockaddr_in& clientAddress); -// -// void setClientAddressToAny(bool ipAddrAnySet); -// -//protected: -// virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; -// -//private: -// int serverSocket = 0; -// std::string udpServerPort; -// -// struct sockaddr_in clientAddress; -// socklen_t clientAddressLen = 0; -// -// bool ipAddrAnySet = false; -// -// //! Access to the client address is mutex protected as it is set by another task. -// MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; -// dur_millis_t mutexTimeoutMs = 20; -// MutexIF* mutex; -//}; -// -//#endif /* FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ */ diff --git a/osal/linux/tcpipHelpers.cpp b/osal/linux/tcpipHelpers.cpp index 1c380769..4c1b9a78 100644 --- a/osal/linux/tcpipHelpers.cpp +++ b/osal/linux/tcpipHelpers.cpp @@ -1,4 +1,4 @@ -#include "tcpipHelpers.h" +#include "../common/tcpipHelpers.h" #include "../../tasks/TaskFactory.h" diff --git a/osal/linux/tcpipHelpers.h b/osal/linux/tcpipHelpers.h deleted file mode 100644 index 6b337c62..00000000 --- a/osal/linux/tcpipHelpers.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef FSFW_OSAL_LINUX_TCPIPHELPERS_H_ -#define FSFW_OSAL_LINUX_TCPIPHELPERS_H_ - -#include "../../timemanager/clockDefinitions.h" -#include "../common/tcpipCommon.h" - -namespace tcpip { - - -void handleError(Protocol protocol, ErrorSources errorSrc, dur_millis_t sleepDuration = 0); - -} - -#endif /* FSFW_OSAL_LINUX_TCPIPHELPERS_H_ */ From 078116c7be61cd5bd74e1b8c49c87950a6dab7ef Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 21 Mar 2021 14:38:28 +0100 Subject: [PATCH 4/6] generic windows udp bridge working as well --- osal/common/TcpIpBase.cpp | 37 ++++++++++++++++---------------- osal/common/UdpTcPollingTask.cpp | 2 +- osal/common/UdpTmTcBridge.cpp | 10 +-------- osal/common/UdpTmTcBridge.h | 8 ++++++- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/osal/common/TcpIpBase.cpp b/osal/common/TcpIpBase.cpp index 35524743..279fd1c4 100644 --- a/osal/common/TcpIpBase.cpp +++ b/osal/common/TcpIpBase.cpp @@ -8,32 +8,16 @@ #endif TcpIpBase::TcpIpBase() { - closeSocket(serverSocket); + } TcpIpBase::~TcpIpBase() { + closeSocket(serverSocket); #ifdef _WIN32 WSACleanup(); #endif } - -int TcpIpBase::closeSocket(socket_t socket) { -#ifdef _WIN32 - return closesocket(socket); -#elif defined(__unix__) - return close(socket); -#endif -} - -int TcpIpBase::getLastSocketError() { -#ifdef _WIN32 - return WSAGetLastError(); -#elif defined(__unix__) - return errno; -#endif -} - ReturnValue_t TcpIpBase::initialize() { #ifdef _WIN32 /* Initiates Winsock DLL. */ @@ -51,3 +35,20 @@ ReturnValue_t TcpIpBase::initialize() { #endif return HasReturnvaluesIF::RETURN_OK; } + +int TcpIpBase::closeSocket(socket_t socket) { +#ifdef _WIN32 + return closesocket(socket); +#elif defined(__unix__) + return close(socket); +#endif +} + +int TcpIpBase::getLastSocketError() { +#ifdef _WIN32 + return WSAGetLastError(); +#elif defined(__unix__) + return errno; +#endif +} + diff --git a/osal/common/UdpTcPollingTask.cpp b/osal/common/UdpTcPollingTask.cpp index bace593f..759cee05 100644 --- a/osal/common/UdpTcPollingTask.cpp +++ b/osal/common/UdpTcPollingTask.cpp @@ -154,7 +154,7 @@ ReturnValue_t UdpTcPollingTask::initializeAfterTaskCreation() { void UdpTcPollingTask::setTimeout(double timeoutSeconds) { #ifdef _WIN32 DWORD timeoutMs = timeoutSeconds * 1000.0; - int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO, + int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast(&timeoutMs), sizeof(DWORD)); if(result == -1) { #if FSFW_CPP_OSTREAM_ENABLED == 1 diff --git a/osal/common/UdpTmTcBridge.cpp b/osal/common/UdpTmTcBridge.cpp index ae74e94b..7f3dc929 100644 --- a/osal/common/UdpTmTcBridge.cpp +++ b/osal/common/UdpTmTcBridge.cpp @@ -65,19 +65,11 @@ ReturnValue_t UdpTmTcBridge::initialize() { #endif struct addrinfo *addrResult = nullptr; - struct addrinfo hints = { 0 }; + struct addrinfo hints = {}; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; -//#ifdef _WIN32 -// /* See: -// https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo -// and -// -// for information about AI_PASSIVE. */ -// hints.ai_flags = AI_PASSIVE; -//#endif /* Set up UDP socket: https://en.wikipedia.org/wiki/Getaddrinfo diff --git a/osal/common/UdpTmTcBridge.h b/osal/common/UdpTmTcBridge.h index afc8ee98..6f38034e 100644 --- a/osal/common/UdpTmTcBridge.h +++ b/osal/common/UdpTmTcBridge.h @@ -4,8 +4,14 @@ #include "TcpIpBase.h" #include "../../tmtcservices/TmTcBridge.h" -#ifdef __unix__ +#ifdef _WIN32 + +#include + +#elif defined(__unix__) + #include + #endif #include From e3c44fd27f8a8a20ad25d291d7cc6e96e0e43114 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 21 Mar 2021 16:20:13 +0100 Subject: [PATCH 5/6] implemented deadlien missed print for host --- osal/host/PeriodicTask.cpp | 33 ++------ osal/host/TaskFactory.cpp | 39 +++++++++- osal/linux/PosixThread.cpp | 16 ++-- osal/windows/CMakeLists.txt | 1 + osal/windows/winTaskHelpers.cpp | 130 ++++++++++++++++++++++++++++++++ osal/windows/winTaskHelpers.h | 40 ++++++++++ tasks/TaskFactory.h | 16 +++- tasks/Typedef.h | 2 +- 8 files changed, 236 insertions(+), 41 deletions(-) create mode 100644 osal/windows/winTaskHelpers.cpp create mode 100644 osal/windows/winTaskHelpers.h diff --git a/osal/host/PeriodicTask.cpp b/osal/host/PeriodicTask.cpp index 7663d522..4c0bf338 100644 --- a/osal/host/PeriodicTask.cpp +++ b/osal/host/PeriodicTask.cpp @@ -10,6 +10,7 @@ #if defined(WIN32) #include +#include #elif defined(LINUX) #include #endif @@ -22,33 +23,11 @@ PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, // It is propably possible to set task priorities by using the native // task handles for Windows / Linux mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this); -#if defined(WIN32) - /* List of possible priority classes: - * https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ - * nf-processthreadsapi-setpriorityclass - * And respective thread priority numbers: - * https://docs.microsoft.com/en-us/windows/ - * win32/procthread/scheduling-priorities */ - int result = SetPriorityClass( - reinterpret_cast(mainThread.native_handle()), - ABOVE_NORMAL_PRIORITY_CLASS); - if(result != 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; -#endif - } - result = SetThreadPriority( - reinterpret_cast(mainThread.native_handle()), - THREAD_PRIORITY_NORMAL); - if(result != 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; -#endif - } -#elif defined(LINUX) - // we can just copy and paste the code from linux here. +#if defined(_WIN32) + tasks::setTaskPriority(reinterpret_cast(mainThread.native_handle()), setPriority); + tasks::insertTaskName(mainThread.get_id(), taskName); +#elif defined(__unix__) + // TODO: We could reuse existing code here. #endif } diff --git a/osal/host/TaskFactory.cpp b/osal/host/TaskFactory.cpp index 4fafd349..4ac44364 100644 --- a/osal/host/TaskFactory.cpp +++ b/osal/host/TaskFactory.cpp @@ -1,14 +1,20 @@ +#include "../../tasks/TaskFactory.h" #include "../../osal/host/FixedTimeslotTask.h" #include "../../osal/host/PeriodicTask.h" -#include "../../tasks/TaskFactory.h" #include "../../returnvalues/HasReturnvaluesIF.h" #include "../../tasks/PeriodicTaskIF.h" +#ifdef _WIN32 + +#include "../windows/winTaskHelpers.h" + +#endif + #include TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); -// Will propably not be used for hosted implementation +// Not used for the host implementation for now because C++ thread abstraction is used const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0; TaskFactory::TaskFactory() { @@ -49,8 +55,33 @@ ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){ } void TaskFactory::printMissedDeadline() { - /* TODO: Implement */ - return; +#ifdef __unix__ + char name[20] = {0}; + int status = pthread_getname_np(pthread_self(), name, sizeof(name)); +#if FSFW_CPP_OSTREAM_ENABLED == 1 + if(status == 0) { + sif::warning << "TaskFactory::printMissedDeadline: " << name << "" << std::endl; + } + else { + sif::warning << "TaskFactory::printMissedDeadline: Unknown task name" << status << + std::endl; + } +#else + if(status == 0) { + sif::printWarning("TaskFactory::printMissedDeadline: %s\n", name); + } + else { + sif::printWarning("TaskFactory::printMissedDeadline: Unknown task name\n", name); + } +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ +#elif defined(_WIN32) + std::string name = tasks::getTaskName(std::this_thread::get_id()); +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "TaskFactory::printMissedDeadline: " << name << std::endl; +#else + sif::printWarning("TaskFactory::printMissedDeadline: %s\n", name); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ +#endif /* defined(_WIN32) */ } diff --git a/osal/linux/PosixThread.cpp b/osal/linux/PosixThread.cpp index bd8e7258..5296dfb5 100644 --- a/osal/linux/PosixThread.cpp +++ b/osal/linux/PosixThread.cpp @@ -6,7 +6,7 @@ #include PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_): - thread(0),priority(priority_),stackSize(stackSize_) { + thread(0), priority(priority_), stackSize(stackSize_) { name[0] = '\0'; std::strncat(name, name_, PTHREAD_MAX_NAMELEN - 1); } @@ -75,18 +75,18 @@ bool PosixThread::delayUntil(uint64_t* const prevoiusWakeTime_ms, if (currentTime_ms < *prevoiusWakeTime_ms) { /* The tick count has overflowed since this function was - lasted called. In this case the only time we should ever - actually delay is if the wake time has also overflowed, - and the wake time is greater than the tick time. When this - is the case it is as if neither time had overflowed. */ + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ if ((nextTimeToWake_ms < *prevoiusWakeTime_ms) && (nextTimeToWake_ms > currentTime_ms)) { shouldDelay = true; } } else { - /* The tick time has not overflowed. In this case we will - delay if either the wake time has overflowed, and/or the - tick time is less than the wake time. */ + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ if ((nextTimeToWake_ms < *prevoiusWakeTime_ms) || (nextTimeToWake_ms > currentTime_ms)) { shouldDelay = true; diff --git a/osal/windows/CMakeLists.txt b/osal/windows/CMakeLists.txt index 1bb39b37..36a54765 100644 --- a/osal/windows/CMakeLists.txt +++ b/osal/windows/CMakeLists.txt @@ -1,3 +1,4 @@ target_sources(${LIB_FSFW_NAME} PRIVATE tcpipHelpers.cpp + winTaskHelpers.cpp ) diff --git a/osal/windows/winTaskHelpers.cpp b/osal/windows/winTaskHelpers.cpp new file mode 100644 index 00000000..e96cd70e --- /dev/null +++ b/osal/windows/winTaskHelpers.cpp @@ -0,0 +1,130 @@ +#include +#include + +std::mutex nameMapLock; +std::map taskNameMap; + +TaskPriority tasks::makeWinPriority(PriorityClass prioClass, PriorityNumber prioNumber) { + return (static_cast(prioClass) << 16) | static_cast (prioNumber); +} + +void tasks::getWinPriorityParameters(TaskPriority priority, + DWORD& priorityClass, int& priorityNumber) { + PriorityClass classInternal = static_cast(priority >> 16 & 0xff); + PriorityNumber numberInternal = static_cast(priority & 0xff); + switch(classInternal) { + case(CLASS_IDLE): { + priorityClass = IDLE_PRIORITY_CLASS; + break; + } + case(CLASS_BELOW_NORMAL): { + priorityClass = BELOW_NORMAL_PRIORITY_CLASS; + break; + } + case(CLASS_NORMAL): { + priorityClass = NORMAL_PRIORITY_CLASS; + break; + } + case(CLASS_ABOVE_NORMAL): { + priorityClass = ABOVE_NORMAL_PRIORITY_CLASS; + break; + } + case(CLASS_HIGH): { + priorityClass = HIGH_PRIORITY_CLASS; + break; + } + case(CLASS_REALTIME): { + priorityClass = REALTIME_PRIORITY_CLASS; + break; + } + default: { + priorityClass = NORMAL_PRIORITY_CLASS; + } + } + + switch(numberInternal) { + case(IDLE): { + priorityNumber = THREAD_PRIORITY_IDLE; + break; + } + case(LOWEST): { + priorityNumber = THREAD_PRIORITY_LOWEST; + break; + } + case(BELOW_NORMAL): { + priorityNumber = THREAD_PRIORITY_BELOW_NORMAL; + break; + } + case(NORMAL): { + priorityNumber = THREAD_PRIORITY_NORMAL; + break; + } + case(ABOVE_NORMAL): { + priorityNumber = THREAD_PRIORITY_ABOVE_NORMAL; + break; + } + case(HIGHEST): { + priorityNumber = THREAD_PRIORITY_HIGHEST; + break; + } + case(CRITICAL): { + priorityNumber = THREAD_PRIORITY_TIME_CRITICAL; + break; + } + default: { + priorityNumber = THREAD_PRIORITY_NORMAL; + } + } +} + +ReturnValue_t tasks::setTaskPriority(HANDLE nativeHandle, TaskPriority priority) { + /* List of possible priority classes: + https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setpriorityclass + And respective thread priority numbers: + https://docs.microsoft.com/en-us/windows/win32/procthread/scheduling-priorities + */ + DWORD dwPriorityClass = 0; + int nPriorityNumber = 0; + tasks::getWinPriorityParameters(priority, dwPriorityClass, nPriorityNumber); + int result = SetPriorityClass( + reinterpret_cast(nativeHandle), + dwPriorityClass); + if(result != 0) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +#endif + } + result = SetThreadPriority( + reinterpret_cast(nativeHandle), + nPriorityNumber); + if(result != 0) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PeriodicTask: Windows SetPriorityClass failed with code " + << GetLastError() << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +#endif + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t tasks::insertTaskName(std::thread::id threadId, std::string taskName) { + std::lock_guard lg(nameMapLock); + auto returnPair = taskNameMap.emplace(threadId, taskName); + if(not returnPair.second) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +std::string tasks::getTaskName(std::thread::id threadId) { + std::lock_guard lg(nameMapLock); + auto resultIter = taskNameMap.find(threadId); + if(resultIter != taskNameMap.end()) { + return resultIter->second; + } + else { + return "Unknown task"; + } +} diff --git a/osal/windows/winTaskHelpers.h b/osal/windows/winTaskHelpers.h new file mode 100644 index 00000000..d17b611a --- /dev/null +++ b/osal/windows/winTaskHelpers.h @@ -0,0 +1,40 @@ +#include "../../tasks/TaskFactory.h" + +#include +#include + +#ifdef _WIN32 + +namespace tasks { + +enum PriorityClass: uint16_t { + CLASS_IDLE, + CLASS_BELOW_NORMAL, + CLASS_NORMAL, + CLASS_ABOVE_NORMAL, + CLASS_HIGH, + CLASS_REALTIME +}; +enum PriorityNumber: uint16_t { + IDLE, + LOWEST, + BELOW_NORMAL, + NORMAL, + ABOVE_NORMAL, + HIGHEST, + CRITICAL +}; +TaskPriority makeWinPriority(PriorityClass prioClass = PriorityClass::CLASS_NORMAL, + PriorityNumber prioNumber = PriorityNumber::NORMAL); +void getWinPriorityParameters(TaskPriority priority, DWORD& priorityClass, + int& priorityNumber); + +ReturnValue_t setTaskPriority(HANDLE nativeHandle, TaskPriority priority); + +ReturnValue_t insertTaskName(std::thread::id threadId, std::string taskName); +std::string getTaskName(std::thread::id threadId); + +} + +#endif + diff --git a/tasks/TaskFactory.h b/tasks/TaskFactory.h index 03b5163c..4fba345f 100644 --- a/tasks/TaskFactory.h +++ b/tasks/TaskFactory.h @@ -22,9 +22,23 @@ public: /** * Creates a new periodic task and returns the interface pointer. * @param name_ Name of the task - * @param taskPriority_ Priority of the task + * @param taskPriority_ + * Priority of the task. This value might have different ranges for the various OSALs. + * Linux: Value ranging from 0 to 99 with 99 being the highest value. + * Host: Value can be retrieved by using the #tasks::makeWinPriority function. + * FreeRTOS: Value depends on the FreeRTOS configuration, higher number means higher priority + * RTEMS: Values ranging from 0 to 99 with 99 being the highest value. + * * @param stackSize_ Stack Size of the task + * This value might have different recommended ranges for the various OSALs. + * Linux: Lowest limit is the PeriodicTaskIF::MINIMUM_STACK_SIZE value + * Host: Value is ignored for now because the C++ threading abstraction layer is used. + * FreeRTOS: Stack size in bytes. It is recommended to specify at least 1kB of stack for + * FSFW tasks, but the lowest possible size is specified in the FreeRTOSConfig.h file. + * RTEMS: Lowest limit is the PeriodicTaskIF::MINIMUM_STACK_SIZE value. + * * @param period_ Period of the task + * * @param deadLineMissedFunction_ Function to be called if a deadline was missed * @return PeriodicTaskIF* Pointer to the newly created Task */ diff --git a/tasks/Typedef.h b/tasks/Typedef.h index 07d96b00..55f6bda2 100644 --- a/tasks/Typedef.h +++ b/tasks/Typedef.h @@ -2,7 +2,7 @@ #define FRAMEWORK_TASKS_TYPEDEF_H_ typedef const char* TaskName; -typedef uint8_t TaskPriority; +typedef uint32_t TaskPriority; typedef size_t TaskStackSize; typedef double TaskPeriod; typedef void (*TaskDeadlineMissedFunction)(); From 614d1ccb7c0cb99acfafef1e137247db44d3e989 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 21 Mar 2021 16:29:04 +0100 Subject: [PATCH 6/6] resorted functions --- osal/common/TcpIpBase.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osal/common/TcpIpBase.cpp b/osal/common/TcpIpBase.cpp index 279fd1c4..27384ecc 100644 --- a/osal/common/TcpIpBase.cpp +++ b/osal/common/TcpIpBase.cpp @@ -11,13 +11,6 @@ TcpIpBase::TcpIpBase() { } -TcpIpBase::~TcpIpBase() { - closeSocket(serverSocket); -#ifdef _WIN32 - WSACleanup(); -#endif -} - ReturnValue_t TcpIpBase::initialize() { #ifdef _WIN32 /* Initiates Winsock DLL. */ @@ -36,6 +29,13 @@ ReturnValue_t TcpIpBase::initialize() { return HasReturnvaluesIF::RETURN_OK; } +TcpIpBase::~TcpIpBase() { + closeSocket(serverSocket); +#ifdef _WIN32 + WSACleanup(); +#endif +} + int TcpIpBase::closeSocket(socket_t socket) { #ifdef _WIN32 return closesocket(socket);