From 8c48c9bcbebd1181c8f90cc6cbb30ab131d5f4df Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sat, 8 Feb 2025 20:36:43 -0500 Subject: [PATCH] fix huge glaring bug where the dvmhost was trying to transmit TDULCs across the network as TSBKs; implement proper support to transit TDULC data across the network; --- src/common/network/BaseNetwork.cpp | 51 +++++++++++++++++++++- src/common/network/BaseNetwork.h | 23 +++++++++- src/fne/network/callhandler/TagP25Data.cpp | 25 +++++++++++ src/host/p25/packet/ControlSignaling.cpp | 2 +- src/host/p25/packet/Voice.cpp | 4 +- 5 files changed, 101 insertions(+), 4 deletions(-) diff --git a/src/common/network/BaseNetwork.cpp b/src/common/network/BaseNetwork.cpp index f5235b39..cdfa4e16 100644 --- a/src/common/network/BaseNetwork.cpp +++ b/src/common/network/BaseNetwork.cpp @@ -5,7 +5,7 @@ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX - * Copyright (C) 2020-2024 Bryan Biedenkapp, N2PLL + * Copyright (C) 2020-2025 Bryan Biedenkapp, N2PLL * Copyright (C) 2024 Caleb, KO4UYJ * */ @@ -572,6 +572,26 @@ bool BaseNetwork::writeP25TSDU(const p25::lc::LC& control, const uint8_t* data) return writeMaster({ NET_FUNC::PROTOCOL, NET_SUBFUNC::PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, RTP_END_OF_CALL_SEQ, m_p25StreamId); } +/* Writes P25 TDULC frame data to the network. */ + +bool BaseNetwork::writeP25TDULC(const p25::lc::LC& control, const uint8_t* data) +{ + if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING) + return false; + + if (m_p25StreamId == 0U) { + m_p25StreamId = createStreamId(); + } + + uint32_t messageLength = 0U; + UInt8Array message = createP25_TDULCMessage(messageLength, control, data); + if (message == nullptr) { + return false; + } + + return writeMaster({ NET_FUNC::PROTOCOL, NET_SUBFUNC::PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, RTP_END_OF_CALL_SEQ, m_p25StreamId); +} + /* Writes P25 PDU frame data to the network. */ bool BaseNetwork::writeP25PDU(const p25::data::DataHeader& header, const uint8_t currentBlock, const uint8_t* data, @@ -1025,6 +1045,35 @@ UInt8Array BaseNetwork::createP25_TSDUMessage(uint32_t& length, const p25::lc::L return UInt8Array(buffer); } +/* Creates an P25 TDULC frame message. */ + +UInt8Array BaseNetwork::createP25_TDULCMessage(uint32_t& length, const p25::lc::LC& control, const uint8_t* data) +{ + using namespace p25::defines; + assert(data != nullptr); + + uint8_t* buffer = new uint8_t[P25_TDULC_PACKET_LENGTH + PACKET_PAD]; + ::memset(buffer, 0x00U, P25_TDULC_PACKET_LENGTH + PACKET_PAD); + + // construct P25 message header + p25::data::LowSpeedData lsd = p25::data::LowSpeedData(); + createP25_MessageHdr(buffer, DUID::TDULC, control, lsd, FrameType::TERMINATOR); + + // pack raw P25 TSDU bytes + uint32_t count = MSG_HDR_SIZE; + + ::memcpy(buffer + 24U, data, P25_TDULC_FRAME_LENGTH_BYTES); + count += P25_TDULC_FRAME_LENGTH_BYTES; + + buffer[23U] = count; + + if (m_debug) + Utils::dump(1U, "Network Message, P25 TDULC", buffer, (P25_TDULC_PACKET_LENGTH + PACKET_PAD)); + + length = (P25_TDULC_PACKET_LENGTH + PACKET_PAD); + return UInt8Array(buffer); +} + /* Writes P25 PDU frame data to the network. */ UInt8Array BaseNetwork::createP25_PDUMessage(uint32_t& length, const p25::data::DataHeader& header, diff --git a/src/common/network/BaseNetwork.h b/src/common/network/BaseNetwork.h index c3a6b26e..8919b8c5 100644 --- a/src/common/network/BaseNetwork.h +++ b/src/common/network/BaseNetwork.h @@ -5,7 +5,7 @@ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright (C) 2015,2016,2017,2018 Jonathan Naylor, G4KLX - * Copyright (C) 2020-2024 Bryan Biedenkapp, N2PLL + * Copyright (C) 2020-2025 Bryan Biedenkapp, N2PLL * */ /** @@ -84,6 +84,7 @@ namespace network const uint32_t P25_LDU1_PACKET_LENGTH = 193U; // 24 byte header + DFSI data + 1 byte frame type + 12 byte enc sync const uint32_t P25_LDU2_PACKET_LENGTH = 181U; // 24 byte header + DFSI data + 1 byte frame type const uint32_t P25_TSDU_PACKET_LENGTH = 69U; // 24 byte header + TSDU data + const uint32_t P25_TDULC_PACKET_LENGTH = 78U; // 24 byte header + TDULC data /** * @brief Network Peer Connection Status @@ -381,6 +382,13 @@ namespace network * @returns bool True, if message was sent, otherwise false. */ virtual bool writeP25TSDU(const p25::lc::LC& control, const uint8_t* data); + /** + * @brief Writes P25 TDULC frame data to the network. + * @param[in] control Instance of p25::lc::LC containing link control data. + * @param[in] data Buffer containing P25 TDULC data to send. + * @returns bool True, if message was sent, otherwise false. + */ + virtual bool writeP25TDULC(const p25::lc::LC& control, const uint8_t* data); /** * @brief Writes P25 PDU frame data to the network. * @param[in] dataHeader Instance of p25::data::DataHeader containing PDU header data. @@ -634,6 +642,19 @@ namespace network */ UInt8Array createP25_TSDUMessage(uint32_t& length, const p25::lc::LC& control, const uint8_t* data); + /** + * @brief Creates an P25 TDULC frame message. + * + * The data packed into a P25 TDULC frame message is essentially just a message header with the FEC encoded + * raw TDULC data. + * + * @param[out] length Length of network message buffer. + * @param[in] control Instance of p25::lc::LC containing link control data. + * @param[in] data Buffer containing P25 TDULC data to send. + * @returns UInt8Array Buffer containing the built network message. + */ + UInt8Array createP25_TDULCMessage(uint32_t& length, const p25::lc::LC& control, const uint8_t* data); + /** * @brief Creates an P25 PDU frame message. * \code{.unparsed} diff --git a/src/fne/network/callhandler/TagP25Data.cpp b/src/fne/network/callhandler/TagP25Data.cpp index f0c35540..bd5c188f 100644 --- a/src/fne/network/callhandler/TagP25Data.cpp +++ b/src/fne/network/callhandler/TagP25Data.cpp @@ -9,6 +9,7 @@ */ #include "fne/Defines.h" #include "common/p25/lc/tsbk/TSBKFactory.h" +#include "common/p25/lc/tdulc/TDULCFactory.h" #include "common/p25/Sync.h" #include "common/Clock.h" #include "common/Log.h" @@ -764,6 +765,30 @@ bool TagP25Data::processTSDUFrom(uint8_t* buffer, uint32_t peerId, uint8_t duid) } } + // are we receiving a TDULC? + if (duid == DUID::TDULC) { + uint32_t frameLength = buffer[23U]; + + UInt8Array data = std::unique_ptr(new uint8_t[frameLength]); + ::memset(data.get(), 0x00U, frameLength); + ::memcpy(data.get(), buffer + 24U, frameLength); + + std::unique_ptr tdulc = lc::tdulc::TDULCFactory::createTDULC(data.get()); + if (tdulc != nullptr) { + // handle standard P25 reference opcodes + switch (tdulc->getLCO()) { + case LCO::CALL_TERM: + return false; // discard call terms at the FNE + default: + break; + } + } else { + // bryanb: should these be logged? + //std::string peerIdentity = m_network->resolvePeerIdentity(peerId); + //LogWarning(LOG_NET, "PEER %u (%s), passing TDULC that failed to decode? tdulc == nullptr", peerId, peerIdentity.c_str()); + } + } + return true; } diff --git a/src/host/p25/packet/ControlSignaling.cpp b/src/host/p25/packet/ControlSignaling.cpp index 58f694d8..9cd38c29 100644 --- a/src/host/p25/packet/ControlSignaling.cpp +++ b/src/host/p25/packet/ControlSignaling.cpp @@ -1355,7 +1355,7 @@ void ControlSignaling::writeNetworkRF(lc::TDULC* tduLc, const uint8_t* data, boo lc.setSrcId(tduLc->getSrcId()); lc.setDstId(tduLc->getDstId()); - m_p25->m_network->writeP25TSDU(lc, data); + m_p25->m_network->writeP25TDULC(lc, data); if (autoReset) m_p25->m_network->resetP25(); } diff --git a/src/host/p25/packet/Voice.cpp b/src/host/p25/packet/Voice.cpp index 5106a8f8..5141d2ec 100644 --- a/src/host/p25/packet/Voice.cpp +++ b/src/host/p25/packet/Voice.cpp @@ -1358,7 +1358,6 @@ bool Voice::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L // currently ignored -- this is a TODO break; case DUID::TDU: - case DUID::TDULC: // ignore a TDU that doesn't contain our destination ID if (control.getDstId() != m_p25->m_netLastDstId) { return false; @@ -1385,6 +1384,9 @@ bool Voice::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L resetNet(); } break; + case DUID::TDULC: + // currently ignored + break; default: break;