diff --git a/configs/talkgroup_rules.example.yml b/configs/talkgroup_rules.example.yml
index 73a56508..f7467983 100644
--- a/configs/talkgroup_rules.example.yml
+++ b/configs/talkgroup_rules.example.yml
@@ -16,6 +16,8 @@ groupVoice:
config:
# Flag indicating whether this talkgroup is active or not.
active: true
+ # Flag indicating whether this talkgroup will only repeat with affiliations.
+ affiliated: false
# List of peer IDs included for this talkgroup (peers listed here will be selected for traffic).
inclusion: []
# List of peer IDs excluded for this talkgroup (peers listed here will be ignored for traffic).
@@ -39,6 +41,8 @@ groupVoice:
config:
# Flag indicating whether this talkgroup is active or not.
active: true
+ # Flag indicating whether this talkgroup will only repeat with affiliations.
+ affiliated: false
# Flag indicating whether or not this talkgroup is a parrot talkgroup.
parrot: true
# List of peer IDs included for this talkgroup (peers listed here will be selected for traffic).
@@ -57,13 +61,15 @@ groupVoice:
slot: 1
# Textual name of the talkgroup.
- - name: Parrot Mutation Example
+ - name: Rewrite Example
#
# Talkgroup Configuration
#
config:
# Flag indicating whether this talkgroup is active or not.
active: true
+ # Flag indicating whether this talkgroup will only repeat with affiliations.
+ affiliated: false
# Flag indicating whether or not this talkgroup is a parrot talkgroup.
parrot: true
# List of peer IDs included for this talkgroup (peers listed here will be selected for traffic).
@@ -83,7 +89,7 @@ groupVoice:
#
source:
# Numerical talkgroup ID number.
- tgid: 9990
+ tgid: 5
# DMR slot number.
slot: 1
@@ -95,6 +101,8 @@ groupVoice:
config:
# Flag indicating whether this talkgroup is active or not.
active: true
+ # Flag indicating whether this talkgroup will only repeat with affiliations.
+ affiliated: false
# List of peer IDs included for this talkgroup (peers listed here will be selected for traffic).
inclusion: []
# List of peer IDs excluded for this talkgroup (peers listed here will be ignored for traffic).
@@ -118,6 +126,8 @@ groupVoice:
config:
# Flag indicating whether this talkgroup is active or not.
active: true
+ # Flag indicating whether this talkgroup will only repeat with affiliations.
+ affiliated: false
# List of peer IDs included for this talkgroup (peers listed here will be selected for traffic).
inclusion: []
# List of peer IDs excluded for this talkgroup (peers listed here will be ignored for traffic).
@@ -141,6 +151,8 @@ groupVoice:
config:
# Flag indicating whether this talkgroup is active or not.
active: true
+ # Flag indicating whether this talkgroup will only repeat with affiliations.
+ affiliated: false
# List of peer IDs included for this talkgroup (peers listed here will be selected for traffic).
inclusion: []
# List of peer IDs excluded for this talkgroup (peers listed here will be ignored for traffic).
diff --git a/src/common/lookups/AffiliationLookup.cpp b/src/common/lookups/AffiliationLookup.cpp
index c8e50140..972c639d 100644
--- a/src/common/lookups/AffiliationLookup.cpp
+++ b/src/common/lookups/AffiliationLookup.cpp
@@ -177,6 +177,23 @@ bool AffiliationLookup::groupUnaff(uint32_t srcId)
}
}
+///
+/// Helper to determine if the group destination ID has any affiations.
+///
+///
+///
+///
+bool AffiliationLookup::hasGroupAff(uint32_t dstId) const
+{
+ for (auto entry : m_grpAffTable) {
+ if (entry.second == dstId) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
///
/// Helper to determine if the source ID has affiliated to the group destination ID.
///
diff --git a/src/common/lookups/AffiliationLookup.h b/src/common/lookups/AffiliationLookup.h
index 38494acd..e37f0c3f 100644
--- a/src/common/lookups/AffiliationLookup.h
+++ b/src/common/lookups/AffiliationLookup.h
@@ -125,6 +125,8 @@ namespace lookups
virtual void groupAff(uint32_t srcId, uint32_t dstId);
/// Helper to group unaffiliate a source ID.
virtual bool groupUnaff(uint32_t srcId);
+ /// Helper to determine if the group destination ID has any affiations.
+ virtual bool hasGroupAff(uint32_t dstId) const;
/// Helper to determine if the source ID has affiliated to the group destination ID.
virtual bool isGroupAff(uint32_t srcId, uint32_t dstId) const;
/// Helper to release group affiliations.
diff --git a/src/common/lookups/TalkgroupRulesLookup.h b/src/common/lookups/TalkgroupRulesLookup.h
index 923823ae..430bf9b8 100644
--- a/src/common/lookups/TalkgroupRulesLookup.h
+++ b/src/common/lookups/TalkgroupRulesLookup.h
@@ -121,6 +121,7 @@ namespace lookups
/// Initializes a new instance of the TalkgroupRuleConfig class.
TalkgroupRuleConfig() :
m_active(false),
+ m_affiliated(false),
m_parrot(false),
m_inclusion(),
m_exclusion(),
@@ -134,6 +135,7 @@ namespace lookups
TalkgroupRuleConfig()
{
m_active = node["active"].as(false);
+ m_affiliated = node["affiliated"].as(false);
m_parrot = node["parrot"].as(false);
yaml::Node& inclusionList = node["inclusion"];
@@ -166,6 +168,7 @@ namespace lookups
{
if (this != &data) {
m_active = data.m_active;
+ m_affiliated = data.m_affiliated;
m_parrot = data.m_parrot;
m_inclusion = data.m_inclusion;
m_exclusion = data.m_exclusion;
@@ -178,6 +181,8 @@ namespace lookups
public:
/// Flag indicating whether the rule is active.
__PROPERTY_PLAIN(bool, active);
+ /// Flag indicating whether this talkgroup will only repeat with affiliations.
+ __PROPERTY_PLAIN(bool, affiliated);
/// Flag indicating whether or not the talkgroup is a parrot.
__PROPERTY_PLAIN(bool, parrot);
/// List of peer IDs included by this rule.
diff --git a/src/fne/network/fne/TagDMRData.cpp b/src/fne/network/fne/TagDMRData.cpp
index 4389df27..2c7b4eb5 100644
--- a/src/fne/network/fne/TagDMRData.cpp
+++ b/src/fne/network/fne/TagDMRData.cpp
@@ -438,6 +438,15 @@ bool TagDMRData::isPeerPermitted(uint32_t peerId, data::Data& data, uint32_t str
}
}
}
+
+ // is this a TG that requires affiliations to repeat?
+ if (tg.config().affiliated()) {
+ // check the affiliations for this peer to see if we can repeat traffic
+ lookups::AffiliationLookup* aff = m_network->m_peerAffiliations[peerId];
+ if (!aff->hasGroupAff(data.getDstId())) {
+ return false;
+ }
+ }
}
return true;
diff --git a/src/fne/network/fne/TagNXDNData.cpp b/src/fne/network/fne/TagNXDNData.cpp
index e53d94b2..db63f689 100644
--- a/src/fne/network/fne/TagNXDNData.cpp
+++ b/src/fne/network/fne/TagNXDNData.cpp
@@ -360,6 +360,15 @@ bool TagNXDNData::isPeerPermitted(uint32_t peerId, lc::RTCH& lc, uint8_t message
}
}
}
+
+ // is this a TG that requires affiliations to repeat?
+ if (tg.config().affiliated()) {
+ // check the affiliations for this peer to see if we can repeat traffic
+ lookups::AffiliationLookup* aff = m_network->m_peerAffiliations[peerId];
+ if (!aff->hasGroupAff(lc.getDstId())) {
+ return false;
+ }
+ }
}
return true;
diff --git a/src/fne/network/fne/TagP25Data.cpp b/src/fne/network/fne/TagP25Data.cpp
index 9eab1249..d7484234 100644
--- a/src/fne/network/fne/TagP25Data.cpp
+++ b/src/fne/network/fne/TagP25Data.cpp
@@ -495,6 +495,15 @@ bool TagP25Data::isPeerPermitted(uint32_t peerId, lc::LC& control, uint8_t duid,
}
}
+ // is this a TG that requires affiliations to repeat?
+ if (tg.config().affiliated()) {
+ // check the affiliations for this peer to see if we can repeat traffic
+ lookups::AffiliationLookup* aff = m_network->m_peerAffiliations[peerId];
+ if (!aff->hasGroupAff(control.getDstId())) {
+ return false;
+ }
+ }
+
return true;
}