|
|
|
|
@ -38,7 +38,9 @@ The harness code is split as follows:
|
|
|
|
|
including optional OpenBridge/FBP peer sections.
|
|
|
|
|
- `FreeDmrProcess`: starts and stops `bridge_master.py`.
|
|
|
|
|
- `HbpRepeater`: UDP HBP client emulator with login, ping, packet send, stream
|
|
|
|
|
send, and capture support.
|
|
|
|
|
send, and capture support. The initial login challenge is retried for a
|
|
|
|
|
bounded startup window so subprocess startup work does not race the first
|
|
|
|
|
test packet.
|
|
|
|
|
- `FbpPeer`: UDP FBP v5 peer emulator with signed packet sends, keepalive,
|
|
|
|
|
version negotiation, STUN and source-quench control helpers.
|
|
|
|
|
- `UdpBlackBoxScenario`: process plus two-master loopback topology with
|
|
|
|
|
@ -125,17 +127,19 @@ for rule timeout checks without sleeping.
|
|
|
|
|
target. When AllStar is disabled it reports busy; when enabled it enters
|
|
|
|
|
AllStar mode and schedules reset. It should not create or retune reflector
|
|
|
|
|
state or announce a dial-a-TG link.
|
|
|
|
|
- Dial-a-TG default-reflector configuration bugs: startup and live options reload
|
|
|
|
|
should use the same prohibited default-reflector targets. Reserved/control
|
|
|
|
|
targets such as `6`, `7`, and AllStar control target `8` should not create an
|
|
|
|
|
active default TS2 reflector at startup. The FreeDMR policy cap should match
|
|
|
|
|
RF dial-a-TG handling: `999999` is valid and higher default reflectors are
|
|
|
|
|
rejected. Invalid default-reflector options should disable any existing
|
|
|
|
|
default reflector for the current session rather than preserving stale TS2 TG9
|
|
|
|
|
reflector state. Invalid startup defaults should be logged and should not
|
|
|
|
|
create bridge state; the in-memory effective default should normalize to `0`
|
|
|
|
|
without writing back to the config file. System-wide defaults are intended for
|
|
|
|
|
sparing use; client requested settings are preferential.
|
|
|
|
|
- Dial-a-TG default-dial configuration bugs: startup and live options reload
|
|
|
|
|
should use the same prohibited default targets. Reserved/control targets such
|
|
|
|
|
as `6`, `7`, and AllStar control target `8` should not create an active
|
|
|
|
|
default reflector at startup. `DEFAULT_DIAL_TS1` and `DEFAULT_DIAL_TS2` are
|
|
|
|
|
the canonical per-slot defaults; deprecated `DEFAULT_REFLECTOR`, `DIAL` and
|
|
|
|
|
`StartRef` remain TS2 compatibility aliases. The FreeDMR policy cap should
|
|
|
|
|
match RF dial-a-TG handling: `999999` is valid and higher defaults are
|
|
|
|
|
rejected. Invalid default options should disable any existing default for the
|
|
|
|
|
current session rather than preserving stale TG9 reflector state. Invalid
|
|
|
|
|
startup defaults should be logged and should not create bridge state; the
|
|
|
|
|
in-memory effective default should normalize to `0` without writing back to
|
|
|
|
|
the config file. System-wide defaults are intended for sparing use; client
|
|
|
|
|
requested settings are preferential.
|
|
|
|
|
- Static TG configuration bugs: startup and live options reload should reject
|
|
|
|
|
prohibited local/control TGs consistently on both TS1 and TS2 after parsing the
|
|
|
|
|
configured TG strings to integers. Invalid IDs at or above `16777215` should
|
|
|
|
|
@ -146,9 +150,9 @@ for rule timeout checks without sleeping.
|
|
|
|
|
- Client options parsing bugs: malformed independent numeric fields such as
|
|
|
|
|
`IDENTTG=A`, `VOICE=A`, or `SINGLE=A` should not abort otherwise valid session
|
|
|
|
|
options in the same string. `VOICE` and `SINGLE` accept only `0` or `1`.
|
|
|
|
|
Empty `DIAL` / `DEFAULT_REFLECTOR` is equivalent to `0` and means no default
|
|
|
|
|
reflector. Invalid `TIMER` values should be logged and should not block valid
|
|
|
|
|
static TG changes, which should use the current effective timer.
|
|
|
|
|
Empty `DIAL` / `DEFAULT_REFLECTOR` is equivalent to `0` and means no TS2
|
|
|
|
|
default reflector. Invalid `TIMER` values should be logged and should not
|
|
|
|
|
block valid static TG changes, which should use the current effective timer.
|
|
|
|
|
- Voice ident override bugs: `OVERRIDE_IDENT_TG` should be parsed before packet
|
|
|
|
|
generation. Valid positive TGs below all-call are used as the destination;
|
|
|
|
|
empty or false override values use all-call; malformed, out-of-range, or
|
|
|
|
|
@ -197,7 +201,12 @@ for rule timeout checks without sleeping.
|
|
|
|
|
data-only state.
|
|
|
|
|
- Voice LC rewrite boundary bugs: embedded-LC rewrite should apply only to voice
|
|
|
|
|
bursts B-E and must not mutate data-sync/control payload bytes while forwarding
|
|
|
|
|
over HBP or FBP paths.
|
|
|
|
|
over HBP or FBP paths. Same-TG voice forwarding should preserve burst payload
|
|
|
|
|
bytes so embedded Talker Alias/GPS-like LC can traverse; target-TG mapped
|
|
|
|
|
forwarding should still regenerate embedded LC for the rewritten TG.
|
|
|
|
|
- Embedded-LC observability bugs: accepted in-call Talker Alias and GPS LC cycles
|
|
|
|
|
should be decoded with the standalone MMDVMHost-style embedded-LC codec and
|
|
|
|
|
logged without changing packet routing or mutation behaviour.
|
|
|
|
|
- HBP group/VCSBK rate-control bugs: same-timestamp packet bursts should not
|
|
|
|
|
raise during local packet-rate calculation before duplicate/drop handling can
|
|
|
|
|
run.
|
|
|
|
|
@ -334,10 +343,11 @@ Implemented:
|
|
|
|
|
and alias downloads disabled. The generated config supports scenario-level
|
|
|
|
|
knobs for global ACL fields, static TG lists and optional FBP peers.
|
|
|
|
|
- Black-box HBP coverage for static routing, global ACL startup parsing,
|
|
|
|
|
data/control payload preservation, sequence wrap, duplicate sequence `0`
|
|
|
|
|
suppression, terminator lifecycle suppression, recorded fixture replay, burst
|
|
|
|
|
loss and duplicate UDP profiles, and local generated prompt output for
|
|
|
|
|
dial-a-TG reserved controls.
|
|
|
|
|
data/control payload preservation, same-TG voice embedded-LC payload
|
|
|
|
|
preservation, in-call Talker Alias/GPS log observability, sequence wrap,
|
|
|
|
|
duplicate sequence `0` suppression, terminator lifecycle suppression, recorded
|
|
|
|
|
fixture replay, burst loss and duplicate UDP profiles, and local generated
|
|
|
|
|
prompt output for dial-a-TG reserved controls.
|
|
|
|
|
- Black-box FBP coverage for enhanced keepalive/version setup, static TG routing
|
|
|
|
|
from HBP to FBP and from FBP to HBP, BCKA gating of enhanced HBP-to-FBP
|
|
|
|
|
forwarding, BCSQ source-quench suppression, invalid BCSQ rejection, BCST STUN
|
|
|
|
|
@ -476,6 +486,22 @@ fixture readers once recorded fixtures are added:
|
|
|
|
|
destination TG or unit ID, stream ID, sequence, frame type, call type,
|
|
|
|
|
dtype/voice sequence, payload bytes and optional frame delay.
|
|
|
|
|
- Synthetic fixtures build canonical `DMRD` payload bytes from `PacketSpec`.
|
|
|
|
|
- `freedmr_dmr_codec.py` is a standalone codec proving ground for protocol
|
|
|
|
|
helpers before they are linked into packet routing. Its first scope is
|
|
|
|
|
MMDVMHost-style embedded LC encode/decode with Hamming(16,11,4), column parity
|
|
|
|
|
and 5-bit checksum validation. It now also covers full LC header/terminator
|
|
|
|
|
BPTC generation, RS(12,9) LC parity masks, a small LC classifier and
|
|
|
|
|
Golay(20,8,7) slot type encode/decode correction. TA/GPS logging fixtures are
|
|
|
|
|
generated through this module so the logging path sees valid embedded-LC
|
|
|
|
|
cycles rather than hand-coded bit slices. The module also exposes
|
|
|
|
|
legacy-compatible LC generation function names used by
|
|
|
|
|
`bridge_master.py`, `bridge.py` and `mk_voice.py`, plus compatible
|
|
|
|
|
`voice_head_term()` and `voice()` decode helpers used by `bridge_master.py`
|
|
|
|
|
and `bridge.py`. Synthetic group voice LC fallback is generated through this
|
|
|
|
|
module with normal service options (`0x00`); decoded inbound LC bytes remain
|
|
|
|
|
the source of truth when a real voice header is available. Active runtime
|
|
|
|
|
byte/alias helpers are FreeDMR-owned in `utils.py`; remaining `dmr_utils3`
|
|
|
|
|
imports are limited to legacy/lab tools unless those tools are updated later.
|
|
|
|
|
- Recorded fixture support is not implemented yet. When added, fixtures should
|
|
|
|
|
keep raw bytes plus sidecar metadata describing expected decoded fields and
|
|
|
|
|
allowed rewrite regions.
|
|
|
|
|
@ -516,11 +542,13 @@ Assertions should be grouped by intent:
|
|
|
|
|
test claiming login, HMAC, UDP parsing or real cadence coverage belongs in the
|
|
|
|
|
UDP layer.
|
|
|
|
|
- Minimal synthetic voice payloads may not be sufficient for scenarios that
|
|
|
|
|
assert full LC encoding. Recorded fixtures or carefully generated payloads
|
|
|
|
|
should be used for those cases.
|
|
|
|
|
assert full packet audio behaviour. Full LC and slot type codec behaviour is
|
|
|
|
|
covered in the standalone codec layer, while recorded fixtures or carefully
|
|
|
|
|
generated payloads should still be used for packet-path scenarios.
|
|
|
|
|
- Embedded LC can carry information such as embedded GPS and talker alias. The
|
|
|
|
|
current harness protects against accidental mutation of data/control packets,
|
|
|
|
|
but it does not yet verify future source-to-destination embedded-LC carry-over.
|
|
|
|
|
current harness protects same-TG carry-over and standalone codec behavior, but
|
|
|
|
|
does not yet verify selective embedded-LC rewrite/preservation on TG-mapped
|
|
|
|
|
streams.
|
|
|
|
|
- Generated prompt interruption is covered in both layers for state and
|
|
|
|
|
UDP-visible routing. The harness still does not prove RF-side audio behavior
|
|
|
|
|
or how a physical repeater/radio reacts to an abandoned prompt without a
|
|
|
|
|
@ -539,8 +567,9 @@ Assertions should be grouped by intent:
|
|
|
|
|
- Deterministic cross-slot routing tests verify that TS1-to-TS2 routing rewrites
|
|
|
|
|
only the slot bit while preserving source ID, destination TG, peer ID, stream
|
|
|
|
|
ID and packet bytes outside the expected header bit.
|
|
|
|
|
- Deterministic dial-a-TG tests verify that TS1 private calls create, retune,
|
|
|
|
|
disconnect and query TS2 reflector state without emitting network traffic.
|
|
|
|
|
- Deterministic dial-a-TG tests verify that private-call control is slot-local:
|
|
|
|
|
TS1 controls TS1 reflector state, TS2 controls TS2 reflector state, and TS1 no
|
|
|
|
|
longer retunes TS2.
|
|
|
|
|
- Deterministic generated-prompt tests verify first-packet prompt state, prompt
|
|
|
|
|
cancellation when real HBP voice wins the same slot, and embedded-LC rewrite
|
|
|
|
|
for late entry after cancellation.
|
|
|
|
|
@ -556,20 +585,22 @@ Assertions should be grouped by intent:
|
|
|
|
|
- Deterministic reserved control-range tests verify that TS1 private calls to
|
|
|
|
|
`4001..4999` do not create or retune reflector bridges and report busy rather
|
|
|
|
|
than linked.
|
|
|
|
|
- Deterministic echo-target tests verify that TS1 private call `9990` creates
|
|
|
|
|
and activates the TS2 reflector state and announces a link.
|
|
|
|
|
- Deterministic echo-target tests verify that TS1 private call `9990` is an
|
|
|
|
|
intentional linkable echo/test target and announces a link without creating an
|
|
|
|
|
FBP route target.
|
|
|
|
|
- Deterministic information-service tests verify that `9991..9999` schedules
|
|
|
|
|
both the requested AMBE file and the generic silence prompt without creating a
|
|
|
|
|
reflector.
|
|
|
|
|
- Deterministic policy-range tests verify that `999999` is still linkable while
|
|
|
|
|
`1000000` does not create or retune reflector state and reports busy rather
|
|
|
|
|
than linked.
|
|
|
|
|
- Deterministic default-reflector tests verify that startup rejects reserved
|
|
|
|
|
control targets `6`, `7`, and `8`, while still allowing a linkable default
|
|
|
|
|
reflector target to create an active TS2 reflector. They also verify
|
|
|
|
|
`999999` remains valid and startup/options reject default reflector targets
|
|
|
|
|
above that policy cap, with invalid options disabling any active default
|
|
|
|
|
reflector state and invalid startup defaults producing a warning while
|
|
|
|
|
- Deterministic default-dial tests verify that startup rejects reserved control
|
|
|
|
|
targets `6`, `7`, and `8`, while still allowing linkable
|
|
|
|
|
`DEFAULT_DIAL_TS1` and `DEFAULT_DIAL_TS2` targets to create active per-slot
|
|
|
|
|
reflectors. Deprecated `DEFAULT_REFLECTOR`, `DIAL` and `StartRef` remain TS2
|
|
|
|
|
aliases. These tests also verify `999999` remains valid and startup/options
|
|
|
|
|
reject targets above that policy cap, with invalid options disabling active
|
|
|
|
|
default state and invalid startup defaults producing a warning while
|
|
|
|
|
normalizing runtime state to `0`.
|
|
|
|
|
- Deterministic static-TG configuration tests verify that startup rejects
|
|
|
|
|
prohibited TS1 and TS2 static TGs after integer parsing, rejects invalid IDs
|
|
|
|
|
@ -578,9 +609,10 @@ Assertions should be grouped by intent:
|
|
|
|
|
prohibition. They also verify whitespace normalization and token-level
|
|
|
|
|
skipping of invalid static TG tokens while valid tokens still apply.
|
|
|
|
|
- Deterministic options parser tests verify malformed independent numeric fields
|
|
|
|
|
do not block valid DIAL/static fields, boolean-like options reject values other
|
|
|
|
|
than `0` or `1`, empty `DIAL` disables default reflector state, and invalid
|
|
|
|
|
`TIMER` values are logged without blocking valid static TG changes.
|
|
|
|
|
do not block valid default-dial/static fields, boolean-like options reject
|
|
|
|
|
values other than `0` or `1`, empty `DIAL` disables TS2 default reflector
|
|
|
|
|
state, and invalid `TIMER` values are logged without blocking valid static TG
|
|
|
|
|
changes.
|
|
|
|
|
- Deterministic voice-ident tests verify override destination selection for
|
|
|
|
|
valid string TGs, empty/false overrides, malformed values, control TGs, and
|
|
|
|
|
all-call.
|
|
|
|
|
|