mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-11-26 15:30:18 +00:00
Compare commits
7 Commits
b5cb3a65dd
...
c5248d53d6
Author | SHA1 | Date | |
---|---|---|---|
|
c5248d53d6 | ||
|
2d2f0947ac | ||
|
4fa616a326 | ||
|
136713eec1 | ||
|
0fd75cb819 | ||
|
ea52153969 | ||
|
3854781028 |
@ -217,7 +217,7 @@ class Identity:
|
|||||||
return Identity.truncated_hash(os.urandom(Identity.TRUNCATED_HASHLENGTH//8))
|
return Identity.truncated_hash(os.urandom(Identity.TRUNCATED_HASHLENGTH//8))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def validate_announce(packet):
|
def validate_announce(packet, only_validate_signature=False):
|
||||||
try:
|
try:
|
||||||
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
||||||
destination_hash = packet.destination_hash
|
destination_hash = packet.destination_hash
|
||||||
@ -238,6 +238,10 @@ class Identity:
|
|||||||
announced_identity.load_public_key(public_key)
|
announced_identity.load_public_key(public_key)
|
||||||
|
|
||||||
if announced_identity.pub != None and announced_identity.validate(signature, signed_data):
|
if announced_identity.pub != None and announced_identity.validate(signature, signed_data):
|
||||||
|
if only_validate_signature:
|
||||||
|
del announced_identity
|
||||||
|
return True
|
||||||
|
|
||||||
hash_material = name_hash+announced_identity.hash
|
hash_material = name_hash+announced_identity.hash
|
||||||
expected_hash = RNS.Identity.full_hash(hash_material)[:RNS.Reticulum.TRUNCATED_HASHLENGTH//8]
|
expected_hash = RNS.Identity.full_hash(hash_material)[:RNS.Reticulum.TRUNCATED_HASHLENGTH//8]
|
||||||
|
|
||||||
|
@ -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.log("You can install one with the command: python3 -m pip install pyserial", RNS.LOG_CRITICAL)
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
|
|
||||||
self.rxb = 0
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 564
|
self.HW_MTU = 564
|
||||||
|
|
||||||
|
@ -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):
|
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
|
from RNS.vendor.ifaddr import niwrapper
|
||||||
|
super().__init__()
|
||||||
self.netinfo = niwrapper
|
self.netinfo = niwrapper
|
||||||
|
|
||||||
self.rxb = 0
|
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
self.IN = True
|
self.IN = True
|
||||||
|
@ -390,8 +390,7 @@ class I2PInterfacePeer(Interface):
|
|||||||
TUNNEL_STATE_STALE = 0x02
|
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
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
@ -832,8 +831,7 @@ class I2PInterface(Interface):
|
|||||||
BITRATE_GUESS = 256*1000
|
BITRATE_GUESS = 256*1000
|
||||||
|
|
||||||
def __init__(self, owner, name, rns_storagepath, peers, connectable = False, ifac_size = 16, ifac_netname = None, ifac_netkey = None):
|
def __init__(self, owner, name, rns_storagepath, peers, connectable = False, ifac_size = 16, ifac_netname = None, ifac_netkey = None):
|
||||||
self.rxb = 0
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
@ -964,6 +962,12 @@ class I2PInterface(Interface):
|
|||||||
def processOutgoing(self, data):
|
def processOutgoing(self, data):
|
||||||
pass
|
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):
|
def detach(self):
|
||||||
RNS.log("Detaching "+str(self), RNS.LOG_DEBUG)
|
RNS.log("Detaching "+str(self), RNS.LOG_DEBUG)
|
||||||
self.i2p.stop()
|
self.i2p.stop()
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
import RNS
|
import RNS
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
class Interface:
|
class Interface:
|
||||||
IN = False
|
IN = False
|
||||||
@ -43,14 +44,65 @@ class Interface:
|
|||||||
# should actively discover paths for.
|
# should actively discover paths for.
|
||||||
DISCOVER_PATHS_FOR = [MODE_ACCESS_POINT, MODE_GATEWAY]
|
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):
|
def __init__(self):
|
||||||
self.rxb = 0
|
self.rxb = 0
|
||||||
self.txb = 0
|
self.txb = 0
|
||||||
self.online = False
|
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):
|
def get_hash(self):
|
||||||
return RNS.Identity.full_hash(str(self).encode("utf-8"))
|
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):
|
def process_announce_queue(self):
|
||||||
if not hasattr(self, "announce_cap"):
|
if not hasattr(self, "announce_cap"):
|
||||||
self.announce_cap = RNS.Reticulum.ANNOUNCE_CAP
|
self.announce_cap = RNS.Reticulum.ANNOUNCE_CAP
|
||||||
@ -79,6 +131,7 @@ class Interface:
|
|||||||
self.announce_allowed_at = now + wait_time
|
self.announce_allowed_at = now + wait_time
|
||||||
|
|
||||||
self.processOutgoing(selected["raw"])
|
self.processOutgoing(selected["raw"])
|
||||||
|
self.sent_announce()
|
||||||
|
|
||||||
if selected in self.announce_queue:
|
if selected in self.announce_queue:
|
||||||
self.announce_queue.remove(selected)
|
self.announce_queue.remove(selected)
|
||||||
|
@ -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.log("You can install one with the command: python3 -m pip install pyserial", RNS.LOG_CRITICAL)
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
|
|
||||||
self.rxb = 0
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 564
|
self.HW_MTU = 564
|
||||||
|
|
||||||
|
@ -53,8 +53,7 @@ class LocalClientInterface(Interface):
|
|||||||
RECONNECT_WAIT = 3
|
RECONNECT_WAIT = 3
|
||||||
|
|
||||||
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
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
# TODO: Remove at some point
|
# TODO: Remove at some point
|
||||||
# self.rxptime = 0
|
# self.rxptime = 0
|
||||||
@ -280,8 +279,7 @@ class LocalClientInterface(Interface):
|
|||||||
class LocalServerInterface(Interface):
|
class LocalServerInterface(Interface):
|
||||||
|
|
||||||
def __init__(self, owner, bindport=None):
|
def __init__(self, owner, bindport=None):
|
||||||
self.rxb = 0
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
self.online = False
|
self.online = False
|
||||||
self.clients = 0
|
self.clients = 0
|
||||||
|
|
||||||
@ -338,6 +336,12 @@ class LocalServerInterface(Interface):
|
|||||||
def processOutgoing(self, data):
|
def processOutgoing(self, data):
|
||||||
pass
|
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):
|
def __str__(self):
|
||||||
return "Shared Instance["+str(self.bind_port)+"]"
|
return "Shared Instance["+str(self.bind_port)+"]"
|
||||||
|
|
||||||
|
@ -54,8 +54,7 @@ class PipeInterface(Interface):
|
|||||||
if respawn_delay == None:
|
if respawn_delay == None:
|
||||||
respawn_delay = 5
|
respawn_delay = 5
|
||||||
|
|
||||||
self.rxb = 0
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
|
@ -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.log("You can install one with the command: python3 -m pip install pyserial", RNS.LOG_CRITICAL)
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
|
|
||||||
self.rxb = 0
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 508
|
self.HW_MTU = 508
|
||||||
|
|
||||||
|
@ -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.log("You can install one with the command: python3 -m pip install pyserial", RNS.LOG_CRITICAL)
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
|
|
||||||
self.rxb = 0
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 564
|
self.HW_MTU = 564
|
||||||
|
|
||||||
|
@ -79,8 +79,7 @@ class TCPClientInterface(Interface):
|
|||||||
I2P_PROBES = 5
|
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):
|
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
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
@ -419,8 +418,7 @@ class TCPServerInterface(Interface):
|
|||||||
return ifaddr[netinfo.AF_INET][0]["broadcast"]
|
return ifaddr[netinfo.AF_INET][0]["broadcast"]
|
||||||
|
|
||||||
def __init__(self, owner, name, device=None, bindip=None, bindport=None, i2p_tunneled=False):
|
def __init__(self, owner, name, device=None, bindip=None, bindport=None, i2p_tunneled=False):
|
||||||
self.rxb = 0
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
@ -505,6 +503,12 @@ class TCPServerInterface(Interface):
|
|||||||
self.clients += 1
|
self.clients += 1
|
||||||
spawned_interface.read_loop()
|
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):
|
def processOutgoing(self, data):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -45,8 +45,7 @@ class UDPInterface(Interface):
|
|||||||
return ifaddr[netinfo.AF_INET][0]["broadcast"]
|
return ifaddr[netinfo.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
|
super().__init__()
|
||||||
self.txb = 0
|
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
|
@ -1143,6 +1143,8 @@ class Reticulum:
|
|||||||
ifstats["name"] = str(interface)
|
ifstats["name"] = str(interface)
|
||||||
ifstats["rxb"] = interface.rxb
|
ifstats["rxb"] = interface.rxb
|
||||||
ifstats["txb"] = interface.txb
|
ifstats["txb"] = interface.txb
|
||||||
|
ifstats["incoming_announce_frequency"] = interface.incoming_announce_frequency()
|
||||||
|
ifstats["outgoing_announce_frequency"] = interface.outgoing_announce_frequency()
|
||||||
ifstats["status"] = interface.online
|
ifstats["status"] = interface.online
|
||||||
ifstats["mode"] = interface.mode
|
ifstats["mode"] = interface.mode
|
||||||
|
|
||||||
|
@ -887,6 +887,8 @@ class Transport:
|
|||||||
# thread.start()
|
# thread.start()
|
||||||
|
|
||||||
Transport.transmit(interface, packet.raw)
|
Transport.transmit(interface, packet.raw)
|
||||||
|
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
||||||
|
interface.sent_announce()
|
||||||
sent = True
|
sent = True
|
||||||
|
|
||||||
if sent:
|
if sent:
|
||||||
@ -1227,8 +1229,11 @@ class Transport:
|
|||||||
# announces, queueing rebroadcasts of these, and removal
|
# announces, queueing rebroadcasts of these, and removal
|
||||||
# of queued announce rebroadcasts once handed to the next node.
|
# of queued announce rebroadcasts once handed to the next node.
|
||||||
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
||||||
|
if interface != None and RNS.Identity.validate_announce(packet, only_validate_signature=True):
|
||||||
|
interface.received_announce()
|
||||||
|
|
||||||
local_destination = next((d for d in Transport.destinations if d.hash == packet.destination_hash), None)
|
local_destination = next((d for d in Transport.destinations if d.hash == packet.destination_hash), None)
|
||||||
if local_destination == None and RNS.Identity.validate_announce(packet):
|
if local_destination == None and RNS.Identity.validate_announce(packet):
|
||||||
if packet.transport_id != None:
|
if packet.transport_id != None:
|
||||||
received_from = packet.transport_id
|
received_from = packet.transport_id
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ def size_str(num, suffix='B'):
|
|||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return "%.2f%s%s" % (num, last_unit, suffix)
|
||||||
|
|
||||||
def program_setup(configdir, dispall=False, verbosity=0, name_filter=None,json=False):
|
def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=False, astats=False, sorting=None, sort_reverse=False):
|
||||||
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
||||||
|
|
||||||
stats = None
|
stats = None
|
||||||
@ -62,16 +62,36 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None,json=F
|
|||||||
if isinstance(stats[s], bytes):
|
if isinstance(stats[s], bytes):
|
||||||
stats[s] = RNS.hexrep(stats[s], delimit=False)
|
stats[s] = RNS.hexrep(stats[s], delimit=False)
|
||||||
|
|
||||||
for i in stats[s]:
|
if isinstance(stats[s], dict):
|
||||||
if isinstance(i, dict):
|
for i in stats[s]:
|
||||||
for k in i:
|
if isinstance(i, dict):
|
||||||
if isinstance(i[k], bytes):
|
for k in i:
|
||||||
i[k] = RNS.hexrep(i[k], delimit=False)
|
if isinstance(i[k], bytes):
|
||||||
|
i[k] = RNS.hexrep(i[k], delimit=False)
|
||||||
|
|
||||||
print(json.dumps(stats))
|
print(json.dumps(stats))
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
interfaces = stats["interfaces"]
|
||||||
|
if sorting != None and isinstance(sorting, str):
|
||||||
|
sorting = sorting.lower()
|
||||||
|
if sorting == "rate" or sorting == "bitrate":
|
||||||
|
interfaces.sort(key=lambda i: i["bitrate"], reverse=not sort_reverse)
|
||||||
|
if sorting == "rx":
|
||||||
|
interfaces.sort(key=lambda i: i["rxb"], reverse=not sort_reverse)
|
||||||
|
if sorting == "tx":
|
||||||
|
interfaces.sort(key=lambda i: i["txb"], reverse=not sort_reverse)
|
||||||
|
if sorting == "traffic":
|
||||||
|
interfaces.sort(key=lambda i: i["rxb"]+i["txb"], reverse=not sort_reverse)
|
||||||
|
if sorting == "announces" or sorting == "announce":
|
||||||
|
interfaces.sort(key=lambda i: i["incoming_announce_frequency"]+i["outgoing_announce_frequency"], reverse=not sort_reverse)
|
||||||
|
if sorting == "arx":
|
||||||
|
interfaces.sort(key=lambda i: i["incoming_announce_frequency"], reverse=not sort_reverse)
|
||||||
|
if sorting == "atx":
|
||||||
|
interfaces.sort(key=lambda i: i["outgoing_announce_frequency"], reverse=not sort_reverse)
|
||||||
|
|
||||||
|
|
||||||
for ifstat in stats["interfaces"]:
|
for ifstat in interfaces:
|
||||||
name = ifstat["name"]
|
name = ifstat["name"]
|
||||||
|
|
||||||
if dispall or not (
|
if dispall or not (
|
||||||
@ -113,7 +133,7 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None,json=F
|
|||||||
else:
|
else:
|
||||||
spec_str = " programs"
|
spec_str = " programs"
|
||||||
|
|
||||||
clients_string = "Serving : "+str(cnum)+spec_str
|
clients_string = "Serving : "+str(cnum)+spec_str
|
||||||
elif name.startswith("I2PInterface["):
|
elif name.startswith("I2PInterface["):
|
||||||
if "i2p_connectable" in ifstat and ifstat["i2p_connectable"] == True:
|
if "i2p_connectable" in ifstat and ifstat["i2p_connectable"] == True:
|
||||||
cnum = clients
|
cnum = clients
|
||||||
@ -122,11 +142,11 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None,json=F
|
|||||||
else:
|
else:
|
||||||
spec_str = " connected I2P endpoints"
|
spec_str = " connected I2P endpoints"
|
||||||
|
|
||||||
clients_string = "Peers : "+str(cnum)+spec_str
|
clients_string = "Peers : "+str(cnum)+spec_str
|
||||||
else:
|
else:
|
||||||
clients_string = ""
|
clients_string = ""
|
||||||
else:
|
else:
|
||||||
clients_string = "Clients : "+str(clients)
|
clients_string = "Clients : "+str(clients)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
clients = None
|
clients = None
|
||||||
@ -134,46 +154,50 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None,json=F
|
|||||||
print(" {n}".format(n=ifstat["name"]))
|
print(" {n}".format(n=ifstat["name"]))
|
||||||
|
|
||||||
if "ifac_netname" in ifstat and ifstat["ifac_netname"] != None:
|
if "ifac_netname" in ifstat and ifstat["ifac_netname"] != None:
|
||||||
print(" Network : {nn}".format(nn=ifstat["ifac_netname"]))
|
print(" Network : {nn}".format(nn=ifstat["ifac_netname"]))
|
||||||
|
|
||||||
print(" Status : {ss}".format(ss=ss))
|
print(" Status : {ss}".format(ss=ss))
|
||||||
|
|
||||||
if clients != None and clients_string != "":
|
if clients != None and clients_string != "":
|
||||||
print(" "+clients_string)
|
print(" "+clients_string)
|
||||||
|
|
||||||
if not (name.startswith("Shared Instance[") or name.startswith("TCPInterface[Client") or name.startswith("LocalInterface[")):
|
if not (name.startswith("Shared Instance[") or name.startswith("TCPInterface[Client") or name.startswith("LocalInterface[")):
|
||||||
print(" Mode : {mode}".format(mode=modestr))
|
print(" Mode : {mode}".format(mode=modestr))
|
||||||
|
|
||||||
if "bitrate" in ifstat and ifstat["bitrate"] != None:
|
if "bitrate" in ifstat and ifstat["bitrate"] != None:
|
||||||
print(" Rate : {ss}".format(ss=speed_str(ifstat["bitrate"])))
|
print(" Rate : {ss}".format(ss=speed_str(ifstat["bitrate"])))
|
||||||
|
|
||||||
if "airtime_short" in ifstat and "airtime_long" in ifstat:
|
if "airtime_short" in ifstat and "airtime_long" in ifstat:
|
||||||
print(" Airtime : {atl}% (1h), {ats}% (15s)".format(ats=str(ifstat["airtime_short"]),atl=str(ifstat["airtime_long"])))
|
print(" Airtime : {atl}% (1h), {ats}% (15s)".format(ats=str(ifstat["airtime_short"]),atl=str(ifstat["airtime_long"])))
|
||||||
|
|
||||||
if "channel_load_short" in ifstat and "channel_load_long" in ifstat:
|
if "channel_load_short" in ifstat and "channel_load_long" in ifstat:
|
||||||
print(" Ch.Load : {atl}% (1h), {ats}% (15s)".format(ats=str(ifstat["channel_load_short"]),atl=str(ifstat["channel_load_long"])))
|
print(" Ch.Load : {atl}% (1h), {ats}% (15s)".format(ats=str(ifstat["channel_load_short"]),atl=str(ifstat["channel_load_long"])))
|
||||||
|
|
||||||
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:
|
if "tunnelstate" in ifstat and ifstat["tunnelstate"] != None:
|
||||||
print(" I2P : {ts}".format(ts=ifstat["tunnelstate"]))
|
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))
|
||||||
|
|
||||||
if "i2p_b32" in ifstat and ifstat["i2p_b32"] != None:
|
if "i2p_b32" in ifstat and ifstat["i2p_b32"] != None:
|
||||||
print(" I2P B32 : {ep}".format(ep=str(ifstat["i2p_b32"])))
|
print(" I2P B32 : {ep}".format(ep=str(ifstat["i2p_b32"])))
|
||||||
|
|
||||||
if "announce_queue" in ifstat and ifstat["announce_queue"] != None and ifstat["announce_queue"] > 0:
|
if astats and "announce_queue" in ifstat and ifstat["announce_queue"] != None and ifstat["announce_queue"] > 0:
|
||||||
aqn = ifstat["announce_queue"]
|
aqn = ifstat["announce_queue"]
|
||||||
if aqn == 1:
|
if aqn == 1:
|
||||||
print(" Queued : {np} announce".format(np=aqn))
|
print(" Queued : {np} announce".format(np=aqn))
|
||||||
else:
|
else:
|
||||||
print(" Queued : {np} announces".format(np=aqn))
|
print(" Queued : {np} announces".format(np=aqn))
|
||||||
|
|
||||||
print(" Traffic : {txb}↑\n {rxb}↓".format(rxb=size_str(ifstat["rxb"]), txb=size_str(ifstat["txb"])))
|
if astats and "incoming_announce_frequency" in ifstat and ifstat["incoming_announce_frequency"] != None:
|
||||||
|
print(" Announces : {iaf}↑".format(iaf=RNS.prettyfrequency(ifstat["outgoing_announce_frequency"])))
|
||||||
|
print(" {iaf}↓".format(iaf=RNS.prettyfrequency(ifstat["incoming_announce_frequency"])))
|
||||||
|
|
||||||
|
print(" Traffic : {txb}↑\n {rxb}↓".format(rxb=size_str(ifstat["rxb"]), txb=size_str(ifstat["txb"])))
|
||||||
|
|
||||||
if "transport_id" in stats and stats["transport_id"] != None:
|
if "transport_id" in stats and stats["transport_id"] != None:
|
||||||
print("\n Transport Instance "+RNS.prettyhexrep(stats["transport_id"])+" running")
|
print("\n Transport Instance "+RNS.prettyhexrep(stats["transport_id"])+" running")
|
||||||
@ -200,6 +224,31 @@ def main():
|
|||||||
default=False
|
default=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-A",
|
||||||
|
"--announce-stats",
|
||||||
|
action="store_true",
|
||||||
|
help="show announce stats",
|
||||||
|
default=False
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-s",
|
||||||
|
"--sort",
|
||||||
|
action="store",
|
||||||
|
help="sort interfaces by [traffic, rx, tx, announces, arx, atx, rate]",
|
||||||
|
default=None,
|
||||||
|
type=str
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-r",
|
||||||
|
"--reverse",
|
||||||
|
action="store_true",
|
||||||
|
help="reverse sorting",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-j",
|
"-j",
|
||||||
"--json",
|
"--json",
|
||||||
@ -219,7 +268,16 @@ def main():
|
|||||||
else:
|
else:
|
||||||
configarg = None
|
configarg = None
|
||||||
|
|
||||||
program_setup(configdir = configarg, dispall = args.all, verbosity=args.verbose, name_filter=args.filter, json=args.json)
|
program_setup(
|
||||||
|
configdir = configarg,
|
||||||
|
dispall = args.all,
|
||||||
|
verbosity=args.verbose,
|
||||||
|
name_filter=args.filter,
|
||||||
|
json=args.json,
|
||||||
|
astats=args.announce_stats,
|
||||||
|
sorting=args.sort,
|
||||||
|
sort_reverse=args.reverse,
|
||||||
|
)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("")
|
print("")
|
||||||
|
@ -180,6 +180,18 @@ def prettysize(num, suffix='B'):
|
|||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return "%.2f%s%s" % (num, last_unit, suffix)
|
||||||
|
|
||||||
|
def prettyfrequency(hz, suffix="Hz"):
|
||||||
|
num = hz*1e6
|
||||||
|
units = ["µ", "m", "", "K","M","G","T","P","E","Z"]
|
||||||
|
last_unit = "Y"
|
||||||
|
|
||||||
|
for unit in units:
|
||||||
|
if abs(num) < 1000.0:
|
||||||
|
return "%.2f %s%s" % (num, unit, suffix)
|
||||||
|
num /= 1000.0
|
||||||
|
|
||||||
|
return "%.2f%s%s" % (num, last_unit, suffix)
|
||||||
|
|
||||||
def prettytime(time, verbose=False):
|
def prettytime(time, verbose=False):
|
||||||
days = int(time // (24 * 3600))
|
days = int(time // (24 * 3600))
|
||||||
time = time % (24 * 3600)
|
time = time % (24 * 3600)
|
||||||
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user