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);

82-dvmbridge---implement-notch-filter-for-2175hz-trc-guard-tone
Bryan Biedenkapp 1 year ago
parent ff0a5c57c7
commit da3a2a1869

@ -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"

@ -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);
}
}

@ -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.
*/

@ -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)

@ -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.

@ -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 <cassert>
#include <cstring>
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
}

@ -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__

@ -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);
}

@ -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

@ -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 */
}

@ -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

@ -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> 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<FSCMessage>(new FSCConnect(data));
message = new FSCConnect();
break;
case FSCMessageType::FSC_HEARTBEAT:
return std::unique_ptr<FSCMessage>(new FSCHeartbeat(data));
message = new FSCHeartbeat();
break;
case FSCMessageType::FSC_ACK:
return std::unique_ptr<FSCMessage>(new FSCACK(data));
message = new FSCACK();
break;
case FSCMessageType::FSC_DISCONNECT:
return std::unique_ptr<FSCMessage>(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<FSCMessage>(message);
}

@ -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.

@ -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 <cassert>
#include <cstring>
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
}

@ -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__

@ -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<modem::port::specialized::V24UDPPort*>(m_udpDFSIRemotePort);
udpPort->openFSC();
}
bool ret = m_modem->open();
if (!ret) {
delete m_modem;

@ -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<modem::port::specialized::V24UDPPort*>(m_udpDSFIRemotePort);
modem::port::specialized::V24UDPPort* udpPort = dynamic_cast<modem::port::specialized::V24UDPPort*>(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<modem::port::specialized::V24UDPPort*>(m_udpDFSIRemotePort);
udpPort->closeFSC();
}
if (m_modem != nullptr) {
m_modem->close();
delete m_modem;

@ -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;

@ -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<FSCMessage> message = FSCMessage::createMessage(req->buffer);
if (message != nullptr) {
switch (message->getMessageId())
{
switch (message->getMessageId()) {
case FSCMessageType::FSC_ACK:
{
FSCACK* ackMessage = static_cast<FSCACK*>(message.get());
switch (ackMessage->getResponseCode())
{
FSCACK* ackMessage = static_cast<FSCACK*>(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<FSCConnect*>(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);
}

@ -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;

Loading…
Cancel
Save

Powered by TurnKey Linux.