diff --git a/osal/common/CMakeLists.txt b/osal/common/CMakeLists.txt index af76484d3..b7c8c033a 100644 --- a/osal/common/CMakeLists.txt +++ b/osal/common/CMakeLists.txt @@ -5,6 +5,7 @@ if(DEFINED WIN32 OR DEFINED UNIX) UdpTcPollingTask.cpp UdpTmTcBridge.cpp TcpTmTcServer.cpp + TcpTmTcBridge.cpp ) endif() diff --git a/osal/common/TcpTmTcBridge.cpp b/osal/common/TcpTmTcBridge.cpp new file mode 100644 index 000000000..a88b68e96 --- /dev/null +++ b/osal/common/TcpTmTcBridge.cpp @@ -0,0 +1,57 @@ +#include "TcpTmTcBridge.h" +#include "tcpipHelpers.h" + +#include +#include +#include + +#ifdef _WIN32 + +#include + +#elif defined(__unix__) + +#include +#include + +#endif + +const std::string TcpTmTcBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; + +TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, + object_id_t tmStoreId, object_id_t tcStoreId): + TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { + mutex = MutexFactory::instance()->createMutex(); + communicationLinkUp = false; +} + +ReturnValue_t TcpTmTcBridge::initialize() { + ReturnValue_t result = TmTcBridge::initialize(); + if(result != HasReturnvaluesIF::RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "TmTcUdpBridge::initialize: TmTcBridge initialization failed!" + << std::endl; +#endif + return result; + } + + return HasReturnvaluesIF::RETURN_OK; +} + +TcpTmTcBridge::~TcpTmTcBridge() { + if(mutex != nullptr) { + MutexFactory::instance()->deleteMutex(mutex); + } +} + +ReturnValue_t TcpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) { + + return HasReturnvaluesIF::RETURN_OK; +} + + +void TcpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, + dur_millis_t timeoutMs) { + this->timeoutType = timeoutType; + this->mutexTimeoutMs = timeoutMs; +} diff --git a/osal/common/TcpTmTcBridge.h b/osal/common/TcpTmTcBridge.h new file mode 100644 index 000000000..db45fca89 --- /dev/null +++ b/osal/common/TcpTmTcBridge.h @@ -0,0 +1,54 @@ +#ifndef FSFW_OSAL_COMMON_TCPTMTCBRIDGE_H_ +#define FSFW_OSAL_COMMON_TCPTMTCBRIDGE_H_ + +#include "TcpIpBase.h" +#include "../../tmtcservices/TmTcBridge.h" + +#ifdef _WIN32 + +#include + +#elif defined(__unix__) + +#include + +#endif + +#include + +/** + * @brief This class should be used with the UdpTcPollingTask to implement a UDP server + * for receiving and sending PUS TMTC. + */ +class TcpTmTcBridge: + public TmTcBridge { + //friend class UdpTcPollingTask; +public: + /* The ports chosen here should not be used by any other process. */ + static const std::string DEFAULT_UDP_SERVER_PORT; + + TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, + object_id_t tmStoreId = objects::TM_STORE, + object_id_t tcStoreId = objects::TC_STORE); + virtual~ TcpTmTcBridge(); + + /** + * Set properties of internal mutex. + */ + void setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs); + + ReturnValue_t initialize() override; + +protected: + virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; + +private: + + //! 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 /* FSFW_OSAL_COMMON_TCPTMTCBRIDGE_H_ */ + diff --git a/osal/common/TcpTmTcServer.cpp b/osal/common/TcpTmTcServer.cpp index 08a62ffb9..8717783e7 100644 --- a/osal/common/TcpTmTcServer.cpp +++ b/osal/common/TcpTmTcServer.cpp @@ -1,6 +1,12 @@ #include "TcpTmTcServer.h" +#include "TcpTmTcBridge.h" #include "tcpipHelpers.h" + +#include "../../container/SharedRingBuffer.h" +#include "../../ipc/MessageQueueSenderIF.h" +#include "../../objectmanager/ObjectManagerIF.h" #include "../../serviceinterface/ServiceInterface.h" +#include "../../tmtcservices/TmTcMessage.h" #ifdef _WIN32 #include @@ -12,12 +18,17 @@ #endif -const std::string TcpTmTcServer::DEFAULT_TCP_SERVER_PORT = "7301"; -const std::string TcpTmTcServer::DEFAULT_TCP_CLIENT_PORT = "7302"; +#ifndef FSFW_TCP_RECV_WIRETAPPING_ENABLED +#define FSFW_TCP_RECV_WIRETAPPING_ENABLED 0 +#endif -TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge, +const std::string TcpTmTcServer::DEFAULT_TCP_SERVER_PORT = "7301"; + +TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, + /*SharedRingBuffer* tcpRingBuffer, */ size_t receptionBufferSize, std::string customTcpServerPort): - SystemObject(objectId), tcpPort(customTcpServerPort) { + SystemObject(objectId), tmtcBridgeId(tmtcTcpBridge), tcpPort(customTcpServerPort), + receptionBuffer(receptionBufferSize) /*, tcpRingBuffer(tcpRingBuffer) */ { if(tcpPort == "") { tcpPort = DEFAULT_TCP_SERVER_PORT; } @@ -26,11 +37,34 @@ TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge ReturnValue_t TcpTmTcServer::initialize() { using namespace tcpip; + /* + 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; } + tcStore = objectManager->get(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(tmtcBridgeId); + int retval = 0; struct addrinfo *addrResult = nullptr; struct addrinfo hints = {}; @@ -42,10 +76,6 @@ ReturnValue_t TcpTmTcServer::initialize() { retval = getaddrinfo(nullptr, tcpPort.c_str(), &hints, &addrResult); if (retval != 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TcWinTcpServer::TcpTmTcServer: Retrieving address info failed!" << - std::endl; -#endif handleError(Protocol::TCP, ErrorSources::GETADDRINFO_CALL); return HasReturnvaluesIF::RETURN_FAILED; } @@ -54,9 +84,6 @@ ReturnValue_t TcpTmTcServer::initialize() { listenerTcpSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol); if(listenerTcpSocket == INVALID_SOCKET) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TcWinTcpServer::TcWinTcpServer: Socket creation failed!" << std::endl; -#endif freeaddrinfo(addrResult); handleError(Protocol::TCP, ErrorSources::SOCKET_CALL); return HasReturnvaluesIF::RETURN_FAILED; @@ -64,10 +91,6 @@ ReturnValue_t TcpTmTcServer::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::TcpTmTcServer: Binding socket failed!" << - std::endl; -#endif freeaddrinfo(addrResult); handleError(Protocol::TCP, ErrorSources::BIND_CALL); return HasReturnvaluesIF::RETURN_FAILED; @@ -85,7 +108,7 @@ TcpTmTcServer::~TcpTmTcServer() { 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_t clientSocket = 0; + socket_t connSocket = 0; sockaddr clientSockAddr = {}; socklen_t connectorSockAddrLen = 0; int retval = 0; @@ -98,35 +121,92 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) { continue; } - clientSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen); + connSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen); - if(clientSocket == INVALID_SOCKET) { + if(connSocket == INVALID_SOCKET) { handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500); - closeSocket(clientSocket); + closeSocket(connSocket); continue; }; - retval = recv(clientSocket, reinterpret_cast(receptionBuffer.data()), - receptionBuffer.size(), 0); - if(retval > 0) { -#if FSFW_TCP_RCV_WIRETAPPING_ENABLED == 1 - sif::info << "TcpTmTcServer::performOperation: Received " << retval << " bytes." - std::endl; -#endif - handleError(Protocol::TCP, ErrorSources::RECV_CALL, 500); - } - else if(retval == 0) { - - } - else { - - } + handleServerOperation(connSocket); /* Done, shut down connection */ - retval = shutdown(clientSocket, SHUT_SEND); - closeSocket(clientSocket); + retval = shutdown(connSocket, SHUT_SEND); + if(retval != 0) { + handleError(Protocol::TCP, ErrorSources::SHUTDOWN_CALL); + } + 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 */ +// } +// } + + return HasReturnvaluesIF::RETURN_OK; +} + +void TcpTmTcServer::handleServerOperation(socket_t connSocket) { + int retval = 0; + do { + retval = recv(connSocket, + reinterpret_cast(receptionBuffer.data()), + receptionBuffer.capacity(), + tcpFlags); + if (retval > 0) { + handleTcReception(retval); + } + else if(retval == 0) { + /* Client has finished sending telecommands, send telemetry now */ + } + else { + /* Should not happen */ + } + } while(retval > 0); +} + +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 */ + } + + 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::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; +} diff --git a/osal/common/TcpTmTcServer.h b/osal/common/TcpTmTcServer.h index 4dcc77a2d..6db6621d4 100644 --- a/osal/common/TcpTmTcServer.h +++ b/osal/common/TcpTmTcServer.h @@ -2,7 +2,11 @@ #define FSFW_OSAL_WINDOWS_TCWINTCPSERVER_H_ #include "TcpIpBase.h" +#include "../../ipc/messageQueueDefinitions.h" +#include "../../ipc/MessageQueueIF.h" +#include "../../objectmanager/frameworkObjects.h" #include "../../objectmanager/SystemObject.h" +#include "../../storagemanager/StorageManagerIF.h" #include "../../tasks/ExecutableObjectIF.h" #ifdef __unix__ @@ -12,8 +16,9 @@ #include #include -//! Debugging preprocessor define. -#define FSFW_TCP_RCV_WIRETAPPING_ENABLED 0 +class TcpTmTcBridge; +//class SharedRingBuffer; + /** * @brief Windows TCP server used to receive telecommands on a Windows Host @@ -28,26 +33,39 @@ 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; + static constexpr size_t ETHERNET_MTU_SIZE = 1500; - TcpTmTcServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge, + TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge /*, SharedRingBuffer* tcpRingBuffer*/, + size_t receptionBufferSize = ETHERNET_MTU_SIZE, std::string customTcpServerPort = ""); virtual~ TcpTmTcServer(); ReturnValue_t initialize() override; ReturnValue_t performOperation(uint8_t opCode) override; + ReturnValue_t initializeAfterTaskCreation() override; + +protected: + StorageManagerIF* tcStore = nullptr; private: + //! TMTC bridge is cached. + object_id_t tmtcBridgeId = objects::NO_OBJECT; + TcpTmTcBridge* tmtcBridge = nullptr; std::string tcpPort; + int tcpFlags = 0; socket_t listenerTcpSocket = 0; struct sockaddr tcpAddress; + MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; int tcpAddrLen = sizeof(tcpAddress); int currentBacklog = 3; std::vector receptionBuffer; + //SharedRingBuffer* tcpRingBuffer; int tcpSockOpt = 0; - + void handleServerOperation(socket_t connSocket); + ReturnValue_t handleTcReception(size_t bytesRecvd); }; #endif /* FSFW_OSAL_WINDOWS_TCWINTCPSERVER_H_ */ diff --git a/osal/common/UdpTcPollingTask.cpp b/osal/common/UdpTcPollingTask.cpp index 47f67b295..d79e24479 100644 --- a/osal/common/UdpTcPollingTask.cpp +++ b/osal/common/UdpTcPollingTask.cpp @@ -18,9 +18,9 @@ #define FSFW_UDP_RECV_WIRETAPPING_ENABLED 0 UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, - object_id_t tmtcUnixUdpBridge, size_t maxRecvSize, + object_id_t tmtcUdpBridge, size_t maxRecvSize, double timeoutSeconds): SystemObject(objectId), - tmtcBridgeId(tmtcUnixUdpBridge) { + tmtcBridgeId(tmtcUdpBridge) { if(frameSize > 0) { this->frameSize = frameSize; } diff --git a/osal/common/UdpTcPollingTask.h b/osal/common/UdpTcPollingTask.h index 052eced52..cfe74b346 100644 --- a/osal/common/UdpTcPollingTask.h +++ b/osal/common/UdpTcPollingTask.h @@ -1,5 +1,5 @@ -#ifndef FSFW_OSAL_WINDOWS_TCSOCKETPOLLINGTASK_H_ -#define FSFW_OSAL_WINDOWS_TCSOCKETPOLLINGTASK_H_ +#ifndef FSFW_OSAL_COMMON_UDPTCPOLLINGTASK_H_ +#define FSFW_OSAL_COMMON_UDPTCPOLLINGTASK_H_ #include "UdpTmTcBridge.h" #include "../../objectmanager/SystemObject.h" @@ -22,7 +22,7 @@ public: //! 0.5 default milliseconds timeout for now. static constexpr timeval DEFAULT_TIMEOUT = {0, 500}; - UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge, + UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge, size_t maxRecvSize = 0, double timeoutSeconds = -1); virtual~ UdpTcPollingTask(); @@ -57,4 +57,4 @@ private: ReturnValue_t handleSuccessfullTcRead(size_t bytesRead); }; -#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */ +#endif /* FSFW_OSAL_COMMON_UDPTCPOLLINGTASK_H_ */ diff --git a/osal/common/UdpTmTcBridge.cpp b/osal/common/UdpTmTcBridge.cpp index ba23f521b..ccbb194e3 100644 --- a/osal/common/UdpTmTcBridge.cpp +++ b/osal/common/UdpTmTcBridge.cpp @@ -16,7 +16,9 @@ #endif //! Debugging preprocessor define. +#ifndef FSFW_UDP_SEND_WIRETAPPING_ENABLED #define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0 +#endif const std::string UdpTmTcBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; @@ -38,7 +40,7 @@ ReturnValue_t UdpTmTcBridge::initialize() { ReturnValue_t result = TmTcBridge::initialize(); if(result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TmTcUdpBridge::initialize: TmTcBridge initialization failed!" + sif::error << "UdpTmTcBridge::initialize: TmTcBridge initialization failed!" << std::endl; #endif return result; @@ -54,10 +56,10 @@ ReturnValue_t UdpTmTcBridge::initialize() { /* Tell the user that we could not find a usable */ /* Winsock DLL. */ #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TmTcUdpBridge::TmTcUdpBridge: WSAStartup failed with error: " << + sif::error << "UdpTmTcBridge::UdpTmTcBridge: WSAStartup failed with error: " << err << std::endl; #else - sif::printError("TmTcUdpBridge::TmTcUdpBridge: WSAStartup failed with error: %d\n", + sif::printError("UdpTmTcBridge::UdpTmTcBridge: WSAStartup failed with error: %d\n", err); #endif return HasReturnvaluesIF::RETURN_FAILED; @@ -78,19 +80,12 @@ ReturnValue_t UdpTmTcBridge::initialize() { 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 << "TmTcUdpBridge::TmTcUdpBridge: Retrieving address info failed!" << - std::endl; -#endif + tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::GETADDRINFO_CALL); return HasReturnvaluesIF::RETURN_FAILED; } serverSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol); if(serverSocket == INVALID_SOCKET) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "TmTcUdpBridge::TmTcUdpBridge: Could not open UDP socket!" << - std::endl; -#endif freeaddrinfo(addrResult); tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SOCKET_CALL); return HasReturnvaluesIF::RETURN_FAILED; @@ -102,10 +97,6 @@ ReturnValue_t UdpTmTcBridge::initialize() { retval = bind(serverSocket, addrResult->ai_addr, static_cast(addrResult->ai_addrlen)); if(retval != 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "TmTcUdpBridge::TmTcUdpBridge: Could not bind " - "local port (" << udpServerPort << ") to server socket!" << std::endl; -#endif freeaddrinfo(addrResult); tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::BIND_CALL); return HasReturnvaluesIF::RETURN_FAILED; diff --git a/osal/common/UdpTmTcBridge.h b/osal/common/UdpTmTcBridge.h index 8b8d19491..290f5eb0d 100644 --- a/osal/common/UdpTmTcBridge.h +++ b/osal/common/UdpTmTcBridge.h @@ -1,5 +1,5 @@ -#ifndef FSFW_OSAL_WINDOWS_TMTCWINUDPBRIDGE_H_ -#define FSFW_OSAL_WINDOWS_TMTCWINUDPBRIDGE_H_ +#ifndef FSFW_OSAL_COMMON_TMTCUDPBRIDGE_H_ +#define FSFW_OSAL_COMMON_TMTCUDPBRIDGE_H_ #include "TcpIpBase.h" #include "../../tmtcservices/TmTcBridge.h" @@ -56,5 +56,5 @@ private: MutexIF* mutex; }; -#endif /* FSFW_OSAL_HOST_TMTCWINUDPBRIDGE_H_ */ +#endif /* FSFW_OSAL_COMMON_TMTCUDPBRIDGE_H_ */ diff --git a/osal/common/tcpipCommon.cpp b/osal/common/tcpipCommon.cpp index 551e2a426..d4a3e8e6f 100644 --- a/osal/common/tcpipCommon.cpp +++ b/osal/common/tcpipCommon.cpp @@ -35,6 +35,9 @@ void tcpip::determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std: else if(errorSrc == ErrorSources::GETADDRINFO_CALL) { srcString = "getaddrinfo call"; } + else if(errorSrc == ErrorSources::SHUTDOWN_CALL) { + srcString = "shutdown call"; + } else { srcString = "unknown call"; } diff --git a/osal/common/tcpipCommon.h b/osal/common/tcpipCommon.h index 22b914dc1..eb1bd9100 100644 --- a/osal/common/tcpipCommon.h +++ b/osal/common/tcpipCommon.h @@ -29,7 +29,8 @@ enum class ErrorSources { RECVFROM_CALL, LISTEN_CALL, ACCEPT_CALL, - SENDTO_CALL + SENDTO_CALL, + SHUTDOWN_CALL }; void determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std::string& protStr,