diff --git a/src/common/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.cpp b/src/common/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.cpp index 5a09f95d..cdc0f34f 100644 --- a/src/common/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.cpp +++ b/src/common/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.cpp @@ -23,7 +23,10 @@ using namespace p25::lc::tsbk; /* Initializes a new instance of the OSP_GRP_VCH_GRANT_UPD class. */ -OSP_GRP_VCH_GRANT_UPD::OSP_GRP_VCH_GRANT_UPD() : TSBK() +OSP_GRP_VCH_GRANT_UPD::OSP_GRP_VCH_GRANT_UPD() : TSBK(), + m_grpVchIdB(0U), + m_grpVchNoB(0U), + m_dstIdB(0U) { m_lco = TSBKO::OSP_GRP_VCH_GRANT_UPD; } @@ -43,9 +46,12 @@ bool OSP_GRP_VCH_GRANT_UPD::decode(const uint8_t* data, bool rawTSBK) ulong64_t tsbkValue = TSBK::toValue(tsbk); - m_grpVchId = (uint8_t)((tsbkValue >> 60) & 0xFU); // Channel ID - m_grpVchNo = (uint32_t)((tsbkValue >> 48) & 0xFFFU); // Channel Number - m_dstId = (uint32_t)((tsbkValue >> 32) & 0xFFFFU); // Talkgroup Address + m_grpVchId = (uint8_t)((tsbkValue >> 60) & 0xFU); // Channel ID (A) + m_grpVchNo = (uint32_t)((tsbkValue >> 48) & 0xFFFU); // Channel Number (A) + m_dstId = (uint32_t)((tsbkValue >> 32) & 0xFFFFU); // Talkgroup Address (A) + m_grpVchIdB = (uint8_t)((tsbkValue >> 28) & 0xFU); // Channel ID (B) + m_grpVchNoB = (uint32_t)((tsbkValue >> 16) & 0xFFFU); // Channel Number (B) + m_dstIdB = (uint32_t)(tsbkValue & 0xFFFFU); // Talkgroup Address (B) return true; } @@ -59,14 +65,22 @@ void OSP_GRP_VCH_GRANT_UPD::encode(uint8_t* data, bool rawTSBK, bool noTrellis) ulong64_t tsbkValue = 0U; if (m_grpVchId != 0U) { - tsbkValue = m_grpVchId; // Channel ID + tsbkValue = m_grpVchId; // Channel ID (A) } else { - tsbkValue = m_siteData.channelId(); // Channel ID + tsbkValue = m_siteData.channelId(); // Channel ID (Site) } - tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number - tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address - tsbkValue = (tsbkValue << 32) + 0; + tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number (A) + tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address (A) + + if (m_grpVchIdB != 0U) { + tsbkValue = (tsbkValue << 4) + m_grpVchIdB; // Channel ID (B) + } + else { + tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID (Site) + } + tsbkValue = (tsbkValue << 12) + m_grpVchNoB; // Channel Number (A) + tsbkValue = (tsbkValue << 16) + m_dstIdB; // Talkgroup Address (B) std::unique_ptr tsbk = TSBK::fromValue(tsbkValue); TSBK::encode(data, tsbk.get(), rawTSBK, noTrellis); diff --git a/src/common/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h b/src/common/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h index 65fb5d62..f21a9f4c 100644 --- a/src/common/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h +++ b/src/common/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h @@ -60,6 +60,20 @@ namespace p25 * @returns std::string String representation of the TSBK. */ std::string toString(bool isp = false) override; + + public: + /** + * @brief Voice channel ID. + */ + __PROPERTY(uint8_t, grpVchIdB, GrpVchIdB); + /** + * @brief Voice channel number. + */ + __PROPERTY(uint32_t, grpVchNoB, GrpVchNoB); + /** + * @brief Destination ID. + */ + __PROPERTY(uint32_t, dstIdB, DstIdB); }; } // namespace tsbk } // namespace lc diff --git a/src/fne/network/callhandler/TagDMRData.cpp b/src/fne/network/callhandler/TagDMRData.cpp index de731038..a30826d1 100644 --- a/src/fne/network/callhandler/TagDMRData.cpp +++ b/src/fne/network/callhandler/TagDMRData.cpp @@ -30,6 +30,12 @@ using namespace dmr::defines; #include #include +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- + +const uint32_t CALL_COLL_TIMEOUT = 10U; + // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- @@ -193,6 +199,13 @@ bool TagDMRData::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId RxStatus status = it->second; if (streamId != status.streamId) { if (status.srcId != 0U && status.srcId != srcId) { + uint64_t lastPktDuration = hrc::diff(hrc::now(), status.lastPacket); + if ((lastPktDuration / 1000) > CALL_COLL_TIMEOUT) { + LogWarning(LOG_NET, "DMR, Call Collision, lasted more then %us with no further updates, forcibly ending call"); + m_status.erase(dstId); + m_network->m_callInProgress = false; + } + LogWarning(LOG_NET, "DMR, Call Collision, peer = %u, srcId = %u, dstId = %u, slotNo = %u, streamId = %u, rxPeer = %u, rxSrcId = %u, rxDstId = %u, rxSlotNo = %u, rxStreamId = %u, external = %u", peerId, srcId, dstId, slotNo, streamId, status.peerId, status.srcId, status.dstId, status.slotNo, status.streamId, external); return false; @@ -261,6 +274,8 @@ bool TagDMRData::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId return false; } + m_status[dstId].lastPacket = hrc::now(); + // repeat traffic to the connected peers if (m_network->m_peers.size() > 0U) { uint32_t i = 0U; diff --git a/src/fne/network/callhandler/TagDMRData.h b/src/fne/network/callhandler/TagDMRData.h index cba156c7..7d90afad 100644 --- a/src/fne/network/callhandler/TagDMRData.h +++ b/src/fne/network/callhandler/TagDMRData.h @@ -132,6 +132,7 @@ namespace network class RxStatus { public: system_clock::hrc::hrc_t callStartTime; + system_clock::hrc::hrc_t lastPacket; uint32_t srcId; uint32_t dstId; uint8_t slotNo; diff --git a/src/fne/network/callhandler/TagNXDNData.cpp b/src/fne/network/callhandler/TagNXDNData.cpp index 054d97c1..617395da 100644 --- a/src/fne/network/callhandler/TagNXDNData.cpp +++ b/src/fne/network/callhandler/TagNXDNData.cpp @@ -31,6 +31,12 @@ using namespace nxdn::defines; #include #include +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- + +const uint32_t CALL_COLL_TIMEOUT = 10U; + // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- @@ -153,6 +159,13 @@ bool TagNXDNData::processFrame(const uint8_t* data, uint32_t len, uint32_t peerI RxStatus status = m_status[dstId]; if (streamId != status.streamId) { if (status.srcId != 0U && status.srcId != srcId) { + uint64_t lastPktDuration = hrc::diff(hrc::now(), status.lastPacket); + if ((lastPktDuration / 1000) > CALL_COLL_TIMEOUT) { + LogWarning(LOG_NET, "NXDN, Call Collision, lasted more then %us with no further updates, forcibly ending call"); + m_status.erase(dstId); + m_network->m_callInProgress = false; + } + LogWarning(LOG_NET, "NXDN, Call Collision, peer = %u, srcId = %u, dstId = %u, streamId = %u, rxPeer = %u, rxSrcId = %u, rxDstId = %u, rxStreamId = %u, external = %u", peerId, srcId, dstId, streamId, status.peerId, status.srcId, status.dstId, status.streamId, external); return false; @@ -214,6 +227,8 @@ bool TagNXDNData::processFrame(const uint8_t* data, uint32_t len, uint32_t peerI } } + m_status[dstId].lastPacket = hrc::now(); + // repeat traffic to the connected peers if (m_network->m_peers.size() > 0U) { uint32_t i = 0U; diff --git a/src/fne/network/callhandler/TagNXDNData.h b/src/fne/network/callhandler/TagNXDNData.h index 31acd50a..003235f1 100644 --- a/src/fne/network/callhandler/TagNXDNData.h +++ b/src/fne/network/callhandler/TagNXDNData.h @@ -110,6 +110,7 @@ namespace network class RxStatus { public: system_clock::hrc::hrc_t callStartTime; + system_clock::hrc::hrc_t lastPacket; uint32_t srcId; uint32_t dstId; uint32_t streamId; diff --git a/src/fne/network/callhandler/TagP25Data.cpp b/src/fne/network/callhandler/TagP25Data.cpp index e05622ca..eb62b7e3 100644 --- a/src/fne/network/callhandler/TagP25Data.cpp +++ b/src/fne/network/callhandler/TagP25Data.cpp @@ -33,6 +33,7 @@ using namespace p25::defines; // --------------------------------------------------------------------------- const uint32_t GRANT_TIMER_TIMEOUT = 15U; +const uint32_t CALL_COLL_TIMEOUT = 10U; // --------------------------------------------------------------------------- // Public Class Members @@ -224,6 +225,13 @@ bool TagP25Data::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId RxStatus status = m_status[dstId]; if (streamId != status.streamId && ((duid != DUID::TDU) && (duid != DUID::TDULC))) { if (status.srcId != 0U && status.srcId != srcId) { + uint64_t lastPktDuration = hrc::diff(hrc::now(), status.lastPacket); + if ((lastPktDuration / 1000) > CALL_COLL_TIMEOUT) { + LogWarning(LOG_NET, "P25, Call Collision, lasted more then %us with no further updates, forcibly ending call"); + m_status.erase(dstId); + m_network->m_callInProgress = false; + } + LogWarning(LOG_NET, "P25, Call Collision, peer = %u, srcId = %u, dstId = %u, streamId = %u, rxPeer = %u, rxSrcId = %u, rxDstId = %u, rxStreamId = %u, external = %u", peerId, srcId, dstId, streamId, status.peerId, status.srcId, status.dstId, status.streamId, external); return false; @@ -290,6 +298,8 @@ bool TagP25Data::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId return false; } + m_status[dstId].lastPacket = hrc::now(); + // repeat traffic to the connected peers if (m_network->m_peers.size() > 0U) { uint32_t i = 0U; diff --git a/src/fne/network/callhandler/TagP25Data.h b/src/fne/network/callhandler/TagP25Data.h index d4852e31..429c6400 100644 --- a/src/fne/network/callhandler/TagP25Data.h +++ b/src/fne/network/callhandler/TagP25Data.h @@ -160,6 +160,7 @@ namespace network class RxStatus { public: system_clock::hrc::hrc_t callStartTime; + system_clock::hrc::hrc_t lastPacket; uint32_t srcId; uint32_t dstId; uint32_t streamId;