correct issue where GROUP_UPDT would incorrectly override the currently active dstId;

pull/121/head
Bryan Biedenkapp 3 weeks ago
parent e47524a21c
commit 0776f91ba8

@ -120,7 +120,11 @@ namespace p25
* @return bool True, if MAC PDU decoded, otherwise false.
*/
bool decodeVCH_MACPDU_IEMI(const uint8_t* data, bool sync);
/** @brief Encode an inbound/IEMI Phase 2 VCH MAC PDU. */
/**
* @brief Encode an inbound/IEMI Phase 2 VCH MAC PDU.
* @param[out] data Buffer to encode the MAC PDU.
* @param sync Flag indicating if sync is to be included.
*/
void encodeVCH_MACPDU_IEMI(uint8_t* data, bool sync);
/**
* @brief Decode a xOEMI VCH MAC PDU.

@ -746,14 +746,13 @@ bool Voice::process(uint8_t* data, uint32_t len)
else {
std::lock_guard<std::mutex> lock(m_p25->s_activeTGLock);
if (m_p25->m_activeTG.size() > 0) {
uint32_t dstId = 0U;
const uint32_t dstId = m_rfLC.getDstId();
uint32_t dstIdB = 0U;
bool hasDstIdB = false;
if (nextActiveTalkgroups(m_p25->m_activeTG, m_grpUpdtCount, dstId, dstIdB, hasDstIdB)) {
m_rfLC.setMFId(MFG_STANDARD);
m_rfLC.setLCO(LCO::GROUP_UPDT);
m_rfLC.setDstId(dstId);
if (hasDstIdB) {
m_rfLC.setMFId(MFG_STANDARD);
m_rfLC.setLCO(LCO::GROUP_UPDT);
m_rfLC.setDstIdB(dstIdB);
}
}
@ -2094,14 +2093,13 @@ void Voice::writeNet_LDU1()
else {
std::lock_guard<std::mutex> lock(m_p25->s_activeTGLock);
if (m_p25->m_activeTG.size() > 0) {
uint32_t dstId = 0U;
const uint32_t dstId = m_netLC.getDstId();
uint32_t dstIdB = 0U;
bool hasDstIdB = false;
if (nextActiveTalkgroups(m_p25->m_activeTG, m_grpUpdtCount, dstId, dstIdB, hasDstIdB)) {
m_netLC.setMFId(MFG_STANDARD);
m_netLC.setLCO(LCO::GROUP_UPDT);
m_netLC.setDstId(dstId);
if (hasDstIdB) {
m_netLC.setMFId(MFG_STANDARD);
m_netLC.setLCO(LCO::GROUP_UPDT);
m_netLC.setDstIdB(dstIdB);
}
}
@ -2428,33 +2426,32 @@ bool Voice::applyUserAlias(lc::LC& control, uint8_t& phase)
/* Helper to determine the next active talkgroup in a active multi-group scenario. */
bool Voice::nextActiveTalkgroups(const std::vector<uint32_t>& activeTG, uint8_t& groupUpdtIndex, uint32_t& dstId, uint32_t& dstIdB, bool& hasDstIdB)
bool Voice::nextActiveTalkgroups(const std::vector<uint32_t>& activeTG, uint8_t& groupUpdtIndex, const uint32_t dstId, uint32_t& dstIdB, bool& hasDstIdB)
{
const size_t count = activeTG.size();
dstIdB = 0U;
hasDstIdB = false;
if (count == 0U) {
groupUpdtIndex = 0U;
hasDstIdB = false;
return false;
}
size_t index = static_cast<size_t>(groupUpdtIndex);
if (index >= count) {
index = 0U;
}
const size_t startIndex = static_cast<size_t>(groupUpdtIndex) < count ? static_cast<size_t>(groupUpdtIndex) : 0U;
size_t index = startIndex;
do {
if (activeTG[index] != dstId) {
dstIdB = activeTG[index];
hasDstIdB = true;
groupUpdtIndex = static_cast<uint8_t>((index + 1U) % count);
return true;
}
dstId = activeTG[index];
if (count < 2U) {
groupUpdtIndex = static_cast<uint8_t>(index);
hasDstIdB = false;
return true;
index = (index + 1U) % count;
}
while (index != startIndex);
const size_t nextIndex = (index + 1U) % count;
dstIdB = activeTG[nextIndex];
hasDstIdB = true;
// move the rolling index forward for the next report cycle
groupUpdtIndex = static_cast<uint8_t>(nextIndex);
groupUpdtIndex = static_cast<uint8_t>(startIndex);
return true;
}

@ -238,12 +238,12 @@ namespace p25
* this is intended to update the GROUP_UPDT LC field for the next transmission.
* @param activeTG Vector of active talkgroups.
* @param groupUpdtIndex Index of the current group update.
* @param dstId Destination ID of the current talkgroup.
* @param dstId Destination ID of the channel's current working talkgroup. This value is not modified.
* @param dstIdB Destination ID of the secondary talkgroup.
* @param hasDstIdB Flag indicating whether a secondary talkgroup exists.
* @return bool True if there is a next active talkgroup, otherwise false.
*/
bool nextActiveTalkgroups(const std::vector<uint32_t>& activeTG, uint8_t& groupUpdtIndex, uint32_t& dstId, uint32_t& dstIdB, bool& hasDstIdB);
bool nextActiveTalkgroups(const std::vector<uint32_t>& activeTG, uint8_t& groupUpdtIndex, const uint32_t dstId, uint32_t& dstIdB, bool& hasDstIdB);
/**
* @brief Given the last MI, generate the next MI using LFSR.

@ -383,6 +383,14 @@ bool HostTestHooks::p25TerminateNetCall(p25::Control& control, const p25::lc::LC
return voice->processNetwork(buffer, 1U, localControl, lsd, localDuid, frameType);
}
/* Selects the next secondary active talkgroup for a P25 voice channel. */
bool HostTestHooks::p25NextActiveTalkgroups(p25::Control& control, const std::vector<uint32_t>& activeTG,
uint8_t& groupUpdtIndex, const uint32_t& dstId, uint32_t& dstIdB, bool& hasDstIdB)
{
return control.m_voice->nextActiveTalkgroups(activeTG, groupUpdtIndex, dstId, dstIdB, hasDstIdB);
}
/* Gets NXDN network state. */
RPT_NET_STATE HostTestHooks::nxdnNetState(const nxdn::Control& control) { return control.m_netState; }

@ -375,6 +375,11 @@ public:
* @return bool True if termination processing succeeds.
*/
static bool p25TerminateNetCall(p25::Control& control, const p25::lc::LC& lc, p25::defines::DUID::E duid = p25::defines::DUID::TDU);
/**
* @brief Selects the next secondary active talkgroup for a P25 voice channel.
*/
static bool p25NextActiveTalkgroups(p25::Control& control, const std::vector<uint32_t>& activeTG,
uint8_t& groupUpdtIndex, const uint32_t& dstId, uint32_t& dstIdB, bool& hasDstIdB);
/** @} */
/**

@ -436,6 +436,46 @@ public:
p25::Control* m_control;
};
TEST_CASE("P25 active talkgroup updates preserve the working TGID", "[p25][active_tg]")
{
P25HostHarness harness;
const uint32_t workingDstId = 2001U;
uint8_t index = 0U;
uint32_t dstIdB = 0U;
bool hasDstIdB = false;
const std::vector<uint32_t> activeTG = { workingDstId, 2002U, 2003U, 2004U, 2005U };
REQUIRE(HostTestHooks::p25NextActiveTalkgroups(*harness.m_control, activeTG, index,
workingDstId, dstIdB, hasDstIdB));
REQUIRE(hasDstIdB);
REQUIRE(dstIdB == 2002U);
REQUIRE(dstIdB != workingDstId);
REQUIRE(HostTestHooks::p25NextActiveTalkgroups(*harness.m_control, activeTG, index,
workingDstId, dstIdB, hasDstIdB));
REQUIRE(hasDstIdB);
REQUIRE(dstIdB == 2003U);
REQUIRE(dstIdB != workingDstId);
REQUIRE(HostTestHooks::p25NextActiveTalkgroups(*harness.m_control, activeTG, index,
workingDstId, dstIdB, hasDstIdB));
REQUIRE(hasDstIdB);
REQUIRE(dstIdB == 2004U);
REQUIRE(dstIdB != workingDstId);
REQUIRE(HostTestHooks::p25NextActiveTalkgroups(*harness.m_control, activeTG, index,
workingDstId, dstIdB, hasDstIdB));
REQUIRE(hasDstIdB);
REQUIRE(dstIdB == 2005U);
REQUIRE(dstIdB != workingDstId);
const std::vector<uint32_t> onlyWorkingTG = { workingDstId, workingDstId };
REQUIRE(HostTestHooks::p25NextActiveTalkgroups(*harness.m_control, onlyWorkingTG, index,
workingDstId, dstIdB, hasDstIdB));
REQUIRE_FALSE(hasDstIdB);
REQUIRE(dstIdB == 0U);
}
TEST_CASE("P25 host arms the network watchdog when network voice starts", "[p25][host][control]")
{
P25HostHarness harness;

Loading…
Cancel
Save

Powered by TurnKey Linux.