From eba4db610445a7293fabd5893e1114416a3a799c Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Mon, 15 Jan 2024 00:37:00 -0500 Subject: [PATCH] refactor RTP code slightly to better handle tracking the RTP timestamp properly; --- src/common/network/BaseNetwork.cpp | 53 ++++++++++++++++++----- src/common/network/BaseNetwork.h | 8 ++-- src/common/network/FrameQueue.cpp | 46 ++++++++++++++++++-- src/common/network/FrameQueue.h | 8 +++- src/common/network/RTPFNEHeader.h | 2 + src/common/network/RTPHeader.cpp | 13 +----- src/common/network/RTPHeader.h | 4 -- src/fne/network/FNENetwork.cpp | 26 ++++++----- src/host/dmr/Slot.cpp | 10 +++-- src/host/dmr/Slot.h | 4 +- src/host/dmr/packet/ControlSignaling.cpp | 4 +- src/host/network/Network.cpp | 13 ++++-- src/host/nxdn/Control.cpp | 2 +- src/host/nxdn/packet/ControlSignaling.cpp | 4 +- src/host/p25/Control.cpp | 1 - src/host/p25/packet/Data.cpp | 13 +++--- src/host/p25/packet/Data.h | 4 +- 17 files changed, 148 insertions(+), 67 deletions(-) diff --git a/src/common/network/BaseNetwork.cpp b/src/common/network/BaseNetwork.cpp index 6ffc6533..93afec03 100644 --- a/src/common/network/BaseNetwork.cpp +++ b/src/common/network/BaseNetwork.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX -* Copyright (C) 2020-2023 by Bryan Biedenkapp N2PLL +* Copyright (C) 2020-2024 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,7 @@ */ #include "Defines.h" #include "common/dmr/DMRDefines.h" +#include "common/nxdn/NXDNDefines.h" #include "common/p25/dfsi/DFSIDefines.h" #include "common/p25/dfsi/LC.h" #include "edac/SHA256.h" @@ -301,8 +302,9 @@ UInt8Array BaseNetwork::readDMR(bool& ret, uint32_t& frameLength) /// Writes DMR frame data to the network. /// /// +/// /// -bool BaseNetwork::writeDMR(const dmr::data::Data& data) +bool BaseNetwork::writeDMR(const dmr::data::Data& data, bool noSequence) { if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING) return false; @@ -336,7 +338,16 @@ bool BaseNetwork::writeDMR(const dmr::data::Data& data) return false; } - return writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_DMR }, message.get(), messageLength, pktSeq(resetSeq), m_dmrStreamId[slotIndex]); + uint16_t seq = pktSeq(resetSeq); + if (dataType == dmr::DT_TERMINATOR_WITH_LC) { + seq = RTP_END_OF_CALL_SEQ; + } + + if (noSequence) { + seq = RTP_END_OF_CALL_SEQ; + } + + return writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_DMR }, message.get(), messageLength, seq, m_dmrStreamId[slotIndex]); } /// @@ -463,7 +474,12 @@ bool BaseNetwork::writeP25TDU(const p25::lc::LC& control, const p25::data::LowSp return false; } - return writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, pktSeq(resetSeq), m_p25StreamId); + uint16_t seq = pktSeq(resetSeq); + if (controlByte == 0x00U) { + seq = RTP_END_OF_CALL_SEQ; + } + + return writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, seq, m_p25StreamId); } /// @@ -489,7 +505,7 @@ bool BaseNetwork::writeP25TSDU(const p25::lc::LC& control, const uint8_t* data) return false; } - return writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, pktSeq(resetSeq), m_p25StreamId); + return writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, RTP_END_OF_CALL_SEQ, m_p25StreamId); } /// @@ -499,9 +515,10 @@ bool BaseNetwork::writeP25TSDU(const p25::lc::LC& control, const uint8_t* data) /// /// /// +/// /// bool BaseNetwork::writeP25PDU(const p25::data::DataHeader& header, const uint8_t currentBlock, const uint8_t* data, - const uint32_t len) + const uint32_t len, bool lastBlock) { if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING) return false; @@ -518,7 +535,12 @@ bool BaseNetwork::writeP25PDU(const p25::data::DataHeader& header, const uint8_t return false; } - return writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, pktSeq(resetSeq), m_p25StreamId); + uint16_t seq = pktSeq(resetSeq); + if (lastBlock) { + seq = RTP_END_OF_CALL_SEQ; + } + + return writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, seq, m_p25StreamId); } /// @@ -572,8 +594,9 @@ UInt8Array BaseNetwork::readNXDN(bool& ret, uint32_t& frameLength) /// /// /// +/// /// -bool BaseNetwork::writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const uint32_t len) +bool BaseNetwork::writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const uint32_t len, bool noSequence) { if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING) return false; @@ -590,7 +613,17 @@ bool BaseNetwork::writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const return false; } - return writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_NXDN }, message.get(), messageLength, pktSeq(resetSeq), m_nxdnStreamId); + uint16_t seq = pktSeq(resetSeq); + if (lc.getMessageType() == nxdn::RTCH_MESSAGE_TYPE_TX_REL || + lc.getMessageType() == nxdn::RTCH_MESSAGE_TYPE_TX_REL_EX) { + seq = RTP_END_OF_CALL_SEQ; + } + + if (noSequence) { + seq = RTP_END_OF_CALL_SEQ; + } + + return writeMaster({ NET_FUNC_PROTOCOL, NET_PROTOCOL_SUBFUNC_NXDN }, message.get(), messageLength, seq, m_nxdnStreamId); } /// @@ -622,7 +655,7 @@ uint16_t BaseNetwork::pktSeq(bool reset) uint16_t curr = m_pktSeq; ++m_pktSeq; - if (m_pktSeq > UINT16_MAX) { + if (m_pktSeq >= RTP_END_OF_CALL_SEQ - 1U) { m_pktSeq = 0U; } diff --git a/src/common/network/BaseNetwork.h b/src/common/network/BaseNetwork.h index 75320698..4d9b444d 100644 --- a/src/common/network/BaseNetwork.h +++ b/src/common/network/BaseNetwork.h @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX -* Copyright (C) 2020-2023 by Bryan Biedenkapp N2PLL +* Copyright (C) 2020-2024 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -191,7 +191,7 @@ namespace network /// Reads DMR raw frame data from the DMR ring buffer. virtual UInt8Array readDMR(bool& ret, uint32_t& frameLength); /// Writes DMR frame data to the network. - virtual bool writeDMR(const dmr::data::Data& data); + virtual bool writeDMR(const dmr::data::Data& data, bool noSequence = false); /// Helper to test if the DMR ring buffer has data. bool hasDMRData() const; @@ -210,7 +210,7 @@ namespace network virtual bool writeP25TSDU(const p25::lc::LC& control, const uint8_t* data); /// Writes P25 PDU frame data to the network. virtual bool writeP25PDU(const p25::data::DataHeader& header, const uint8_t currentBlock, const uint8_t* data, - const uint32_t len); + const uint32_t len, bool lastBlock); /// Helper to test if the P25 ring buffer has data. bool hasP25Data() const; @@ -219,7 +219,7 @@ namespace network /// Reads NXDN raw frame data from the NXDN ring buffer. virtual UInt8Array readNXDN(bool& ret, uint32_t& frameLength); /// Writes NXDN frame data to the network. - virtual bool writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const uint32_t len); + virtual bool writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const uint32_t len, bool noSequence = false); /// Helper to test if the NXDN ring buffer has data. bool hasNXDNData() const; diff --git a/src/common/network/FrameQueue.cpp b/src/common/network/FrameQueue.cpp index 1af0ddd8..6298667e 100644 --- a/src/common/network/FrameQueue.cpp +++ b/src/common/network/FrameQueue.cpp @@ -7,7 +7,7 @@ * */ /* -* Copyright (C) 2023 by Bryan Biedenkapp N2PLL +* Copyright (C) 2023-2024 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,7 +51,8 @@ using namespace network::frame; /// Local port used to listen for incoming data. /// Unique ID of this modem on the network. FrameQueue::FrameQueue(UDPSocket* socket, uint32_t peerId, bool debug) : RawFrameQueue(socket, debug), - m_peerId(peerId) + m_peerId(peerId), + m_streamTimestamps() { assert(peerId < 999999999U); } @@ -189,6 +190,21 @@ void FrameQueue::enqueueMessage(const uint8_t* message, uint32_t length, uint32_ assert(message != nullptr); assert(length > 0U); + uint32_t timestamp = INVALID_TS; + if (streamId != 0U) { + auto entry = m_streamTimestamps.find(streamId); + if (entry != m_streamTimestamps.end()) { + timestamp = entry->second; + } + + if (timestamp != INVALID_TS) { + timestamp += (RTP_GENERIC_CLOCK_RATE / 133); + if (m_debug) + LogDebug(LOG_NET, "FrameQueue::enqueueMessage() RTP streamId = %u, previous TS = %u, TS = %u, rtpSeq = %u", streamId, m_streamTimestamps[streamId], timestamp, rtpSeq); + m_streamTimestamps[streamId] = timestamp; + } + } + uint32_t bufferLen = RTP_HEADER_LENGTH_BYTES + RTP_EXTENSION_HEADER_LENGTH_BYTES + RTP_FNE_HEADER_LENGTH_BYTES + length; uint8_t* buffer = new uint8_t[bufferLen]; ::memset(buffer, 0x00U, bufferLen); @@ -197,6 +213,7 @@ void FrameQueue::enqueueMessage(const uint8_t* message, uint32_t length, uint32_ header.setExtension(true); header.setPayloadType(DVM_RTP_PAYLOAD_TYPE); + header.setTimestamp(timestamp); header.setSequence(rtpSeq); header.setSSRC(ssrc); @@ -208,6 +225,21 @@ void FrameQueue::enqueueMessage(const uint8_t* message, uint32_t length, uint32_ header.encode(buffer); + if (streamId != 0U && timestamp == INVALID_TS && rtpSeq != RTP_END_OF_CALL_SEQ) { + if (m_debug) + LogDebug(LOG_NET, "FrameQueue::enqueueMessage() RTP streamId = %u, initial TS = %u, rtpSeq = %u", streamId, header.getTimestamp(), rtpSeq); + m_streamTimestamps[streamId] = header.getTimestamp(); + } + + if (streamId != 0U && rtpSeq == RTP_END_OF_CALL_SEQ) { + auto entry = m_streamTimestamps.find(streamId); + if (entry != m_streamTimestamps.end()) { + if (m_debug) + LogDebug(LOG_NET, "FrameQueue::enqueueMessage() RTP streamId = %u, rtpSeq = %u", streamId, rtpSeq); + m_streamTimestamps.erase(streamId); + } + } + RTPFNEHeader fneHeader = RTPFNEHeader(); fneHeader.setCRC(edac::CRC::createCRC16(message, length * 8U)); fneHeader.setStreamId(streamId); @@ -224,7 +256,7 @@ void FrameQueue::enqueueMessage(const uint8_t* message, uint32_t length, uint32_ if (m_debug) Utils::dump(1U, "FrameQueue::enqueueMessage() Buffered Message", buffer, bufferLen); - UDPDatagram* dgram = new UDPDatagram; + UDPDatagram *dgram = new UDPDatagram; dgram->buffer = buffer; dgram->length = bufferLen; dgram->address = addr; @@ -232,3 +264,11 @@ void FrameQueue::enqueueMessage(const uint8_t* message, uint32_t length, uint32_ m_buffers.push_back(dgram); } + +/// +/// Helper method to clear any tracked stream timestamps. +/// +void FrameQueue::clearTimestamps() +{ + m_streamTimestamps.clear(); +} diff --git a/src/common/network/FrameQueue.h b/src/common/network/FrameQueue.h index 5b8209ba..ba8c4d87 100644 --- a/src/common/network/FrameQueue.h +++ b/src/common/network/FrameQueue.h @@ -7,7 +7,7 @@ * */ /* -* Copyright (C) 2023 by Bryan Biedenkapp N2PLL +* Copyright (C) 2023-2024 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,6 +31,8 @@ #include "common/network/RTPFNEHeader.h" #include "common/network/RawFrameQueue.h" +#include + namespace network { // --------------------------------------------------------------------------- @@ -64,8 +66,12 @@ namespace network void enqueueMessage(const uint8_t* message, uint32_t length, uint32_t streamId, uint32_t peerId, uint32_t ssrc, OpcodePair opcode, uint16_t rtpSeq, sockaddr_storage& addr, uint32_t addrLen); + /// Helper method to clear any tracked stream timestamps. + void clearTimestamps(); + private: uint32_t m_peerId; + std::unordered_map m_streamTimestamps; }; } // namespace network diff --git a/src/common/network/RTPFNEHeader.h b/src/common/network/RTPFNEHeader.h index 2d56df8c..6042abbd 100644 --- a/src/common/network/RTPFNEHeader.h +++ b/src/common/network/RTPFNEHeader.h @@ -40,6 +40,8 @@ #define RTP_FNE_HEADER_LENGTH_BYTES 16 #define RTP_FNE_HEADER_LENGTH_EXT_LEN 4 +#define RTP_END_OF_CALL_SEQ 65535 + namespace network { namespace frame diff --git a/src/common/network/RTPHeader.cpp b/src/common/network/RTPHeader.cpp index 0df754ff..62d9b1c5 100644 --- a/src/common/network/RTPHeader.cpp +++ b/src/common/network/RTPHeader.cpp @@ -38,7 +38,6 @@ using namespace network::frame; // --------------------------------------------------------------------------- hrc::hrc_t RTPHeader::m_wcStart = hrc::hrc_t(); -uint32_t RTPHeader::m_prevTimestamp = INVALID_TS; // --------------------------------------------------------------------------- // Public Class Members @@ -57,9 +56,7 @@ RTPHeader::RTPHeader() : m_timestamp(INVALID_TS), m_ssrc(0U) { - std::random_device rd; - std::mt19937 mt(rd()); - m_random = mt; + /* stub */ } /// @@ -114,15 +111,10 @@ void RTPHeader::encode(uint8_t* data) data[2U] = (m_seq >> 8) & 0xFFU; // Sequence MSB data[3U] = (m_seq >> 0) & 0xFFU; // Sequence LSB - if (m_prevTimestamp == INVALID_TS) { + if (m_timestamp == INVALID_TS) { uint64_t timeSinceStart = hrc::diffNow(m_wcStart); uint64_t microSeconds = timeSinceStart * RTP_GENERIC_CLOCK_RATE; m_timestamp = uint32_t(microSeconds / 1000000); - m_prevTimestamp = m_timestamp; - } - else { - m_timestamp = m_prevTimestamp + (RTP_GENERIC_CLOCK_RATE / 133); - m_prevTimestamp = m_timestamp; } __SET_UINT32(m_timestamp, data, 4U); // Timestamp @@ -135,5 +127,4 @@ void RTPHeader::encode(uint8_t* data) void RTPHeader::resetStartTime() { m_wcStart = hrc::hrc_t(); - m_prevTimestamp = INVALID_TS; } diff --git a/src/common/network/RTPHeader.h b/src/common/network/RTPHeader.h index cf15d516..adc8bb24 100644 --- a/src/common/network/RTPHeader.h +++ b/src/common/network/RTPHeader.h @@ -29,7 +29,6 @@ #include "common/Defines.h" #include -#include #include // --------------------------------------------------------------------------- @@ -87,9 +86,6 @@ namespace network private: static std::chrono::time_point m_wcStart; - static uint32_t m_prevTimestamp; - - std::mt19937 m_random; }; } // namespace frame } // namespace network diff --git a/src/fne/network/FNENetwork.cpp b/src/fne/network/FNENetwork.cpp index d0bd4f98..332d71ee 100644 --- a/src/fne/network/FNENetwork.cpp +++ b/src/fne/network/FNENetwork.cpp @@ -166,6 +166,7 @@ void FNENetwork::clock(uint32_t ms) // roll the RTP timestamp if no call is in progress if (!m_callInProgress) { frame::RTPHeader::resetStartTime(); + m_frameQueue->clearTimestamps(); } m_maintainenceTimer.start(); @@ -206,15 +207,20 @@ void FNENetwork::clock(uint32_t ms) uint16_t pktSeq = rtpHeader.getSequence(); if (connection != nullptr) { - if ((connection->currStreamId() == streamId) && (pktSeq != connection->pktNextSeq())) { - LogWarning(LOG_NET, "PEER %u Stream %u out-of-sequence; %u != %u", peerId, streamId, pktSeq, connection->pktNextSeq()); - } - - connection->currStreamId(streamId); - connection->pktLastSeq(pktSeq); - connection->pktNextSeq(pktSeq + 1); - if (connection->pktNextSeq() > UINT16_MAX) { + if (pktSeq == RTP_END_OF_CALL_SEQ) { + connection->pktLastSeq(pktSeq); connection->pktNextSeq(0U); + } else { + if ((connection->currStreamId() == streamId) && (pktSeq != connection->pktNextSeq())) { + LogWarning(LOG_NET, "PEER %u Stream %u out-of-sequence; %u != %u", peerId, streamId, pktSeq, connection->pktNextSeq()); + } + + connection->currStreamId(streamId); + connection->pktLastSeq(pktSeq); + connection->pktNextSeq(pktSeq + 1); + if (connection->pktNextSeq() > UINT16_MAX) { + connection->pktNextSeq(0U); + } } } @@ -1048,7 +1054,7 @@ bool FNENetwork::writePeerACK(uint32_t peerId, const uint8_t* data, uint32_t len ::memcpy(buffer + 6U, data, length); } - return writePeer(peerId, { NET_FUNC_ACK, NET_SUBFUNC_NOP }, buffer, length + 10U, 0U, false, true); + return writePeer(peerId, { NET_FUNC_ACK, NET_SUBFUNC_NOP }, buffer, length + 10U, RTP_END_OF_CALL_SEQ, false, true); } /// @@ -1067,7 +1073,7 @@ bool FNENetwork::writePeerNAK(uint32_t peerId, const char* tag) __SET_UINT32(peerId, buffer, 6U); // Peer ID LogWarning(LOG_NET, "%s from unauth PEER %u", tag, peerId); - return writePeer(peerId, { NET_FUNC_NAK, NET_SUBFUNC_NOP }, buffer, 10U, 0U, false, true); + return writePeer(peerId, { NET_FUNC_NAK, NET_SUBFUNC_NOP }, buffer, 10U, RTP_END_OF_CALL_SEQ, false, true); } /// diff --git a/src/host/dmr/Slot.cpp b/src/host/dmr/Slot.cpp index 3152c8d3..3688368e 100644 --- a/src/host/dmr/Slot.cpp +++ b/src/host/dmr/Slot.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015,2016,2017,2018 Jonathan Naylor, G4KLX -* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2024 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1158,7 +1158,8 @@ void Slot::notifyCC_TouchGrant(uint32_t dstId) /// /// /// -void Slot::writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t errors) +/// +void Slot::writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t errors, bool noSequence) { assert(data != nullptr); assert(m_rfLC != nullptr); @@ -1175,8 +1176,9 @@ void Slot::writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t errors) /// /// /// +/// void Slot::writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t flco, uint32_t srcId, - uint32_t dstId, uint8_t errors) + uint32_t dstId, uint8_t errors, bool noSequence) { assert(data != nullptr); @@ -1201,7 +1203,7 @@ void Slot::writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t flco, uin dmrData.setData(data + 2U); - m_network->writeDMR(dmrData); + m_network->writeDMR(dmrData, noSequence); } /// diff --git a/src/host/dmr/Slot.h b/src/host/dmr/Slot.h index 3b36576c..869462a3 100644 --- a/src/host/dmr/Slot.h +++ b/src/host/dmr/Slot.h @@ -292,10 +292,10 @@ namespace dmr void notifyCC_TouchGrant(uint32_t dstId); /// Write data frame to the network. - void writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t errors = 0U); + void writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t errors = 0U, bool noSequence = false); /// Write data frame to the network. void writeNetwork(const uint8_t* data, uint8_t dataType, uint8_t flco, uint32_t srcId, - uint32_t dstId, uint8_t errors = 0U); + uint32_t dstId, uint8_t errors = 0U, bool noSequence = false); /// Helper to write RF end of frame data. void writeEndRF(bool writeEnd = false); diff --git a/src/host/dmr/packet/ControlSignaling.cpp b/src/host/dmr/packet/ControlSignaling.cpp index d8725fb9..f0233029 100644 --- a/src/host/dmr/packet/ControlSignaling.cpp +++ b/src/host/dmr/packet/ControlSignaling.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015,2016,2017,2018 Jonathan Naylor, G4KLX -* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2024 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -394,7 +394,7 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) if (m_slot->m_duplex) m_slot->addFrame(data); - m_slot->writeNetwork(data, DT_CSBK, gi ? FLCO_GROUP : FLCO_PRIVATE, srcId, dstId); + m_slot->writeNetwork(data, DT_CSBK, gi ? FLCO_GROUP : FLCO_PRIVATE, srcId, dstId, 0U, true); } return true; diff --git a/src/host/network/Network.cpp b/src/host/network/Network.cpp index b212c9dc..b91f9546 100644 --- a/src/host/network/Network.cpp +++ b/src/host/network/Network.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX -* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2024 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -295,6 +295,11 @@ void Network::clock(uint32_t ms) } m_pktSeq = rtpHeader.getSequence(); + + if (m_pktSeq == RTP_END_OF_CALL_SEQ) { + m_pktSeq = 0U; + m_pktLastSeq = 0U; + } // process incoming message frame opcodes switch (fneHeader.getFunction()) { @@ -732,7 +737,7 @@ bool Network::writeConfig() rcon["port"].set(m_restApiPort); // REST API Port config["rcon"].set(rcon); - config["software"].set(std::string(software)); // Software ID + config["software"].set(std::string(software)); // Software ID json::value v = json::value(config); std::string json = v.serialize(); @@ -746,7 +751,7 @@ bool Network::writeConfig() Utils::dump(1U, "Network Message, Configuration", (uint8_t*)buffer, json.length() + 8U); } - return writeMaster({ NET_FUNC_RPTC, NET_SUBFUNC_NOP }, (uint8_t*)buffer, json.length() + 8U, pktSeq(), m_loginStreamId); + return writeMaster({ NET_FUNC_RPTC, NET_SUBFUNC_NOP }, (uint8_t*)buffer, json.length() + 8U, RTP_END_OF_CALL_SEQ, m_loginStreamId); } /// @@ -760,5 +765,5 @@ bool Network::writePing() if (m_debug) Utils::dump(1U, "Network Message, Ping", buffer, 11U); - return writeMaster({ NET_FUNC_PING, NET_SUBFUNC_NOP }, buffer, 1U, 0U, createStreamId()); + return writeMaster({ NET_FUNC_PING, NET_SUBFUNC_NOP }, buffer, 1U, RTP_END_OF_CALL_SEQ, createStreamId()); } diff --git a/src/host/nxdn/Control.cpp b/src/host/nxdn/Control.cpp index 7223bec8..c4baae04 100644 --- a/src/host/nxdn/Control.cpp +++ b/src/host/nxdn/Control.cpp @@ -1217,5 +1217,5 @@ void Control::writeEndNet() m_networkWatchdog.stop(); if (m_network != nullptr) - m_network->resetP25(); + m_network->resetNXDN(); } diff --git a/src/host/nxdn/packet/ControlSignaling.cpp b/src/host/nxdn/packet/ControlSignaling.cpp index b9d03c9e..c93677d4 100644 --- a/src/host/nxdn/packet/ControlSignaling.cpp +++ b/src/host/nxdn/packet/ControlSignaling.cpp @@ -11,7 +11,7 @@ // Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0) // /* -* Copyright (C) 2022-2023 by Bryan Biedenkapp N2PLL +* Copyright (C) 2022-2024 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -371,7 +371,7 @@ void ControlSignaling::writeNetwork(const uint8_t *data, uint32_t len) if (m_nxdn->m_rfTimeout.isRunning() && m_nxdn->m_rfTimeout.hasExpired()) return; - m_nxdn->m_network->writeNXDN(m_nxdn->m_rfLC, data, len); + m_nxdn->m_network->writeNXDN(m_nxdn->m_rfLC, data, len, true); } /* diff --git a/src/host/p25/Control.cpp b/src/host/p25/Control.cpp index f8280594..b9481633 100644 --- a/src/host/p25/Control.cpp +++ b/src/host/p25/Control.cpp @@ -1408,7 +1408,6 @@ void Control::processFrameLoss() writeRF_TDU(false); m_voice->m_lastDUID = P25_DUID_TDU; - //m_voice->writeNetwork(data + 2U, P25_DUID_TDU); m_voice->writeNet_TDU(); m_rfState = RS_RF_LISTENING; diff --git a/src/host/p25/packet/Data.cpp b/src/host/p25/packet/Data.cpp index 45788ac9..a8d56997 100644 --- a/src/host/p25/packet/Data.cpp +++ b/src/host/p25/packet/Data.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX -* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2024 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -185,7 +185,7 @@ bool Data::process(uint8_t* data, uint32_t len) if ((m_rfDataHeader.getFormat() != PDU_FMT_AMBT) && (m_rfDataHeader.getFormat() != PDU_FMT_RSP) && (m_rfDataHeader.getSAP() != PDU_SAP_REG)) { - writeNetwork(0, buffer, P25_PDU_FEC_LENGTH_BYTES); + writeNetwork(0U, buffer, P25_PDU_FEC_LENGTH_BYTES, false); } } @@ -225,7 +225,7 @@ bool Data::process(uint8_t* data, uint32_t len) if ((m_rfDataHeader.getFormat() != PDU_FMT_AMBT) && (m_rfDataHeader.getFormat() != PDU_FMT_RSP) && (m_rfDataHeader.getSAP() != PDU_SAP_REG)) { - writeNetwork(1, buffer, P25_PDU_FEC_LENGTH_BYTES); + writeNetwork(1U, buffer, P25_PDU_FEC_LENGTH_BYTES, false); } offset += P25_PDU_FEC_LENGTH_BITS; @@ -292,7 +292,7 @@ bool Data::process(uint8_t* data, uint32_t len) if ((m_rfDataHeader.getFormat() != PDU_FMT_AMBT) && (m_rfDataHeader.getFormat() != PDU_FMT_RSP) && (m_rfDataHeader.getSAP() != PDU_SAP_REG)) { - writeNetwork(m_rfDataBlockCnt, buffer, P25_PDU_FEC_LENGTH_BYTES); + writeNetwork(m_rfDataBlockCnt, buffer, P25_PDU_FEC_LENGTH_BYTES, m_rfData[i].getLastBlock()); } m_rfDataBlockCnt++; @@ -874,7 +874,8 @@ Data::~Data() /// /// /// -void Data::writeNetwork(const uint8_t currentBlock, const uint8_t *data, uint32_t len) +/// +void Data::writeNetwork(const uint8_t currentBlock, const uint8_t *data, uint32_t len, bool lastBlock) { assert(data != nullptr); @@ -886,7 +887,7 @@ void Data::writeNetwork(const uint8_t currentBlock, const uint8_t *data, uint32_ // Utils::dump(1U, "Outgoing Network PDU Frame", data, len); - m_p25->m_network->writeP25PDU(m_rfDataHeader, currentBlock, data, len); + m_p25->m_network->writeP25PDU(m_rfDataHeader, currentBlock, data, len, lastBlock); } /// diff --git a/src/host/p25/packet/Data.h b/src/host/p25/packet/Data.h index f8d2a34d..727a6a4f 100644 --- a/src/host/p25/packet/Data.h +++ b/src/host/p25/packet/Data.h @@ -12,7 +12,7 @@ // /* * Copyright (C) 2016,2017 by Jonathan Naylor G4KLX -* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2024 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -124,7 +124,7 @@ namespace p25 ~Data(); /// Write data processed from RF to the network. - void writeNetwork(const uint8_t currentBlock, const uint8_t* data, uint32_t len); + void writeNetwork(const uint8_t currentBlock, const uint8_t* data, uint32_t len, bool lastBlock); /// Helper to write a P25 PDU packet. void writeRF_PDU(const uint8_t* pdu, uint32_t bitLength, bool noNulls = false);