Added better I2P state visibility to rnstatus util

This commit is contained in:
Mark Qvist 2022-11-03 17:49:25 +01:00
parent 01e520b082
commit 76fcad0b53
4 changed files with 55 additions and 23 deletions

View File

@ -161,8 +161,6 @@ class I2PController:
raise tn.status["exception"] raise tn.status["exception"]
else: else:
self.client_tunnels[i2p_destination] = True
owner.awaiting_i2p_tunnel = False
if owner.socket != None: if owner.socket != None:
if hasattr(owner.socket, "close"): if hasattr(owner.socket, "close"):
if callable(owner.socket.close): if callable(owner.socket.close):
@ -175,6 +173,8 @@ class I2PController:
owner.socket.close() owner.socket.close()
except Exception as e: except Exception as e:
RNS.log("Error while closing socket for "+str(owner)+": "+str(e)) RNS.log("Error while closing socket for "+str(owner)+": "+str(e))
self.client_tunnels[i2p_destination] = True
owner.awaiting_i2p_tunnel = False
RNS.log(str(owner)+" tunnel setup complete", RNS.LOG_VERBOSE) RNS.log(str(owner)+" tunnel setup complete", RNS.LOG_VERBOSE)
@ -385,6 +385,10 @@ class I2PInterfacePeer(Interface):
I2P_PROBES = 5 I2P_PROBES = 5
I2P_READ_TIMEOUT = (I2P_PROBE_INTERVAL * I2P_PROBES + I2P_PROBE_AFTER)*2 I2P_READ_TIMEOUT = (I2P_PROBE_INTERVAL * I2P_PROBES + I2P_PROBE_AFTER)*2
TUNNEL_STATE_INIT = 0x00
TUNNEL_STATE_ACTIVE = 0x01
TUNNEL_STATE_STALE = 0x02
def __init__(self, parent_interface, owner, name, target_i2p_dest=None, connected_socket=None, max_reconnect_tries=None): def __init__(self, parent_interface, owner, name, target_i2p_dest=None, connected_socket=None, max_reconnect_tries=None):
self.rxb = 0 self.rxb = 0
self.txb = 0 self.txb = 0
@ -413,6 +417,7 @@ class I2PInterfacePeer(Interface):
self.last_read = 0 self.last_read = 0
self.last_write = 0 self.last_write = 0
self.wd_reset = False self.wd_reset = False
self.i2p_tunnel_state = I2PInterfacePeer.TUNNEL_STATE_INIT
self.ifac_size = self.parent_interface.ifac_size self.ifac_size = self.parent_interface.ifac_size
self.ifac_netname = self.parent_interface.ifac_netname self.ifac_netname = self.parent_interface.ifac_netname
@ -478,7 +483,7 @@ class I2PInterfacePeer(Interface):
RNS.log("Error while while configuring "+str(self)+": "+str(e), RNS.LOG_ERROR) RNS.log("Error while while configuring "+str(self)+": "+str(e), RNS.LOG_ERROR)
RNS.log("Check that I2P is installed and running, and that SAM is enabled. Retrying tunnel setup later.", RNS.LOG_ERROR) RNS.log("Check that I2P is installed and running, and that SAM is enabled. Retrying tunnel setup later.", RNS.LOG_ERROR)
time.sleep(15) time.sleep(8)
thread = threading.Thread(target=tunnel_job) thread = threading.Thread(target=tunnel_job)
thread.daemon = True thread.daemon = True
@ -487,6 +492,7 @@ class I2PInterfacePeer(Interface):
def wait_job(): def wait_job():
while self.awaiting_i2p_tunnel: while self.awaiting_i2p_tunnel:
time.sleep(0.25) time.sleep(0.25)
time.sleep(2)
if not self.kiss_framing: if not self.kiss_framing:
self.wants_tunnel = True self.wants_tunnel = True
@ -664,23 +670,32 @@ class I2PInterfacePeer(Interface):
while should_run and not self.wd_reset: while should_run and not self.wd_reset:
time.sleep(1) time.sleep(1)
if (time.time()-self.last_write > I2PInterfacePeer.I2P_PROBE_AFTER*0.66): if (time.time()-self.last_read > I2PInterfacePeer.I2P_PROBE_AFTER*2):
self.processOutgoing(bytes([0x00])) self.i2p_tunnel_state = I2PInterfacePeer.TUNNEL_STATE_STALE
else:
self.i2p_tunnel_state = I2PInterfacePeer.TUNNEL_STATE_ACTIVE
if (time.time()-self.last_read > I2PInterfacePeer.I2P_READ_TIMEOUT): if (time.time()-self.last_write > I2PInterfacePeer.I2P_PROBE_AFTER*1):
RNS.log("I2P socket seems dead, restarting...", RNS.LOG_DEBUG) try:
if self.socket != None: self.socket.sendall(bytes([HDLC.FLAG, HDLC.FLAG]))
try: except Exception as e:
self.socket.shutdown(socket.SHUT_RDWR) RNS.log("An error ocurred while sending I2P keepalive. The contained exception was: "+str(e), RNS.LOG_ERROR)
except Exception as e: self.shutdown_socket(self.socket)
RNS.log("Error while shutting down socket for "+str(self)+": "+str(e))
try: # if (time.time()-self.last_read > I2PInterfacePeer.I2P_READ_TIMEOUT):
self.socket.close() # RNS.log("I2P socket seems dead, restarting...", RNS.LOG_WARNING)
except Exception as e: # if self.socket != None:
RNS.log("Error while closing socket for "+str(self)+": "+str(e)) # try:
# self.socket.shutdown(socket.SHUT_RDWR)
# except Exception as e:
# RNS.log("Error while shutting down socket for "+str(self)+": "+str(e))
should_run = False # try:
# self.socket.close()
# except Exception as e:
# RNS.log("Error while closing socket for "+str(self)+": "+str(e))
# should_run = False
finally: finally:
self.wd_reset = False self.wd_reset = False
@ -701,7 +716,7 @@ class I2PInterfacePeer(Interface):
data_in = self.socket.recv(4096) data_in = self.socket.recv(4096)
if len(data_in) > 0: if len(data_in) > 0:
pointer = 0 pointer = 0
last_read = time.time() self.last_read = time.time()
while pointer < len(data_in): while pointer < len(data_in):
byte = data_in[pointer] byte = data_in[pointer]
pointer += 1 pointer += 1
@ -710,8 +725,7 @@ class I2PInterfacePeer(Interface):
# Read loop for KISS framing # Read loop for KISS framing
if (in_frame and byte == KISS.FEND and command == KISS.CMD_DATA): if (in_frame and byte == KISS.FEND and command == KISS.CMD_DATA):
in_frame = False in_frame = False
if len(data_buffer) > RNS.Reticulum.HEADER_MINSIZE+1: self.processIncoming(data_buffer)
self.processIncoming(data_buffer)
elif (byte == KISS.FEND): elif (byte == KISS.FEND):
in_frame = True in_frame = True
command = KISS.CMD_UNKNOWN command = KISS.CMD_UNKNOWN
@ -738,8 +752,7 @@ class I2PInterfacePeer(Interface):
# Read loop for HDLC framing # Read loop for HDLC framing
if (in_frame and byte == HDLC.FLAG): if (in_frame and byte == HDLC.FLAG):
in_frame = False in_frame = False
if len(data_buffer) > RNS.Reticulum.HEADER_MINSIZE+1: self.processIncoming(data_buffer)
self.processIncoming(data_buffer)
elif (byte == HDLC.FLAG): elif (byte == HDLC.FLAG):
in_frame = True in_frame = True
data_buffer = b"" data_buffer = b""

