Skip to content

Commit

Permalink
Improved interface detach on shared instance shutdown
Browse files Browse the repository at this point in the history
  • Loading branch information
markqvist committed Jan 16, 2025
1 parent 1b48f43 commit 4f49612
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 33 deletions.
31 changes: 18 additions & 13 deletions RNS/Interfaces/AutoInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,21 +456,23 @@ def refresh_peer(self, addr):
self.peers[addr][1] = time.time()

def process_incoming(self, data):
data_hash = RNS.Identity.full_hash(data)
deque_hit = False
if data_hash in self.mif_deque:
for te in self.mif_deque_times:
if te[0] == data_hash and time.time() < te[1]+AutoInterface.MULTI_IF_DEQUE_TTL:
deque_hit = True
break

if not deque_hit:
self.mif_deque.append(data_hash)
self.mif_deque_times.append([data_hash, time.time()])
self.rxb += len(data)
self.owner.inbound(data, self)
if self.online:
data_hash = RNS.Identity.full_hash(data)
deque_hit = False
if data_hash in self.mif_deque:
for te in self.mif_deque_times:
if te[0] == data_hash and time.time() < te[1]+AutoInterface.MULTI_IF_DEQUE_TTL:
deque_hit = True
break

if not deque_hit:
self.mif_deque.append(data_hash)
self.mif_deque_times.append([data_hash, time.time()])
self.rxb += len(data)
self.owner.inbound(data, self)

def process_outgoing(self,data):
if self.online:
for peer in self.peers:
try:
if self.outbound_udp_socket == None:
Expand All @@ -492,6 +494,9 @@ def process_outgoing(self,data):
def should_ingress_limit(self):
return False

def detach(self):
self.online = False

def __str__(self):
return "AutoInterface["+self.name+"]"

Expand Down
13 changes: 7 additions & 6 deletions RNS/Interfaces/Interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,13 @@ class Interface:
AUTOCONFIGURE_MTU = False

def __init__(self):
self.rxb = 0
self.txb = 0
self.created = time.time()
self.online = False
self.bitrate = 62500
self.HW_MTU = None
self.rxb = 0
self.txb = 0
self.created = time.time()
self.detached = False
self.online = False
self.bitrate = 62500
self.HW_MTU = None

self.ingress_control = True
self.ic_max_held_announces = Interface.MAX_HELD_ANNOUNCES
Expand Down
1 change: 1 addition & 0 deletions RNS/Interfaces/RNodeInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ def __init__(self, owner, configuration):
self.online = False
self.detached = False
self.reconnecting= False
self.hw_errors = []

self.use_ble = False
self.ble_name = ble_name
Expand Down
15 changes: 8 additions & 7 deletions RNS/Interfaces/TCPInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,10 @@ def set_timeouts_osx(self):
self.socket.setsockopt(socket.IPPROTO_TCP, TCP_KEEPIDLE, int(TCPClientInterface.I2P_PROBE_AFTER))

def detach(self):
self.online = False
if self.socket != None:
if hasattr(self.socket, "close"):
if callable(self.socket.close):
RNS.log("Detaching "+str(self), RNS.LOG_DEBUG)
self.detached = True

try:
Expand Down Expand Up @@ -288,14 +288,15 @@ def reconnect(self):
raise IOError("Attempt to reconnect on a non-initiator TCP interface")

def process_incoming(self, data):
self.rxb += len(data)
if hasattr(self, "parent_interface") and self.parent_interface != None:
self.parent_interface.rxb += len(data)

self.owner.inbound(data, self)
if self.online and not self.detached:
self.rxb += len(data)
if hasattr(self, "parent_interface") and self.parent_interface != None:
self.parent_interface.rxb += len(data)

self.owner.inbound(data, self)

def process_outgoing(self, data):
if self.online:
if self.online and not self.detached:
# while self.writing:
# time.sleep(0.01)

Expand Down
10 changes: 6 additions & 4 deletions RNS/Reticulum.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,16 @@ class Reticulum:
interfacepath = ""

__instance = None


__interface_detach_ran = False
@staticmethod
def exit_handler():
# This exit handler is called whenever Reticulum is asked to
# shut down, and will in turn call exit handlers in other
# classes, saving necessary information to disk and carrying
# out cleanup operations.

if not Reticulum.__interface_detach_ran:
RNS.Transport.detach_interfaces()
RNS.Transport.exit_handler()
RNS.Identity.exit_handler()

Expand All @@ -178,15 +180,15 @@ def exit_handler():
@staticmethod
def sigint_handler(signal, frame):
RNS.Transport.detach_interfaces()
Reticulum.__interface_detach_ran = True
RNS.exit()


@staticmethod
def sigterm_handler(signal, frame):
RNS.Transport.detach_interfaces()
Reticulum.__interface_detach_ran = True
RNS.exit()


@staticmethod
def get_instance():
"""
Expand Down
33 changes: 30 additions & 3 deletions RNS/Transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -2662,7 +2662,7 @@ def detach_interfaces():
# Currently no rules are being applied
# here, and all interfaces will be sent
# the detach call on RNS teardown.
if True:
if not interface.detached:
detachable_interfaces.append(interface)
else:
pass
Expand All @@ -2671,17 +2671,44 @@ def detach_interfaces():
# Currently no rules are being applied
# here, and all interfaces will be sent
# the detach call on RNS teardown.
if True:
if not interface.detached:
detachable_interfaces.append(interface)
else:
pass

shared_instance_master = None
local_interfaces = []
detach_threads = []
for interface in detachable_interfaces:
try:
interface.detach()
if type(interface) == RNS.Interfaces.LocalInterface.LocalServerInterface:
shared_instance_master = interface
elif type(interface) == RNS.Interfaces.LocalInterface.LocalClientInterface:
local_interfaces.append(interface)
else:
def detach_job():
RNS.log(f"Detaching {interface}", RNS.LOG_DEBUG)
interface.detach()
dt = threading.Thread(target=detach_job, daemon=True)
dt.start()
detach_threads.append(dt)

except Exception as e:
RNS.log("An error occurred while detaching "+str(interface)+". The contained exception was: "+str(e), RNS.LOG_ERROR)

for dt in detach_threads:
dt.join()

RNS.log("Detaching local clients", RNS.LOG_DEBUG)
for li in local_interfaces:
li.detach()

RNS.log("Detaching shared instance", RNS.LOG_DEBUG)
if shared_instance_master != None:
shared_instance_master.detach()

RNS.log("All interfaces detached", RNS.LOG_DEBUG)

@staticmethod
def shared_connection_disappeared():
for link in Transport.active_links:
Expand Down

0 comments on commit 4f49612

Please sign in to comment.