From 0fd75cb819c12f33857c82a8ff96286dda336039 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Sat, 30 Sep 2023 19:11:10 +0200 Subject: [PATCH] Added announce frequency sampling to interfaces --- RNS/Interfaces/AX25KISSInterface.py | 3 +- RNS/Interfaces/AutoInterface.py | 4 +-- RNS/Interfaces/I2PInterface.py | 12 ++++--- RNS/Interfaces/Interface.py | 53 +++++++++++++++++++++++++++++ RNS/Interfaces/KISSInterface.py | 3 +- RNS/Interfaces/LocalInterface.py | 12 ++++--- RNS/Interfaces/PipeInterface.py | 3 +- RNS/Interfaces/RNodeInterface.py | 3 +- RNS/Interfaces/SerialInterface.py | 3 +- RNS/Interfaces/TCPInterface.py | 12 ++++--- RNS/Interfaces/UDPInterface.py | 3 +- 11 files changed, 84 insertions(+), 27 deletions(-) diff --git a/RNS/Interfaces/AX25KISSInterface.py b/RNS/Interfaces/AX25KISSInterface.py index bc70fb1..eea9e13 100644 --- a/RNS/Interfaces/AX25KISSInterface.py +++ b/RNS/Interfaces/AX25KISSInterface.py @@ -77,8 +77,7 @@ class AX25KISSInterface(Interface): RNS.log("You can install one with the command: python3 -m pip install pyserial", RNS.LOG_CRITICAL) RNS.panic() - self.rxb = 0 - self.txb = 0 + super().__init__() self.HW_MTU = 564 diff --git a/RNS/Interfaces/AutoInterface.py b/RNS/Interfaces/AutoInterface.py index 5405571..356829c 100644 --- a/RNS/Interfaces/AutoInterface.py +++ b/RNS/Interfaces/AutoInterface.py @@ -76,11 +76,9 @@ class AutoInterface(Interface): def __init__(self, owner, name, group_id=None, discovery_scope=None, discovery_port=None, data_port=None, allowed_interfaces=None, ignored_interfaces=None, configured_bitrate=None): from RNS.vendor.ifaddr import niwrapper + super().__init__() self.netinfo = niwrapper - self.rxb = 0 - self.txb = 0 - self.HW_MTU = 1064 self.IN = True diff --git a/RNS/Interfaces/I2PInterface.py b/RNS/Interfaces/I2PInterface.py index 80b749e..64dee4a 100644 --- a/RNS/Interfaces/I2PInterface.py +++ b/RNS/Interfaces/I2PInterface.py @@ -390,8 +390,7 @@ class I2PInterfacePeer(Interface): TUNNEL_STATE_STALE = 0x02 def __init__(self, parent_interface, owner, name, target_i2p_dest=None, connected_socket=None, max_reconnect_tries=None): - self.rxb = 0 - self.txb = 0 + super().__init__() self.HW_MTU = 1064 @@ -832,8 +831,7 @@ class I2PInterface(Interface): BITRATE_GUESS = 256*1000 def __init__(self, owner, name, rns_storagepath, peers, connectable = False, ifac_size = 16, ifac_netname = None, ifac_netkey = None): - self.rxb = 0 - self.txb = 0 + super().__init__() self.HW_MTU = 1064 @@ -964,6 +962,12 @@ class I2PInterface(Interface): def processOutgoing(self, data): pass + def received_announce(self, from_spawned=False): + if from_spawned: self.ia_freq_deque.append(time.time()) + + def sent_announce(self, from_spawned=False): + if from_spawned: self.oa_freq_deque.append(time.time()) + def detach(self): RNS.log("Detaching "+str(self), RNS.LOG_DEBUG) self.i2p.stop() diff --git a/RNS/Interfaces/Interface.py b/RNS/Interfaces/Interface.py index 816f314..9d1f969 100755 --- a/RNS/Interfaces/Interface.py +++ b/RNS/Interfaces/Interface.py @@ -23,6 +23,7 @@ import RNS import time import threading +from collections import deque class Interface: IN = False @@ -43,14 +44,65 @@ class Interface: # should actively discover paths for. DISCOVER_PATHS_FOR = [MODE_ACCESS_POINT, MODE_GATEWAY] + # How many samples to use for incoming + # announce frequency calculation + IA_FREQ_SAMPLES = 6 + OA_FREQ_SAMPLES = 6 + def __init__(self): self.rxb = 0 self.txb = 0 self.online = False + self.ia_freq_deque = deque(maxlen=Interface.IA_FREQ_SAMPLES) + self.oa_freq_deque = deque(maxlen=Interface.OA_FREQ_SAMPLES) def get_hash(self): return RNS.Identity.full_hash(str(self).encode("utf-8")) + def received_announce(self): + self.ia_freq_deque.append(time.time()) + if hasattr(self, "parent_interface") and self.parent_interface != None: + self.parent_interface.received_announce(from_spawned=True) + + def sent_announce(self): + self.oa_freq_deque.append(time.time()) + if hasattr(self, "parent_interface") and self.parent_interface != None: + self.parent_interface.sent_announce(from_spawned=True) + + def incoming_announce_frequency(self): + if not len(self.ia_freq_deque) > 1: + return 0 + else: + dq_len = len(self.ia_freq_deque) + delta_sum = 0 + for i in range(1,dq_len): + delta_sum += self.ia_freq_deque[i]-self.ia_freq_deque[i-1] + delta_sum += time.time() - self.ia_freq_deque[dq_len-1] + + if delta_sum == 0: + avg = 0 + else: + avg = 1/(delta_sum/(dq_len)) + + return avg + + def outgoing_announce_frequency(self): + if not len(self.oa_freq_deque) > 1: + return 0 + else: + dq_len = len(self.oa_freq_deque) + delta_sum = 0 + for i in range(1,dq_len): + delta_sum += self.oa_freq_deque[i]-self.oa_freq_deque[i-1] + delta_sum += time.time() - self.oa_freq_deque[dq_len-1] + + if delta_sum == 0: + avg = 0 + else: + avg = 1/(delta_sum/(dq_len)) + + return avg + def process_announce_queue(self): if not hasattr(self, "announce_cap"): self.announce_cap = RNS.Reticulum.ANNOUNCE_CAP @@ -79,6 +131,7 @@ class Interface: self.announce_allowed_at = now + wait_time self.processOutgoing(selected["raw"]) + self.sent_announce() if selected in self.announce_queue: self.announce_queue.remove(selected) diff --git a/RNS/Interfaces/KISSInterface.py b/RNS/Interfaces/KISSInterface.py index e70a12e..68f4fdb 100644 --- a/RNS/Interfaces/KISSInterface.py +++ b/RNS/Interfaces/KISSInterface.py @@ -70,8 +70,7 @@ class KISSInterface(Interface): RNS.log("You can install one with the command: python3 -m pip install pyserial", RNS.LOG_CRITICAL) RNS.panic() - self.rxb = 0 - self.txb = 0 + super().__init__() self.HW_MTU = 564 diff --git a/RNS/Interfaces/LocalInterface.py b/RNS/Interfaces/LocalInterface.py index a8433b2..624cbe4 100644 --- a/RNS/Interfaces/LocalInterface.py +++ b/RNS/Interfaces/LocalInterface.py @@ -53,8 +53,7 @@ class LocalClientInterface(Interface): RECONNECT_WAIT = 3 def __init__(self, owner, name, target_port = None, connected_socket=None): - self.rxb = 0 - self.txb = 0 + super().__init__() # TODO: Remove at some point # self.rxptime = 0 @@ -280,8 +279,7 @@ class LocalClientInterface(Interface): class LocalServerInterface(Interface): def __init__(self, owner, bindport=None): - self.rxb = 0 - self.txb = 0 + super().__init__() self.online = False self.clients = 0 @@ -338,6 +336,12 @@ class LocalServerInterface(Interface): def processOutgoing(self, data): pass + def received_announce(self, from_spawned=False): + if from_spawned: self.ia_freq_deque.append(time.time()) + + def sent_announce(self, from_spawned=False): + if from_spawned: self.oa_freq_deque.append(time.time()) + def __str__(self): return "Shared Instance["+str(self.bind_port)+"]" diff --git a/RNS/Interfaces/PipeInterface.py b/RNS/Interfaces/PipeInterface.py index 1b5b88a..ffe5c9e 100644 --- a/RNS/Interfaces/PipeInterface.py +++ b/RNS/Interfaces/PipeInterface.py @@ -54,8 +54,7 @@ class PipeInterface(Interface): if respawn_delay == None: respawn_delay = 5 - self.rxb = 0 - self.txb = 0 + super().__init__() self.HW_MTU = 1064 diff --git a/RNS/Interfaces/RNodeInterface.py b/RNS/Interfaces/RNodeInterface.py index a29d5f5..475b090 100644 --- a/RNS/Interfaces/RNodeInterface.py +++ b/RNS/Interfaces/RNodeInterface.py @@ -114,8 +114,7 @@ class RNodeInterface(Interface): RNS.log("You can install one with the command: python3 -m pip install pyserial", RNS.LOG_CRITICAL) RNS.panic() - self.rxb = 0 - self.txb = 0 + super().__init__() self.HW_MTU = 508 diff --git a/RNS/Interfaces/SerialInterface.py b/RNS/Interfaces/SerialInterface.py index 91c60a5..b787d0c 100755 --- a/RNS/Interfaces/SerialInterface.py +++ b/RNS/Interfaces/SerialInterface.py @@ -60,8 +60,7 @@ class SerialInterface(Interface): RNS.log("You can install one with the command: python3 -m pip install pyserial", RNS.LOG_CRITICAL) RNS.panic() - self.rxb = 0 - self.txb = 0 + super().__init__() self.HW_MTU = 564 diff --git a/RNS/Interfaces/TCPInterface.py b/RNS/Interfaces/TCPInterface.py index 4074c06..06d6bd6 100644 --- a/RNS/Interfaces/TCPInterface.py +++ b/RNS/Interfaces/TCPInterface.py @@ -79,8 +79,7 @@ class TCPClientInterface(Interface): I2P_PROBES = 5 def __init__(self, owner, name, target_ip=None, target_port=None, connected_socket=None, max_reconnect_tries=None, kiss_framing=False, i2p_tunneled = False, connect_timeout = None): - self.rxb = 0 - self.txb = 0 + super().__init__() self.HW_MTU = 1064 @@ -419,8 +418,7 @@ class TCPServerInterface(Interface): return ifaddr[netinfo.AF_INET][0]["broadcast"] def __init__(self, owner, name, device=None, bindip=None, bindport=None, i2p_tunneled=False): - self.rxb = 0 - self.txb = 0 + super().__init__() self.HW_MTU = 1064 @@ -505,6 +503,12 @@ class TCPServerInterface(Interface): self.clients += 1 spawned_interface.read_loop() + def received_announce(self, from_spawned=False): + if from_spawned: self.ia_freq_deque.append(time.time()) + + def sent_announce(self, from_spawned=False): + if from_spawned: self.oa_freq_deque.append(time.time()) + def processOutgoing(self, data): pass diff --git a/RNS/Interfaces/UDPInterface.py b/RNS/Interfaces/UDPInterface.py index e2d8d57..f230af9 100644 --- a/RNS/Interfaces/UDPInterface.py +++ b/RNS/Interfaces/UDPInterface.py @@ -45,8 +45,7 @@ class UDPInterface(Interface): return ifaddr[netinfo.AF_INET][0]["broadcast"] def __init__(self, owner, name, device=None, bindip=None, bindport=None, forwardip=None, forwardport=None): - self.rxb = 0 - self.txb = 0 + super().__init__() self.HW_MTU = 1064