Skip to content

Commit

Permalink
refactor FSC (it was entirely just broken);
Browse files Browse the repository at this point in the history
  • Loading branch information
gatekeep committed Jan 7, 2025
1 parent 88dcb0b commit 19d8f22
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 89 deletions.
6 changes: 4 additions & 2 deletions configs/config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -590,8 +590,10 @@ system:
jitter: 200
# Timer which will reset local/remote call flags if frames aren't received longer than this time in ms
callTimeout: 200
# Flag indicating when operating in V.24 UDP mode should the FSC protocol be used to negotiate connection.
useFSC: false
# Flag indicating when operating in V.24 UDP mode, the FSC protocol should be used to negotiate connection.
fsc: false
# Flag indicating when operating in V.24 UDP mode, this instance should initiate the FSC protocol handshake.
initiator: false

# Sets received the signal offset from DC.
rxDCOffset: 0 # Valid values between -128 and 128
Expand Down
2 changes: 1 addition & 1 deletion src/common/p25/dfsi/frames/fsc/FSCACK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ FSCACK::FSCACK(const uint8_t* data) : FSCMessage(data),
m_responseCode(FSCAckResponseCode::CONTROL_ACK),
m_respLength(0U)
{
decode(data);
FSCACK::decode(data);
}

/* Decode a FSC ACK frame. */
Expand Down
2 changes: 1 addition & 1 deletion src/common/p25/dfsi/frames/fsc/FSCConnect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ FSCConnect::FSCConnect(const uint8_t* data) : FSCMessage(data),
m_fsHeartbeatPeriod(5U),
m_hostHeartbeatPeriod(5U)
{
decode(data);
FSCConnect::decode(data);
}

/* Decode a FSC connect frame. */
Expand Down
2 changes: 1 addition & 1 deletion src/common/p25/dfsi/frames/fsc/FSCConnectResponse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ FSCConnectResponse::FSCConnectResponse() : FSCResponse(),
FSCConnectResponse::FSCConnectResponse(const uint8_t* data) : FSCResponse(data),
m_vcBasePort(0U)
{
decode(data);
FSCConnectResponse::decode(data);
}

/* Decode a FSC connect frame. */
Expand Down
4 changes: 2 additions & 2 deletions src/common/p25/dfsi/frames/fsc/FSCDisconnect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* 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
* Copyright (C) 2024-2025 Bryan Biedenkapp, N2PLL
*
*/
#include "common/p25/dfsi/frames/fsc/FSCDisconnect.h"
Expand Down Expand Up @@ -34,5 +34,5 @@ FSCDisconnect::FSCDisconnect() : FSCMessage()

FSCDisconnect::FSCDisconnect(const uint8_t* data) : FSCMessage(data)
{
decode(data);
FSCMessage::decode(data);
}
4 changes: 2 additions & 2 deletions src/common/p25/dfsi/frames/fsc/FSCHeartbeat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* 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
* Copyright (C) 2024-2025 Bryan Biedenkapp, N2PLL
*
*/
#include "common/p25/dfsi/frames/fsc/FSCHeartbeat.h"
Expand Down Expand Up @@ -34,5 +34,5 @@ FSCHeartbeat::FSCHeartbeat() : FSCMessage()

FSCHeartbeat::FSCHeartbeat(const uint8_t* data) : FSCMessage(data)
{
decode(data);
/* stub */
}
2 changes: 1 addition & 1 deletion src/common/p25/dfsi/frames/fsc/FSCMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ namespace p25
/**
* @brief
*/
__PROTECTED_READONLY_PROPERTY(uint8_t, correlationTag, CorrelationTag);
__PROPERTY(uint8_t, correlationTag, CorrelationTag);
};
} // namespace fsc
} // namespace frames
Expand Down
11 changes: 7 additions & 4 deletions src/host/Host.Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @package DVM / Modem Host Software
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
*
* Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL
* Copyright (C) 2017-2025 Bryan Biedenkapp, N2PLL
*
*/
#include "Defines.h"
Expand Down Expand Up @@ -461,8 +461,9 @@ bool Host::createModem()
bool rtrt = dfsiParams["rtrt"].as<bool>(true);
bool diu = dfsiParams["diu"].as<bool>(true);
uint16_t jitter = dfsiParams["jitter"].as<uint16_t>(200U);
bool useFSCForUDP = dfsiParams["useFSC"].as<bool>(false);
uint16_t dfsiCallTimeout = dfsiParams["callTimeout"].as<uint16_t>(200U);
bool useFSCForUDP = dfsiParams["fsc"].as<bool>(false);
bool fscInitiator = dfsiParams["initiator"].as<bool>(false);

