mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 08:20:36 +00:00
Prevent duplicate channel messages
This commit is contained in:
@@ -646,11 +646,18 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
if (existing.channelIdx != message.channelIdx) {
|
if (existing.channelIdx != message.channelIdx) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final timestampDeltaSeconds = (existing.senderTimestamp -
|
||||||
|
message.senderTimestamp)
|
||||||
|
.abs();
|
||||||
|
final withinChannelRepeatWindow = timestampDeltaSeconds <= 5;
|
||||||
|
|
||||||
final existingSenderKey = existing.senderKeyShort;
|
final existingSenderKey = existing.senderKeyShort;
|
||||||
final incomingSenderKey = message.senderKeyShort;
|
final incomingSenderKey = message.senderKeyShort;
|
||||||
if (existingSenderKey != null &&
|
if (existingSenderKey != null &&
|
||||||
incomingSenderKey != null &&
|
incomingSenderKey != null &&
|
||||||
existingSenderKey == incomingSenderKey) {
|
existingSenderKey == incomingSenderKey &&
|
||||||
|
withinChannelRepeatWindow) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -663,23 +670,20 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When we send to a channel we add a local "sent" bubble immediately,
|
if (!withinChannelRepeatWindow) {
|
||||||
// then firmware may later sync back the same message as a received
|
return false;
|
||||||
// channel item under our public handle. Only fold that replay into the
|
}
|
||||||
// original bubble after LOG_RX_DATA has already confirmed it as our
|
|
||||||
// transmitted packet.
|
// Mirror meshcore-open behavior for self-authored channel messages:
|
||||||
|
// zero-hop self replays are dropped earlier in AppProvider, while
|
||||||
|
// routed self replays should fold into the local sent bubble when the
|
||||||
|
// public sender name matches within a short window.
|
||||||
if (existing.isSentMessage &&
|
if (existing.isSentMessage &&
|
||||||
existing.echoCount > 0 &&
|
|
||||||
!message.isSentMessage &&
|
!message.isSentMessage &&
|
||||||
(existing.senderTimestamp - message.senderTimestamp).abs() <= 1) {
|
existingSenderName == incomingSenderName) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (existing.isSentMessage &&
|
|
||||||
existing.echoCount > 0 &&
|
|
||||||
!message.isSentMessage &&
|
|
||||||
existing.senderTimestamp == message.senderTimestamp) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'channel replay is deduped after raw echo detection confirms our send',
|
'channel replay is deduped for self sender within repeat window',
|
||||||
() {
|
() {
|
||||||
final provider = MessagesProvider();
|
final provider = MessagesProvider();
|
||||||
provider.resolveContactNameCallback = (_) => 'dz0ny (SI)';
|
provider.resolveContactNameCallback = (_) => 'dz0ny (SI)';
|
||||||
@@ -185,12 +185,11 @@ void main() {
|
|||||||
_buildSentChannelMessage(id: 'c-echo', senderTimestamp: 1700000100),
|
_buildSentChannelMessage(id: 'c-echo', senderTimestamp: 1700000100),
|
||||||
);
|
);
|
||||||
provider.markMessageSent('c-echo', 0, 0);
|
provider.markMessageSent('c-echo', 0, 0);
|
||||||
provider.handleMessageEcho('c-echo', 1, 12, -90);
|
|
||||||
|
|
||||||
provider.addMessage(
|
provider.addMessage(
|
||||||
_buildReceivedChannelReplay(
|
_buildReceivedChannelReplay(
|
||||||
id: 'c-echo-incoming',
|
id: 'c-echo-incoming',
|
||||||
senderTimestamp: 1700000101,
|
senderTimestamp: 1700000104,
|
||||||
senderName: 'dz0ny (SI)',
|
senderName: 'dz0ny (SI)',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -202,7 +201,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'channel replay is not deduped before raw echo detection confirms it',
|
'channel replay is not deduped for different sender with same text',
|
||||||
() {
|
() {
|
||||||
final provider = MessagesProvider();
|
final provider = MessagesProvider();
|
||||||
provider.resolveContactNameCallback = (_) => 'dz0ny (SI)';
|
provider.resolveContactNameCallback = (_) => 'dz0ny (SI)';
|
||||||
@@ -218,7 +217,7 @@ void main() {
|
|||||||
_buildReceivedChannelReplay(
|
_buildReceivedChannelReplay(
|
||||||
id: 'c-no-echo-incoming',
|
id: 'c-no-echo-incoming',
|
||||||
senderTimestamp: 1700000201,
|
senderTimestamp: 1700000201,
|
||||||
senderName: 'dz0ny (SI)',
|
senderName: 'Radio Alpha',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -226,6 +225,25 @@ void main() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test('channel replay is not deduped outside repeat window', () {
|
||||||
|
final provider = MessagesProvider();
|
||||||
|
provider.resolveContactNameCallback = (_) => 'dz0ny (SI)';
|
||||||
|
provider.addSentMessage(
|
||||||
|
_buildSentChannelMessage(id: 'c-late', senderTimestamp: 1700000300),
|
||||||
|
);
|
||||||
|
provider.markMessageSent('c-late', 0, 0);
|
||||||
|
|
||||||
|
provider.addMessage(
|
||||||
|
_buildReceivedChannelReplay(
|
||||||
|
id: 'c-late-incoming',
|
||||||
|
senderTimestamp: 1700000306,
|
||||||
|
senderName: 'dz0ny (SI)',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(provider.messages, hasLength(2));
|
||||||
|
});
|
||||||
|
|
||||||
test('missing ACK schedules a delayed retransmission', () {
|
test('missing ACK schedules a delayed retransmission', () {
|
||||||
fakeAsync((async) {
|
fakeAsync((async) {
|
||||||
final provider = MessagesProvider();
|
final provider = MessagesProvider();
|
||||||
|
|||||||
Reference in New Issue
Block a user