From b41eb518e74d2803fde93ef87687b8f7c5979431 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 17 Mar 2021 23:28:01 +0100 Subject: [PATCH 01/28] improved internal error reporter --- internalError/InternalErrorReporter.cpp | 187 ++++++++++++------------ internalError/InternalErrorReporter.h | 87 +++++------ 2 files changed, 137 insertions(+), 137 deletions(-) diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp index 7e5a316c..402071b2 100644 --- a/internalError/InternalErrorReporter.cpp +++ b/internalError/InternalErrorReporter.cpp @@ -3,19 +3,20 @@ #include "../ipc/QueueFactory.h" #include "../ipc/MutexFactory.h" #include "../serviceinterface/ServiceInterface.h" +#include "../datapool/PoolReadGuard.h" InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth): SystemObject(setObjectId), - commandQueue(QueueFactory::instance()-> - createMessageQueue(messageQueueDepth)), - poolManager(this, commandQueue), - internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID), - internalErrorDataset(this) { - mutex = MutexFactory::instance()->createMutex(); + commandQueue(QueueFactory::instance()-> + createMessageQueue(messageQueueDepth)), + poolManager(this, commandQueue), + internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID), + internalErrorDataset(this) { + mutex = MutexFactory::instance()->createMutex(); } InternalErrorReporter::~InternalErrorReporter() { - MutexFactory::instance()->deleteMutex(mutex); + MutexFactory::instance()->deleteMutex(mutex); } void InternalErrorReporter::setDiagnosticPrintout(bool enable) { @@ -23,126 +24,127 @@ void InternalErrorReporter::setDiagnosticPrintout(bool enable) { } ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { - internalErrorDataset.read(timeoutType, timeoutMs); + CommandMessage message; + ReturnValue_t result = commandQueue->receiveMessage(&message); + if(result != MessageQueueIF::EMPTY) { + poolManager.handleHousekeepingMessage(&message); + } - uint32_t newQueueHits = getAndResetQueueHits(); - uint32_t newTmHits = getAndResetTmHits(); - uint32_t newStoreHits = getAndResetStoreHits(); + uint32_t newQueueHits = getAndResetQueueHits(); + uint32_t newTmHits = getAndResetTmHits(); + uint32_t newStoreHits = getAndResetStoreHits(); -#if FSFW_VERBOSE_LEVEL == 1 - if(diagnosticPrintout) { - if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) { +#if FSFW_VERBOSE_LEVEL >= 1 + if(diagnosticPrintout) { + if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "InternalErrorReporter::performOperation: Errors " - << "occured!" << std::endl; - sif::debug << "Queue errors: " << newQueueHits << std::endl; - sif::debug << "TM errors: " << newTmHits << std::endl; - sif::debug << "Store errors: " << newStoreHits << std::endl; + sif::debug << "InternalErrorReporter::performOperation: Errors " + << "occured!" << std::endl; + sif::debug << "Queue errors: " << newQueueHits << std::endl; + sif::debug << "TM errors: " << newTmHits << std::endl; + sif::debug << "Store errors: " << newStoreHits << std::endl; #else - sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n"); - sif::printDebug("Queue errors: %lu\n", static_cast(newQueueHits)); - sif::printDebug("TM errors: %lu\n", static_cast(newTmHits)); - sif::printDebug("Store errors: %lu\n", static_cast(newStoreHits)); + sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n"); + sif::printDebug("Queue errors: %lu\n", static_cast(newQueueHits)); + sif::printDebug("TM errors: %lu\n", static_cast(newTmHits)); + sif::printDebug("Store errors: %lu\n", static_cast(newStoreHits)); #endif - } - } + } + } #endif - internalErrorDataset.queueHits.value += newQueueHits; - internalErrorDataset.storeHits.value += newStoreHits; - internalErrorDataset.tmHits.value += newTmHits; - internalErrorDataset.setValidity(true, true); - internalErrorDataset.commit(timeoutType, timeoutMs); + PoolReadGuard readGuard(&internalErrorDataset); + internalErrorDataset.read(timeoutType, timeoutMs); + if(readGuard.getReadResult() == HasReturnvaluesIF::RETURN_OK) { + internalErrorDataset.queueHits.value += newQueueHits; + internalErrorDataset.storeHits.value += newStoreHits; + internalErrorDataset.tmHits.value += newTmHits; + internalErrorDataset.setValidity(true, true); + } - poolManager.performHkOperation(); - - CommandMessage message; - ReturnValue_t result = commandQueue->receiveMessage(&message); - if(result != MessageQueueIF::EMPTY) { - poolManager.handleHousekeepingMessage(&message); - } - return HasReturnvaluesIF::RETURN_OK; + poolManager.performHkOperation(); + return HasReturnvaluesIF::RETURN_OK; } void InternalErrorReporter::queueMessageNotSent() { - incrementQueueHits(); + incrementQueueHits(); } void InternalErrorReporter::lostTm() { - incrementTmHits(); + incrementTmHits(); } uint32_t InternalErrorReporter::getAndResetQueueHits() { - uint32_t value; - mutex->lockMutex(timeoutType, timeoutMs); - value = queueHits; - queueHits = 0; - mutex->unlockMutex(); - return value; + uint32_t value; + mutex->lockMutex(timeoutType, timeoutMs); + value = queueHits; + queueHits = 0; + mutex->unlockMutex(); + return value; } uint32_t InternalErrorReporter::getQueueHits() { - uint32_t value; - mutex->lockMutex(timeoutType, timeoutMs); - value = queueHits; - mutex->unlockMutex(); - return value; + uint32_t value; + mutex->lockMutex(timeoutType, timeoutMs); + value = queueHits; + mutex->unlockMutex(); + return value; } void InternalErrorReporter::incrementQueueHits() { - mutex->lockMutex(timeoutType, timeoutMs); - queueHits++; - mutex->unlockMutex(); + mutex->lockMutex(timeoutType, timeoutMs); + queueHits++; + mutex->unlockMutex(); } uint32_t InternalErrorReporter::getAndResetTmHits() { - uint32_t value; - mutex->lockMutex(timeoutType, timeoutMs); - value = tmHits; - tmHits = 0; - mutex->unlockMutex(); - return value; + uint32_t value; + mutex->lockMutex(timeoutType, timeoutMs); + value = tmHits; + tmHits = 0; + mutex->unlockMutex(); + return value; } uint32_t InternalErrorReporter::getTmHits() { - uint32_t value; - mutex->lockMutex(timeoutType, timeoutMs); - value = tmHits; - mutex->unlockMutex(); - return value; + uint32_t value; + mutex->lockMutex(timeoutType, timeoutMs); + value = tmHits; + mutex->unlockMutex(); + return value; } void InternalErrorReporter::incrementTmHits() { - mutex->lockMutex(timeoutType, timeoutMs); - tmHits++; - mutex->unlockMutex(); + mutex->lockMutex(timeoutType, timeoutMs); + tmHits++; + mutex->unlockMutex(); } void InternalErrorReporter::storeFull() { - incrementStoreHits(); + incrementStoreHits(); } uint32_t InternalErrorReporter::getAndResetStoreHits() { - uint32_t value; - mutex->lockMutex(timeoutType, timeoutMs); - value = storeHits; - storeHits = 0; - mutex->unlockMutex(); - return value; + uint32_t value; + mutex->lockMutex(timeoutType, timeoutMs); + value = storeHits; + storeHits = 0; + mutex->unlockMutex(); + return value; } uint32_t InternalErrorReporter::getStoreHits() { - uint32_t value; - mutex->lockMutex(timeoutType, timeoutMs); - value = storeHits; - mutex->unlockMutex(); - return value; + uint32_t value; + mutex->lockMutex(timeoutType, timeoutMs); + value = storeHits; + mutex->unlockMutex(); + return value; } void InternalErrorReporter::incrementStoreHits() { - mutex->lockMutex(timeoutType, timeoutMs); - storeHits++; - mutex->unlockMutex(); + mutex->lockMutex(timeoutType, timeoutMs); + storeHits++; + mutex->unlockMutex(); } object_id_t InternalErrorReporter::getObjectId() const { @@ -155,14 +157,11 @@ MessageQueueId_t InternalErrorReporter::getCommandQueue() const { ReturnValue_t InternalErrorReporter::initializeLocalDataPool( localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(errorPoolIds::TM_HITS, - new PoolEntry()); - localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, - new PoolEntry()); - localDataPoolMap.emplace(errorPoolIds::STORE_HITS, - new PoolEntry()); - poolManager.subscribeForPeriodicPacket(internalErrorSid, false, - getPeriodicOperationFrequency(), true); + localDataPoolMap.emplace(errorPoolIds::TM_HITS, new PoolEntry()); + localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, new PoolEntry()); + localDataPoolMap.emplace(errorPoolIds::STORE_HITS, new PoolEntry()); + poolManager.subscribeForPeriodicPacket(internalErrorSid, false, getPeriodicOperationFrequency(), + true); internalErrorDataset.setValidity(true, true); return HasReturnvaluesIF::RETURN_OK; } @@ -192,9 +191,9 @@ ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() { } void InternalErrorReporter::setMutexTimeout(MutexIF::TimeoutType timeoutType, - uint32_t timeoutMs) { - this->timeoutType = timeoutType; - this->timeoutMs = timeoutMs; + uint32_t timeoutMs) { + this->timeoutType = timeoutType; + this->timeoutMs = timeoutMs; } LocalDataPoolManager* InternalErrorReporter::getHkManagerHandle() { diff --git a/internalError/InternalErrorReporter.h b/internalError/InternalErrorReporter.h index a237418e..580cb8f6 100644 --- a/internalError/InternalErrorReporter.h +++ b/internalError/InternalErrorReporter.h @@ -17,77 +17,78 @@ * All functions were kept virtual so this class can be extended easily * to store custom internal errors (e.g. communication interface errors). */ -class InternalErrorReporter: public SystemObject, - public ExecutableObjectIF, - public InternalErrorReporterIF, - public HasLocalDataPoolIF { +class InternalErrorReporter: + public SystemObject, + public ExecutableObjectIF, + public InternalErrorReporterIF, + public HasLocalDataPoolIF { public: - InternalErrorReporter(object_id_t setObjectId, - uint32_t messageQueueDepth = 5); + InternalErrorReporter(object_id_t setObjectId, + uint32_t messageQueueDepth = 5); - /** - * Enable diagnostic printout. Please note that this feature will - * only work if DEBUG has been supplied to the build defines. - * @param enable - */ - void setDiagnosticPrintout(bool enable); + /** + * Enable diagnostic printout. Please note that this feature will + * only work if DEBUG has been supplied to the build defines. + * @param enable + */ + void setDiagnosticPrintout(bool enable); - void setMutexTimeout(MutexIF::TimeoutType timeoutType, - uint32_t timeoutMs); + void setMutexTimeout(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs); - virtual ~InternalErrorReporter(); + virtual ~InternalErrorReporter(); virtual object_id_t getObjectId() const override; virtual MessageQueueId_t getCommandQueue() const override; virtual ReturnValue_t initializeLocalDataPool( - localpool::DataPool& localDataPoolMap, + localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) override; virtual dur_millis_t getPeriodicOperationFrequency() const override; virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; - LocalDataPoolManager* getHkManagerHandle() override; + LocalDataPoolManager* getHkManagerHandle() override; virtual ReturnValue_t initialize() override; virtual ReturnValue_t initializeAfterTaskCreation() override; - virtual ReturnValue_t performOperation(uint8_t opCode) override; + virtual ReturnValue_t performOperation(uint8_t opCode) override; - virtual void queueMessageNotSent(); + virtual void queueMessageNotSent(); - virtual void lostTm(); + virtual void lostTm(); - virtual void storeFull(); + virtual void storeFull(); - virtual void setTaskIF(PeriodicTaskIF* task) override; + virtual void setTaskIF(PeriodicTaskIF* task) override; protected: - MessageQueueIF* commandQueue; - LocalDataPoolManager poolManager; + MessageQueueIF* commandQueue; + LocalDataPoolManager poolManager; - PeriodicTaskIF* executingTask = nullptr; + PeriodicTaskIF* executingTask = nullptr; - MutexIF* mutex = nullptr; - MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; - uint32_t timeoutMs = 20; + MutexIF* mutex = nullptr; + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + uint32_t timeoutMs = 20; - sid_t internalErrorSid; - InternalErrorDataset internalErrorDataset; + sid_t internalErrorSid; + InternalErrorDataset internalErrorDataset; - bool diagnosticPrintout = true; + bool diagnosticPrintout = true; - uint32_t queueHits = 0; - uint32_t tmHits = 0; - uint32_t storeHits = 0; + uint32_t queueHits = 0; + uint32_t tmHits = 0; + uint32_t storeHits = 0; - uint32_t getAndResetQueueHits(); - uint32_t getQueueHits(); - void incrementQueueHits(); + uint32_t getAndResetQueueHits(); + uint32_t getQueueHits(); + void incrementQueueHits(); - uint32_t getAndResetTmHits(); - uint32_t getTmHits(); - void incrementTmHits(); + uint32_t getAndResetTmHits(); + uint32_t getTmHits(); + void incrementTmHits(); - uint32_t getAndResetStoreHits(); - uint32_t getStoreHits(); - void incrementStoreHits(); + uint32_t getAndResetStoreHits(); + uint32_t getStoreHits(); + void incrementStoreHits(); }; From a4ca61d8343dcc64fc4667d2ac3ad74045825059 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 18 Mar 2021 00:01:29 +0100 Subject: [PATCH 02/28] bugfix and printout improvement --- datapool/PoolDataSetBase.cpp | 8 ++++---- internalError/InternalErrorReporter.cpp | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/datapool/PoolDataSetBase.cpp b/datapool/PoolDataSetBase.cpp index bdca22c3..cd4eb426 100644 --- a/datapool/PoolDataSetBase.cpp +++ b/datapool/PoolDataSetBase.cpp @@ -61,11 +61,11 @@ ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType, } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "DataSet::read(): Call made in wrong position. Don't forget to commit" - " member datasets!" << std::endl; + sif::warning << "PoolDataSetBase::read: Call made in wrong position. Don't forget to " + "commit member datasets!" << std::endl; #else - sif::printError("DataSet::read(): Call made in wrong position. Don't forget to commit" - " member datasets!\n"); + sif::printWarning("PoolDataSetBase::read: Call made in wrong position. Don't forget to " + "commit member datasets!\n"); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ result = SET_WAS_ALREADY_READ; } diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp index 402071b2..af9acc0d 100644 --- a/internalError/InternalErrorReporter.cpp +++ b/internalError/InternalErrorReporter.cpp @@ -54,7 +54,6 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { #endif PoolReadGuard readGuard(&internalErrorDataset); - internalErrorDataset.read(timeoutType, timeoutMs); if(readGuard.getReadResult() == HasReturnvaluesIF::RETURN_OK) { internalErrorDataset.queueHits.value += newQueueHits; internalErrorDataset.storeHits.value += newStoreHits; From 0da95b75a230e5e12dd0bb15f6ba8e4813f9f143 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 20 Mar 2021 12:49:15 +0100 Subject: [PATCH 03/28] fixed for hosted OSAL --- osal/host/MessageQueue.cpp | 8 +++----- osal/host/QueueMapManager.cpp | 4 ++-- osal/windows/TmTcWinUdpBridge.cpp | 3 ++- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/osal/host/MessageQueue.cpp b/osal/host/MessageQueue.cpp index dfc045e8..18272a68 100644 --- a/osal/host/MessageQueue.cpp +++ b/osal/host/MessageQueue.cpp @@ -3,7 +3,7 @@ #include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../ipc/MutexFactory.h" -#include "../../ipc/MutexHelper.h" +#include "../../ipc/MutexGuard.h" MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize): messageSize(maxMessageSize), messageDepth(messageDepth) { @@ -63,9 +63,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { if(messageQueue.empty()) { return MessageQueueIF::EMPTY; } - // not sure this will work.. - //*message = std::move(messageQueue.front()); - MutexHelper mutexLock(queueLock, MutexIF::TimeoutType::WAITING, 20); + MutexGuard mutexLock(queueLock, MutexIF::TimeoutType::WAITING, 20); MessageQueueMessage* currentMessage = &messageQueue.front(); std::copy(currentMessage->getBuffer(), currentMessage->getBuffer() + messageSize, message->getBuffer()); @@ -130,7 +128,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, return HasReturnvaluesIF::RETURN_FAILED; } if(targetQueue->messageQueue.size() < targetQueue->messageDepth) { - MutexHelper mutexLock(targetQueue->queueLock, + MutexGuard mutexLock(targetQueue->queueLock, MutexIF::TimeoutType::WAITING, 20); // not ideal, works for now though. MessageQueueMessage* mqmMessage = diff --git a/osal/host/QueueMapManager.cpp b/osal/host/QueueMapManager.cpp index 2a54f813..b50d62dc 100644 --- a/osal/host/QueueMapManager.cpp +++ b/osal/host/QueueMapManager.cpp @@ -2,7 +2,7 @@ #include "../../serviceinterface/ServiceInterface.h" #include "../../ipc/MutexFactory.h" -#include "../../ipc/MutexHelper.h" +#include "../../ipc/MutexGuard.h" QueueMapManager* QueueMapManager::mqManagerInstance = nullptr; @@ -43,7 +43,7 @@ ReturnValue_t QueueMapManager::addMessageQueue( MessageQueueIF* QueueMapManager::getMessageQueue( MessageQueueId_t messageQueueId) const { - MutexHelper(mapLock, MutexIF::TimeoutType::WAITING, 50); + MutexGuard(mapLock, MutexIF::TimeoutType::WAITING, 50); auto queueIter = queueMap.find(messageQueueId); if(queueIter != queueMap.end()) { return queueIter->second; diff --git a/osal/windows/TmTcWinUdpBridge.cpp b/osal/windows/TmTcWinUdpBridge.cpp index 94805cdc..9e91db2b 100644 --- a/osal/windows/TmTcWinUdpBridge.cpp +++ b/osal/windows/TmTcWinUdpBridge.cpp @@ -1,5 +1,6 @@ -#include #include "TmTcWinUdpBridge.h" +#include + TmTcWinUdpBridge::TmTcWinUdpBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId, From 8f17d6623af0a2d6448c8255c471820d2836a894 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 20 Mar 2021 12:54:05 +0100 Subject: [PATCH 04/28] removed duplicate include --- osal/windows/TmTcWinUdpBridge.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/osal/windows/TmTcWinUdpBridge.cpp b/osal/windows/TmTcWinUdpBridge.cpp index 67e908a0..a7201bb0 100644 --- a/osal/windows/TmTcWinUdpBridge.cpp +++ b/osal/windows/TmTcWinUdpBridge.cpp @@ -1,7 +1,6 @@ #include "TmTcWinUdpBridge.h" #include "tcpipHelpers.h" -#include #include #include From 951eb40e96c933d3524114037113f68c455b5200 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 20 Mar 2021 13:14:30 +0100 Subject: [PATCH 05/28] relativ include --- osal/windows/TmTcWinUdpBridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osal/windows/TmTcWinUdpBridge.cpp b/osal/windows/TmTcWinUdpBridge.cpp index 4959705a..03ca52cd 100644 --- a/osal/windows/TmTcWinUdpBridge.cpp +++ b/osal/windows/TmTcWinUdpBridge.cpp @@ -1,8 +1,8 @@ #include "TmTcWinUdpBridge.h" #include "tcpipHelpers.h" -#include -#include +#include "../../ipc/MutexGuard.h" +#include "../../serviceinterface/ServiceInterface.h" #include From d625642abcc481b73c06a42c0b87fa614d36294b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 21 Mar 2021 00:30:33 +0100 Subject: [PATCH 06/28] 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 07/28] 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 08/28] 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 09/28] 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 10/28] 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 11/28] 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); From 0c77ce4dcfc66384758971dab61d9086911bf125 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 22 Mar 2021 15:23:47 +0100 Subject: [PATCH 12/28] important bugfix --- controller/ExtendedControllerBase.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/controller/ExtendedControllerBase.h b/controller/ExtendedControllerBase.h index d5d43933..d7f87c98 100644 --- a/controller/ExtendedControllerBase.h +++ b/controller/ExtendedControllerBase.h @@ -65,7 +65,8 @@ protected: virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) override = 0; - virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0; + virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid, store_address_t storeId, + bool* clearMessage = nullptr) override = 0; }; From f6afa36b1c1cbb987be63cd7ad9de24e71ec91ba Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 22 Mar 2021 15:24:25 +0100 Subject: [PATCH 13/28] small tweak --- controller/ExtendedControllerBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/ExtendedControllerBase.h b/controller/ExtendedControllerBase.h index d7f87c98..2c2030bf 100644 --- a/controller/ExtendedControllerBase.h +++ b/controller/ExtendedControllerBase.h @@ -66,7 +66,7 @@ protected: virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) override = 0; virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid, store_address_t storeId, - bool* clearMessage = nullptr) override = 0; + bool* clearMessage) override = 0; }; From 31758833468a063e71854b0eb3046eae2eb17cdf Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 22 Mar 2021 15:28:36 +0100 Subject: [PATCH 14/28] oopsie --- controller/ExtendedControllerBase.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/controller/ExtendedControllerBase.h b/controller/ExtendedControllerBase.h index 2c2030bf..d5d43933 100644 --- a/controller/ExtendedControllerBase.h +++ b/controller/ExtendedControllerBase.h @@ -65,8 +65,7 @@ protected: virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) override = 0; - virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid, store_address_t storeId, - bool* clearMessage) override = 0; + virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0; }; From 1c021651d73259b61147cfbbf73b9eaca69b0cd8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 23 Mar 2021 11:26:44 +0100 Subject: [PATCH 15/28] missing include added --- osal/host/TaskFactory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/osal/host/TaskFactory.cpp b/osal/host/TaskFactory.cpp index 4ac44364..1c40c99a 100644 --- a/osal/host/TaskFactory.cpp +++ b/osal/host/TaskFactory.cpp @@ -3,6 +3,7 @@ #include "../../osal/host/PeriodicTask.h" #include "../../returnvalues/HasReturnvaluesIF.h" #include "../../tasks/PeriodicTaskIF.h" +#include "../../serviceinterface/ServiceInterface.h" #ifdef _WIN32 From d4ab2c6cdbe66d3398720b5d621868fe6a0aa7fd Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 23 Mar 2021 11:32:35 +0100 Subject: [PATCH 16/28] corrected doc --- tasks/TaskFactory.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tasks/TaskFactory.h b/tasks/TaskFactory.h index 4fba345f..7990a9ce 100644 --- a/tasks/TaskFactory.h +++ b/tasks/TaskFactory.h @@ -24,18 +24,21 @@ public: * @param name_ Name 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. + * - Linux Value ranging from 0 to 99 with 99 being the highest value. + * - Host For Windows, the value can be retrieved by using the #tasks::makeWinPriority + * function. For Linux, same priority system as specified above. MacOS not tested + * yet + * - 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. + * - 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 specified the PeriodicTaskIF::MINIMUM_STACK_SIZE value. * * @param period_ Period of the task * From 1d3d2be853232ab113e789cb61c07afff2e40194 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 23 Mar 2021 11:33:40 +0100 Subject: [PATCH 17/28] more doc --- tasks/TaskFactory.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/TaskFactory.h b/tasks/TaskFactory.h index 7990a9ce..d4795202 100644 --- a/tasks/TaskFactory.h +++ b/tasks/TaskFactory.h @@ -51,7 +51,8 @@ public: TaskDeadlineMissedFunction deadLineMissedFunction_); /** - * + * The meaning for the variables for fixed timeslot tasks is the same as for periodic tasks. + * See #createPeriodicTask documentation. * @param name_ Name of the task * @param taskPriority_ Priority of the task * @param stackSize_ Stack Size of the task From b1670decf73776e4742af39791583d5d35bb2e54 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 23 Mar 2021 11:35:23 +0100 Subject: [PATCH 18/28] Using C++ way of zero initializing struct --- osal/common/TcpTmTcServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osal/common/TcpTmTcServer.cpp b/osal/common/TcpTmTcServer.cpp index 2da5da95..296afad8 100644 --- a/osal/common/TcpTmTcServer.cpp +++ b/osal/common/TcpTmTcServer.cpp @@ -33,7 +33,7 @@ ReturnValue_t TcpTmTcServer::initialize() { int retval = 0; struct addrinfo *addrResult = nullptr; - struct addrinfo hints = { 0 }; + struct addrinfo hints = {}; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; From a5f44b858035d2d931ee79c622dfe7ab11c3a7f9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 23 Mar 2021 14:25:50 +0100 Subject: [PATCH 19/28] doc updatedoc updatedd --- osal/common/UdpTcPollingTask.h | 9 ++------- osal/common/UdpTmTcBridge.h | 4 ++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/osal/common/UdpTcPollingTask.h b/osal/common/UdpTcPollingTask.h index ae1c4c44..052eced5 100644 --- a/osal/common/UdpTcPollingTask.h +++ b/osal/common/UdpTcPollingTask.h @@ -9,13 +9,8 @@ #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. + * @brief This class should be used with the UdpTmTcBridge to implement a UDP server + * for receiving and sending PUS TMTC. */ class UdpTcPollingTask: public TcpIpBase, diff --git a/osal/common/UdpTmTcBridge.h b/osal/common/UdpTmTcBridge.h index 6f38034e..8b8d1949 100644 --- a/osal/common/UdpTmTcBridge.h +++ b/osal/common/UdpTmTcBridge.h @@ -16,6 +16,10 @@ #include +/** + * @brief This class should be used with the UdpTcPollingTask to implement a UDP server + * for receiving and sending PUS TMTC. + */ class UdpTmTcBridge: public TmTcBridge, public TcpIpBase { From bdd9889718a26e130f43c9439033e68f28436cf1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 23 Mar 2021 14:28:01 +0100 Subject: [PATCH 20/28] pool read guard in scope --- internalError/InternalErrorReporter.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp index af9acc0d..78618448 100644 --- a/internalError/InternalErrorReporter.cpp +++ b/internalError/InternalErrorReporter.cpp @@ -53,12 +53,14 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { } #endif - PoolReadGuard readGuard(&internalErrorDataset); - if(readGuard.getReadResult() == HasReturnvaluesIF::RETURN_OK) { - internalErrorDataset.queueHits.value += newQueueHits; - internalErrorDataset.storeHits.value += newStoreHits; - internalErrorDataset.tmHits.value += newTmHits; - internalErrorDataset.setValidity(true, true); + { + PoolReadGuard readGuard(&internalErrorDataset); + if(readGuard.getReadResult() == HasReturnvaluesIF::RETURN_OK) { + internalErrorDataset.queueHits.value += newQueueHits; + internalErrorDataset.storeHits.value += newStoreHits; + internalErrorDataset.tmHits.value += newTmHits; + internalErrorDataset.setValidity(true, true); + } } poolManager.performHkOperation(); From d781c6fcecceef0602a147ffbecf7255f24fdcfd Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 23 Mar 2021 14:40:30 +0100 Subject: [PATCH 21/28] name storage abstraction available for linux as well --- osal/host/CMakeLists.txt | 1 + osal/host/PeriodicTask.cpp | 1 + osal/host/TaskFactory.cpp | 28 +--------------------------- osal/host/taskHelpers.cpp | 27 +++++++++++++++++++++++++++ osal/host/taskHelpers.h | 16 ++++++++++++++++ osal/windows/winTaskHelpers.cpp | 23 ----------------------- osal/windows/winTaskHelpers.h | 3 --- 7 files changed, 46 insertions(+), 53 deletions(-) create mode 100644 osal/host/taskHelpers.cpp create mode 100644 osal/host/taskHelpers.h diff --git a/osal/host/CMakeLists.txt b/osal/host/CMakeLists.txt index 367f721e..2d29ce5d 100644 --- a/osal/host/CMakeLists.txt +++ b/osal/host/CMakeLists.txt @@ -10,6 +10,7 @@ target_sources(${LIB_FSFW_NAME} QueueMapManager.cpp SemaphoreFactory.cpp TaskFactory.cpp + taskHelpers.cpp ) if(UNIX) diff --git a/osal/host/PeriodicTask.cpp b/osal/host/PeriodicTask.cpp index 4c0bf338..4a02ee0d 100644 --- a/osal/host/PeriodicTask.cpp +++ b/osal/host/PeriodicTask.cpp @@ -1,5 +1,6 @@ #include "Mutex.h" #include "PeriodicTask.h" +#include "taskHelpers.h" #include "../../ipc/MutexFactory.h" #include "../../serviceinterface/ServiceInterfaceStream.h" diff --git a/osal/host/TaskFactory.cpp b/osal/host/TaskFactory.cpp index 1c40c99a..71d0bf8b 100644 --- a/osal/host/TaskFactory.cpp +++ b/osal/host/TaskFactory.cpp @@ -1,3 +1,4 @@ +#include "taskHelpers.h" #include "../../tasks/TaskFactory.h" #include "../../osal/host/FixedTimeslotTask.h" #include "../../osal/host/PeriodicTask.h" @@ -5,12 +6,6 @@ #include "../../tasks/PeriodicTaskIF.h" #include "../../serviceinterface/ServiceInterface.h" -#ifdef _WIN32 - -#include "../windows/winTaskHelpers.h" - -#endif - #include TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); @@ -56,33 +51,12 @@ ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){ } void TaskFactory::printMissedDeadline() { -#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/host/taskHelpers.cpp b/osal/host/taskHelpers.cpp new file mode 100644 index 00000000..be4c29ad --- /dev/null +++ b/osal/host/taskHelpers.cpp @@ -0,0 +1,27 @@ +#include "taskHelpers.h" +#include +#include + +std::mutex nameMapLock; +std::map taskNameMap; + +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/host/taskHelpers.h b/osal/host/taskHelpers.h new file mode 100644 index 00000000..fa00490f --- /dev/null +++ b/osal/host/taskHelpers.h @@ -0,0 +1,16 @@ +#ifndef FSFW_OSAL_HOST_TASKHELPERS_H_ +#define FSFW_OSAL_HOST_TASKHELPERS_H_ + +#include +#include + +namespace tasks { + +ReturnValue_t insertTaskName(std::thread::id threadId, std::string taskName); +std::string getTaskName(std::thread::id threadId); + +} + + + +#endif /* FSFW_OSAL_HOST_TASKHELPERS_H_ */ diff --git a/osal/windows/winTaskHelpers.cpp b/osal/windows/winTaskHelpers.cpp index e96cd70e..6765b952 100644 --- a/osal/windows/winTaskHelpers.cpp +++ b/osal/windows/winTaskHelpers.cpp @@ -1,9 +1,6 @@ #include #include -std::mutex nameMapLock; -std::map taskNameMap; - TaskPriority tasks::makeWinPriority(PriorityClass prioClass, PriorityNumber prioNumber) { return (static_cast(prioClass) << 16) | static_cast (prioNumber); } @@ -108,23 +105,3 @@ ReturnValue_t tasks::setTaskPriority(HANDLE nativeHandle, TaskPriority priority) } 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 index d17b611a..64e52672 100644 --- a/osal/windows/winTaskHelpers.h +++ b/osal/windows/winTaskHelpers.h @@ -31,9 +31,6 @@ void getWinPriorityParameters(TaskPriority priority, DWORD& priorityClass, 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 From aaceac81af9061892e8d25e66dec9bf963a21d65 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 23 Mar 2021 14:45:33 +0100 Subject: [PATCH 22/28] updated fixed timeslot task --- osal/host/FixedTimeslotTask.cpp | 36 +++++++-------------------------- osal/host/PeriodicTask.cpp | 4 ++-- 2 files changed, 9 insertions(+), 31 deletions(-) diff --git a/osal/host/FixedTimeslotTask.cpp b/osal/host/FixedTimeslotTask.cpp index 272d99b9..3b169b5a 100644 --- a/osal/host/FixedTimeslotTask.cpp +++ b/osal/host/FixedTimeslotTask.cpp @@ -1,9 +1,8 @@ +#include "taskHelpers.h" #include "../../osal/host/FixedTimeslotTask.h" - #include "../../ipc/MutexFactory.h" #include "../../osal/host/Mutex.h" #include "../../osal/host/FixedTimeslotTask.h" - #include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../tasks/ExecutableObjectIF.h" @@ -12,6 +11,7 @@ #if defined(WIN32) #include +#include "../windows/winTaskHelpers.h" #elif defined(LINUX) #include #endif @@ -24,34 +24,12 @@ FixedTimeslotTask::FixedTimeslotTask(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(&FixedTimeslotTask::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 << "FixedTimeslotTask: 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 << "FixedTimeslotTask: Windows SetPriorityClass failed with code " - << GetLastError() << std::endl; -#endif - } -#elif defined(LINUX) - // TODO: we can just copy and paste the code from the linux OSAL here. +#if defined(_WIN32) + tasks::setTaskPriority(reinterpret_cast(mainThread.native_handle()), setPriority); +#elif defined(__unix__) + // TODO: We could reuse existing code here. #endif + tasks::insertTaskName(mainThread.get_id(), taskName); } FixedTimeslotTask::~FixedTimeslotTask(void) { diff --git a/osal/host/PeriodicTask.cpp b/osal/host/PeriodicTask.cpp index 4a02ee0d..d7abf9d0 100644 --- a/osal/host/PeriodicTask.cpp +++ b/osal/host/PeriodicTask.cpp @@ -12,7 +12,7 @@ #if defined(WIN32) #include #include -#elif defined(LINUX) +#elif defined(__unix__) #include #endif @@ -26,10 +26,10 @@ PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority, mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this); #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 + tasks::insertTaskName(mainThread.get_id(), taskName); } PeriodicTask::~PeriodicTask(void) { From 9e559658a7ab16cc6d600cd0008802ae48069953 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 25 Mar 2021 15:35:05 +0100 Subject: [PATCH 23/28] added way to add additional include paths and libraries --- CMakeLists.txt | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b0917fd..6d6fd5ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,9 @@ elseif(${OS_FSFW} STREQUAL linux) set(OS_FSFW_NAME "Linux") elseif(${OS_FSFW} STREQUAL freertos) set(OS_FSFW_NAME "FreeRTOS") - target_link_libraries(${LIB_FSFW_NAME} ${LIB_OS_NAME}) + target_link_libraries(${LIB_FSFW_NAME} PRIVATE + ${LIB_OS_NAME} + ) elseif(${OS_FSFW} STREQUAL rtems) set(OS_FSFW_NAME "RTEMS") else() @@ -107,6 +109,21 @@ else() ) endif() +foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATH}) + if(IS_ABSOLUTE ${INCLUDE_PATH}) + set(CURR_ABS_INC_PATH "${FREERTOS_PATH}") + else() + get_filename_component(CURR_ABS_INC_PATH + ${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}) + endif() + + if(CMAKE_VERBOSE) + message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}") + endif() + + list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH}) +endforeach() + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(NOT DEFINED FSFW_WARNING_FLAGS) set(FSFW_WARNING_FLAGS @@ -140,9 +157,14 @@ target_include_directories(${LIB_FSFW_NAME} INTERFACE target_include_directories(${LIB_FSFW_NAME} PRIVATE ${CMAKE_SOURCE_DIR} ${FSFW_CONFIG_PATH_ABSOLUTE} + ${FSFW_ADD_INC_PATHS_ABS} ) target_compile_options(${LIB_FSFW_NAME} PRIVATE ${FSFW_WARNING_FLAGS} ${COMPILER_FLAGS} ) + +target_link_libraries(${LIB_FSFW_NAME} PRIVATE + ${FSFW_ADDITIONAL_LINK_LIBS} +) \ No newline at end of file From 581832e4f433b8e2b32418ab7a24f9ba256fb334 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 25 Mar 2021 18:05:18 +0100 Subject: [PATCH 24/28] added unittest folder --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d6fd5ed..58ad644b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,7 @@ add_subdirectory(timemanager) add_subdirectory(tmstorage) add_subdirectory(tmtcpacket) add_subdirectory(tmtcservices) +add_subdirectory(unittest) # The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. # If this is not given, we include the default configuration and emit a warning. From 1d818294e4b697a61f45831bc825793c66d9d40c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 25 Mar 2021 18:48:00 +0100 Subject: [PATCH 25/28] added option to remove unused code --- CMakeLists.txt | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58ad644b..f9f49794 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,13 @@ cmake_minimum_required(VERSION 3.13) +option(FSFW_GENERATE_SECTIONS + "Generate function and data sections. Required to remove unused code" ON +) + +if(FSFW_GENERATE_SECTIONS) + option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON) +endif() + option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON) # Options to exclude parts of the FSFW from compilation. option(FSFW_USE_RMAP "Compile with RMAP" ON) @@ -135,7 +143,20 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") -Wno-psabi ) endif() - + + if(FSFW_GENERATE_SECTIONS) + target_compile_options(${LIB_FSFW_NAME} PRIVATE + "-ffunction-sections" + "-fdata-sections" + ) + endif() + + if(FSFW_REMOVE_UNUSED_CODE) + target_link_options(${LIB_FSFW_NAME} PRIVATE + "Wl,--gc-sections" + ) + endif() + if(FSFW_WARNING_SHADOW_LOCAL_GCC) list(APPEND WARNING_FLAGS "-Wshadow=local") endif() From 3a90578780582e0fd8d06dab3bd44dbef066f012 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 27 Mar 2021 10:40:38 +0100 Subject: [PATCH 26/28] minor bridge improveements --- tmtcservices/TmTcBridge.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tmtcservices/TmTcBridge.cpp b/tmtcservices/TmTcBridge.cpp index 228bf4f5..f99b9051 100644 --- a/tmtcservices/TmTcBridge.cpp +++ b/tmtcservices/TmTcBridge.cpp @@ -4,6 +4,8 @@ #include "../serviceinterface/ServiceInterface.h" #include "../globalfunctions/arrayprinter.h" +#define TMTCBRIDGE_WIRETAPPING 0 + TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId): SystemObject(objectId),tmStoreId(tmStoreId), tcStoreId(tcStoreId), @@ -234,17 +236,11 @@ ReturnValue_t TmTcBridge::handleStoredTm() { void TmTcBridge::registerCommConnect() { if(not communicationLinkUp) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - //sif::info << "TMTC Bridge: Registered Comm Link Connect" << std::endl; -#endif communicationLinkUp = true; } } void TmTcBridge::registerCommDisconnect() { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - //sif::info << "TMTC Bridge: Registered Comm Link Disconnect" << std::endl; -#endif if(communicationLinkUp) { communicationLinkUp = false; } From eea482b4388dcfd9365a12015588dedc370dd2c1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 27 Mar 2021 21:27:46 +0100 Subject: [PATCH 27/28] added specific compile definitions --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b0917fd..852c18b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,15 +26,20 @@ if(NOT OS_FSFW) endif() +set(FSFW_OSAL_DEFINITION FSFW_HOST) + if(${OS_FSFW} STREQUAL host) set(OS_FSFW_NAME "Host") elseif(${OS_FSFW} STREQUAL linux) set(OS_FSFW_NAME "Linux") + set(FSFW_OSAL_DEFINITION FSFW_LINUX) elseif(${OS_FSFW} STREQUAL freertos) set(OS_FSFW_NAME "FreeRTOS") target_link_libraries(${LIB_FSFW_NAME} ${LIB_OS_NAME}) + set(FSFW_OSAL_DEFINITION FSFW_FREERTOS) elseif(${OS_FSFW} STREQUAL rtems) set(OS_FSFW_NAME "RTEMS") + set(FSFW_OSAL_DEFINITION FSFW_RTEMS) else() message(WARNING "Invalid operating system for FSFW specified! Setting to host.." @@ -43,6 +48,10 @@ else() set(OS_FSFW "host") endif() +target_compile_definitions(${LIB_FSFW_NAME} INTERFACE PRIVATE + ${FSFW_OSAL_DEFINITION} +) + message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system.") add_subdirectory(action) From 3a75be2683ac48ed7efa03e10f97e308fee99323 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 27 Mar 2021 21:51:04 +0100 Subject: [PATCH 28/28] this version is working --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73b6b873..ff060d7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,11 @@ else() set(OS_FSFW "host") endif() -target_compile_definitions(${LIB_FSFW_NAME} INTERFACE PRIVATE +target_compile_definitions(${LIB_FSFW_NAME} PRIVATE + ${FSFW_OSAL_DEFINITION} +) + +target_compile_definitions(${LIB_FSFW_NAME} INTERFACE ${FSFW_OSAL_DEFINITION} )