From e7a317f0a0b835962d54f8682871af3f46ab158d Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Fri, 15 May 2026 17:08:22 +0200 Subject: [PATCH] Use canonical Transport interface list add/removes. Improved announce cache cleaning. Adjusted logging. --- RNS/Discovery.py | 2 +- RNS/Interfaces/AutoInterface.py | 4 ++-- RNS/Interfaces/BackboneInterface.py | 7 +++---- RNS/Interfaces/I2PInterface.py | 9 ++++----- RNS/Interfaces/LocalInterface.py | 7 +++---- RNS/Interfaces/RNodeMultiInterface.py | 5 ++--- RNS/Interfaces/TCPInterface.py | 7 +++---- RNS/Interfaces/WeaveInterface.py | 5 ++--- RNS/Reticulum.py | 8 ++++---- RNS/Transport.py | 29 ++++++++++++++++++--------- 10 files changed, 44 insertions(+), 39 deletions(-) diff --git a/RNS/Discovery.py b/RNS/Discovery.py index b7a25209..5fde400d 100644 --- a/RNS/Discovery.py +++ b/RNS/Discovery.py @@ -576,7 +576,7 @@ class InterfaceDiscovery(): def teardown_interface(self, interface): interface.detach() - if interface in RNS.Transport.interfaces: RNS.Transport.interfaces.remove(interface) + RNS.Transport.remove_interface(interface) if interface in self.monitored_interfaces: self.monitored_interfaces.remove(interface) def autoconnect_count(self): diff --git a/RNS/Interfaces/AutoInterface.py b/RNS/Interfaces/AutoInterface.py index 0a95bd00..41fbc849 100644 --- a/RNS/Interfaces/AutoInterface.py +++ b/RNS/Interfaces/AutoInterface.py @@ -574,7 +574,7 @@ class AutoInterface(Interface): spawned_interface.mode = self.mode spawned_interface.HW_MTU = self.HW_MTU spawned_interface.online = True - RNS.Transport.interfaces.append(spawned_interface) + RNS.Transport.add_interface(spawned_interface) if addr in self.spawned_interfaces: self.spawned_interfaces[addr].detach() self.spawned_interfaces[addr].teardown() @@ -666,7 +666,7 @@ class AutoInterfacePeer(Interface): except Exception as e: RNS.log(f"Could not remove {self} from parent interface on detach. The contained exception was: {e}", RNS.LOG_ERROR) - if self in RNS.Transport.interfaces: RNS.Transport.interfaces.remove(self) + RNS.Transport.remove_interface(self) class AutoInterfaceHandler(socketserver.BaseRequestHandler): def __init__(self, callback, *args, **keys): diff --git a/RNS/Interfaces/BackboneInterface.py b/RNS/Interfaces/BackboneInterface.py index c2a03c2a..2b5dfe59 100644 --- a/RNS/Interfaces/BackboneInterface.py +++ b/RNS/Interfaces/BackboneInterface.py @@ -454,7 +454,7 @@ class BackboneInterface(Interface): spawned_interface.HW_MTU = self.HW_MTU spawned_interface.online = True RNS.log("Spawned new BackboneClient Interface: "+str(spawned_interface), RNS.LOG_VERBOSE) - RNS.Transport.interfaces.append(spawned_interface) + RNS.Transport.add_interface(spawned_interface) while spawned_interface in self.spawned_interfaces: self.spawned_interfaces.remove(spawned_interface) self.spawned_interfaces.append(spawned_interface) BackboneInterface.add_client_socket(socket, spawned_interface) @@ -769,9 +769,8 @@ class BackboneClientInterface(Interface): while self in self.parent_interface.spawned_interfaces: self.parent_interface.spawned_interfaces.remove(self) - if self in RNS.Transport.interfaces: - if not self.initiator: - RNS.Transport.interfaces.remove(self) + if not self.initiator: + RNS.Transport.remove_interface(self) def __str__(self): diff --git a/RNS/Interfaces/I2PInterface.py b/RNS/Interfaces/I2PInterface.py index 0229d723..532fafcb 100644 --- a/RNS/Interfaces/I2PInterface.py +++ b/RNS/Interfaces/I2PInterface.py @@ -826,9 +826,8 @@ class I2PInterfacePeer(Interface): while self in self.parent_interface.spawned_interfaces: self.parent_interface.spawned_interfaces.remove(self) - if self in RNS.Transport.interfaces: - if not self.initiator: - RNS.Transport.interfaces.remove(self) + if not self.initiator: + RNS.Transport.remove_interface(self) def __str__(self): @@ -940,7 +939,7 @@ class I2PInterface(Interface): peer_interface.IN = True peer_interface.parent_interface = self peer_interface.parent_count = False - RNS.Transport.interfaces.append(peer_interface) + RNS.Transport.add_interface(peer_interface) def incoming_connection(self, handler): RNS.log("Accepting incoming I2P connection", RNS.LOG_VERBOSE) @@ -993,7 +992,7 @@ class I2PInterface(Interface): spawned_interface.mode = self.mode spawned_interface.HW_MTU = self.HW_MTU RNS.log("Spawned new I2PInterface Peer: "+str(spawned_interface), RNS.LOG_VERBOSE) - RNS.Transport.interfaces.append(spawned_interface) + RNS.Transport.add_interface(spawned_interface) while spawned_interface in self.spawned_interfaces: self.spawned_interfaces.remove(spawned_interface) self.spawned_interfaces.append(spawned_interface) diff --git a/RNS/Interfaces/LocalInterface.py b/RNS/Interfaces/LocalInterface.py index e1ae6c53..a214c124 100644 --- a/RNS/Interfaces/LocalInterface.py +++ b/RNS/Interfaces/LocalInterface.py @@ -347,8 +347,7 @@ class LocalClientInterface(Interface): self.OUT = False self.IN = False - if self in RNS.Transport.interfaces: - RNS.Transport.interfaces.remove(self) + RNS.Transport.remove_interface(self) if self in RNS.Transport.local_client_interfaces: RNS.Transport.local_client_interfaces.remove(self) @@ -458,7 +457,7 @@ class LocalServerInterface(Interface): spawned_interface.socket_path = self.socket_path if hasattr(self, "_force_bitrate"): spawned_interface._force_bitrate = self._force_bitrate - RNS.Transport.interfaces.append(spawned_interface) + RNS.Transport.add_interface(spawned_interface) RNS.Transport.local_client_interfaces.append(spawned_interface) BackboneInterface.add_client_socket(client_socket, spawned_interface) self.clients += 1 @@ -474,7 +473,7 @@ class LocalServerInterface(Interface): spawned_interface.parent_interface = self spawned_interface.bitrate = self.bitrate if hasattr(self, "_force_bitrate"): spawned_interface._force_bitrate = self._force_bitrate - RNS.Transport.interfaces.append(spawned_interface) + RNS.Transport.add_interface(spawned_interface) RNS.Transport.local_client_interfaces.append(spawned_interface) self.clients += 1 spawned_interface.read_loop() diff --git a/RNS/Interfaces/RNodeMultiInterface.py b/RNS/Interfaces/RNodeMultiInterface.py index c6416279..d311e736 100644 --- a/RNS/Interfaces/RNodeMultiInterface.py +++ b/RNS/Interfaces/RNodeMultiInterface.py @@ -375,7 +375,7 @@ class RNodeMultiInterface(Interface): interface.mode = self.mode interface.HW_MTU = self.HW_MTU interface.detected = True - RNS.Transport.interfaces.append(interface) + RNS.Transport.add_interface(interface) RNS.log("Spawned new RNode subinterface: "+str(interface), RNS.LOG_VERBOSE) self.clients += 1 @@ -909,8 +909,7 @@ class RNodeMultiInterface(Interface): def teardown_subinterfaces(self): for interface in self.subinterfaces: if interface != 0: - if interface in RNS.Transport.interfaces: - RNS.Transport.interfaces.remove(interface) + RNS.Transport.remove_interface(interface) self.subinterfaces[interface.index] = 0 def should_ingress_limit(self): diff --git a/RNS/Interfaces/TCPInterface.py b/RNS/Interfaces/TCPInterface.py index 547f59de..a5566e31 100644 --- a/RNS/Interfaces/TCPInterface.py +++ b/RNS/Interfaces/TCPInterface.py @@ -436,9 +436,8 @@ class TCPClientInterface(Interface): while self in self.parent_interface.spawned_interfaces: self.parent_interface.spawned_interfaces.remove(self) - if self in RNS.Transport.interfaces: - if not self.initiator: - RNS.Transport.interfaces.remove(self) + if not self.initiator: + RNS.Transport.remove_interface(self) def __str__(self): @@ -627,7 +626,7 @@ class TCPServerInterface(Interface): spawned_interface.HW_MTU = self.HW_MTU spawned_interface.online = True RNS.log("Spawned new TCPClient Interface: "+str(spawned_interface), RNS.LOG_VERBOSE) - RNS.Transport.interfaces.append(spawned_interface) + RNS.Transport.add_interface(spawned_interface) while spawned_interface in self.spawned_interfaces: self.spawned_interfaces.remove(spawned_interface) self.spawned_interfaces.append(spawned_interface) diff --git a/RNS/Interfaces/WeaveInterface.py b/RNS/Interfaces/WeaveInterface.py index 8acdc184..626f2837 100644 --- a/RNS/Interfaces/WeaveInterface.py +++ b/RNS/Interfaces/WeaveInterface.py @@ -981,7 +981,7 @@ class WeaveInterface(Interface): spawned_interface.mode = self.mode spawned_interface.HW_MTU = self.HW_MTU spawned_interface._online = True - RNS.Transport.interfaces.append(spawned_interface) + RNS.Transport.add_interface(spawned_interface) if endpoint_addr in self.spawned_interfaces: self.spawned_interfaces[endpoint_addr].detach() self.spawned_interfaces[endpoint_addr].teardown() @@ -1097,5 +1097,4 @@ class WeaveInterfacePeer(Interface): except Exception as e: RNS.log(f"Could not remove {self} from parent interface on detach. The contained exception was: {e}", RNS.LOG_ERROR) - if self in RNS.Transport.interfaces: - RNS.Transport.interfaces.remove(self) + RNS.Transport.remove_interface(self) diff --git a/RNS/Reticulum.py b/RNS/Reticulum.py index 37f1287d..c15892d9 100755 --- a/RNS/Reticulum.py +++ b/RNS/Reticulum.py @@ -402,7 +402,7 @@ class Reticulum: RNS.log("Existing shared instance required, but this instance started as shared instance. Aborting startup.", RNS.LOG_VERBOSE) else: - RNS.Transport.interfaces.append(interface) + RNS.Transport.add_interface(interface) self.shared_instance_interface = interface self.is_shared_instance = True RNS.log("Started shared instance interface: "+str(interface), RNS.LOG_DEBUG) @@ -422,7 +422,7 @@ class Reticulum: interface._force_bitrate = True RNS.log(f"Forcing shared instance bitrate of {RNS.prettyspeed(interface.bitrate)}", RNS.LOG_WARNING) interface.optimise_mtu() - RNS.Transport.interfaces.append(interface) + RNS.Transport.add_interface(interface) self.is_shared_instance = False self.is_standalone_instance = False self.is_connected_to_shared_instance = True @@ -915,7 +915,7 @@ class Reticulum: interface.ifac_identity = RNS.Identity.from_bytes(interface.ifac_key) interface.ifac_signature = interface.ifac_identity.sign(RNS.Identity.full_hash(interface.ifac_key)) - RNS.Transport.interfaces.append(interface) + RNS.Transport.add_interface(interface) interface.final_init() interface = None @@ -1077,7 +1077,7 @@ class Reticulum: interface.ifac_identity = RNS.Identity.from_bytes(interface.ifac_key) interface.ifac_signature = interface.ifac_identity.sign(RNS.Identity.full_hash(interface.ifac_key)) - RNS.Transport.interfaces.append(interface) + RNS.Transport.add_interface(interface) interface.final_init() def _default_ar_target(self): diff --git a/RNS/Transport.py b/RNS/Transport.py index 4a67d270..ac971da5 100755 --- a/RNS/Transport.py +++ b/RNS/Transport.py @@ -417,6 +417,18 @@ class Transport: gc.collect() + @staticmethod + def add_interface(interface): + with Transport.interfaces_lock: + if not interface in Transport.interfaces: + Transport.interfaces.append(interface) + + @staticmethod + def remove_interface(interface): + with Transport.interfaces_lock: + if interface in Transport.interfaces: + Transport.interfaces.remove(interface) + @staticmethod def set_network_identity(identity): if not Transport.network_identity: @@ -1594,7 +1606,7 @@ class Transport: RNS.log(f"Clamping link MTU to {RNS.prettysize(path_mtu)}", RNS.LOG_DEBUG) if RNS.sl(RNS.LOG_DEBUG) else None new_raw = new_raw[:-RNS.Link.LINK_MTU_SIZE]+clamped_mtu except Exception as e: - RNS.log(f"Dropping link request packet. The contained exception was: {e}", RNS.LOG_WARNING) + RNS.log(f"Dropping link request packet. The contained exception was: {e}", RNS.LOG_DEBUG) if RNS.sl(RNS.LOG_DEBUG) else None return # Entry format is @@ -2518,16 +2530,17 @@ class Transport: def clean_announce_cache(): st = time.time() target_path = os.path.join(RNS.Reticulum.cachepath, "announces") - with Transport.path_table_lock: active_paths = [Transport.path_table[dst_hash][6] for dst_hash in Transport.path_table] - with Transport.tunnels_lock: tunnel_paths = list(set([path_dict[dst_hash][6] for path_dict in [Transport.tunnels[tunnel_id][2] for tunnel_id in Transport.tunnels] for dst_hash in path_dict])) + cached_announce_hashes = os.listdir(target_path) + with Transport.path_table_lock: active_path_hashes = list(set([Transport.path_table[dst_hash][IDX_PT_PACKET] for dst_hash in Transport.path_table])) + with Transport.tunnels_lock: tunnel_path_hashes = list(set([path_dict[dst_hash][IDX_PT_PACKET] for path_dict in [Transport.tunnels[tunnel_id][IDX_TT_PATHS] for tunnel_id in Transport.tunnels] for dst_hash in path_dict])) removed = 0; total = 0 - for packet_hash in os.listdir(target_path): + for packet_hash in cached_announce_hashes: remove = False full_path = os.path.join(target_path, packet_hash) if os.path.isfile(full_path): try: target_hash = bytes.fromhex(packet_hash) except: remove = True - if (not target_hash in active_paths) and (not target_hash in tunnel_paths): remove = True + if (not target_hash in active_path_hashes) and (not target_hash in tunnel_path_hashes): remove = True if remove: os.unlink(full_path); removed += 1 total += 1 @@ -2889,10 +2902,8 @@ class Transport: tag=tag_bytes) else: RNS.log("Ignoring duplicate path request for "+RNS.prettyhexrep(destination_hash)+" with tag "+RNS.prettyhexrep(unique_tag), RNS.LOG_EXTREME) if RNS.sl(RNS.LOG_EXTREME) else None - else: RNS.log("Ignoring tagless path request for "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG) if RNS.sl(RNS.LOG_DEBUG) else None - - except Exception as e: RNS.log("Error while handling path request. The contained exception was: "+str(e), RNS.LOG_ERROR) + except Exception as e: RNS.log(f"Error while handling path request. The contained exception was: {e}", RNS.LOG_ERROR) @staticmethod def path_request(destination_hash, is_from_local_client, attached_interface, requestor_transport_id=None, tag=None): @@ -2933,7 +2944,7 @@ class Transport: received_from = Transport.path_table[destination_hash][IDX_PT_RVCD_IF] if packet == None: - RNS.log("Could not retrieve announce packet from cache while answering path request for "+RNS.prettyhexrep(destination_hash), RNS.LOG_WARNING) + RNS.log(f"Could not retrieve announce packet from cache while answering path request for {RNS.prettyhexrep(destination_hash)}, ignoring path request", RNS.LOG_DEBUG) if RNS.sl(RNS.LOG_DEBUG) else None elif attached_interface.mode == RNS.Interfaces.Interface.Interface.MODE_ROAMING and attached_interface == received_from: RNS.log("Not answering path request on roaming-mode interface, since next hop is on same roaming-mode interface", RNS.LOG_DEBUG) if RNS.sl(RNS.LOG_DEBUG) else None