fix(#309): use each path's captured width in _pathDiag, not the global one

Gemini adversarial review finding (minor, accepted). _pathDiag derived the
expected byte count from the connector's global _pathHashByteWidth, which is
the CONNECTED device's width, while each Contact now carries the width its
path was actually captured at.

Failure case: a contact discovered on a 1-byte net (3 hops, 3 bytes) viewed
while connected to a 2-byte device computes expected = 3 * 2 = 6 and logs
"bytes=3/6 TRUNCATED" for a complete, correct path. A false TRUNCATED in the
very diagnostic added to investigate truncation would actively mislead.

_pathDiag now takes the per-path width; all seven call sites pass
contact.pathHashWidth.

Refs #298, #309

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix/309-path-len-decode
Strycher 2 days ago
parent 73d0fc9888
commit fea8f62e8a

@ -506,9 +506,13 @@ class MeshCoreConnector extends ChangeNotifier {
/// self-evident in any capture, without the device present. /// self-evident in any capture, without the device present.
/// ///
/// One line, existing log sites only, no new per-frame logging. (#298) /// One line, existing log sites only, no new per-frame logging. (#298)
String _pathDiag(List<int> pathBytes, int pathLenField) { /// [pathHashWidth] must be the width the path was CAPTURED at (each Contact
/// carries its own), not the connected device's current global width. Using
/// the global one falsely flags a complete 1-byte-width path as TRUNCATED
/// when the client is connected to a 2-byte device. (#309, Gemini review)
String _pathDiag(List<int> pathBytes, int pathLenField, int pathHashWidth) {
if (pathLenField < 0) return 'flood'; if (pathLenField < 0) return 'flood';
final w = _pathHashByteWidth; final w = pathHashWidth < 1 ? 1 : pathHashWidth;
final expectedBytes = pathLenField * w; final expectedBytes = pathLenField * w;
final hex = pathBytes.isEmpty final hex = pathBytes.isEmpty
? 'none' ? 'none'
@ -4971,7 +4975,7 @@ class MeshCoreConnector extends ChangeNotifier {
: contact.lastMessageAt; : contact.lastMessageAt;
appLogger.info( appLogger.info(
'Refreshing contact ${contact.name}: devicePath=${_pathDiag(contact.path, contact.pathLength)}, existingOverride=${existing.pathOverride}', 'Refreshing contact ${contact.name}: devicePath=${_pathDiag(contact.path, contact.pathLength, contact.pathHashWidth)}, existingOverride=${existing.pathOverride}',
tag: 'Connector', tag: 'Connector',
); );
@ -4986,7 +4990,7 @@ class MeshCoreConnector extends ChangeNotifier {
); );
appLogger.info( appLogger.info(
'After merge: pathOverride=${_contacts[existingIndex].pathOverride}, devicePath=${_pathDiag(_contacts[existingIndex].path, _contacts[existingIndex].pathLength)}', 'After merge: pathOverride=${_contacts[existingIndex].pathOverride}, devicePath=${_pathDiag(_contacts[existingIndex].path, _contacts[existingIndex].pathLength, _contacts[existingIndex].pathHashWidth)}',
tag: 'Connector', tag: 'Connector',
); );
} else { } else {
@ -4997,7 +5001,7 @@ class MeshCoreConnector extends ChangeNotifier {
isContact) { isContact) {
_contacts.add(contact); _contacts.add(contact);
appLogger.info( appLogger.info(
'Added new contact ${contact.name}: pathLen=${_pathDiag(contact.path, contact.pathLength)}', 'Added new contact ${contact.name}: pathLen=${_pathDiag(contact.path, contact.pathLength, contact.pathHashWidth)}',
tag: 'Connector', tag: 'Connector',
); );
} else { } else {
@ -5085,7 +5089,7 @@ class MeshCoreConnector extends ChangeNotifier {
); );
appLogger.info( appLogger.info(
'After merge: pathOverride=${_contacts[existingIndex].pathOverride}, devicePath=${_pathDiag(_contacts[existingIndex].path, _contacts[existingIndex].pathLength)}', 'After merge: pathOverride=${_contacts[existingIndex].pathOverride}, devicePath=${_pathDiag(_contacts[existingIndex].path, _contacts[existingIndex].pathLength, _contacts[existingIndex].pathHashWidth)}',
tag: 'Connector', tag: 'Connector',
); );
} else { } else {
@ -7207,7 +7211,7 @@ class MeshCoreConnector extends ChangeNotifier {
: existing.lastMessageAt; : existing.lastMessageAt;
appLogger.info( appLogger.info(
'Refreshing contact ${existing.name}: devicePath=${_pathDiag(existing.path, existing.pathLength)}, existingOverride=${existing.pathOverride}', 'Refreshing contact ${existing.name}: devicePath=${_pathDiag(existing.path, existing.pathLength, existing.pathHashWidth)}, existingOverride=${existing.pathOverride}',
tag: 'Connector', tag: 'Connector',
); );
@ -7233,7 +7237,7 @@ class MeshCoreConnector extends ChangeNotifier {
_updateDirectRepeater(_contacts[existingIndex], snr, path); _updateDirectRepeater(_contacts[existingIndex], snr, path);
appLogger.info( appLogger.info(
'After merge: pathOverride=${_contacts[existingIndex].pathOverride}, devicePath=${_pathDiag(_contacts[existingIndex].path, _contacts[existingIndex].pathLength)}', 'After merge: pathOverride=${_contacts[existingIndex].pathOverride}, devicePath=${_pathDiag(_contacts[existingIndex].path, _contacts[existingIndex].pathLength, _contacts[existingIndex].pathHashWidth)}',
tag: 'Connector', tag: 'Connector',
); );
} }

Loading…
Cancel
Save

Powered by TurnKey Linux.