fsfw/osal/windows/TcWinUdpPollingTask.cpp

183 lines
5.6 KiB
C++
Raw Normal View History

2020-09-06 15:46:49 +02:00
#include "TcWinUdpPollingTask.h"
#include "../../globalfunctions/arrayprinter.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include <winsock2.h>
#include <windows.h>
2021-03-07 01:35:55 +01:00
#if defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
2020-09-06 15:46:49 +02:00
TcWinUdpPollingTask::TcWinUdpPollingTask(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;
}
2021-03-08 23:00:53 +01:00
/* Set up reception buffer with specified frame size.
For now, it is assumed that only one frame is held in the buffer! */
2020-09-06 15:46:49 +02:00
receptionBuffer.reserve(this->frameSize);
receptionBuffer.resize(this->frameSize);
if(timeoutSeconds == -1) {
receptionTimeout = DEFAULT_TIMEOUT;
}
else {
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
}
}
TcWinUdpPollingTask::~TcWinUdpPollingTask() {}
ReturnValue_t TcWinUdpPollingTask::performOperation(uint8_t opCode) {
2021-03-08 23:00:53 +01:00
/* Poll for new UDP datagrams in permanent loop. */
2020-09-06 15:46:49 +02:00
while(true) {
//! Sender Address is cached here.
struct sockaddr_in senderAddress;
int senderAddressSize = sizeof(senderAddress);
ssize_t bytesReceived = recvfrom(serverUdpSocket,
reinterpret_cast<char*>(receptionBuffer.data()), frameSize,
receptionFlags, reinterpret_cast<sockaddr*>(&senderAddress),
&senderAddressSize);
if(bytesReceived == SOCKET_ERROR) {
2021-03-08 23:00:53 +01:00
/* Handle error */
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-09-06 15:46:49 +02:00
sif::error << "TcWinUdpPollingTask::performOperation: Reception"
" error." << std::endl;
#endif
2020-09-06 15:46:49 +02:00
handleReadError();
continue;
}
2021-03-08 23:00:53 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_WIRETAPPING_ENABLED == 1
sif::debug << "TcWinUdpPollingTask::performOperation: " << bytesReceived <<
" bytes received" << std::endl;
#endif
2020-09-06 15:46:49 +02:00
ReturnValue_t result = handleSuccessfullTcRead(bytesReceived);
if(result != HasReturnvaluesIF::RETURN_FAILED) {
}
tmtcBridge->registerCommConnect();
tmtcBridge->checkAndSetClientAddress(senderAddress);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t TcWinUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
store_address_t storeId;
ReturnValue_t result = tcStore->addData(&storeId,
receptionBuffer.data(), bytesRead);
2021-03-08 23:00:53 +01:00
#if FSFW_UDP_WIRETAPPING_ENABLED == 1
arrayprinter::print(receptionBuffer.data(), bytesRead);#
#endif
2020-09-06 15:46:49 +02:00
if (result != HasReturnvaluesIF::RETURN_OK) {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2021-03-08 23:00:53 +01:00
sif::warning<< "TcSerialPollingTask::transferPusToSoftwareBus: Data "
"storage failed" << std::endl;
sif::warning << "Packet size: " << bytesRead << std::endl;
#endif
2020-09-06 15:46:49 +02:00
return HasReturnvaluesIF::RETURN_FAILED;
}
TmTcMessage message(storeId);
result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message);
if (result != HasReturnvaluesIF::RETURN_OK) {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2021-03-08 23:00:53 +01:00
sif::warning << "Serial Polling: Sending message to queue failed" << std::endl;
#endif
2020-09-06 15:46:49 +02:00
tcStore->deleteData(storeId);
}
return result;
}
ReturnValue_t TcWinUdpPollingTask::initialize() {
tcStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
if (tcStore == nullptr) {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-09-06 15:46:49 +02:00
sif::error << "TcSerialPollingTask::initialize: TC Store uninitialized!"
<< std::endl;
#endif
2020-09-06 15:46:49 +02:00
return ObjectManagerIF::CHILD_INIT_FAILED;
}
tmtcBridge = objectManager->get<TmTcWinUdpBridge>(tmtcBridgeId);
if(tmtcBridge == nullptr) {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-09-06 15:46:49 +02:00
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid"
" TMTC bridge object!" << std::endl;
#endif
2020-09-06 15:46:49 +02:00
return ObjectManagerIF::CHILD_INIT_FAILED;
}
serverUdpSocket = tmtcBridge->serverSocket;
2021-03-08 23:00:53 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_WIRETAPPING_ENABLED == 1
sif::info << "TcWinUdpPollingTask::initialize: Server UDP socket " << serverUdpSocket <<
std::endl;
#endif
2020-09-06 15:46:49 +02:00
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t TcWinUdpPollingTask::initializeAfterTaskCreation() {
// Initialize the destination after task creation. This ensures
// that the destination has already been set in the TMTC bridge.
targetTcDestination = tmtcBridge->getRequestQueue();
return HasReturnvaluesIF::RETURN_OK;
}
void TcWinUdpPollingTask::setTimeout(double timeoutSeconds) {
DWORD timeoutMs = timeoutSeconds * 1000.0;
int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO,
reinterpret_cast<const char*>(&timeoutMs), sizeof(DWORD));
if(result == -1) {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-12-20 01:56:21 +01:00
sif::error << "TcWinUdpPollingTask::TcSocketPollingTask: Setting "
2020-09-06 15:46:49 +02:00
"receive timeout failed with " << strerror(errno) << std::endl;
#endif
2020-09-06 15:46:49 +02:00
}
}
void TcWinUdpPollingTask::handleReadError() {
int error = WSAGetLastError();
switch(error) {
case(WSANOTINITIALISED): {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-12-20 01:56:21 +01:00
sif::info << "TcWinUdpPollingTask::handleReadError: WSANOTINITIALISED: "
2020-09-06 15:46:49 +02:00
<< "WSAStartup(...) call " << "necessary" << std::endl;
#endif
2020-09-06 15:46:49 +02:00
break;
}
case(WSAEFAULT): {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-12-20 01:56:21 +01:00
sif::info << "TcWinUdpPollingTask::handleReadError: WSADEFAULT: "
2020-09-06 15:46:49 +02:00
<< "Bad address " << std::endl;
#endif
2020-09-06 15:46:49 +02:00
break;
}
2020-12-20 01:56:21 +01:00
case(WSAEINVAL): {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-12-20 01:56:21 +01:00
sif::info << "TcWinUdpPollingTask::handleReadError: WSAEINVAL: "
<< "Invalid input parameters. " << std::endl;
#endif
2020-12-20 01:56:21 +01:00
break;
}
2020-09-06 15:46:49 +02:00
default: {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2020-12-20 01:56:21 +01:00
sif::info << "TcWinUdpPollingTask::handleReadError: Error code: "
2020-09-06 15:46:49 +02:00
<< error << std::endl;
#endif
2020-09-06 15:46:49 +02:00
break;
}
}
// to prevent spam.
Sleep(1000);
}