fix(#150): trace flood/empty paths as a direct ping (was sending empty -> firmware error 1)

App Debug Log showed every failing trace sending an empty path ->
"Firmware responded with error code: 1". Cause: repeaters with a flood
route (path stored as all-zeros) were treated as routed; buildPath
collapsed the all-zero path to empty; the firmware rejects an empty trace.

- buildPath: an empty OR all-zero path now traces the target's own width
  prefix (never returns an empty payload).
- _doPathTrace: guard - never send an empty path; surface "not available".
- Repeater menu: constant "Path Trace" label (no more Ping/Path-Trace
  flip-flop); a flood path (all-zero) counts as no route -> direct ping.

Bumps build to +50 for the b50 test binary.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pull/205/head
Strycher 3 weeks ago
parent af1776f83c
commit de97f515a5

@ -1266,31 +1266,32 @@ class _ContactsScreenState extends State<ContactsScreen>
if (isRepeater) ...[
ListTile(
leading: const Icon(Icons.radar, color: Colors.green),
title: Text(
contact.pathBytesForDisplay.isNotEmpty
? context.l10n.contacts_pathTrace
: context.l10n.contacts_ping,
),
title: Text(context.l10n.contacts_pathTrace),
onTap: () {
final hw = context
.read<MeshCoreConnector>()
.pathHashByteWidth;
// A flood route is stored as all-zero bytes = "no real route",
// so trace the target directly instead of routing through (and
// sending) an all-zero/empty path. (#150)
final route = contact.pathBytesForDisplay;
final hasRoute = route.isNotEmpty && route.any((b) => b != 0);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PathTraceMapScreen(
title: contact.pathBytesForDisplay.isNotEmpty
title: hasRoute
? context.l10n.contacts_repeaterPathTrace
: context.l10n.contacts_repeaterPing,
path: contact.pathBytesForDisplay.isNotEmpty
? contact.pathBytesForDisplay
path: hasRoute
? route
: Uint8List.fromList(
contact.publicKey.sublist(
0,
PathHelper.traceHopBytes(hw),
),
),
flipPathAround: contact.pathBytesForDisplay.isNotEmpty,
flipPathAround: hasRoute,
targetContact: contact,
pathHashByteWidth: hw,
),

@ -199,17 +199,15 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
final hopBytes = PathHelper.traceHopBytes(widget.pathHashByteWidth);
final pk = widget.targetContact?.publicKey;
if (pathBytes.isEmpty) {
// Direct target: send its own width prefix.
// Empty path, or an all-zero "flood" marker, means no real route trace
// the target's own width prefix directly. Never return an empty payload:
// the firmware rejects an empty trace with error 1. (#150)
if (pathBytes.isEmpty || pathBytes.every((b) => b == 0)) {
if (pk != null && pk.length >= hopBytes) {
return Uint8List.fromList(pk.sublist(0, hopBytes));
}
return Uint8List.fromList([pk != null && pk.isNotEmpty ? pk[0] : 0]);
}
// An all-zero path is the "no known path" marker no trace payload.
if (pathBytes.every((b) => b == 0)) {
return Uint8List(0);
}
final throughTarget =
widget.targetContact?.type == advTypeRepeater ||
@ -246,6 +244,23 @@ class _PathTraceMapScreenState extends State<PathTraceMapScreen> {
final path = widget.flipPathAround ? buildPath(pathTmp) : pathTmp;
if (path.isEmpty) {
// No route to trace don't send an empty payload (firmware error 1);
// surface "not available" instead. (#150)
appLogger.info(
'Path trace skipped: no route to trace',
tag: 'PathTraceMapScreen',
noNotify: !mounted,
);
if (mounted) {
setState(() {
_isLoading = false;
_failed2Loaded = true;
});
}
return;
}
appLogger.info(
'Initiating path trace with path: ${_formatPathPrefixes(path)}',
tag: 'PathTraceMapScreen',

@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.1.2-rc.1+49
version: 1.1.2-rc.1+50
environment:
sdk: ^3.9.2

Loading…
Cancel
Save

Powered by TurnKey Linux.