add rudimentary support to process NET_FUNC_GRANT_REQ (network grant requests), this is the first step towards eventually supporting non-authorative CCs;

3.6-maint
Bryan Biedenkapp 2 years ago
parent 2f918d759d
commit e7ddfffed3

@ -349,10 +349,42 @@ bool TagDMRData::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId
/// <returns></returns>
bool TagDMRData::processGrantReq(uint32_t srcId, uint32_t dstId, uint8_t slot, bool unitToUnit, uint32_t peerId, uint16_t pktSeq, uint32_t streamId)
{
// bryanb: TODO TODO TODO
// if we have an Rx status for the destination deny the grant
if (std::find_if(m_status.begin(), m_status.end(), [&](StatusMapPair x) { return x.second.dstId == dstId; }) != m_status.end()) {
return false;
}
// is the source ID a blacklisted ID?
lookups::RadioId rid = m_network->m_ridLookup->find(srcId);
if (!rid.radioDefault()) {
if (!rid.radioEnabled()) {
return false;
}
}
lookups::TalkgroupRuleGroupVoice tg = m_network->m_tidLookup->find(dstId);
// check TGID validity
if (tg.isInvalid()) {
return false;
}
if (!tg.config().active()) {
return false;
}
// repeat traffic to the connected peers
if (m_network->m_peers.size() > 0U) {
for (auto peer : m_network->m_peers) {
if (peerId != peer.first) {
write_CSBK_Grant(peer.first, srcId, dstId, 4U, !unitToUnit);
}
}
}
return true;
}
/// <summary>
/// Helper to playback a parrot frame to the network.
/// </summary>
@ -816,6 +848,79 @@ bool TagDMRData::validate(uint32_t peerId, data::Data& data, uint32_t streamId)
return true;
}
/// <summary>
/// Helper to write a grant packet.
/// </summary>
/// <param name="peerId"></param>
/// <param name="srcId"></param>
/// <param name="dstId"></param>
/// <param name="serviceOptions"></param>
/// <param name="grp"></param>
/// <returns></returns>
bool TagDMRData::write_CSBK_Grant(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp)
{
uint8_t slot = 0U;
bool emergency = ((serviceOptions & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
bool privacy = ((serviceOptions & 0xFFU) & 0x40U) == 0x40U; // Privacy Flag
bool broadcast = ((serviceOptions & 0xFFU) & 0x10U) == 0x10U; // Broadcast Flag
uint8_t priority = ((serviceOptions & 0xFFU) & 0x03U); // Priority
if (dstId == DMR_WUID_ALL) {
return true; // do not generate grant packets for $FFFF (All Call) TGID
}
// check the affiliations for this peer to see if we can grant traffic
lookups::AffiliationLookup* aff = m_network->m_peerAffiliations[peerId];
if (aff == nullptr) {
std::string peerIdentity = m_network->resolvePeerIdentity(peerId);
LogError(LOG_NET, "PEER %u (%s) has an invalid affiliations lookup? This shouldn't happen BUGBUG.", peerId, peerIdentity.c_str());
return false; // this will cause no traffic to pass for this peer now...I'm not sure this is good behavior
}
else {
if (!aff->hasGroupAff(dstId)) {
return false;
}
}
if (grp) {
std::unique_ptr<lc::csbk::CSBK_TV_GRANT> csbk = std::make_unique<lc::csbk::CSBK_TV_GRANT>();
if (broadcast)
csbk->setCSBKO(CSBKO_BTV_GRANT);
csbk->setLogicalCh1(0U);
csbk->setSlotNo(slot);
if (m_network->m_verbose) {
LogMessage(LOG_NET, "DMR, DT_CSBK, %s, emerg = %u, privacy = %u, broadcast = %u, prio = %u, chNo = %u, slot = %u, srcId = %u, dstId = %u, peerId = %u",
csbk->toString().c_str(), emergency, privacy, broadcast, priority, csbk->getLogicalCh1(), csbk->getSlotNo(), srcId, dstId, peerId);
}
csbk->setEmergency(emergency);
csbk->setSrcId(srcId);
csbk->setDstId(dstId);
write_CSBK(peerId, 1U, csbk.get());
}
else {
std::unique_ptr<lc::csbk::CSBK_PV_GRANT> csbk = std::make_unique<lc::csbk::CSBK_PV_GRANT>();
csbk->setLogicalCh1(0U);
csbk->setSlotNo(slot);
if (m_network->m_verbose) {
LogMessage(LOG_NET, "DMR, DT_CSBK, %s, emerg = %u, privacy = %u, broadcast = %u, prio = %u, chNo = %u, slot = %u, srcId = %u, dstId = %u, peerId = %u",
csbk->toString().c_str(), emergency, privacy, broadcast, priority, csbk->getLogicalCh1(), csbk->getSlotNo(), srcId, dstId, peerId);
}
csbk->setEmergency(emergency);
csbk->setSrcId(srcId);
csbk->setDstId(dstId);
write_CSBK(peerId, 1U, csbk.get());
}
return true;
}
/// <summary>
/// Helper to write a NACK RSP packet.
/// </summary>

@ -100,6 +100,8 @@ namespace network
/// <summary>Helper to validate the DMR call stream.</summary>
bool validate(uint32_t peerId, dmr::data::Data& data, uint32_t streamId);
/// <summary>Helper to write a grant packet.</summary>
bool write_CSBK_Grant(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp);
/// <summary>Helper to write a NACK RSP packet.</summary>
void write_CSBK_NACK_RSP(uint32_t peerId, uint32_t dstId, uint8_t reason, uint8_t service);

@ -313,10 +313,42 @@ bool TagNXDNData::processFrame(const uint8_t* data, uint32_t len, uint32_t peerI
/// <returns></returns>
bool TagNXDNData::processGrantReq(uint32_t srcId, uint32_t dstId, bool unitToUnit, uint32_t peerId, uint16_t pktSeq, uint32_t streamId)
{
// bryanb: TODO TODO TODO
// if we have an Rx status for the destination deny the grant
if (std::find_if(m_status.begin(), m_status.end(), [&](StatusMapPair x) { return x.second.dstId == dstId; }) != m_status.end()) {
return false;
}
// is the source ID a blacklisted ID?
lookups::RadioId rid = m_network->m_ridLookup->find(srcId);
if (!rid.radioDefault()) {
if (!rid.radioEnabled()) {
return false;
}
}
lookups::TalkgroupRuleGroupVoice tg = m_network->m_tidLookup->find(dstId);
// check TGID validity
if (tg.isInvalid()) {
return false;
}
if (!tg.config().active()) {
return false;
}
// repeat traffic to the connected peers
if (m_network->m_peers.size() > 0U) {
for (auto peer : m_network->m_peers) {
if (peerId != peer.first) {
write_Message_Grant(peer.first, srcId, dstId, 4U, !unitToUnit);
}
}
}
return true;
}
/// <summary>
/// Helper to playback a parrot frame to the network.
/// </summary>
@ -604,6 +636,55 @@ bool TagNXDNData::validate(uint32_t peerId, lc::RTCH& lc, uint8_t messageType, u
return true;
}
/// <summary>
/// Helper to write a grant packet.
/// </summary>
/// <param name="peerId"></param>
/// <param name="srcId"></param>
/// <param name="dstId"></param>
/// <param name="serviceOptions"></param>
/// <param name="grp"></param>
/// <returns></returns>
bool TagNXDNData::write_Message_Grant(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp)
{
bool emergency = ((serviceOptions & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
bool encryption = ((serviceOptions & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
uint8_t priority = ((serviceOptions & 0xFFU) & 0x07U); // Priority
std::unique_ptr<lc::rcch::MESSAGE_TYPE_VCALL_CONN> rcch = std::make_unique<lc::rcch::MESSAGE_TYPE_VCALL_CONN>();
// check the affiliations for this peer to see if we can grant traffic
lookups::AffiliationLookup* aff = m_network->m_peerAffiliations[peerId];
if (aff == nullptr) {
std::string peerIdentity = m_network->resolvePeerIdentity(peerId);
LogError(LOG_NET, "PEER %u (%s) has an invalid affiliations lookup? This shouldn't happen BUGBUG.", peerId, peerIdentity.c_str());
return false; // this will cause no traffic to pass for this peer now...I'm not sure this is good behavior
}
else {
if (!aff->hasGroupAff(dstId)) {
return false;
}
}
rcch->setMessageType(RTCH_MESSAGE_TYPE_VCALL);
rcch->setGrpVchNo(0U);
rcch->setGroup(grp);
rcch->setSrcId(srcId);
rcch->setDstId(dstId);
rcch->setEmergency(emergency);
rcch->setEncrypted(encryption);
rcch->setPriority(priority);
if (m_network->m_verbose) {
LogMessage(LOG_NET, "NXDN, %s, emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u, peerId = %u",
rcch->toString().c_str(), rcch->getEmergency(), rcch->getEncrypted(), rcch->getPriority(), rcch->getGrpVchNo(), rcch->getSrcId(), rcch->getDstId(), peerId);
}
write_Message(peerId, rcch.get());
return true;
}
/// <summary>
/// Helper to write a deny packet.
/// </summary>

@ -89,6 +89,8 @@ namespace network
/// <summary>Helper to validate the NXDN call stream.</summary>
bool validate(uint32_t peerId, nxdn::lc::RTCH& control, uint8_t messageType, uint32_t streamId);
/// <summary>Helper to write a grant packet.</summary>
bool write_Message_Grant(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp);
/// <summary>Helper to write a deny packet.</summary>
void write_Message_Deny(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service);

@ -29,6 +29,12 @@ using namespace p25;
#include <cassert>
#include <chrono>
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const uint32_t GRANT_TIMER_TIMEOUT = 15U;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
@ -384,10 +390,42 @@ bool TagP25Data::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId
/// <returns></returns>
bool TagP25Data::processGrantReq(uint32_t srcId, uint32_t dstId, bool unitToUnit, uint32_t peerId, uint16_t pktSeq, uint32_t streamId)
{
// bryanb: TODO TODO TODO
// if we have an Rx status for the destination deny the grant
if (std::find_if(m_status.begin(), m_status.end(), [&](StatusMapPair x) { return x.second.dstId == dstId; }) != m_status.end()) {
return false;
}
// is the source ID a blacklisted ID?
lookups::RadioId rid = m_network->m_ridLookup->find(srcId);
if (!rid.radioDefault()) {
if (!rid.radioEnabled()) {
return false;
}
}
lookups::TalkgroupRuleGroupVoice tg = m_network->m_tidLookup->find(dstId);
// check TGID validity
if (tg.isInvalid()) {
return false;
}
if (!tg.config().active()) {
return false;
}
// repeat traffic to the connected peers
if (m_network->m_peers.size() > 0U) {
for (auto peer : m_network->m_peers) {
if (peerId != peer.first) {
write_TSDU_Grant(peer.first, srcId, dstId, 4U, !unitToUnit);
}
}
}
return true;
}
/// <summary>
/// Helper to playback a parrot frame to the network.
/// </summary>
@ -1123,6 +1161,76 @@ bool TagP25Data::validate(uint32_t peerId, lc::LC& control, uint8_t duid, const
return true;
}
/// <summary>
/// Helper to write a grant packet.
/// </summary>
/// <param name="peerId"></param>
/// <param name="srcId"></param>
/// <param name="dstId"></param>
/// <param name="grp"></param>
/// <returns></returns>
bool TagP25Data::write_TSDU_Grant(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp)
{
bool emergency = ((serviceOptions & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
bool encryption = ((serviceOptions & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
uint8_t priority = ((serviceOptions & 0xFFU) & 0x07U); // Priority
if (dstId == P25_TGID_ALL) {
return true; // do not generate grant packets for $FFFF (All Call) TGID
}
// check the affiliations for this peer to see if we can grant traffic
lookups::AffiliationLookup* aff = m_network->m_peerAffiliations[peerId];
if (aff == nullptr) {
std::string peerIdentity = m_network->resolvePeerIdentity(peerId);
LogError(LOG_NET, "PEER %u (%s) has an invalid affiliations lookup? This shouldn't happen BUGBUG.", peerId, peerIdentity.c_str());
return false; // this will cause no traffic to pass for this peer now...I'm not sure this is good behavior
}
else {
if (!aff->hasGroupAff(dstId)) {
return false;
}
}
if (grp) {
std::unique_ptr<lc::tsbk::IOSP_GRP_VCH> iosp = std::make_unique<lc::tsbk::IOSP_GRP_VCH>();
iosp->setSrcId(srcId);
iosp->setDstId(dstId);
iosp->setGrpVchId(0U);
iosp->setGrpVchNo(0U);
iosp->setEmergency(emergency);
iosp->setEncrypted(encryption);
iosp->setPriority(priority);
if (m_network->m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", %s, emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u, peerId = %u",
iosp->toString().c_str(), iosp->getEmergency(), iosp->getEncrypted(), iosp->getPriority(), iosp->getGrpVchNo(), iosp->getSrcId(), iosp->getDstId(), peerId);
}
write_TSDU(peerId, iosp.get());
}
else {
std::unique_ptr<lc::tsbk::IOSP_UU_VCH> iosp = std::make_unique<lc::tsbk::IOSP_UU_VCH>();
iosp->setSrcId(srcId);
iosp->setDstId(dstId);
iosp->setGrpVchId(0U);
iosp->setGrpVchNo(0U);
iosp->setEmergency(emergency);
iosp->setEncrypted(encryption);
iosp->setPriority(priority);
if (m_network->m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", %s, emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u, peerId = %u",
iosp->toString().c_str(), iosp->getEmergency(), iosp->getEncrypted(), iosp->getPriority(), iosp->getGrpVchNo(), iosp->getSrcId(), iosp->getDstId(), peerId);
}
write_TSDU(peerId, iosp.get());
}
return true;
}
/// <summary>
/// Helper to write a deny packet.
/// </summary>

@ -113,6 +113,8 @@ namespace network
/// <summary>Helper to validate the P25 call stream.</summary>
bool validate(uint32_t peerId, p25::lc::LC& control, uint8_t duid, const p25::lc::TSBK* tsbk, uint32_t streamId);
/// <summary>Helper to write a grant packet.</summary>
bool write_TSDU_Grant(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp);
/// <summary>Helper to write a deny packet.</summary>
void write_TSDU_Deny(uint32_t peerId, uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool group = false, bool aiv = false);
/// <summary>Helper to write a queue packet.</summary>

Loading…
Cancel
Save

Powered by TurnKey Linux.