diff --git a/configs/fne-config.example.yml b/configs/fne-config.example.yml index 2218f6c2..eb44d760 100644 --- a/configs/fne-config.example.yml +++ b/configs/fne-config.example.yml @@ -139,6 +139,8 @@ master: parrotGrantDemand: true # Flag indicating whether or not a parrot TG call will only be sent to the originating peer. parrotOnlyToOrginiatingPeer: false + # Source ID to override parrot TG calls with (0 for no override). + parrotOverrideSrcId: 0 # Flag indicating whether or not P25 OTAR KMF services are enabled. kmfServicesEnabled: false diff --git a/src/fne/network/FNENetwork.cpp b/src/fne/network/FNENetwork.cpp index 04ad185d..e607ec0f 100644 --- a/src/fne/network/FNENetwork.cpp +++ b/src/fne/network/FNENetwork.cpp @@ -86,6 +86,7 @@ FNENetwork::FNENetwork(HostFNE* host, const std::string& address, uint16_t port, m_parrotDelayTimer(1000U, 0U, parrotDelay), m_parrotGrantDemand(parrotGrantDemand), m_parrotOnlyOriginating(false), + m_parrotOverrideSrcId(0U), m_kmfServicesEnabled(false), m_ridLookup(nullptr), m_tidLookup(nullptr), @@ -240,6 +241,11 @@ void FNENetwork::setOptions(yaml::Node& conf, bool printOptions) } m_parrotOnlyOriginating = conf["parrotOnlyToOrginiatingPeer"].as(false); + m_parrotOverrideSrcId = conf["parrotOverrideSrcId"].as(0U); + if (m_parrotOverrideSrcId > 0U && m_parrotOverrideSrcId > 16777200U) { + LogWarning(LOG_MASTER, "Parrot Override Source ID %u is out of valid range (1 - 16777200), disabling override.", m_parrotOverrideSrcId); + m_parrotOverrideSrcId = 0U; + } // jitter buffer configuration yaml::Node jitterConf = conf["jitterBuffer"]; @@ -378,6 +384,9 @@ void FNENetwork::setOptions(yaml::Node& conf, bool printOptions) LogInfo(" Global Jitter Buffer Default Max Wait: %u microseconds", m_jitterMaxWait); } LogInfo(" Parrot Repeat to Only Originating Peer: %s", m_parrotOnlyOriginating ? "yes" : "no"); + if (m_parrotOverrideSrcId != 0U) { + LogInfo(" Parrot Repeat Source ID Override: %u", m_parrotOverrideSrcId); + } LogInfo(" P25 OTAR KMF Services Enabled: %s", m_kmfServicesEnabled ? "yes" : "no"); LogInfo(" P25 OTAR KMF Listening Address: %s", m_address.c_str()); LogInfo(" P25 OTAR KMF Listening Port: %u", kmfOtarPort); diff --git a/src/fne/network/FNENetwork.h b/src/fne/network/FNENetwork.h index e2ea4274..1d2a1974 100644 --- a/src/fne/network/FNENetwork.h +++ b/src/fne/network/FNENetwork.h @@ -323,6 +323,7 @@ namespace network Timer m_parrotDelayTimer; bool m_parrotGrantDemand; bool m_parrotOnlyOriginating; + uint32_t m_parrotOverrideSrcId; bool m_kmfServicesEnabled; diff --git a/src/fne/network/callhandler/TagAnalogData.cpp b/src/fne/network/callhandler/TagAnalogData.cpp index bbde7737..1773c4ce 100644 --- a/src/fne/network/callhandler/TagAnalogData.cpp +++ b/src/fne/network/callhandler/TagAnalogData.cpp @@ -441,6 +441,14 @@ void TagAnalogData::playbackParrot() auto& pkt = m_parrotFrames[0]; m_parrotFrames.lock(); if (pkt.buffer != nullptr) { + // has the override source ID been set? + if (m_network->m_parrotOverrideSrcId > 0U) { + pkt.srcId = m_network->m_parrotOverrideSrcId; + + // override source ID + SET_UINT24(m_network->m_parrotOverrideSrcId, pkt.buffer, 5U); + } + m_lastParrotPeerId = pkt.peerId; m_lastParrotSrcId = pkt.srcId; m_lastParrotDstId = pkt.dstId; diff --git a/src/fne/network/callhandler/TagDMRData.cpp b/src/fne/network/callhandler/TagDMRData.cpp index 697dac72..53941353 100644 --- a/src/fne/network/callhandler/TagDMRData.cpp +++ b/src/fne/network/callhandler/TagDMRData.cpp @@ -691,6 +691,21 @@ void TagDMRData::playbackParrot() auto& pkt = m_parrotFrames[0]; m_parrotFrames.lock(); if (pkt.buffer != nullptr) { + // has the override source ID been set? + if (m_network->m_parrotOverrideSrcId > 0U) { + pkt.srcId = m_network->m_parrotOverrideSrcId; + + // override source ID + SET_UINT24(m_network->m_parrotOverrideSrcId, pkt.buffer, 5U); + + /* + ** bryanb: DMR is problematic because the VOICE_LC_HEADER, TERMINATOR_WITH_LC, + ** and VOICE_PI_HEADER all contain the source ID in the LC portion of the frame + ** and because we are not updating that the parrot playback will appear to come from + ** the original source ID in those frames + */ + } + m_lastParrotPeerId = pkt.peerId; m_lastParrotSrcId = pkt.srcId; m_lastParrotDstId = pkt.dstId; diff --git a/src/fne/network/callhandler/TagNXDNData.cpp b/src/fne/network/callhandler/TagNXDNData.cpp index 243cd754..4a6d3eb8 100644 --- a/src/fne/network/callhandler/TagNXDNData.cpp +++ b/src/fne/network/callhandler/TagNXDNData.cpp @@ -720,6 +720,14 @@ void TagNXDNData::playbackParrot() auto& pkt = m_parrotFrames[0]; m_parrotFrames.lock(); if (pkt.buffer != nullptr) { + // has the override source ID been set? + if (m_network->m_parrotOverrideSrcId > 0U) { + pkt.srcId = m_network->m_parrotOverrideSrcId; + + // override source ID + SET_UINT24(m_network->m_parrotOverrideSrcId, pkt.buffer, 5U); + } + m_lastParrotPeerId = pkt.peerId; m_lastParrotSrcId = pkt.srcId; m_lastParrotDstId = pkt.dstId; diff --git a/src/fne/network/callhandler/TagP25Data.cpp b/src/fne/network/callhandler/TagP25Data.cpp index 41bd7a36..346db37e 100644 --- a/src/fne/network/callhandler/TagP25Data.cpp +++ b/src/fne/network/callhandler/TagP25Data.cpp @@ -802,6 +802,15 @@ void TagP25Data::playbackParrot() auto& pkt = m_parrotFrames[0]; m_parrotFrames.lock(); if (pkt.buffer != nullptr) { + // has the override source ID been set? + if (m_network->m_parrotOverrideSrcId > 0U) { + pkt.srcId = m_network->m_parrotOverrideSrcId; + + // override source ID + SET_UINT24(m_network->m_parrotOverrideSrcId, pkt.buffer, 5U); + } + + // is this the first parrot frame? if (m_parrotFirstFrame) { if (m_network->m_parrotGrantDemand) { uint32_t srcId = pkt.srcId;