Added rnstatus utility
This commit is contained in:
parent
f5510f9777
commit
7991db5c74
@ -48,6 +48,9 @@ class AX25KISSInterface(Interface):
|
|||||||
serial = None
|
serial = None
|
||||||
|
|
||||||
def __init__(self, owner, name, callsign, ssid, port, speed, databits, parity, stopbits, preamble, txtail, persistence, slottime, flow_control):
|
def __init__(self, owner, name, callsign, ssid, port, speed, databits, parity, stopbits, preamble, txtail, persistence, slottime, flow_control):
|
||||||
|
self.rxb = 0
|
||||||
|
self.txb = 0
|
||||||
|
|
||||||
self.serial = None
|
self.serial = None
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -188,10 +191,12 @@ class AX25KISSInterface(Interface):
|
|||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
if (len(data) > AX25.HEADER_SIZE):
|
if (len(data) > AX25.HEADER_SIZE):
|
||||||
|
self.rxb += len(data)
|
||||||
self.owner.inbound(data[AX25.HEADER_SIZE:], self)
|
self.owner.inbound(data[AX25.HEADER_SIZE:], self)
|
||||||
|
|
||||||
|
|
||||||
def processOutgoing(self,data):
|
def processOutgoing(self,data):
|
||||||
|
datalen = len(data)
|
||||||
if self.online:
|
if self.online:
|
||||||
if self.interface_ready:
|
if self.interface_ready:
|
||||||
if self.flow_control:
|
if self.flow_control:
|
||||||
@ -224,6 +229,8 @@ class AX25KISSInterface(Interface):
|
|||||||
kiss_frame = bytes([KISS.FEND])+bytes([0x00])+data+bytes([KISS.FEND])
|
kiss_frame = bytes([KISS.FEND])+bytes([0x00])+data+bytes([KISS.FEND])
|
||||||
|
|
||||||
written = self.serial.write(kiss_frame)
|
written = self.serial.write(kiss_frame)
|
||||||
|
self.txb += datalen
|
||||||
|
|
||||||
if written != len(kiss_frame):
|
if written != len(kiss_frame):
|
||||||
if self.flow_control:
|
if self.flow_control:
|
||||||
self.interface_ready = True
|
self.interface_ready = True
|
||||||
|
@ -8,7 +8,9 @@ class Interface:
|
|||||||
name = None
|
name = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
self.rxb = 0
|
||||||
|
self.txb = 0
|
||||||
|
self.online = False
|
||||||
|
|
||||||
def get_hash(self):
|
def get_hash(self):
|
||||||
return RNS.Identity.full_hash(str(self).encode("utf-8"))
|
return RNS.Identity.full_hash(str(self).encode("utf-8"))
|
||||||
|
@ -40,6 +40,9 @@ class KISSInterface(Interface):
|
|||||||
serial = None
|
serial = None
|
||||||
|
|
||||||
def __init__(self, owner, name, port, speed, databits, parity, stopbits, preamble, txtail, persistence, slottime, flow_control, beacon_interval, beacon_data):
|
def __init__(self, owner, name, port, speed, databits, parity, stopbits, preamble, txtail, persistence, slottime, flow_control, beacon_interval, beacon_data):
|
||||||
|
self.rxb = 0
|
||||||
|
self.txb = 0
|
||||||
|
|
||||||
if beacon_data == None:
|
if beacon_data == None:
|
||||||
beacon_data = ""
|
beacon_data = ""
|
||||||
|
|
||||||
@ -174,10 +177,12 @@ class KISSInterface(Interface):
|
|||||||
|
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
|
self.rxb += len(data)
|
||||||
self.owner.inbound(data, self)
|
self.owner.inbound(data, self)
|
||||||
|
|
||||||
|
|
||||||
def processOutgoing(self,data):
|
def processOutgoing(self,data):
|
||||||
|
datalen = len(data)
|
||||||
if self.online:
|
if self.online:
|
||||||
if self.interface_ready:
|
if self.interface_ready:
|
||||||
if self.flow_control:
|
if self.flow_control:
|
||||||
@ -189,6 +194,7 @@ class KISSInterface(Interface):
|
|||||||
frame = bytes([KISS.FEND])+bytes([0x00])+data+bytes([KISS.FEND])
|
frame = bytes([KISS.FEND])+bytes([0x00])+data+bytes([KISS.FEND])
|
||||||
|
|
||||||
written = self.serial.write(frame)
|
written = self.serial.write(frame)
|
||||||
|
self.txb += datalen
|
||||||
|
|
||||||
if data == self.beacon_d:
|
if data == self.beacon_d:
|
||||||
self.first_tx = None
|
self.first_tx = None
|
||||||
|
@ -24,6 +24,10 @@ class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
|||||||
class LocalClientInterface(Interface):
|
class LocalClientInterface(Interface):
|
||||||
|
|
||||||
def __init__(self, owner, name, target_port = None, connected_socket=None):
|
def __init__(self, owner, name, target_port = None, connected_socket=None):
|
||||||
|
self.rxb = 0
|
||||||
|
self.txb = 0
|
||||||
|
self.online = False
|
||||||
|
|
||||||
self.IN = True
|
self.IN = True
|
||||||
self.OUT = False
|
self.OUT = False
|
||||||
self.socket = None
|
self.socket = None
|
||||||
@ -58,6 +62,10 @@ class LocalClientInterface(Interface):
|
|||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(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)
|
self.owner.inbound(data, self)
|
||||||
|
|
||||||
def processOutgoing(self, data):
|
def processOutgoing(self, data):
|
||||||
@ -70,6 +78,10 @@ class LocalClientInterface(Interface):
|
|||||||
data = bytes([HDLC.FLAG])+HDLC.escape(data)+bytes([HDLC.FLAG])
|
data = bytes([HDLC.FLAG])+HDLC.escape(data)+bytes([HDLC.FLAG])
|
||||||
self.socket.sendall(data)
|
self.socket.sendall(data)
|
||||||
self.writing = False
|
self.writing = False
|
||||||
|
self.txb += len(data)
|
||||||
|
if hasattr(self, "parent_interface") and self.parent_interface != None:
|
||||||
|
self.parent_interface.txb += len(data)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Exception occurred while transmitting via "+str(self)+", tearing down interface", RNS.LOG_ERROR)
|
RNS.log("Exception occurred while transmitting via "+str(self)+", tearing down interface", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
@ -147,6 +159,8 @@ class LocalClientInterface(Interface):
|
|||||||
|
|
||||||
if self in RNS.Transport.local_client_interfaces:
|
if self in RNS.Transport.local_client_interfaces:
|
||||||
RNS.Transport.local_client_interfaces.remove(self)
|
RNS.Transport.local_client_interfaces.remove(self)
|
||||||
|
if hasattr(self, "parent_interface") and self.parent_interface != None:
|
||||||
|
self.parent_interface.clients -= 1
|
||||||
|
|
||||||
if nowarning == False:
|
if nowarning == False:
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is being torn down. Restart Reticulum to attempt to open this interface again.", RNS.LOG_ERROR)
|
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is being torn down. Restart Reticulum to attempt to open this interface again.", RNS.LOG_ERROR)
|
||||||
@ -170,6 +184,11 @@ class LocalClientInterface(Interface):
|
|||||||
class LocalServerInterface(Interface):
|
class LocalServerInterface(Interface):
|
||||||
|
|
||||||
def __init__(self, owner, bindport=None):
|
def __init__(self, owner, bindport=None):
|
||||||
|
self.rxb = 0
|
||||||
|
self.txb = 0
|
||||||
|
self.online = False
|
||||||
|
self.clients = 0
|
||||||
|
|
||||||
self.IN = True
|
self.IN = True
|
||||||
self.OUT = False
|
self.OUT = False
|
||||||
self.name = "Reticulum"
|
self.name = "Reticulum"
|
||||||
@ -196,6 +215,9 @@ class LocalServerInterface(Interface):
|
|||||||
thread.setDaemon(True)
|
thread.setDaemon(True)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
self.online = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def incoming_connection(self, handler):
|
def incoming_connection(self, handler):
|
||||||
interface_name = str(str(handler.client_address[1]))
|
interface_name = str(str(handler.client_address[1]))
|
||||||
@ -208,13 +230,14 @@ class LocalServerInterface(Interface):
|
|||||||
RNS.log("Accepting new connection to shared instance: "+str(spawned_interface), RNS.LOG_VERBOSE)
|
RNS.log("Accepting new connection to shared instance: "+str(spawned_interface), RNS.LOG_VERBOSE)
|
||||||
RNS.Transport.interfaces.append(spawned_interface)
|
RNS.Transport.interfaces.append(spawned_interface)
|
||||||
RNS.Transport.local_client_interfaces.append(spawned_interface)
|
RNS.Transport.local_client_interfaces.append(spawned_interface)
|
||||||
|
self.clients += 1
|
||||||
spawned_interface.read_loop()
|
spawned_interface.read_loop()
|
||||||
|
|
||||||
def processOutgoing(self, data):
|
def processOutgoing(self, data):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Shared Instance ["+str(self.bind_port)+"]"
|
return "Shared Instance["+str(self.bind_port)+"]"
|
||||||
|
|
||||||
class LocalInterfaceHandler(socketserver.BaseRequestHandler):
|
class LocalInterfaceHandler(socketserver.BaseRequestHandler):
|
||||||
def __init__(self, callback, *args, **keys):
|
def __init__(self, callback, *args, **keys):
|
||||||
|
@ -72,6 +72,9 @@ class RNodeInterface(Interface):
|
|||||||
CALLSIGN_MAX_LEN = 32
|
CALLSIGN_MAX_LEN = 32
|
||||||
|
|
||||||
def __init__(self, owner, name, port, frequency = None, bandwidth = None, txpower = None, sf = None, cr = None, flow_control = False, id_interval = None, id_callsign = None):
|
def __init__(self, owner, name, port, frequency = None, bandwidth = None, txpower = None, sf = None, cr = None, flow_control = False, id_interval = None, id_callsign = None):
|
||||||
|
self.rxb = 0
|
||||||
|
self.txb = 0
|
||||||
|
|
||||||
self.serial = None
|
self.serial = None
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -278,10 +281,12 @@ class RNodeInterface(Interface):
|
|||||||
self.bitrate = 0
|
self.bitrate = 0
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
|
self.rxb += len(data)
|
||||||
self.owner.inbound(data, self)
|
self.owner.inbound(data, self)
|
||||||
|
|
||||||
|
|
||||||
def processOutgoing(self,data):
|
def processOutgoing(self,data):
|
||||||
|
datalen = len(data)
|
||||||
if self.online:
|
if self.online:
|
||||||
if self.interface_ready:
|
if self.interface_ready:
|
||||||
if self.flow_control:
|
if self.flow_control:
|
||||||
@ -297,6 +302,7 @@ class RNodeInterface(Interface):
|
|||||||
frame = bytes([0xc0])+bytes([0x00])+data+bytes([0xc0])
|
frame = bytes([0xc0])+bytes([0x00])+data+bytes([0xc0])
|
||||||
|
|
||||||
written = self.serial.write(frame)
|
written = self.serial.write(frame)
|
||||||
|
self.txb += datalen
|
||||||
|
|
||||||
if written != len(frame):
|
if written != len(frame):
|
||||||
raise IOError("Serial interface only wrote "+str(written)+" bytes of "+str(len(data)))
|
raise IOError("Serial interface only wrote "+str(written)+" bytes of "+str(len(data)))
|
||||||
|
@ -31,6 +31,9 @@ class SerialInterface(Interface):
|
|||||||
serial = None
|
serial = None
|
||||||
|
|
||||||
def __init__(self, owner, name, port, speed, databits, parity, stopbits):
|
def __init__(self, owner, name, port, speed, databits, parity, stopbits):
|
||||||
|
self.rxb = 0
|
||||||
|
self.txb = 0
|
||||||
|
|
||||||
self.serial = None
|
self.serial = None
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -79,6 +82,7 @@ class SerialInterface(Interface):
|
|||||||
|
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
|
self.rxb += len(data)
|
||||||
self.owner.inbound(data, self)
|
self.owner.inbound(data, self)
|
||||||
|
|
||||||
|
|
||||||
@ -86,6 +90,7 @@ class SerialInterface(Interface):
|
|||||||
if self.online:
|
if self.online:
|
||||||
data = bytes([HDLC.FLAG])+HDLC.escape(data)+bytes([HDLC.FLAG])
|
data = bytes([HDLC.FLAG])+HDLC.escape(data)+bytes([HDLC.FLAG])
|
||||||
written = self.serial.write(data)
|
written = self.serial.write(data)
|
||||||
|
self.txb += len(data)
|
||||||
if written != len(data):
|
if written != len(data):
|
||||||
raise IOError("Serial interface only wrote "+str(written)+" bytes of "+str(len(data)))
|
raise IOError("Serial interface only wrote "+str(written)+" bytes of "+str(len(data)))
|
||||||
|
|
||||||
|
@ -34,6 +34,9 @@ class TCPClientInterface(Interface):
|
|||||||
TCP_PROBES = 5
|
TCP_PROBES = 5
|
||||||
|
|
||||||
def __init__(self, owner, name, target_ip=None, target_port=None, connected_socket=None, max_reconnect_tries=None):
|
def __init__(self, owner, name, target_ip=None, target_port=None, connected_socket=None, max_reconnect_tries=None):
|
||||||
|
self.rxb = 0
|
||||||
|
self.txb = 0
|
||||||
|
|
||||||
self.IN = True
|
self.IN = True
|
||||||
self.OUT = False
|
self.OUT = False
|
||||||
self.socket = None
|
self.socket = None
|
||||||
@ -177,6 +180,10 @@ class TCPClientInterface(Interface):
|
|||||||
raise IOError("Attempt to reconnect on a non-initiator TCP interface")
|
raise IOError("Attempt to reconnect on a non-initiator TCP interface")
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(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)
|
self.owner.inbound(data, self)
|
||||||
|
|
||||||
def processOutgoing(self, data):
|
def processOutgoing(self, data):
|
||||||
@ -189,6 +196,10 @@ class TCPClientInterface(Interface):
|
|||||||
data = bytes([HDLC.FLAG])+HDLC.escape(data)+bytes([HDLC.FLAG])
|
data = bytes([HDLC.FLAG])+HDLC.escape(data)+bytes([HDLC.FLAG])
|
||||||
self.socket.sendall(data)
|
self.socket.sendall(data)
|
||||||
self.writing = False
|
self.writing = False
|
||||||
|
self.txb += len(data)
|
||||||
|
if hasattr(self, "parent_interface") and self.parent_interface != None:
|
||||||
|
self.parent_interface.txb += len(data)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Exception occurred while transmitting via "+str(self)+", tearing down interface", RNS.LOG_ERROR)
|
RNS.log("Exception occurred while transmitting via "+str(self)+", tearing down interface", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
@ -248,7 +259,7 @@ class TCPClientInterface(Interface):
|
|||||||
self.teardown()
|
self.teardown()
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
if self.initiator:
|
if self.initiator and not self.detached:
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is being torn down. Restart Reticulum to attempt to open this interface again.", RNS.LOG_ERROR)
|
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is being torn down. Restart Reticulum to attempt to open this interface again.", RNS.LOG_ERROR)
|
||||||
if RNS.Reticulum.panic_on_interface_error:
|
if RNS.Reticulum.panic_on_interface_error:
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
@ -260,6 +271,9 @@ class TCPClientInterface(Interface):
|
|||||||
self.OUT = False
|
self.OUT = False
|
||||||
self.IN = False
|
self.IN = False
|
||||||
|
|
||||||
|
if hasattr(self, "parent_interface") and self.parent_interface != None:
|
||||||
|
self.parent_interface.clients -= 1
|
||||||
|
|
||||||
if self in RNS.Transport.interfaces:
|
if self in RNS.Transport.interfaces:
|
||||||
RNS.Transport.interfaces.remove(self)
|
RNS.Transport.interfaces.remove(self)
|
||||||
|
|
||||||
@ -277,6 +291,11 @@ class TCPServerInterface(Interface):
|
|||||||
return netifaces.ifaddresses(name)[netifaces.AF_INET][0]['broadcast']
|
return netifaces.ifaddresses(name)[netifaces.AF_INET][0]['broadcast']
|
||||||
|
|
||||||
def __init__(self, owner, name, device=None, bindip=None, bindport=None):
|
def __init__(self, owner, name, device=None, bindip=None, bindport=None):
|
||||||
|
self.rxb = 0
|
||||||
|
self.txb = 0
|
||||||
|
self.online = False
|
||||||
|
self.clients = 0
|
||||||
|
|
||||||
self.IN = True
|
self.IN = True
|
||||||
self.OUT = False
|
self.OUT = False
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -304,6 +323,8 @@ class TCPServerInterface(Interface):
|
|||||||
thread.setDaemon(True)
|
thread.setDaemon(True)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
self.online = True
|
||||||
|
|
||||||
|
|
||||||
def incoming_connection(self, handler):
|
def incoming_connection(self, handler):
|
||||||
RNS.log("Accepting incoming TCP connection", RNS.LOG_VERBOSE)
|
RNS.log("Accepting incoming TCP connection", RNS.LOG_VERBOSE)
|
||||||
@ -317,6 +338,7 @@ class TCPServerInterface(Interface):
|
|||||||
spawned_interface.online = True
|
spawned_interface.online = True
|
||||||
RNS.log("Spawned new TCPClient Interface: "+str(spawned_interface), RNS.LOG_VERBOSE)
|
RNS.log("Spawned new TCPClient Interface: "+str(spawned_interface), RNS.LOG_VERBOSE)
|
||||||
RNS.Transport.interfaces.append(spawned_interface)
|
RNS.Transport.interfaces.append(spawned_interface)
|
||||||
|
self.clients += 1
|
||||||
spawned_interface.read_loop()
|
spawned_interface.read_loop()
|
||||||
|
|
||||||
def processOutgoing(self, data):
|
def processOutgoing(self, data):
|
||||||
|
@ -18,9 +18,12 @@ class UDPInterface(Interface):
|
|||||||
return netifaces.ifaddresses(name)[netifaces.AF_INET][0]['broadcast']
|
return netifaces.ifaddresses(name)[netifaces.AF_INET][0]['broadcast']
|
||||||
|
|
||||||
def __init__(self, owner, name, device=None, bindip=None, bindport=None, forwardip=None, forwardport=None):
|
def __init__(self, owner, name, device=None, bindip=None, bindport=None, forwardip=None, forwardport=None):
|
||||||
|
self.rxb = 0
|
||||||
|
self.txb = 0
|
||||||
self.IN = True
|
self.IN = True
|
||||||
self.OUT = False
|
self.OUT = False
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.online = False
|
||||||
|
|
||||||
if device != None:
|
if device != None:
|
||||||
if bindip == None:
|
if bindip == None:
|
||||||
@ -47,6 +50,8 @@ class UDPInterface(Interface):
|
|||||||
thread.setDaemon(True)
|
thread.setDaemon(True)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
self.online = True
|
||||||
|
|
||||||
if (forwardip != None and forwardport != None):
|
if (forwardip != None and forwardport != None):
|
||||||
self.forwards = True
|
self.forwards = True
|
||||||
self.forward_ip = forwardip
|
self.forward_ip = forwardip
|
||||||
@ -54,6 +59,7 @@ class UDPInterface(Interface):
|
|||||||
|
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
|
self.rxb += len(data)
|
||||||
self.owner.inbound(data, self)
|
self.owner.inbound(data, self)
|
||||||
|
|
||||||
def processOutgoing(self,data):
|
def processOutgoing(self,data):
|
||||||
@ -61,6 +67,8 @@ class UDPInterface(Interface):
|
|||||||
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||||
udp_socket.sendto(data, (self.forward_ip, self.forward_port))
|
udp_socket.sendto(data, (self.forward_ip, self.forward_port))
|
||||||
|
self.txb += len(data)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not transmit on "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Could not transmit on "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
from .Interfaces import *
|
from .Interfaces import *
|
||||||
import configparser
|
|
||||||
from .vendor.configobj import ConfigObj
|
from .vendor.configobj import ConfigObj
|
||||||
|
import configparser
|
||||||
|
import multiprocessing.connection
|
||||||
import RNS
|
import RNS
|
||||||
import signal
|
import signal
|
||||||
|
import threading
|
||||||
import atexit
|
import atexit
|
||||||
import struct
|
import struct
|
||||||
import array
|
import array
|
||||||
@ -108,7 +110,9 @@ class Reticulum:
|
|||||||
Reticulum.panic_on_interface_error = False
|
Reticulum.panic_on_interface_error = False
|
||||||
|
|
||||||
self.local_interface_port = 37428
|
self.local_interface_port = 37428
|
||||||
|
self.local_control_port = 37429
|
||||||
self.share_instance = True
|
self.share_instance = True
|
||||||
|
self.rpc_listener = None
|
||||||
|
|
||||||
self.requested_loglevel = loglevel
|
self.requested_loglevel = loglevel
|
||||||
if self.requested_loglevel != None:
|
if self.requested_loglevel != None:
|
||||||
@ -153,6 +157,15 @@ class Reticulum:
|
|||||||
|
|
||||||
RNS.Transport.start(self)
|
RNS.Transport.start(self)
|
||||||
|
|
||||||
|
self.rpc_addr = ("127.0.0.1", self.local_control_port)
|
||||||
|
self.rpc_key = RNS.Identity.full_hash(RNS.Transport.identity.get_private_key())
|
||||||
|
|
||||||
|
if self.is_shared_instance:
|
||||||
|
self.rpc_listener = multiprocessing.connection.Listener(self.rpc_addr, authkey=self.rpc_key)
|
||||||
|
thread = threading.Thread(target=self.rpc_loop)
|
||||||
|
thread.setDaemon(True)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
atexit.register(Reticulum.exit_handler)
|
atexit.register(Reticulum.exit_handler)
|
||||||
signal.signal(signal.SIGINT, Reticulum.sigint_handler)
|
signal.signal(signal.SIGINT, Reticulum.sigint_handler)
|
||||||
|
|
||||||
@ -165,6 +178,7 @@ class Reticulum:
|
|||||||
)
|
)
|
||||||
interface.OUT = True
|
interface.OUT = True
|
||||||
RNS.Transport.interfaces.append(interface)
|
RNS.Transport.interfaces.append(interface)
|
||||||
|
|
||||||
self.is_shared_instance = True
|
self.is_shared_instance = True
|
||||||
RNS.log("Started shared instance interface: "+str(interface), RNS.LOG_DEBUG)
|
RNS.log("Started shared instance interface: "+str(interface), RNS.LOG_DEBUG)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -211,6 +225,9 @@ class Reticulum:
|
|||||||
if option == "shared_instance_port":
|
if option == "shared_instance_port":
|
||||||
value = int(self.config["reticulum"][option])
|
value = int(self.config["reticulum"][option])
|
||||||
self.local_interface_port = value
|
self.local_interface_port = value
|
||||||
|
if option == "instance_control_port":
|
||||||
|
value = int(self.config["reticulum"][option])
|
||||||
|
self.local_control_port = value
|
||||||
if option == "enable_transport":
|
if option == "enable_transport":
|
||||||
v = self.config["reticulum"].as_bool(option)
|
v = self.config["reticulum"].as_bool(option)
|
||||||
if v == True:
|
if v == True:
|
||||||
@ -455,7 +472,7 @@ class Reticulum:
|
|||||||
|
|
||||||
RNS.Transport.interfaces.append(interface)
|
RNS.Transport.interfaces.append(interface)
|
||||||
else:
|
else:
|
||||||
RNS.log("Skipping disabled interface \""+name+"\"", RNS.LOG_NOTICE)
|
RNS.log("Skipping disabled interface \""+name+"\"", RNS.LOG_INFO)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("The interface \""+name+"\" could not be created. Check your configuration file for errors!", RNS.LOG_ERROR)
|
RNS.log("The interface \""+name+"\" could not be created. Check your configuration file for errors!", RNS.LOG_ERROR)
|
||||||
@ -475,6 +492,47 @@ class Reticulum:
|
|||||||
self.config.write()
|
self.config.write()
|
||||||
self.__apply_config()
|
self.__apply_config()
|
||||||
|
|
||||||
|
def rpc_loop(self):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
rpc_connection = self.rpc_listener.accept()
|
||||||
|
call = rpc_connection.recv()
|
||||||
|
|
||||||
|
if "get" in call:
|
||||||
|
path = call["get"]
|
||||||
|
|
||||||
|
if path == "interface_stats":
|
||||||
|
rpc_connection.send(self.get_interface_stats())
|
||||||
|
|
||||||
|
rpc_connection.close()
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("An error ocurred while handling RPC call from local client: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
def get_interface_stats(self):
|
||||||
|
if self.is_connected_to_shared_instance:
|
||||||
|
rpc_connection = multiprocessing.connection.Client(self.rpc_addr, authkey=self.rpc_key)
|
||||||
|
rpc_connection.send({"get": "interface_stats"})
|
||||||
|
response = rpc_connection.recv()
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
stats = []
|
||||||
|
for interface in RNS.Transport.interfaces:
|
||||||
|
ifstats = {}
|
||||||
|
|
||||||
|
if hasattr(interface, "clients"):
|
||||||
|
ifstats["clients"] = interface.clients
|
||||||
|
else:
|
||||||
|
ifstats["clients"] = None
|
||||||
|
|
||||||
|
ifstats["name"] = str(interface)
|
||||||
|
ifstats["rxb"] = interface.rxb
|
||||||
|
ifstats["txb"] = interface.txb
|
||||||
|
ifstats["status"] = interface.online
|
||||||
|
stats.append(ifstats)
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def should_use_implicit_proof():
|
def should_use_implicit_proof():
|
||||||
"""
|
"""
|
||||||
|
@ -124,7 +124,7 @@ def main():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--version",
|
"--version",
|
||||||
action="version",
|
action="version",
|
||||||
version="rnpath {version}".format(version=__version__)
|
version="rnprobe {version}".format(version=__version__)
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
90
RNS/Utilities/rnstatus.py
Normal file
90
RNS/Utilities/rnstatus.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import RNS
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from RNS._version import __version__
|
||||||
|
|
||||||
|
def size_str(num, suffix='B'):
|
||||||
|
units = ['','K','M','G','T','P','E','Z']
|
||||||
|
last_unit = 'Y'
|
||||||
|
|
||||||
|
if suffix == 'b':
|
||||||
|
num *= 8
|
||||||
|
units = ['','K','M','G','T','P','E','Z']
|
||||||
|
last_unit = 'Y'
|
||||||
|
|
||||||
|
for unit in units:
|
||||||
|
if abs(num) < 1000.0:
|
||||||
|
if unit == "":
|
||||||
|
return "%.0f %s%s" % (num, unit, suffix)
|
||||||
|
else:
|
||||||
|
return "%.2f %s%s" % (num, unit, suffix)
|
||||||
|
num /= 1000.0
|
||||||
|
|
||||||
|
return "%.2f%s%s" % (num, last_unit, suffix)
|
||||||
|
|
||||||
|
def program_setup(configdir, dispall=False, verbosity = 0):
|
||||||
|
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
||||||
|
|
||||||
|
ifstats = reticulum.get_interface_stats()
|
||||||
|
if ifstats != None:
|
||||||
|
for ifstat in ifstats:
|
||||||
|
name = ifstat["name"]
|
||||||
|
|
||||||
|
if dispall or not (name.startswith("LocalInterface[") or name.startswith("TCPInterface[Client")):
|
||||||
|
if ifstat["status"]:
|
||||||
|
ss = "Up"
|
||||||
|
else:
|
||||||
|
ss = "Down"
|
||||||
|
|
||||||
|
if ifstat["clients"] != None:
|
||||||
|
clients = ifstat["clients"]
|
||||||
|
if name.startswith("Shared Instance["):
|
||||||
|
clients_string = "Connected applications: "+str(clients-1)
|
||||||
|
else:
|
||||||
|
clients_string = "Connected clients: "+str(clients)
|
||||||
|
|
||||||
|
else:
|
||||||
|
clients = None
|
||||||
|
|
||||||
|
print(" {n}".format(n=ifstat["name"]))
|
||||||
|
print("\tStatus: {ss}".format(ss=ss))
|
||||||
|
if clients != None:
|
||||||
|
print("\t"+clients_string)
|
||||||
|
print("\tRX: {rxb}\n\tTX: {txb}".format(rxb=size_str(ifstat["rxb"]), txb=size_str(ifstat["txb"])))
|
||||||
|
print("")
|
||||||
|
else:
|
||||||
|
print("Could not get RNS status")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
try:
|
||||||
|
parser = argparse.ArgumentParser(description="Reticulum Network Stack Status")
|
||||||
|
parser.add_argument("--config", action="store", default=None, help="path to alternative Reticulum config directory", type=str)
|
||||||
|
parser.add_argument("--version", action="version", version="rnstatus {version}".format(version=__version__))
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-a",
|
||||||
|
"--all",
|
||||||
|
action="store_true",
|
||||||
|
help="show all interfaces",
|
||||||
|
default=False
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument('-v', '--verbose', action='count', default=0)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.config:
|
||||||
|
configarg = args.config
|
||||||
|
else:
|
||||||
|
configarg = None
|
||||||
|
|
||||||
|
program_setup(configdir = configarg, dispall = args.all, verbosity=args.verbose)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user