# MIT License # # Copyright (c) 2016-2022 Mark Qvist / unsigned.io # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import RNS import time import threading class Interface: IN = False OUT = False FWD = False RPT = False name = None MODE_FULL = 0x01 MODE_POINT_TO_POINT = 0x02 MODE_ACCESS_POINT = 0x03 def __init__(self): self.rxb = 0 self.txb = 0 self.online = False def get_hash(self): return RNS.Identity.full_hash(str(self).encode("utf-8")) # TODO: Clean # def bogus_queue(self): # self.announce_queue = [] # import random # import time # now = time.time() # random.seed(45) # for i in range(1,32): # entry = {"time": now+i*3, "hops":random.randint(4,16), "raw": str("bogus_data_"+str(i)).encode("utf-8")} # self.announce_queue.append(entry) def process_announce_queue(self): if not hasattr(self, "announce_cap"): self.announce_cap = RNS.Reticulum.ANNOUNCE_CAP if hasattr(self, "announce_queue"): # TODO: Clean # RNS.log("Processing announce queue on "+str(self), RNS.LOG_DEBUG) try: now = time.time() stale = [] for a in self.announce_queue: if now > a["time"]+RNS.Reticulum.QUEUED_ANNOUNCE_LIFE: stale.append(a) for s in stale: self.announce_queue.remove(s) if len(self.announce_queue) > 0: min_hops = min(entry["hops"] for entry in self.announce_queue) entries = list(filter(lambda e: e["hops"] == min_hops, self.announce_queue)) entries.sort(key=lambda e: e["time"]) selected = entries[0] now = time.time() tx_time = (len(selected["raw"])*8) / self.bitrate wait_time = (tx_time / self.announce_cap) self.announce_allowed_at = now + wait_time self.processOutgoing(selected["raw"]) self.announce_queue.remove(selected) # TODO: Clean debug statements # RNS.log("Sent queued announce with "+str(selected["hops"])+" hops on "+str(self)) if len(self.announce_queue) > 0: # TODO: Clean debug statements # RNS.log("Still have "+str(len(self.announce_queue))+" announces in queue, scheduling next for tx in "+str(round(wait_time*1000,6))+"ms", RNS.LOG_DEBUG) timer = threading.Timer(wait_time, self.process_announce_queue) timer.start() except Exception as e: self.announce_queue = [] RNS.log("Error while processing announce queue on "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR) RNS.log("The announce queue for this interface has been cleared.", RNS.LOG_ERROR) def detach(self): pass