fix: stop unit calls to 4000 from being broadcast to every peer

TG/ID 4000 is the dynamic-TG reset control code and can never appear in
_SUB_MAP, so the unknown-destination fallback in _pvt_repeat_targets treated
it as a private call to an unlocated radio and blasted it to every connected
peer. That fallback runs before dmrd_received's own dst_id == 4000 guard, so
the control code has to be filtered at the targeting step too.
pull/70/head
Rodrigo Pérez 1 month ago
parent c2bd1c89af
commit 62225c9f07

@ -436,12 +436,22 @@ class HBPProtocol(DatagramProtocol):
to blast the call to peers it can't possibly be for. Returns a
1-tuple with the exact peer_id when it's still connected here.
TG/ID 4000 is the dynamic-TG reset control code (see
``_handle_tg4000_packet``/``routing_use_cases.dmrd_received``), never
a real subscriber -- it can never appear in _SUB_MAP, so it would
otherwise always fall into the "unknown destination" broadcast
fallback above and get blasted to every peer. That fallback runs
before dmrd_received's own dst_id == 4000 guard ever sees the
packet, so it must be special-cased here too.
The report_slot / "SYSTEM-N" monitor display name is NOT used for
this — it's cosmetic and can be reassigned to a different peer across
refreshes (self-service peers without a stable report_slot fall back
to a sorted-by-id allocation recomputed each time). The raw peer_id
is what's actually stable.
"""
if int_id(dst_id) == 4000:
return ()
sub_map = self._CONFIG.get("_SUB_MAP")
if not sub_map:
return None

@ -31,6 +31,8 @@ parity) -- see test_hbp_repeat_private_call.py."""
from __future__ import annotations
import dataclasses
from tests.harness.deterministic import DeterministicScenario, PacketSpec
from tests.support.hbp_repeat_stack import build_hbp_repeat_stack
@ -110,6 +112,24 @@ def test_private_call_not_delivered_locally_when_known_on_different_system() ->
assert not stack.transport.for_addr(_ADDR_OTHER), "destination known elsewhere must not repeat locally"
def test_private_call_to_4000_not_broadcast() -> None:
"""TG/ID 4000 is the dynamic-TG reset control code, never a real subscriber --
it can never appear in _SUB_MAP, so without a special case it always fell into
the "unknown destination" broadcast fallback and reached every connected peer
instead of being stopped at the server (dmrd_received's own dst_id == 4000
guard runs too late: _pvt_repeat_targets/the REPEAT loop already ran)."""
stack = build_hbp_repeat_stack(talker_alias=True)
stack.register_peer(_PEER_TX, _ADDR_TX, options="TS2=7304;")
stack.register_peer(_PEER_RX, _ADDR_RX, options="TS2=7304;")
stack.register_peer(_PEER_OTHER, _ADDR_OTHER, options="TS2=7304;")
base = dataclasses.replace(_private_spec(), dst_id=4000)
_fire_private_call(stack, base)
assert not stack.transport.for_addr(_ADDR_RX), "TG 4000 must not be broadcast to any peer"
assert not stack.transport.for_addr(_ADDR_OTHER), "TG 4000 must not be broadcast to any peer"
def test_sub_map_entries_for_peer_purged_on_reconnect() -> None:
"""Once a hotspot finishes (re)logging in, any SUB_MAP entry pointing at it is
stale -- the radio may have moved to a different hotspot while this one was

Loading…
Cancel
Save

Powered by TurnKey Linux.