diff --git a/repeater/engine.py b/repeater/engine.py index 6d95c78..16f1d9e 100644 --- a/repeater/engine.py +++ b/repeater/engine.py @@ -132,7 +132,7 @@ async def __call__(self, packet: Packet, metadata: Optional[dict] = None, local_ # For local transmissions, create a direct transmission result if local_transmission and not monitor_mode: # Mark local packet as seen to prevent duplicate processing when received back - self.mark_seen(packet) + self.has_seen(packet) # Calculate transmission delay for local packets delay = self._calculate_tx_delay(packet, snr) result = (packet, delay) @@ -320,10 +320,6 @@ def cleanup_cache(self): del self.seen_packets[k] def _get_drop_reason(self, packet: Packet) -> str: - - if self.is_duplicate(packet): - return "Duplicate" - if not packet or not packet.payload: return "Empty payload" @@ -348,20 +344,14 @@ def _get_drop_reason(self, packet: Packet) -> str: # Default reason return "Unknown" - def is_duplicate(self, packet: Packet) -> bool: - + def has_seen(self, packet: Packet) -> bool: pkt_hash = packet.calculate_packet_hash().hex().upper() if pkt_hash in self.seen_packets: return True - return False - - def mark_seen(self, packet: Packet): - - pkt_hash = packet.calculate_packet_hash().hex().upper() self.seen_packets[pkt_hash] = time.time() - if len(self.seen_packets) > self.max_cache_size: self.seen_packets.popitem(last=False) + return False def validate_packet(self, packet: Packet) -> Tuple[bool, str]: @@ -482,8 +472,7 @@ def flood_forward(self, packet: Packet) -> Optional[Packet]: packet.drop_reason = "Global flood policy disabled" return None - # Suppress duplicates - if self.is_duplicate(packet): + if self.has_seen(packet): packet.drop_reason = "Duplicate" return None @@ -495,8 +484,6 @@ def flood_forward(self, packet: Packet) -> Optional[Packet]: packet.path.append(self.local_hash) packet.path_len = len(packet.path) - self.mark_seen(packet) - return packet def direct_forward(self, packet: Packet) -> Optional[Packet]: @@ -506,12 +493,15 @@ def direct_forward(self, packet: Packet) -> Optional[Packet]: packet.drop_reason = "Direct: no path" return None - next_hop = packet.path[0] + next_hop = packet.path[0] if next_hop != self.local_hash: packet.drop_reason = "Direct: not for us" return None - original_path = list(packet.path) + if self.has_seen(packet): + packet.drop_reason = "Duplicate" + return None + packet.path = bytearray(packet.path[1:]) packet.path_len = len(packet.path) diff --git a/repeater/handler_helpers/trace.py b/repeater/handler_helpers/trace.py index 0a84dbf..4cad93c 100644 --- a/repeater/handler_helpers/trace.py +++ b/repeater/handler_helpers/trace.py @@ -201,7 +201,7 @@ def _should_forward_trace(self, packet, trace_path: list, trace_path_len: int) - return (packet.path_len < trace_path_len and len(trace_path) > packet.path_len and trace_path[packet.path_len] == self.local_hash and - self.repeater_handler and not self.repeater_handler.is_duplicate(packet)) + self.repeater_handler and not self.repeater_handler.has_seen(packet)) async def _forward_trace_packet(self, packet, trace_path_len: int) -> None: """ @@ -267,5 +267,5 @@ def _log_no_forward_reason(self, packet, trace_path: list, trace_path_len: int) elif trace_path[packet.path_len] != self.local_hash: expected_hash = trace_path[packet.path_len] if packet.path_len < len(trace_path) else None logger.info(f"Not our turn (next hop: 0x{expected_hash:02x})") - elif self.repeater_handler and self.repeater_handler.is_duplicate(packet): + else: logger.info("Duplicate packet, ignoring") diff --git a/repeater/main.py b/repeater/main.py index ef11e51..f06edc5 100644 --- a/repeater/main.py +++ b/repeater/main.py @@ -208,7 +208,7 @@ async def send_advert(self) -> bool: # Mark our own advert as seen to prevent re-forwarding it if self.repeater_handler: - self.repeater_handler.mark_seen(packet) + self.repeater_handler.has_seen(packet) logger.debug("Marked own advert as seen in duplicate cache") logger.info(f"Sent flood advert '{node_name}' at ({latitude: .6f}, {longitude: .6f})")