// clamp fifo sizes
if (dmrFifoLength < DMR_TX_BUFFER_LEN) {
Expand Down Expand Up @@ -580,6 +581,7 @@ bool Host::createModem()
LogInfo(" DFSI Jitter Size: %u ms", jitter);
if (g_remoteModemMode) {
LogInfo(" DFSI Use FSC: %s", useFSCForUDP ? "yes" : "no");
LogInfo(" DFSI FSC Initiator: %s", fscInitiator ? "yes" : "no");
}
}

Expand All @@ -594,9 +596,10 @@ bool Host::createModem()
if (modemMode == MODEM_MODE_DFSI) {
yaml::Node networkConf = m_conf["network"];
uint32_t id = networkConf["id"].as<uint32_t>(1000U);
modemPort = new port::specialized::V24UDPPort(id, g_remoteAddress, g_remotePort, 0U, useFSCForUDP, debug);
if (useFSCForUDP) {
modemPort = new port::specialized::V24UDPPort(id, g_remoteAddress, g_remotePort + 1U, g_remotePort, useFSCForUDP, debug);
modemPort = new port::specialized::V24UDPPort(id, g_remoteAddress, g_remotePort + 1U, g_remotePort, true, fscInitiator, debug);
} else {
modemPort = new port::specialized::V24UDPPort(id, g_remoteAddress, g_remotePort, 0U, false, false, debug);
}
m_udpDSFIRemotePort = modemPort;
} else {
Expand Down
174 changes: 100 additions & 74 deletions src/host/modem/port/specialized/V24UDPPort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ std::mutex V24UDPPort::m_bufferMutex;

/* Initializes a new instance of the V24UDPPort class. */

V24UDPPort::V24UDPPort(uint32_t peerId, const std::string& address, uint16_t modemPort, uint16_t controlPort, bool useFSC, bool debug) :
V24UDPPort::V24UDPPort(uint32_t peerId, const std::string& address, uint16_t modemPort, uint16_t controlPort, bool useFSC, bool fscInitiator, bool debug) :
m_socket(nullptr),
m_localPort(modemPort),
m_controlSocket(nullptr),
Expand All @@ -61,6 +61,8 @@ V24UDPPort::V24UDPPort(uint32_t peerId, const std::string& address, uint16_t mod
m_addrLen(0U),
m_ctrlAddrLen(0U),
m_buffer(2000U, "UDP Port Ring Buffer"),
m_fscInitiator(fscInitiator),
m_timeoutTimer(1000U, 30U),
m_reqConnectionTimer(1000U, 30U),
m_heartbeatTimer(1000U, 5U),
m_reqConnectionToPeer(true),
Expand Down Expand Up @@ -120,7 +122,7 @@ void V24UDPPort::clock(uint32_t ms)
{
// if we have a FSC control socket
if (m_controlSocket != nullptr) {
if (m_reqConnectionToPeer) {
if (!m_establishedConnection && m_fscInitiator) {
if (!m_reqConnectionTimer.isRunning()) {
// make initial request
writeConnect();
Expand All @@ -130,6 +132,7 @@ void V24UDPPort::clock(uint32_t ms)
if (m_reqConnectionTimer.isRunning() && m_reqConnectionTimer.hasExpired()) {
// make another request
writeConnect();
m_reqConnectionTimer.start();
}
}
}
Expand All @@ -142,6 +145,16 @@ void V24UDPPort::clock(uint32_t ms)
}
}

m_timeoutTimer.clock(ms);
if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) {
LogError(LOG_NET, "PEER %u connection to the DFSI endpoint has timed out, disconnected");
m_reqConnectionTimer.stop();
m_reqConnectionToPeer = true;
m_establishedConnection = false;
m_heartbeatTimer.stop();
m_timeoutTimer.stop();
}

processCtrlNetwork();
}

Expand Down Expand Up @@ -268,7 +281,7 @@ void V24UDPPort::processCtrlNetwork()
// read message
UInt8Array buffer = m_ctrlFrameQueue->read(length, address, addrLen);
if (length > 0) {
if (m_debug)
//if (m_debug)
Utils::dump(1U, "FSC Control Network Message", buffer.get(), length);

V24PacketRequest* req = new V24PacketRequest();
Expand Down Expand Up @@ -299,14 +312,16 @@ void* V24UDPPort::threadedCtrlNetworkRx(void* arg)
::pthread_detach(req->thread);
#endif // defined(_WIN32)

uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();

V24UDPPort* network = static_cast<V24UDPPort*>(req->obj);
if (network == nullptr) {
delete req;
return nullptr;
}

if (req->length > 0) {
if (network->m_reqConnectionToPeer) {
if (network->m_reqConnectionToPeer && !network->m_establishedConnection) {
// FSC_CONNECT response -- is ... strange
if (req->buffer[0] == 1U) {
network->m_reqConnectionToPeer = false;
Expand All @@ -319,91 +334,100 @@ void* V24UDPPort::threadedCtrlNetworkRx(void* arg)
network->m_localPort = vcBasePort;
network->createVCPort(vcBasePort);
network->m_heartbeatTimer.start();
network->m_timeoutTimer.start();

uint8_t buffer[FSCConnectResponse::LENGTH];
::memset(buffer, 0x00U, FSCConnectResponse::LENGTH);

resp.setVCBasePort(network->m_localPort);
resp.encode(buffer);
LogMessage(LOG_MODEM, "Established DFSI FSC Connection, vcBasePort = %u", vcBasePort);

network->m_ctrlFrameQueue->write(buffer, FSCConnectResponse::LENGTH, network->m_controlAddr, network->m_ctrlAddrLen);
if (req->buffer != nullptr)
delete[] req->buffer;
delete req;
return nullptr;
}
}
else
{
std::unique_ptr<FSCMessage> message = FSCMessage::createMessage(req->buffer);
if (message != nullptr) {
switch (message->getMessageId())
{
case FSCMessageType::FSC_ACK:

std::unique_ptr<FSCMessage> message = FSCMessage::createMessage(req->buffer);
if (message != nullptr) {
switch (message->getMessageId())
{
case FSCMessageType::FSC_ACK:
{
FSCACK* ackMessage = static_cast<FSCACK*>(message.get());
switch (ackMessage->getResponseCode())
{
FSCACK* ackMessage = static_cast<FSCACK*>(message.get());
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:
{
if (ackMessage->getAckMessageId() == FSCMessageType::FSC_DISCONNECT) {
network->m_reqConnectionTimer.stop();
network->m_reqConnectionToPeer = false;
network->m_establishedConnection = false;
network->m_heartbeatTimer.stop();
}
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:
{
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();
}
break;
}
break;

default:
LogError(LOG_MODEM, "V.24 UDP, unknown ACK opcode, ackMessageId = $%02X", ackMessage->getAckMessageId());
break;
}
default:
LogError(LOG_MODEM, "V.24 UDP, unknown ACK opcode, ackMessageId = $%02X", ackMessage->getAckMessageId());
break;
}
}
break;

case FSCMessageType::FSC_CONNECT:
{
if (network->m_socket != nullptr) {
network->m_socket->close();
delete network->m_socket;
}
break;

case FSCMessageType::FSC_CONNECT:
{
network->createVCPort(network->m_localPort);
network->m_heartbeatTimer.start();
network->createVCPort(network->m_localPort);

uint8_t buffer[FSCConnectResponse::LENGTH];
::memset(buffer, 0x00U, FSCConnectResponse::LENGTH);
network->m_reqConnectionToPeer = false;
network->m_reqConnectionTimer.stop();
network->m_establishedConnection = true;
network->m_heartbeatTimer.start();
network->m_timeoutTimer.start();

FSCConnectResponse resp = FSCConnectResponse(req->buffer);
resp.setVCBasePort(network->m_localPort);
resp.encode(buffer);
LogMessage(LOG_MODEM, "Incoming DFSI FSC Connection, vcBasePort = %u", network->m_localPort);

network->m_ctrlFrameQueue->write(buffer, FSCConnectResponse::LENGTH, network->m_controlAddr, network->m_ctrlAddrLen);
}
break;
uint8_t buffer[FSCConnectResponse::LENGTH];
::memset(buffer, 0x00U, FSCConnectResponse::LENGTH);

case FSCMessageType::FSC_DISCONNECT:
{
network->m_reqConnectionTimer.stop();
network->m_reqConnectionToPeer = false;
network->m_establishedConnection = false;
network->m_heartbeatTimer.stop();
}
break;
FSCConnectResponse resp = FSCConnectResponse();
resp.setVCBasePort(network->m_localPort);
resp.encode(buffer);

case FSCMessageType::FSC_HEARTBEAT:
{
if (network->m_establishedConnection) {
network->writeHeartbeat();
}
}
break;
network->m_ctrlFrameQueue->write(buffer, FSCConnectResponse::LENGTH, 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();
}
break;

default:
break;
}
case FSCMessageType::FSC_HEARTBEAT:
network->m_timeoutTimer.start();
break;

default:
break;
}
}
}
Expand Down Expand Up @@ -536,6 +560,8 @@ void V24UDPPort::createVCPort(uint16_t port)

void V24UDPPort::writeConnect()
{
LogMessage(LOG_MODEM, "Attempting DFSI FSC Connection, peerId = %u, vcBasePort = %u", m_peerId, m_localPort);

FSCConnect connect = FSCConnect();
connect.setFSHeartbeatPeriod(5U); // hardcoded?
connect.setHostHeartbeatPeriod(5U); // hardcoded?
Expand Down
Loading

0 comments on commit 19d8f22

Please sign in to comment.