View File

@ -1073,6 +1073,19 @@ class Reticulum:
else: else:
ifstats["i2p_b32"] = None ifstats["i2p_b32"] = None
if hasattr(interface, "i2p_tunnel_state"):
if interface.i2p_tunnel_state != None:
state_description = "Unknown State"
if interface.i2p_tunnel_state == I2PInterface.I2PInterfacePeer.TUNNEL_STATE_ACTIVE:
state_description = "Tunnel Active"
elif interface.i2p_tunnel_state == I2PInterface.I2PInterfacePeer.TUNNEL_STATE_INIT:
state_description = "Creating Tunnel"
elif interface.i2p_tunnel_state == I2PInterface.I2PInterfacePeer.TUNNEL_STATE_STALE:
state_description = "Tunnel Unresponsive"
ifstats["tunnelstate"] = state_description
else:
ifstats["tunnelstate"] = None
if hasattr(interface, "bitrate"): if hasattr(interface, "bitrate"):
if interface.bitrate != None: if interface.bitrate != None:
ifstats["bitrate"] = interface.bitrate ifstats["bitrate"] = interface.bitrate

View File

@ -833,7 +833,7 @@ class Transport:
def inbound(raw, interface=None): def inbound(raw, interface=None):
# If interface access codes are enabled, # If interface access codes are enabled,
# we must authenticate each packet. # we must authenticate each packet.
if len(raw) > 1: if len(raw) > 2:
if interface != None and hasattr(interface, "ifac_identity") and interface.ifac_identity != None: if interface != None and hasattr(interface, "ifac_identity") and interface.ifac_identity != None:
# Check that IFAC flag is set # Check that IFAC flag is set
if raw[0] & 0x80 == 0x80: if raw[0] & 0x80 == 0x80:
@ -871,6 +871,9 @@ class Transport:
# If the flag is set, drop the packet # If the flag is set, drop the packet
return return
else:
return
while (Transport.jobs_running): while (Transport.jobs_running):
sleep(0.0005) sleep(0.0005)

View File

@ -135,6 +135,9 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None):
if "peers" in ifstat and ifstat["peers"] != None: if "peers" in ifstat and ifstat["peers"] != None:
print(" Peers : {np} reachable".format(np=ifstat["peers"])) print(" Peers : {np} reachable".format(np=ifstat["peers"]))
if "tunnelstate" in ifstat and ifstat["tunnelstate"] != None:
print(" I2P : {ts}".format(ts=ifstat["tunnelstate"]))
if "ifac_signature" in ifstat and ifstat["ifac_signature"] != None: if "ifac_signature" in ifstat and ifstat["ifac_signature"] != None:
sigstr = "<…"+RNS.hexrep(ifstat["ifac_signature"][-5:], delimit=False)+">" sigstr = "<…"+RNS.hexrep(ifstat["ifac_signature"][-5:], delimit=False)+">"
print(" Access : {nb}-bit IFAC by {sig}".format(nb=ifstat["ifac_size"]*8, sig=sigstr)) print(" Access : {nb}-bit IFAC by {sig}".format(nb=ifstat["ifac_size"]*8, sig=sigstr))