mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-06-22 19:14:49 +02:00
Don't dedupe adverts on payload (since what we care about is the path)
This commit is contained in:
@@ -521,8 +521,10 @@ async def process_raw_packet(
|
||||
if decrypt_result:
|
||||
result.update(decrypt_result)
|
||||
|
||||
elif payload_type == PayloadType.ADVERT and is_new_packet:
|
||||
# Only process new advertisements (duplicates don't add value)
|
||||
elif payload_type == PayloadType.ADVERT:
|
||||
# Process all advert arrivals (even payload-hash duplicates) so the
|
||||
# path-freshness logic in _process_advertisement can pick the shortest
|
||||
# path heard within the freshness window.
|
||||
await _process_advertisement(raw_bytes, ts, packet_info)
|
||||
|
||||
elif payload_type == PayloadType.TEXT_MESSAGE:
|
||||
|
||||
@@ -1651,7 +1651,11 @@ export function PacketVisualizer3D({
|
||||
</>
|
||||
)}
|
||||
<div
|
||||
className={!showControls ? 'flex flex-col gap-2' : 'border-t border-border pt-2 mt-1 flex flex-col gap-2'}
|
||||
className={
|
||||
!showControls
|
||||
? 'flex flex-col gap-2'
|
||||
: 'border-t border-border pt-2 mt-1 flex flex-col gap-2'
|
||||
}
|
||||
>
|
||||
<label className="flex items-center gap-2 cursor-pointer">
|
||||
<Checkbox
|
||||
|
||||
@@ -14,7 +14,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
||||
import pytest
|
||||
|
||||
from app.database import Database
|
||||
from app.decoder import DecryptedDirectMessage, PacketInfo, PayloadType
|
||||
from app.decoder import DecryptedDirectMessage, PacketInfo, ParsedAdvertisement, PayloadType
|
||||
from app.repository import (
|
||||
ChannelRepository,
|
||||
ContactRepository,
|
||||
@@ -1552,8 +1552,9 @@ class TestProcessRawPacketIntegration:
|
||||
assert mock_gt.await_count == 2
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_dispatches_advert_only_for_new_packets(self, test_db, captured_broadcasts):
|
||||
"""ADVERT packets are dispatched only when is_new_packet is True."""
|
||||
async def test_dispatches_advert_for_all_arrivals(self, test_db, captured_broadcasts):
|
||||
"""ADVERT packets are dispatched for every arrival (including duplicates)
|
||||
so path-freshness logic can pick the shortest path."""
|
||||
from app.packet_processor import process_raw_packet
|
||||
|
||||
broadcasts, mock_broadcast = captured_broadcasts
|
||||
@@ -1575,12 +1576,64 @@ class TestProcessRawPacketIntegration:
|
||||
"app.packet_processor._process_advertisement",
|
||||
new_callable=AsyncMock,
|
||||
) as mock_adv:
|
||||
# First call: new packet -> should dispatch
|
||||
# Both calls should dispatch so path logic can compare
|
||||
await process_raw_packet(raw, timestamp=3000)
|
||||
# Second call: duplicate -> should NOT dispatch
|
||||
await process_raw_packet(raw, timestamp=3001)
|
||||
|
||||
assert mock_adv.await_count == 1
|
||||
assert mock_adv.await_count == 2
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_duplicate_advert_shorter_path_wins(self, test_db, captured_broadcasts):
|
||||
"""When the same advert arrives via a shorter path, the contact path is updated."""
|
||||
from app.packet_processor import process_raw_packet
|
||||
|
||||
broadcasts, mock_broadcast = captured_broadcasts
|
||||
|
||||
test_pubkey = "ab" * 32 # 64-char hex
|
||||
|
||||
long_path_info = PacketInfo(
|
||||
route_type=1,
|
||||
payload_type=PayloadType.ADVERT,
|
||||
payload_version=0,
|
||||
path_length=3,
|
||||
path=bytes.fromhex("aabbcc"),
|
||||
payload=b"\x00" * 101,
|
||||
)
|
||||
short_path_info = PacketInfo(
|
||||
route_type=1,
|
||||
payload_type=PayloadType.ADVERT,
|
||||
payload_version=0,
|
||||
path_length=1,
|
||||
path=bytes.fromhex("dd"),
|
||||
payload=b"\x00" * 101,
|
||||
)
|
||||
|
||||
advert = ParsedAdvertisement(
|
||||
public_key=test_pubkey,
|
||||
name="TestNode",
|
||||
timestamp=5000,
|
||||
lat=None,
|
||||
lon=None,
|
||||
device_role=1,
|
||||
)
|
||||
|
||||
# Same raw bytes → same payload hash → second call is a duplicate
|
||||
raw = b"\x11\x00" + b"\xee" * 30
|
||||
|
||||
with patch("app.packet_processor.broadcast_event", mock_broadcast):
|
||||
with patch("app.packet_processor.parse_advertisement", return_value=advert):
|
||||
# First arrival: long path
|
||||
with patch("app.packet_processor.parse_packet", return_value=long_path_info):
|
||||
await process_raw_packet(raw, timestamp=5000)
|
||||
|
||||
# Second arrival (duplicate payload): shorter path
|
||||
with patch("app.packet_processor.parse_packet", return_value=short_path_info):
|
||||
await process_raw_packet(raw, timestamp=5001)
|
||||
|
||||
contact = await ContactRepository.get_by_key(test_pubkey)
|
||||
assert contact is not None
|
||||
assert contact.last_path_len == 1 # Shorter path won
|
||||
assert contact.last_path == "dd"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_dispatches_text_message(self, test_db, captured_broadcasts):
|
||||
|
||||
Reference in New Issue
Block a user