#include "TmTcWinUdpBridge.h" #include TmTcWinUdpBridge::TmTcWinUdpBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId, uint16_t serverPort, uint16_t clientPort): TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) { mutex = MutexFactory::instance()->createMutex(); communicationLinkUp = false; // 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; } uint16_t setServerPort = DEFAULT_UDP_SERVER_PORT; if(serverPort != 0xFFFF) { setServerPort = serverPort; } uint16_t setClientPort = DEFAULT_UDP_CLIENT_PORT; if(clientPort != 0xFFFF) { setClientPort = clientPort; } // Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html //clientSocket = socket(AF_INET, SOCK_DGRAM, 0); serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(serverSocket == INVALID_SOCKET) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not open" " UDP socket!" << std::endl; #endif handleSocketError(); return; } serverAddress.sin_family = AF_INET; // Accept packets from any interface. (potentially insecure). serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); serverAddress.sin_port = htons(setServerPort); serverAddressLen = sizeof(serverAddress); setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&serverSocketOptions), sizeof(serverSocketOptions)); clientAddress.sin_family = AF_INET; clientAddress.sin_addr.s_addr = htonl(INADDR_ANY); clientAddress.sin_port = htons(setClientPort); clientAddressLen = sizeof(clientAddress); int result = bind(serverSocket, reinterpret_cast(&serverAddress), serverAddressLen); if(result != 0) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not bind " "local port " << setServerPort << " to server socket!" << std::endl; #endif handleBindError(); } } TmTcWinUdpBridge::~TmTcWinUdpBridge() { WSACleanup(); } ReturnValue_t TmTcWinUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { int flags = 0; //clientAddress.sin_addr.s_addr = htons(INADDR_ANY); //clientAddressLen = sizeof(serverAddress); // char ipAddress [15]; #if FSFW_CPP_OSTREAM_ENABLED == 1 // sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, // &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; #endif ssize_t bytesSent = sendto(serverSocket, reinterpret_cast(data), dataLen, flags, reinterpret_cast(&clientAddress), clientAddressLen); if(bytesSent == SOCKET_ERROR) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "TmTcWinUdpBridge::sendTm: Send operation failed." << std::endl; #endif handleSendError(); } #if FSFW_CPP_OSTREAM_ENABLED == 1 // sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were" // " sent." << std::endl; #endif return HasReturnvaluesIF::RETURN_OK; } void TmTcWinUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) { MutexGuard lock(mutex, MutexIF::TimeoutType::WAITING, 10); // char ipAddress [15]; #if FSFW_CPP_OSTREAM_ENABLED == 1 // 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 if it has changed. if(clientAddress.sin_addr.s_addr != newAddress.sin_addr.s_addr) { clientAddress.sin_addr.s_addr = newAddress.sin_addr.s_addr; clientAddressLen = sizeof(clientAddress); } } void TmTcWinUdpBridge::handleSocketError() { int errCode = WSAGetLastError(); switch(errCode) { case(WSANOTINITIALISED): { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TmTcWinUdpBridge::handleSocketError: WSANOTINITIALISED: " << "WSAStartup(...) call necessary" << std::endl; #endif break; } default: { /* https://docs.microsoft.com/en-us/windows/win32/winsock/ windows-sockets-error-codes-2 */ #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TmTcWinUdpBridge::handleSocketError: Error code: " << errCode << std::endl; #endif break; } } } void TmTcWinUdpBridge::handleBindError() { int errCode = WSAGetLastError(); switch(errCode) { case(WSANOTINITIALISED): { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TmTcWinUdpBridge::handleBindError: WSANOTINITIALISED: " << "WSAStartup(...) call " << "necessary" << std::endl; #endif break; } case(WSAEADDRINUSE): { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "TmTcWinUdpBridge::handleBindError: WSAEADDRINUSE: " << "Port is already in use!" << std::endl; #endif break; } default: { /* https://docs.microsoft.com/en-us/windows/win32/winsock/ windows-sockets-error-codes-2 */ #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TmTcWinUdpBridge::handleBindError: Error code: " << errCode << std::endl; #endif break; } } } void TmTcWinUdpBridge::handleSendError() { int errCode = WSAGetLastError(); switch(errCode) { case(WSANOTINITIALISED): { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TmTcWinUdpBridge::handleSendError: WSANOTINITIALISED: " << "WSAStartup(...) call necessary" << std::endl; #endif break; } case(WSAEADDRNOTAVAIL): { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TmTcWinUdpBridge::handleSendError: WSAEADDRNOTAVAIL: " << "Check target address. " << std::endl; #endif break; } default: { /* https://docs.microsoft.com/en-us/windows/win32/winsock/ windows-sockets-error-codes-2 */ #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TmTcWinUdpBridge::handleSendError: Error code: " << errCode << std::endl; #endif break; } } }