fsfw/osal/common/TcpTmTcServer.cpp

213 lines
6.8 KiB
C++
Raw Normal View History

#include "TcpTmTcServer.h"
2021-05-05 12:59:42 +02:00
#include "TcpTmTcBridge.h"
2021-03-12 02:15:21 +01:00
#include "tcpipHelpers.h"
2021-05-05 12:59:42 +02:00
#include "../../container/SharedRingBuffer.h"
#include "../../ipc/MessageQueueSenderIF.h"
#include "../../objectmanager/ObjectManagerIF.h"
2021-03-11 14:47:47 +01:00
#include "../../serviceinterface/ServiceInterface.h"
2021-05-05 12:59:42 +02:00
#include "../../tmtcservices/TmTcMessage.h"
2021-03-11 14:47:47 +01:00
#ifdef _WIN32
2021-03-11 14:47:47 +01:00
#include <winsock2.h>
#include <ws2tcpip.h>
2021-03-21 12:51:28 +01:00
#elif defined(__unix__)
#include <netdb.h>
#endif
2021-03-11 14:47:47 +01:00
2021-05-05 12:59:42 +02:00
#ifndef FSFW_TCP_RECV_WIRETAPPING_ENABLED
#define FSFW_TCP_RECV_WIRETAPPING_ENABLED 0
#endif
const std::string TcpTmTcServer::DEFAULT_TCP_SERVER_PORT = "7301";
2021-03-11 14:47:47 +01:00
2021-05-05 12:59:42 +02:00
TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
/*SharedRingBuffer* tcpRingBuffer, */ size_t receptionBufferSize,
2021-03-11 14:47:47 +01:00
std::string customTcpServerPort):
2021-05-05 12:59:42 +02:00
SystemObject(objectId), tmtcBridgeId(tmtcTcpBridge), tcpPort(customTcpServerPort),
receptionBuffer(receptionBufferSize) /*, tcpRingBuffer(tcpRingBuffer) */ {
2021-03-11 14:47:47 +01:00
if(tcpPort == "") {
tcpPort = DEFAULT_TCP_SERVER_PORT;
}
}
ReturnValue_t TcpTmTcServer::initialize() {
2021-03-12 02:15:21 +01:00
using namespace tcpip;
2021-05-05 12:59:42 +02:00
/*
if(tcpRingBuffer == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcpTmTcServer::initialize: Invalid ring buffer!" << std::endl;
#else
sif::printError("TcpTmTcServer::initialize: Invalid ring buffer!\n");
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
*/
ReturnValue_t result = TcpIpBase::initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
2021-05-05 12:59:42 +02:00
tcStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
if (tcStore == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcpTmTcServer::initialize: TC store uninitialized!" << std::endl;
#else
sif::printError("TcpTmTcServer::initialize: TC store uninitialized!\n");
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
tmtcBridge = objectManager->get<TcpTmTcBridge>(tmtcBridgeId);
2021-03-11 14:47:47 +01:00
int retval = 0;
struct addrinfo *addrResult = nullptr;
struct addrinfo hints = {};
2021-03-11 14:47:47 +01:00
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
retval = getaddrinfo(nullptr, tcpPort.c_str(), &hints, &addrResult);
if (retval != 0) {
2021-03-12 02:15:21 +01:00
handleError(Protocol::TCP, ErrorSources::GETADDRINFO_CALL);
2021-03-11 14:47:47 +01:00
return HasReturnvaluesIF::RETURN_FAILED;
}
/* Open TCP (stream) socket */
listenerTcpSocket = socket(addrResult->ai_family, addrResult->ai_socktype,
addrResult->ai_protocol);
if(listenerTcpSocket == INVALID_SOCKET) {
freeaddrinfo(addrResult);
2021-03-12 02:15:21 +01:00
handleError(Protocol::TCP, ErrorSources::SOCKET_CALL);
2021-03-11 14:47:47 +01:00
return HasReturnvaluesIF::RETURN_FAILED;
}
2021-03-12 00:34:30 +01:00
retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
2021-03-11 14:47:47 +01:00
if(retval == SOCKET_ERROR) {
freeaddrinfo(addrResult);
2021-03-12 02:15:21 +01:00
handleError(Protocol::TCP, ErrorSources::BIND_CALL);
2021-04-11 21:54:48 +02:00
return HasReturnvaluesIF::RETURN_FAILED;
2021-03-11 14:47:47 +01:00
}
freeaddrinfo(addrResult);
return HasReturnvaluesIF::RETURN_OK;
}
TcpTmTcServer::~TcpTmTcServer() {
2021-03-21 12:51:28 +01:00
closeSocket(listenerTcpSocket);
2021-03-11 14:47:47 +01:00
}
ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
2021-03-12 02:15:21 +01:00
using namespace tcpip;
2021-03-11 14:47:47 +01:00
/* If a connection is accepted, the corresponding socket will be assigned to the new socket */
2021-05-05 12:59:42 +02:00
socket_t connSocket = 0;
2021-04-11 21:54:48 +02:00
sockaddr clientSockAddr = {};
2021-03-21 12:51:28 +01:00
socklen_t connectorSockAddrLen = 0;
2021-03-11 14:47:47 +01:00
int retval = 0;
2021-03-12 02:15:21 +01:00
2021-03-11 14:47:47 +01:00
/* Listen for connection requests permanently for lifetime of program */
while(true) {
retval = listen(listenerTcpSocket, currentBacklog);
if(retval == SOCKET_ERROR) {
2021-03-12 02:15:21 +01:00
handleError(Protocol::TCP, ErrorSources::LISTEN_CALL, 500);
2021-03-11 14:47:47 +01:00
continue;
}
2021-05-05 12:59:42 +02:00
connSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen);
2021-03-11 14:47:47 +01:00
2021-05-05 12:59:42 +02:00
if(connSocket == INVALID_SOCKET) {
2021-03-12 02:15:21 +01:00
handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500);
2021-05-05 12:59:42 +02:00
closeSocket(connSocket);
2021-03-11 14:47:47 +01:00
continue;
};
2021-05-05 12:59:42 +02:00
handleServerOperation(connSocket);
/* Done, shut down connection */
retval = shutdown(connSocket, SHUT_SEND);
if(retval != 0) {
handleError(Protocol::TCP, ErrorSources::SHUTDOWN_CALL);
2021-03-11 14:47:47 +01:00
}
2021-05-05 12:59:42 +02:00
closeSocket(connSocket);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() {
/* Initialize the destination after task creation. This ensures
that the destination has already been set in the TMTC bridge. */
targetTcDestination = tmtcBridge->getRequestQueue();
//
// if(tcpRingBuffer != nullptr) {
// auto fifoCheck = tcpRingBuffer->getReceiveSizesFIFO();
// if (fifoCheck == nullptr) {
//#if FSFW_CPP_OSTREAM_ENABLED == 1
// sif::error << "TcpTmTcServer::initializeAfterTaskCreation: "
// "TCP ring buffer does not have a FIFO!" << std::endl;
//#else
// sif::printError("TcpTmTcServer::initialize: TCP ring buffer does not have a FIFO!\n");
//#endif /* FSFW_CPP_OSTREAM_ENABLED == 0 */
// }
// }
2021-03-11 14:47:47 +01:00
2021-05-05 12:59:42 +02:00
return HasReturnvaluesIF::RETURN_OK;
}
void TcpTmTcServer::handleServerOperation(socket_t connSocket) {
int retval = 0;
do {
retval = recv(connSocket,
reinterpret_cast<char*>(receptionBuffer.data()),
receptionBuffer.capacity(),
tcpFlags);
if (retval > 0) {
handleTcReception(retval);
}
else if(retval == 0) {
/* Client has finished sending telecommands, send telemetry now */
2021-03-11 14:47:47 +01:00
}
else {
2021-05-05 12:59:42 +02:00
/* Should not happen */
2021-03-11 14:47:47 +01:00
}
2021-05-05 12:59:42 +02:00
} while(retval > 0);
}
2021-03-11 14:47:47 +01:00
2021-05-05 12:59:42 +02:00
ReturnValue_t TcpTmTcServer::handleTcReception(size_t bytesRecvd) {
#if FSFW_TCP_RECV_WIRETAPPING_ENABLED == 1
arrayprinter::print(receptionBuffer.data(), bytesRead);
#endif
store_address_t storeId;
ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRecvd);
if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning<< "TcpTmTcServer::handleServerOperation: Data storage failed." << std::endl;
sif::warning << "Packet size: " << bytesRecvd << std::endl;
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
2021-03-11 14:47:47 +01:00
}
2021-05-05 12:59:42 +02:00
TmTcMessage message(storeId);
2021-03-11 14:47:47 +01:00
2021-05-05 12:59:42 +02:00
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;
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
tcStore->deleteData(storeId);
}
return result;
}