From da3a2a1869f3ade2cb1c64dc7a941ab0ef3096c4 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Wed, 8 Jan 2025 20:41:23 -0500 Subject: [PATCH] fix long standing dvmhost shutdown bug (object cleanup wasn't occuring due to bad state change handling); refactor FSC packet data classes; remove FSCResponse and FSCConnectResponse (these were ill conceived due to bad interpretation of TIA-102 specifications); correct FSCACK not properly decoding response user data after packet data; refactor the way the FSC message factory createMessage() function created instances of FSC packets; refactor how opening and closing the FSC port is handled; better implement the FSC state machine; correct bad response to an FSC_CONNECT (due to incorrect understanding of TIA-102 specifications); --- src/common/p25/dfsi/frames/Frames.h | 2 - src/common/p25/dfsi/frames/fsc/FSCACK.cpp | 16 +- src/common/p25/dfsi/frames/fsc/FSCACK.h | 9 +- src/common/p25/dfsi/frames/fsc/FSCConnect.cpp | 11 - src/common/p25/dfsi/frames/fsc/FSCConnect.h | 7 +- .../dfsi/frames/fsc/FSCConnectResponse.cpp | 62 ---- .../p25/dfsi/frames/fsc/FSCConnectResponse.h | 78 ----- .../p25/dfsi/frames/fsc/FSCDisconnect.cpp | 7 - .../p25/dfsi/frames/fsc/FSCDisconnect.h | 7 +- .../p25/dfsi/frames/fsc/FSCHeartbeat.cpp | 7 - src/common/p25/dfsi/frames/fsc/FSCHeartbeat.h | 7 +- src/common/p25/dfsi/frames/fsc/FSCMessage.cpp | 37 ++- src/common/p25/dfsi/frames/fsc/FSCMessage.h | 5 - .../p25/dfsi/frames/fsc/FSCResponse.cpp | 60 ---- src/common/p25/dfsi/frames/fsc/FSCResponse.h | 77 ----- src/host/Host.Config.cpp | 7 +- src/host/Host.cpp | 14 +- src/host/Host.h | 2 +- .../modem/port/specialized/V24UDPPort.cpp | 273 ++++++++++++------ src/host/modem/port/specialized/V24UDPPort.h | 27 +- 20 files changed, 241 insertions(+), 474 deletions(-) delete mode 100644 src/common/p25/dfsi/frames/fsc/FSCConnectResponse.cpp delete mode 100644 src/common/p25/dfsi/frames/fsc/FSCConnectResponse.h delete mode 100644 src/common/p25/dfsi/frames/fsc/FSCResponse.cpp delete mode 100644 src/common/p25/dfsi/frames/fsc/FSCResponse.h diff --git a/src/common/p25/dfsi/frames/Frames.h b/src/common/p25/dfsi/frames/Frames.h index b529d58d..3e71e77e 100644 --- a/src/common/p25/dfsi/frames/Frames.h +++ b/src/common/p25/dfsi/frames/Frames.h @@ -30,10 +30,8 @@ // FSC #include "common/p25/dfsi/frames/fsc/FSCMessage.h" -#include "common/p25/dfsi/frames/fsc/FSCResponse.h" #include "common/p25/dfsi/frames/fsc/FSCACK.h" #include "common/p25/dfsi/frames/fsc/FSCConnect.h" -#include "common/p25/dfsi/frames/fsc/FSCConnectResponse.h" #include "common/p25/dfsi/frames/fsc/FSCDisconnect.h" #include "common/p25/dfsi/frames/fsc/FSCHeartbeat.h" diff --git a/src/common/p25/dfsi/frames/fsc/FSCACK.cpp b/src/common/p25/dfsi/frames/fsc/FSCACK.cpp index 10abc999..6d5d025a 100644 --- a/src/common/p25/dfsi/frames/fsc/FSCACK.cpp +++ b/src/common/p25/dfsi/frames/fsc/FSCACK.cpp @@ -35,18 +35,6 @@ FSCACK::FSCACK() : FSCMessage(), m_messageId = FSCMessageType::FSC_ACK; } -/* Initializes a instance of the FSCACK class. */ - -FSCACK::FSCACK(const uint8_t* data) : FSCMessage(data), - m_ackMessageId(FSCMessageType::FSC_INVALID), - m_ackVersion(1U), - m_ackCorrelationTag(0U), - m_responseCode(FSCAckResponseCode::CONTROL_ACK), - m_respLength(0U) -{ - FSCACK::decode(data); -} - /* Decode a FSC ACK frame. */ bool FSCACK::decode(const uint8_t* data) @@ -65,7 +53,7 @@ bool FSCACK::decode(const uint8_t* data) delete responseData; responseData = new uint8_t[m_respLength]; ::memset(responseData, 0x00U, m_respLength); - ::memcpy(responseData, data, m_respLength); + ::memcpy(responseData, data + 7U, m_respLength); } else { if (responseData != nullptr) @@ -90,6 +78,6 @@ void FSCACK::encode(uint8_t* data) data[6U] = m_respLength; // Response Data Length if (m_respLength > 0U && responseData != nullptr) { - ::memcpy(data, responseData, m_respLength); + ::memcpy(data + 7U, responseData, m_respLength); } } diff --git a/src/common/p25/dfsi/frames/fsc/FSCACK.h b/src/common/p25/dfsi/frames/fsc/FSCACK.h index f2df8f51..2c378a82 100644 --- a/src/common/p25/dfsi/frames/fsc/FSCACK.h +++ b/src/common/p25/dfsi/frames/fsc/FSCACK.h @@ -41,17 +41,12 @@ namespace p25 */ class HOST_SW_API FSCACK : public FSCMessage { public: - static const uint8_t LENGTH = 6; + static const uint8_t LENGTH = 7U; /** * @brief Initializes a copy instance of the FSCACK class. */ FSCACK(); - /** - * @brief Initializes a copy instance of the FSCACK class. - * @param data Buffer to containing FSCACK to decode. - */ - FSCACK(const uint8_t* data); /** * @brief Decode a FSC ACK frame. @@ -78,7 +73,7 @@ namespace p25 /** * @brief */ - __READONLY_PROPERTY(uint8_t, ackCorrelationTag, AckCorrelationTag); + __PROPERTY(uint8_t, ackCorrelationTag, AckCorrelationTag); /** * @brief Response code. */ diff --git a/src/common/p25/dfsi/frames/fsc/FSCConnect.cpp b/src/common/p25/dfsi/frames/fsc/FSCConnect.cpp index 9d3f6fdd..ed0f7149 100644 --- a/src/common/p25/dfsi/frames/fsc/FSCConnect.cpp +++ b/src/common/p25/dfsi/frames/fsc/FSCConnect.cpp @@ -34,17 +34,6 @@ FSCConnect::FSCConnect() : FSCMessage(), m_messageId = FSCMessageType::FSC_CONNECT; } -/* Initializes a instance of the FSCConnect class. */ - -FSCConnect::FSCConnect(const uint8_t* data) : FSCMessage(data), - m_vcBasePort(0U), - m_vcSSRC(0U), - m_fsHeartbeatPeriod(5U), - m_hostHeartbeatPeriod(5U) -{ - FSCConnect::decode(data); -} - /* Decode a FSC connect frame. */ bool FSCConnect::decode(const uint8_t* data) diff --git a/src/common/p25/dfsi/frames/fsc/FSCConnect.h b/src/common/p25/dfsi/frames/fsc/FSCConnect.h index 067a93bd..9dc3d60e 100644 --- a/src/common/p25/dfsi/frames/fsc/FSCConnect.h +++ b/src/common/p25/dfsi/frames/fsc/FSCConnect.h @@ -41,17 +41,12 @@ namespace p25 */ class HOST_SW_API FSCConnect : public FSCMessage { public: - static const uint8_t LENGTH = 11; + static const uint8_t LENGTH = 11U; /** * @brief Initializes a copy instance of the FSCConnect class. */ FSCConnect(); - /** - * @brief Initializes a copy instance of the FSCConnect class. - * @param data Buffer to containing FSCConnect to decode. - */ - FSCConnect(const uint8_t* data); /** * @brief Decode a FSC connect frame. diff --git a/src/common/p25/dfsi/frames/fsc/FSCConnectResponse.cpp b/src/common/p25/dfsi/frames/fsc/FSCConnectResponse.cpp deleted file mode 100644 index d93332ed..00000000 --- a/src/common/p25/dfsi/frames/fsc/FSCConnectResponse.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Common Library - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2024 Bryan Biedenkapp, N2PLL - * - */ -#include "common/p25/dfsi/frames/fsc/FSCConnectResponse.h" -#include "common/p25/dfsi/DFSIDefines.h" -#include "common/Utils.h" -#include "common/Log.h" - -#include -#include - -using namespace p25::dfsi; -using namespace p25::dfsi::frames; -using namespace p25::dfsi::frames::fsc; - -// --------------------------------------------------------------------------- -// Public Class Members -// --------------------------------------------------------------------------- - -/* Initializes a instance of the FSCConnectResponse class. */ - -FSCConnectResponse::FSCConnectResponse() : FSCResponse(), - m_vcBasePort(0U) -{ - /* stub */ -} - -/* Initializes a instance of the FSCConnectResponse class. */ - -FSCConnectResponse::FSCConnectResponse(const uint8_t* data) : FSCResponse(data), - m_vcBasePort(0U) -{ - FSCConnectResponse::decode(data); -} - -/* Decode a FSC connect frame. */ - -bool FSCConnectResponse::decode(const uint8_t* data) -{ - assert(data != nullptr); - FSCResponse::decode(data); - - m_vcBasePort = __GET_UINT16B(data, 1U); // Voice Conveyance RTP Port - - return true; -} - -/* Encode a FSC connect frame. */ - -void FSCConnectResponse::encode(uint8_t* data) -{ - assert(data != nullptr); - FSCResponse::encode(data); - - __SET_UINT16B(m_vcBasePort, data, 1U); // Voice Conveyance RTP Port -} diff --git a/src/common/p25/dfsi/frames/fsc/FSCConnectResponse.h b/src/common/p25/dfsi/frames/fsc/FSCConnectResponse.h deleted file mode 100644 index 18196c15..00000000 --- a/src/common/p25/dfsi/frames/fsc/FSCConnectResponse.h +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Common Library - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2024 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file FSCConnectResponse.h - * @ingroup dfsi_fsc_frames - * @file FSCConnectResponse.cpp - * @ingroup dfsi_fsc_frames - */ -#if !defined(__FSC_CONNECT_RESPONSE_H__) -#define __FSC_CONNECT_RESPONSE_H__ - -#include "Defines.h" -#include "common/Defines.h" -#include "common/Log.h" -#include "common/Utils.h" -#include "common/p25/dfsi/frames/FrameDefines.h" -#include "common/p25/dfsi/frames/fsc/FSCResponse.h" - -namespace p25 -{ - namespace dfsi - { - namespace frames - { - namespace fsc - { - // --------------------------------------------------------------------------- - // Class Declaration - // --------------------------------------------------------------------------- - - /** - * @brief Implements the FSC Connect Response Message. - * @ingroup dfsi_fsc_frames - */ - class HOST_SW_API FSCConnectResponse : public FSCResponse { - public: - static const uint8_t LENGTH = 3; - - /** - * @brief Initializes a copy instance of the FSCConnectResponse class. - */ - FSCConnectResponse(); - /** - * @brief Initializes a copy instance of the FSCConnectResponse class. - * @param data Buffer to containing FSCConnectResponse to decode. - */ - FSCConnectResponse(const uint8_t* data); - - /** - * @brief Decode a FSC connect response frame. - * @param[in] data Buffer to containing FSCConnectResponse to decode. - */ - bool decode(const uint8_t* data) override; - /** - * @brief Encode a FSC connect response frame. - * @param[out] data Buffer to encode a FSCConnectResponse. - */ - void encode(uint8_t* data) override; - - public: - /** - * @brief Voice Conveyance RTP Port. - */ - __PROPERTY(uint16_t, vcBasePort, VCBasePort); - }; - } // namespace fsc - } // namespace frames - } // namespace dfsi -} // namespace p25 - -#endif // __FSC_CONNECT_RESPONSE_H__ \ No newline at end of file diff --git a/src/common/p25/dfsi/frames/fsc/FSCDisconnect.cpp b/src/common/p25/dfsi/frames/fsc/FSCDisconnect.cpp index 03255b49..2001055b 100644 --- a/src/common/p25/dfsi/frames/fsc/FSCDisconnect.cpp +++ b/src/common/p25/dfsi/frames/fsc/FSCDisconnect.cpp @@ -29,10 +29,3 @@ FSCDisconnect::FSCDisconnect() : FSCMessage() { m_messageId = FSCMessageType::FSC_DISCONNECT; } - -/* Initializes a instance of the FSCDisconnect class. */ - -FSCDisconnect::FSCDisconnect(const uint8_t* data) : FSCMessage(data) -{ - FSCMessage::decode(data); -} diff --git a/src/common/p25/dfsi/frames/fsc/FSCDisconnect.h b/src/common/p25/dfsi/frames/fsc/FSCDisconnect.h index 0cea9537..1e9517b9 100644 --- a/src/common/p25/dfsi/frames/fsc/FSCDisconnect.h +++ b/src/common/p25/dfsi/frames/fsc/FSCDisconnect.h @@ -41,17 +41,12 @@ namespace p25 */ class HOST_SW_API FSCDisconnect : public FSCMessage { public: - static const uint8_t LENGTH = 3; + static const uint8_t LENGTH = 3U; /** * @brief Initializes a copy instance of the FSCDisconnect class. */ FSCDisconnect(); - /** - * @brief Initializes a copy instance of the FSCDisconnect class. - * @param data Buffer to containing FSCDisconnect to decode. - */ - FSCDisconnect(const uint8_t* data); }; } // namespace fsc } // namespace frames diff --git a/src/common/p25/dfsi/frames/fsc/FSCHeartbeat.cpp b/src/common/p25/dfsi/frames/fsc/FSCHeartbeat.cpp index a37613a2..339d0325 100644 --- a/src/common/p25/dfsi/frames/fsc/FSCHeartbeat.cpp +++ b/src/common/p25/dfsi/frames/fsc/FSCHeartbeat.cpp @@ -29,10 +29,3 @@ FSCHeartbeat::FSCHeartbeat() : FSCMessage() { m_messageId = FSCMessageType::FSC_HEARTBEAT; } - -/* Initializes a instance of the FSCHeartbeat class. */ - -FSCHeartbeat::FSCHeartbeat(const uint8_t* data) : FSCMessage(data) -{ - /* stub */ -} diff --git a/src/common/p25/dfsi/frames/fsc/FSCHeartbeat.h b/src/common/p25/dfsi/frames/fsc/FSCHeartbeat.h index 15a33d1f..ccc7e68e 100644 --- a/src/common/p25/dfsi/frames/fsc/FSCHeartbeat.h +++ b/src/common/p25/dfsi/frames/fsc/FSCHeartbeat.h @@ -41,17 +41,12 @@ namespace p25 */ class HOST_SW_API FSCHeartbeat : public FSCMessage { public: - static const uint8_t LENGTH = 3; + static const uint8_t LENGTH = 3U; /** * @brief Initializes a copy instance of the FSCHeartbeat class. */ FSCHeartbeat(); - /** - * @brief Initializes a copy instance of the FSCHeartbeat class. - * @param data Buffer to containing FSCHeartbeat to decode. - */ - FSCHeartbeat(const uint8_t* data); }; } // namespace fsc } // namespace frames diff --git a/src/common/p25/dfsi/frames/fsc/FSCMessage.cpp b/src/common/p25/dfsi/frames/fsc/FSCMessage.cpp index cd483f35..dc3f4f54 100644 --- a/src/common/p25/dfsi/frames/fsc/FSCMessage.cpp +++ b/src/common/p25/dfsi/frames/fsc/FSCMessage.cpp @@ -29,21 +29,11 @@ using namespace p25::dfsi::frames::fsc; FSCMessage::FSCMessage() : m_messageId(FSCMessageType::FSC_INVALID), m_version(1U), - m_correlationTag(0U) + m_correlationTag(1U) { /* stub */ } -/* Initializes a instance of the FSCMessage class. */ - -FSCMessage::FSCMessage(const uint8_t* data) : - m_messageId(FSCMessageType::FSC_INVALID), - m_version(1U), - m_correlationTag(0U) -{ - decode(data); -} - /* Decode a FSC message frame. */ bool FSCMessage::decode(const uint8_t* data) @@ -78,25 +68,32 @@ std::unique_ptr FSCMessage::createMessage(const uint8_t* data) { assert(data != nullptr); - uint8_t msg[FSCMessage::LENGTH + 1U]; - ::memset(msg, 0x00U, FSCMessage::LENGTH); + uint8_t messageId = (FSCMessageType::E)(data[0U]); // Message ID - uint8_t messageId = (FSCMessageType::E)(msg[0U]); // Message ID + FSCMessage* message = nullptr; // standard P25 reference opcodes switch (messageId) { case FSCMessageType::FSC_CONNECT: - return std::unique_ptr(new FSCConnect(data)); + message = new FSCConnect(); + break; case FSCMessageType::FSC_HEARTBEAT: - return std::unique_ptr(new FSCHeartbeat(data)); + message = new FSCHeartbeat(); + break; case FSCMessageType::FSC_ACK: - return std::unique_ptr(new FSCACK(data)); + message = new FSCACK(); + break; case FSCMessageType::FSC_DISCONNECT: - return std::unique_ptr(new FSCDisconnect(data)); + message = new FSCDisconnect(); + break; default: - LogError(LOG_P25, "FSCMessage::create(), unknown message value, messageId = $%02X", messageId); + LogError(LOG_P25, "FSCMessage::createMessage(), unknown message value, messageId = $%02X", messageId); break; } - return nullptr; + if (!message->decode(data)) { + return nullptr; + } + + return std::unique_ptr(message); } diff --git a/src/common/p25/dfsi/frames/fsc/FSCMessage.h b/src/common/p25/dfsi/frames/fsc/FSCMessage.h index 2b5b6252..08398c7a 100644 --- a/src/common/p25/dfsi/frames/fsc/FSCMessage.h +++ b/src/common/p25/dfsi/frames/fsc/FSCMessage.h @@ -46,11 +46,6 @@ namespace p25 * @brief Initializes a copy instance of the FSCMessage class. */ FSCMessage(); - /** - * @brief Initializes a copy instance of the FSCMessage class. - * @param data Buffer to containing FSCMessage to decode. - */ - FSCMessage(const uint8_t* data); /** * @brief Decode a FSC message frame. diff --git a/src/common/p25/dfsi/frames/fsc/FSCResponse.cpp b/src/common/p25/dfsi/frames/fsc/FSCResponse.cpp deleted file mode 100644 index 4cf5b57d..00000000 --- a/src/common/p25/dfsi/frames/fsc/FSCResponse.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Common Library - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2024 Bryan Biedenkapp, N2PLL - * - */ -#include "common/p25/dfsi/frames/fsc/FSCResponse.h" -#include "common/p25/dfsi/DFSIDefines.h" -#include "common/Utils.h" -#include "common/Log.h" - -#include -#include - -using namespace p25::dfsi; -using namespace p25::dfsi::frames; -using namespace p25::dfsi::frames::fsc; - -// --------------------------------------------------------------------------- -// Public Class Members -// --------------------------------------------------------------------------- - -/* Initializes a instance of the FSCResponse class. */ - -FSCResponse::FSCResponse() : - m_version(1U) -{ - /* stub */ -} - -/* Initializes a instance of the FSCResponse class. */ - -FSCResponse::FSCResponse(const uint8_t* data) : - m_version(1U) -{ - decode(data); -} - -/* Decode a FSC message frame. */ - -bool FSCResponse::decode(const uint8_t* data) -{ - assert(data != nullptr); - - m_version = data[0U]; // Response Version - - return true; -} - -/* Encode a FSC message frame. */ - -void FSCResponse::encode(uint8_t* data) -{ - assert(data != nullptr); - - data[0U] = m_version; // Response Version -} diff --git a/src/common/p25/dfsi/frames/fsc/FSCResponse.h b/src/common/p25/dfsi/frames/fsc/FSCResponse.h deleted file mode 100644 index cb4cbf18..00000000 --- a/src/common/p25/dfsi/frames/fsc/FSCResponse.h +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Common Library - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2024 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file FSCResponse.h - * @ingroup dfsi_fsc_frames - * @file FSCResponse.cpp - * @ingroup dfsi_fsc_frames - */ -#if !defined(__FSC_RESPONSE_H__) -#define __FSC_RESPONSE_H__ - -#include "Defines.h" -#include "common/Defines.h" -#include "common/Log.h" -#include "common/Utils.h" -#include "common/p25/dfsi/frames/FrameDefines.h" - -namespace p25 -{ - namespace dfsi - { - namespace frames - { - namespace fsc - { - // --------------------------------------------------------------------------- - // Class Declaration - // --------------------------------------------------------------------------- - - /** - * @brief Base class FSC response messages derive from. - * @ingroup dfsi_fsc_frames - */ - class HOST_SW_API FSCResponse { - public: - static const uint8_t LENGTH = 1; - - /** - * @brief Initializes a copy instance of the FSCResponse class. - */ - FSCResponse(); - /** - * @brief Initializes a copy instance of the FSCResponse class. - * @param data Buffer to containing FSCResponse to decode. - */ - FSCResponse(const uint8_t* data); - - /** - * @brief Decode a FSC message frame. - * @param[in] data Buffer to containing FSCResponse to decode. - */ - virtual bool decode(const uint8_t* data); - /** - * @brief Encode a FSC message frame. - * @param[out] data Buffer to encode a FSCResponse. - */ - virtual void encode(uint8_t* data); - - public: - /** - * @brief Response Version. - */ - __PROTECTED_READONLY_PROPERTY(uint8_t, version, Version); - }; - } // namespace fsc - } // namespace frames - } // namespace dfsi -} // namespace p25 - -#endif // __FSC_RESPONSE_H__ \ No newline at end of file diff --git a/src/host/Host.Config.cpp b/src/host/Host.Config.cpp index 4f8318ad..007103f2 100644 --- a/src/host/Host.Config.cpp +++ b/src/host/Host.Config.cpp @@ -601,7 +601,7 @@ bool Host::createModem() } else { modemPort = new port::specialized::V24UDPPort(id, g_remoteAddress, g_remotePort, 0U, false, false, debug); } - m_udpDSFIRemotePort = modemPort; + m_udpDFSIRemotePort = modemPort; } else { modemPort = new port::UDPPort(g_remoteAddress, g_remotePort); } @@ -687,6 +687,11 @@ bool Host::createModem() m_modem->setResponseHandler(MODEM_RESP_HANDLER_BIND(Host::rmtPortModemHandler, this)); } + if (useFSCForUDP) { + modem::port::specialized::V24UDPPort* udpPort = dynamic_cast(m_udpDFSIRemotePort); + udpPort->openFSC(); + } + bool ret = m_modem->open(); if (!ret) { delete m_modem; diff --git a/src/host/Host.cpp b/src/host/Host.cpp index 012bb016..f1effa93 100644 --- a/src/host/Host.cpp +++ b/src/host/Host.cpp @@ -64,7 +64,7 @@ Host::Host(const std::string& confFile) : m_modem(nullptr), m_modemRemote(false), m_isModemDFSI(false), - m_udpDSFIRemotePort(nullptr), + m_udpDFSIRemotePort(nullptr), m_network(nullptr), m_modemRemotePort(nullptr), m_state(STATE_IDLE), @@ -945,10 +945,9 @@ int Host::run() } } - if (m_udpDSFIRemotePort != nullptr) { + if (m_udpDFSIRemotePort != nullptr) { m_mainLoopStage = 11U; // intentional magic number - modem::port::specialized::V24UDPPort* udpPort = dynamic_cast(m_udpDSFIRemotePort); - + modem::port::specialized::V24UDPPort* udpPort = dynamic_cast(m_udpDFSIRemotePort); udpPort->clock(ms); } @@ -1638,9 +1637,14 @@ void Host::setState(uint8_t state) m_modeTimer.stop(); - if (m_state == HOST_STATE_QUIT) { + if (state == HOST_STATE_QUIT) { ::LogInfoEx(LOG_HOST, "Host is shutting down"); + if (m_udpDFSIRemotePort != nullptr) { + modem::port::specialized::V24UDPPort* udpPort = dynamic_cast(m_udpDFSIRemotePort); + udpPort->closeFSC(); + } + if (m_modem != nullptr) { m_modem->close(); delete m_modem; diff --git a/src/host/Host.h b/src/host/Host.h index 50117cfa..f1aec2fb 100644 --- a/src/host/Host.h +++ b/src/host/Host.h @@ -99,7 +99,7 @@ private: modem::Modem* m_modem; bool m_modemRemote; bool m_isModemDFSI; - modem::port::IModemPort* m_udpDSFIRemotePort; + modem::port::IModemPort* m_udpDFSIRemotePort; network::Network* m_network; modem::port::IModemPort* m_modemRemotePort; diff --git a/src/host/modem/port/specialized/V24UDPPort.cpp b/src/host/modem/port/specialized/V24UDPPort.cpp index ed376d84..92cc7cec 100644 --- a/src/host/modem/port/specialized/V24UDPPort.cpp +++ b/src/host/modem/port/specialized/V24UDPPort.cpp @@ -65,13 +65,12 @@ V24UDPPort::V24UDPPort(uint32_t peerId, const std::string& address, uint16_t mod m_timeoutTimer(1000U, 30U), m_reqConnectionTimer(1000U, 30U), m_heartbeatTimer(1000U, 5U), - m_reqConnectionToPeer(true), - m_establishedConnection(false), m_random(), m_peerId(peerId), m_streamId(0U), m_timestamp(INVALID_TS), m_pktSeq(0U), + m_fscState(CS_NOT_CONNECTED), m_modemState(STATE_P25), m_tx(false), m_debug(debug) @@ -122,7 +121,7 @@ void V24UDPPort::clock(uint32_t ms) { // if we have a FSC control socket if (m_controlSocket != nullptr) { - if (!m_establishedConnection && m_fscInitiator) { + if ((m_fscState == CS_NOT_CONNECTED) && m_fscInitiator) { if (!m_reqConnectionTimer.isRunning()) { // make initial request writeConnect(); @@ -137,7 +136,7 @@ void V24UDPPort::clock(uint32_t ms) } } - if (m_establishedConnection) { + if (m_fscState == CS_CONNECTED) { m_heartbeatTimer.clock(ms); if (m_heartbeatTimer.isRunning() && m_heartbeatTimer.hasExpired()) { writeHeartbeat(); @@ -147,10 +146,12 @@ void V24UDPPort::clock(uint32_t ms) m_timeoutTimer.clock(ms); if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) { - LogError(LOG_NET, "DFSI connection to the remote endpoint has timed out, disconnected"); - m_reqConnectionTimer.stop(); - m_reqConnectionToPeer = true; - m_establishedConnection = false; + LogError(LOG_NET, "V.24 UDP, DFSI connection to the remote endpoint has timed out, disconnected"); + m_fscState = CS_NOT_CONNECTED; + if (!m_fscInitiator) + m_reqConnectionTimer.stop(); + else + m_reqConnectionTimer.start(); m_heartbeatTimer.stop(); m_timeoutTimer.stop(); } @@ -170,18 +171,34 @@ void V24UDPPort::reset() m_streamId = createStreamId(); } -/* Opens a connection to the port. */ +/* Opens a connection to the FSC port. */ -bool V24UDPPort::open() +bool V24UDPPort::openFSC() { - if (m_addrLen == 0U && m_ctrlAddrLen == 0U) { + if (m_ctrlAddrLen == 0U) { LogError(LOG_NET, "Unable to resolve the address of the modem"); return false; } if (m_controlSocket != nullptr) { return m_controlSocket->open(m_controlAddr); + } + + return false; +} + +/* Opens a connection to the port. */ + +bool V24UDPPort::open() +{ + if (m_controlSocket != nullptr) { + return true; // FSC mode always returns that the port was opened } else { + if (m_addrLen == 0U) { + LogError(LOG_NET, "Unable to resolve the address of the modem"); + return false; + } + if (m_socket != nullptr) { return m_socket->open(m_addr); } @@ -256,12 +273,33 @@ int V24UDPPort::write(const uint8_t* buffer, uint32_t length) return -1; } +/* Closes the connection to the FSC port. */ + +void V24UDPPort::closeFSC() +{ + if (m_controlSocket != nullptr) { + if (m_fscState == CS_CONNECTED) { + LogMessage(LOG_MODEM, "V.24 UDP, Closing DFSI FSC Connection, vcBasePort = %u", m_localPort); + + FSCDisconnect discoMessage = FSCDisconnect(); + + uint8_t buffer[FSCDisconnect::LENGTH]; + ::memset(buffer, 0x00U, FSCDisconnect::LENGTH); + discoMessage.encode(buffer); + + m_ctrlFrameQueue->write(buffer, FSCDisconnect::LENGTH, m_controlAddr, m_ctrlAddrLen); + + Thread::sleep(500U); + } + + m_controlSocket->close(); + } +} + /* Closes the connection to the port. */ void V24UDPPort::close() { - if (m_controlSocket != nullptr) - m_controlSocket->close(); if (m_socket != nullptr) m_socket->close(); } @@ -319,108 +357,157 @@ void* V24UDPPort::threadedCtrlNetworkRx(void* arg) } if (req->length > 0) { - if (network->m_reqConnectionToPeer && !network->m_establishedConnection) { - // FSC_CONNECT response -- is ... strange - if (req->buffer[0] == 1U) { - network->m_reqConnectionToPeer = false; - network->m_reqConnectionTimer.stop(); - network->m_establishedConnection = true; - - FSCConnectResponse resp = FSCConnectResponse(req->buffer); - uint16_t vcBasePort = resp.getVCBasePort(); - - network->m_localPort = vcBasePort; - network->createVCPort(vcBasePort); - network->m_socket->open(network->m_addr); - network->m_heartbeatTimer.start(); - network->m_timeoutTimer.start(); - - LogMessage(LOG_MODEM, "Established DFSI FSC Connection, vcBasePort = %u", vcBasePort); - - if (req->buffer != nullptr) - delete[] req->buffer; - delete req; - return nullptr; - } - } - std::unique_ptr message = FSCMessage::createMessage(req->buffer); if (message != nullptr) { - switch (message->getMessageId()) - { + switch (message->getMessageId()) { case FSCMessageType::FSC_ACK: - { - FSCACK* ackMessage = static_cast(message.get()); - switch (ackMessage->getResponseCode()) + { + FSCACK* ackMessage = static_cast(message.get()); + if (network->m_debug) + LogDebug(LOG_MODEM, "V.24 UDP, ACK, ackMessageId = $%02X, ackResponseCode = $%02X, respLength = %u", ackMessage->getAckMessageId(), ackMessage->getResponseCode(), ackMessage->getResponseLength()); + + switch (ackMessage->getResponseCode()) { + case FSCAckResponseCode::CONTROL_NAK: + case FSCAckResponseCode::CONTROL_NAK_CONNECTED: + case FSCAckResponseCode::CONTROL_NAK_M_UNSUPP: + case FSCAckResponseCode::CONTROL_NAK_V_UNSUPP: + case FSCAckResponseCode::CONTROL_NAK_F_UNSUPP: + case FSCAckResponseCode::CONTROL_NAK_PARMS: + case FSCAckResponseCode::CONTROL_NAK_BUSY: + LogError(LOG_MODEM, "V.24 UDP, ACK, ackMessageId = $%02X, ackResponseCode = $%02X", ackMessage->getAckMessageId(), ackMessage->getResponseCode()); + break; + + case FSCAckResponseCode::CONTROL_ACK: { - case FSCAckResponseCode::CONTROL_NAK: - case FSCAckResponseCode::CONTROL_NAK_CONNECTED: - case FSCAckResponseCode::CONTROL_NAK_M_UNSUPP: - case FSCAckResponseCode::CONTROL_NAK_V_UNSUPP: - case FSCAckResponseCode::CONTROL_NAK_F_UNSUPP: - case FSCAckResponseCode::CONTROL_NAK_PARMS: - case FSCAckResponseCode::CONTROL_NAK_BUSY: - LogError(LOG_MODEM, "V.24 UDP, ACK, ackMessageId = $%02X, ackResponseCode = $%02X", ackMessage->getAckMessageId(), ackMessage->getResponseCode()); + switch (ackMessage->getAckMessageId()) { + case FSCMessageType::FSC_CONNECT: + { + uint16_t vcBasePort = __GET_UINT16B(ackMessage->responseData, 1U); + + if (network->m_socket != nullptr) { + network->m_socket->close(); + delete network->m_socket; + network->m_socket = nullptr; + } + + network->m_localPort = vcBasePort; + network->createVCPort(vcBasePort); + network->m_socket->open(network->m_addr); + + network->m_fscState = CS_CONNECTED; + network->m_reqConnectionTimer.stop(); + network->m_heartbeatTimer.start(); + network->m_timeoutTimer.start(); + + LogMessage(LOG_MODEM, "V.24 UDP, Established DFSI FSC Connection, vcBasePort = %u", vcBasePort); + } break; - case FSCAckResponseCode::CONTROL_ACK: + case FSCMessageType::FSC_DISCONNECT: { - if (ackMessage->getAckMessageId() == FSCMessageType::FSC_DISCONNECT) { - network->m_reqConnectionTimer.stop(); - network->m_reqConnectionToPeer = true; - network->m_establishedConnection = false; - network->m_heartbeatTimer.stop(); - network->m_timeoutTimer.stop(); + if (network->m_socket != nullptr) { + network->m_socket->close(); + delete network->m_socket; + network->m_socket = nullptr; } + + network->m_fscState = CS_NOT_CONNECTED; + if (!network->m_fscInitiator) + network->m_reqConnectionTimer.stop(); + else + network->m_reqConnectionTimer.start(); + network->m_heartbeatTimer.stop(); + network->m_timeoutTimer.stop(); } break; - default: - LogError(LOG_MODEM, "V.24 UDP, unknown ACK opcode, ackMessageId = $%02X", ackMessage->getAckMessageId()); - break; + default: + break; + } } + break; + + default: + LogError(LOG_MODEM, "V.24 UDP, unknown ACK opcode, ackMessageId = $%02X", ackMessage->getAckMessageId()); + break; } - break; + } + break; case FSCMessageType::FSC_CONNECT: - { - if (network->m_socket != nullptr) { - network->m_socket->close(); - delete network->m_socket; - } + { + FSCConnect* connMessage = static_cast(message.get()); + FSCACK ackResp = FSCACK(); + ackResp.setCorrelationTag(connMessage->getCorrelationTag()); + ackResp.setAckMessageId(FSCMessageType::FSC_CONNECT); + ackResp.setResponseCode(FSCAckResponseCode::CONTROL_ACK); + ackResp.setAckCorrelationTag(connMessage->getCorrelationTag()); + + if (connMessage->getVersion() != 1U) { + ackResp.setResponseCode(FSCAckResponseCode::CONTROL_NAK_V_UNSUPP); + + uint8_t buffer[FSCACK::LENGTH]; + ::memset(buffer, 0x00U, FSCACK::LENGTH); + ackResp.encode(buffer); + + network->m_ctrlFrameQueue->write(buffer, FSCACK::LENGTH, network->m_controlAddr, network->m_ctrlAddrLen); + break; + } + + if (network->m_socket != nullptr) { + network->m_socket->close(); + delete network->m_socket; + network->m_socket = nullptr; + } - network->createVCPort(network->m_localPort); - network->m_socket->open(network->m_addr); + uint16_t vcPort = connMessage->getVCBasePort(); + network->m_localPort = vcPort; - network->m_reqConnectionToPeer = false; - network->m_reqConnectionTimer.stop(); - network->m_establishedConnection = true; - network->m_heartbeatTimer.start(); - network->m_timeoutTimer.start(); + network->createVCPort(network->m_localPort); + network->m_socket->open(network->m_addr); - LogMessage(LOG_MODEM, "Incoming DFSI FSC Connection, vcBasePort = %u", network->m_localPort); + network->m_fscState = CS_CONNECTED; + network->m_reqConnectionTimer.stop(); + network->m_heartbeatTimer.start(); + network->m_timeoutTimer.start(); - uint8_t buffer[FSCConnectResponse::LENGTH]; - ::memset(buffer, 0x00U, FSCConnectResponse::LENGTH); + LogMessage(LOG_MODEM, "V.24 UDP, Incoming DFSI FSC Connection, vcBasePort = %u", network->m_localPort); - FSCConnectResponse resp = FSCConnectResponse(); - resp.setVCBasePort(network->m_localPort); - resp.encode(buffer); + // construct connect ACK response data + uint8_t respData[3U]; + ::memset(respData, 0x00U, 3U); - network->m_ctrlFrameQueue->write(buffer, FSCConnectResponse::LENGTH, network->m_controlAddr, network->m_ctrlAddrLen); - } - break; + respData[0U] = 1U; // Version 1 + __SET_UINT16B(network->m_localPort, respData, 1U); + + // pack ack + ackResp.setResponseLength(3U); + ackResp.responseData = respData; + + uint8_t buffer[FSCACK::LENGTH + 3U]; + ::memset(buffer, 0x00U, FSCACK::LENGTH + 3U); + ackResp.encode(buffer); + + network->m_ctrlFrameQueue->write(buffer, FSCACK::LENGTH + 3U, network->m_controlAddr, network->m_ctrlAddrLen); + } + break; case FSCMessageType::FSC_DISCONNECT: - { - LogMessage(LOG_MODEM, "DFSI FSC Disconnect"); - network->m_reqConnectionTimer.stop(); - network->m_reqConnectionToPeer = true; - network->m_establishedConnection = false; - network->m_heartbeatTimer.stop(); - network->m_timeoutTimer.stop(); + { + LogMessage(LOG_MODEM, "V.24 UDP, DFSI FSC Disconnect, vcBasePort = %u", network->m_localPort); + + if (network->m_socket != nullptr) { + network->m_socket->close(); + delete network->m_socket; + network->m_socket = nullptr; } - break; + + network->m_fscState = CS_NOT_CONNECTED; + network->m_reqConnectionTimer.stop(); + network->m_heartbeatTimer.stop(); + network->m_timeoutTimer.stop(); + } + break; case FSCMessageType::FSC_HEARTBEAT: network->m_timeoutTimer.start(); @@ -560,7 +647,7 @@ void V24UDPPort::createVCPort(uint16_t port) void V24UDPPort::writeConnect() { - LogMessage(LOG_MODEM, "Attempting DFSI FSC Connection, peerId = %u, vcBasePort = %u", m_peerId, m_localPort); + LogMessage(LOG_MODEM, "V.24 UDP, Attempting DFSI FSC Connection, peerId = %u, vcBasePort = %u", m_peerId, m_localPort); FSCConnect connect = FSCConnect(); connect.setFSHeartbeatPeriod(5U); // hardcoded? @@ -573,6 +660,8 @@ void V24UDPPort::writeConnect() connect.encode(buffer); + m_fscState = CS_CONNECTING; + m_ctrlFrameQueue->write(buffer, FSCConnect::LENGTH, m_controlAddr, m_ctrlAddrLen); } diff --git a/src/host/modem/port/specialized/V24UDPPort.h b/src/host/modem/port/specialized/V24UDPPort.h index 6b2d8392..750f54cf 100644 --- a/src/host/modem/port/specialized/V24UDPPort.h +++ b/src/host/modem/port/specialized/V24UDPPort.h @@ -93,20 +93,25 @@ namespace modem void reset(); /** - * @brief Opens a connection to the serial port. + * @brief Opens a connection to the FSC port. + * @returns bool True, if connection is opened, otherwise false. + */ + bool openFSC(); + /** + * @brief Opens a connection to the port. * @returns bool True, if connection is opened, otherwise false. */ bool open() override; /** - * @brief Reads data from the serial port. + * @brief Reads data from the port. * @param[out] buffer Buffer to read data from the port to. * @param length Length of data to read from the port. * @returns int Actual length of data read from serial port. */ int read(uint8_t* buffer, uint32_t length) override; /** - * @brief Writes data to the serial port. + * @brief Writes data to the port. * @param[in] buffer Buffer containing data to write to port. * @param length Length of data to write to port. * @returns int Actual length of data written to the port. @@ -114,7 +119,11 @@ namespace modem int write(const uint8_t* buffer, uint32_t length) override; /** - * @brief Closes the connection to the serial port. + * @brief Closes the connection to the FSC port. + */ + void closeFSC(); + /** + * @brief Closes the connection to the port. */ void close() override; @@ -140,9 +149,6 @@ namespace modem Timer m_reqConnectionTimer; Timer m_heartbeatTimer; - bool m_reqConnectionToPeer; - bool m_establishedConnection; - std::mt19937 m_random; uint32_t m_peerId; @@ -151,6 +157,13 @@ namespace modem uint32_t m_timestamp; uint16_t m_pktSeq; + enum CS_STATE : uint8_t { + CS_NOT_CONNECTED = 0, + CS_CONNECTING = 1, + CS_CONNECTED = 2 + }; + CS_STATE m_fscState; + uint8_t m_modemState; bool m_tx;