mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-11-26 15:30:18 +00:00
Compare commits
No commits in common. "cf87b1352ababfc8f55ecf85a723e20d1ce343e1" and "bce37fe8c01f11ae8ea7cac944206fc3f819aa70" have entirely different histories.
cf87b1352a
...
bce37fe8c0
@ -216,7 +216,6 @@ class Reticulum:
|
|||||||
Reticulum.identitypath = Reticulum.configdir+"/storage/identities"
|
Reticulum.identitypath = Reticulum.configdir+"/storage/identities"
|
||||||
|
|
||||||
Reticulum.__transport_enabled = False
|
Reticulum.__transport_enabled = False
|
||||||
Reticulum.__remote_management_enabled = False
|
|
||||||
Reticulum.__use_implicit_proof = True
|
Reticulum.__use_implicit_proof = True
|
||||||
Reticulum.__allow_probes = False
|
Reticulum.__allow_probes = False
|
||||||
|
|
||||||
@ -347,7 +346,6 @@ class Reticulum:
|
|||||||
self.is_standalone_instance = False
|
self.is_standalone_instance = False
|
||||||
self.is_connected_to_shared_instance = True
|
self.is_connected_to_shared_instance = True
|
||||||
Reticulum.__transport_enabled = False
|
Reticulum.__transport_enabled = False
|
||||||
Reticulum.__remote_management_enabled = False
|
|
||||||
Reticulum.__allow_probes = False
|
Reticulum.__allow_probes = False
|
||||||
RNS.log("Connected to locally available Reticulum instance via: "+str(interface), RNS.LOG_DEBUG)
|
RNS.log("Connected to locally available Reticulum instance via: "+str(interface), RNS.LOG_DEBUG)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -398,23 +396,6 @@ class Reticulum:
|
|||||||
v = self.config["reticulum"].as_bool(option)
|
v = self.config["reticulum"].as_bool(option)
|
||||||
if v == True:
|
if v == True:
|
||||||
Reticulum.__transport_enabled = True
|
Reticulum.__transport_enabled = True
|
||||||
if option == "enable_remote_management":
|
|
||||||
v = self.config["reticulum"].as_bool(option)
|
|
||||||
if v == True:
|
|
||||||
Reticulum.__remote_management_enabled = True
|
|
||||||
if option == "remote_management_allowed":
|
|
||||||
v = self.config["reticulum"].as_list(option)
|
|
||||||
for hexhash in v:
|
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
|
||||||
if len(hexhash) != dest_len:
|
|
||||||
raise ValueError("Identity hash length for remote management ACL "+str(hexhash)+" is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
|
||||||
try:
|
|
||||||
allowed_hash = bytes.fromhex(hexhash)
|
|
||||||
except Exception as e:
|
|
||||||
raise ValueError("Invalid identity hash for remote management ACL: "+str(hexhash))
|
|
||||||
|
|
||||||
if not allowed_hash in RNS.Transport.remote_management_allowed:
|
|
||||||
RNS.Transport.remote_management_allowed.append(allowed_hash)
|
|
||||||
if option == "respond_to_probes":
|
if option == "respond_to_probes":
|
||||||
v = self.config["reticulum"].as_bool(option)
|
v = self.config["reticulum"].as_bool(option)
|
||||||
if v == True:
|
if v == True:
|
||||||
@ -1194,8 +1175,7 @@ class Reticulum:
|
|||||||
rpc_connection.send(self.get_interface_stats())
|
rpc_connection.send(self.get_interface_stats())
|
||||||
|
|
||||||
if path == "path_table":
|
if path == "path_table":
|
||||||
mh = call["max_hops"]
|
rpc_connection.send(self.get_path_table())
|
||||||
rpc_connection.send(self.get_path_table(max_hops=mh))
|
|
||||||
|
|
||||||
if path == "rate_table":
|
if path == "rate_table":
|
||||||
rpc_connection.send(self.get_rate_table())
|
rpc_connection.send(self.get_rate_table())
|
||||||
@ -1341,27 +1321,25 @@ class Reticulum:
|
|||||||
|
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
def get_path_table(self, max_hops=None):
|
def get_path_table(self):
|
||||||
if self.is_connected_to_shared_instance:
|
if self.is_connected_to_shared_instance:
|
||||||
rpc_connection = multiprocessing.connection.Client(self.rpc_addr, authkey=self.rpc_key)
|
rpc_connection = multiprocessing.connection.Client(self.rpc_addr, authkey=self.rpc_key)
|
||||||
rpc_connection.send({"get": "path_table", "max_hops": max_hops})
|
rpc_connection.send({"get": "path_table"})
|
||||||
response = rpc_connection.recv()
|
response = rpc_connection.recv()
|
||||||
return response
|
return response
|
||||||
|
|
||||||
else:
|
else:
|
||||||
path_table = []
|
path_table = []
|
||||||
for dst_hash in RNS.Transport.destination_table:
|
for dst_hash in RNS.Transport.destination_table:
|
||||||
path_hops = RNS.Transport.destination_table[dst_hash][2]
|
entry = {
|
||||||
if max_hops == None or path_hops <= max_hops:
|
"hash": dst_hash,
|
||||||
entry = {
|
"timestamp": RNS.Transport.destination_table[dst_hash][0],
|
||||||
"hash": dst_hash,
|
"via": RNS.Transport.destination_table[dst_hash][1],
|
||||||
"timestamp": RNS.Transport.destination_table[dst_hash][0],
|
"hops": RNS.Transport.destination_table[dst_hash][2],
|
||||||
"via": RNS.Transport.destination_table[dst_hash][1],
|
"expires": RNS.Transport.destination_table[dst_hash][3],
|
||||||
"hops": path_hops,
|
"interface": str(RNS.Transport.destination_table[dst_hash][5]),
|
||||||
"expires": RNS.Transport.destination_table[dst_hash][3],
|
}
|
||||||
"interface": str(RNS.Transport.destination_table[dst_hash][5]),
|
path_table.append(entry)
|
||||||
}
|
|
||||||
path_table.append(entry)
|
|
||||||
|
|
||||||
return path_table
|
return path_table
|
||||||
|
|
||||||
@ -1538,19 +1516,6 @@ class Reticulum:
|
|||||||
"""
|
"""
|
||||||
return Reticulum.__transport_enabled
|
return Reticulum.__transport_enabled
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def remote_management_enabled():
|
|
||||||
"""
|
|
||||||
Returns whether remote management is enabled for the
|
|
||||||
running instance.
|
|
||||||
|
|
||||||
When remote management is enabled, authenticated peers
|
|
||||||
can remotely query and manage this instance.
|
|
||||||
|
|
||||||
:returns: True if remote management is enabled, False if not.
|
|
||||||
"""
|
|
||||||
return Reticulum.__remote_management_enabled
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def probe_destination_enabled():
|
def probe_destination_enabled():
|
||||||
return Reticulum.__allow_probes
|
return Reticulum.__allow_probes
|
||||||
|
169
RNS/Transport.py
169
RNS/Transport.py
@ -35,110 +35,109 @@ class Transport:
|
|||||||
Transport system of Reticulum.
|
Transport system of Reticulum.
|
||||||
"""
|
"""
|
||||||
# Constants
|
# Constants
|
||||||
BROADCAST = 0x00;
|
BROADCAST = 0x00;
|
||||||
TRANSPORT = 0x01;
|
TRANSPORT = 0x01;
|
||||||
RELAY = 0x02;
|
RELAY = 0x02;
|
||||||
TUNNEL = 0x03;
|
TUNNEL = 0x03;
|
||||||
types = [BROADCAST, TRANSPORT, RELAY, TUNNEL]
|
types = [BROADCAST, TRANSPORT, RELAY, TUNNEL]
|
||||||
|
|
||||||
REACHABILITY_UNREACHABLE = 0x00
|
REACHABILITY_UNREACHABLE = 0x00
|
||||||
REACHABILITY_DIRECT = 0x01
|
REACHABILITY_DIRECT = 0x01
|
||||||
REACHABILITY_TRANSPORT = 0x02
|
REACHABILITY_TRANSPORT = 0x02
|
||||||
|
|
||||||
APP_NAME = "rnstransport"
|
APP_NAME = "rnstransport"
|
||||||
|
|
||||||
PATHFINDER_M = 128 # Max hops
|
PATHFINDER_M = 128 # Max hops
|
||||||
"""
|
"""
|
||||||
Maximum amount of hops that Reticulum will transport a packet.
|
Maximum amount of hops that Reticulum will transport a packet.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PATHFINDER_R = 1 # Retransmit retries
|
PATHFINDER_R = 1 # Retransmit retries
|
||||||
PATHFINDER_G = 5 # Retry grace period
|
PATHFINDER_G = 5 # Retry grace period
|
||||||
PATHFINDER_RW = 0.5 # Random window for announce rebroadcast
|
PATHFINDER_RW = 0.5 # Random window for announce rebroadcast
|
||||||
PATHFINDER_E = 60*60*24*7 # Path expiration of one week
|
PATHFINDER_E = 60*60*24*7 # Path expiration of one week
|
||||||
AP_PATH_TIME = 60*60*24 # Path expiration of one day for Access Point paths
|
AP_PATH_TIME = 60*60*24 # Path expiration of one day for Access Point paths
|
||||||
ROAMING_PATH_TIME = 60*60*6 # Path expiration of 6 hours for Roaming paths
|
ROAMING_PATH_TIME = 60*60*6 # Path expiration of 6 hours for Roaming paths
|
||||||
|
|
||||||
# TODO: Calculate an optimal number for this in
|
# TODO: Calculate an optimal number for this in
|
||||||
# various situations
|
# various situations
|
||||||
LOCAL_REBROADCASTS_MAX = 2 # How many local rebroadcasts of an announce is allowed
|
LOCAL_REBROADCASTS_MAX = 2 # How many local rebroadcasts of an announce is allowed
|
||||||
|
|
||||||
PATH_REQUEST_TIMEOUT = 15 # Default timuout for client path requests in seconds
|
PATH_REQUEST_TIMEOUT = 15 # Default timuout for client path requests in seconds
|
||||||
PATH_REQUEST_GRACE = 0.4 # Grace time before a path announcement is made, allows directly reachable peers to respond first
|
PATH_REQUEST_GRACE = 0.4 # Grace time before a path announcement is made, allows directly reachable peers to respond first
|
||||||
PATH_REQUEST_RG = 0.6 # Extra grace time for roaming-mode interfaces to allow more suitable peers to respond first
|
PATH_REQUEST_RG = 0.6 # Extra grace time for roaming-mode interfaces to allow more suitable peers to respond first
|
||||||
PATH_REQUEST_MI = 20 # Minimum interval in seconds for automated path requests
|
PATH_REQUEST_MI = 20 # Minimum interval in seconds for automated path requests
|
||||||
|
|
||||||
STATE_UNKNOWN = 0x00
|
STATE_UNKNOWN = 0x00
|
||||||
STATE_UNRESPONSIVE = 0x01
|
STATE_UNRESPONSIVE = 0x01
|
||||||
STATE_RESPONSIVE = 0x02
|
STATE_RESPONSIVE = 0x02
|
||||||
|
|
||||||
LINK_TIMEOUT = RNS.Link.STALE_TIME * 1.25
|
LINK_TIMEOUT = RNS.Link.STALE_TIME * 1.25
|
||||||
REVERSE_TIMEOUT = 30*60 # Reverse table entries are removed after 30 minutes
|
REVERSE_TIMEOUT = 30*60 # Reverse table entries are removed after 30 minutes
|
||||||
DESTINATION_TIMEOUT = 60*60*24*7 # Destination table entries are removed if unused for one week
|
DESTINATION_TIMEOUT = 60*60*24*7 # Destination table entries are removed if unused for one week
|
||||||
MAX_RECEIPTS = 1024 # Maximum number of receipts to keep track of
|
MAX_RECEIPTS = 1024 # Maximum number of receipts to keep track of
|
||||||
MAX_RATE_TIMESTAMPS = 16 # Maximum number of announce timestamps to keep per destination
|
MAX_RATE_TIMESTAMPS = 16 # Maximum number of announce timestamps to keep per destination
|
||||||
PERSIST_RANDOM_BLOBS = 32 # Maximum number of random blobs per destination to persist to disk
|
PERSIST_RANDOM_BLOBS = 32 # Maximum number of random blobs per destination to persist to disk
|
||||||
MAX_RANDOM_BLOBS = 64 # Maximum number of random blobs per destination to keep in memory
|
MAX_RANDOM_BLOBS = 64 # Maximum number of random blobs per destination to keep in memory
|
||||||
|
|
||||||
interfaces = [] # All active interfaces
|
interfaces = [] # All active interfaces
|
||||||
destinations = [] # All active destinations
|
destinations = [] # All active destinations
|
||||||
pending_links = [] # Links that are being established
|
pending_links = [] # Links that are being established
|
||||||
active_links = [] # Links that are active
|
active_links = [] # Links that are active
|
||||||
packet_hashlist = [] # A list of packet hashes for duplicate detection
|
packet_hashlist = [] # A list of packet hashes for duplicate detection
|
||||||
receipts = [] # Receipts of all outgoing packets for proof processing
|
receipts = [] # Receipts of all outgoing packets for proof processing
|
||||||
|
|
||||||
# TODO: "destination_table" should really be renamed to "path_table"
|
# TODO: "destination_table" should really be renamed to "path_table"
|
||||||
# Notes on memory usage: 1 megabyte of memory can store approximately
|
# Notes on memory usage: 1 megabyte of memory can store approximately
|
||||||
# 55.100 path table entries or approximately 22.300 link table entries.
|
# 55.100 path table entries or approximately 22.300 link table entries.
|
||||||
|
|
||||||
announce_table = {} # A table for storing announces currently waiting to be retransmitted
|
announce_table = {} # A table for storing announces currently waiting to be retransmitted
|
||||||
destination_table = {} # A lookup table containing the next hop to a given destination
|
destination_table = {} # A lookup table containing the next hop to a given destination
|
||||||
reverse_table = {} # A lookup table for storing packet hashes used to return proofs and replies
|
reverse_table = {} # A lookup table for storing packet hashes used to return proofs and replies
|
||||||
link_table = {} # A lookup table containing hops for links
|
link_table = {} # A lookup table containing hops for links
|
||||||
held_announces = {} # A table containing temporarily held announce-table entries
|
held_announces = {} # A table containing temporarily held announce-table entries
|
||||||
announce_handlers = [] # A table storing externally registered announce handlers
|
announce_handlers = [] # A table storing externally registered announce handlers
|
||||||
tunnels = {} # A table storing tunnels to other transport instances
|
tunnels = {} # A table storing tunnels to other transport instances
|
||||||
announce_rate_table = {} # A table for keeping track of announce rates
|
announce_rate_table = {} # A table for keeping track of announce rates
|
||||||
path_requests = {} # A table for storing path request timestamps
|
path_requests = {} # A table for storing path request timestamps
|
||||||
path_states = {} # A table for keeping track of path states
|
path_states = {} # A table for keeping track of path states
|
||||||
|
|
||||||
discovery_path_requests = {} # A table for keeping track of path requests on behalf of other nodes
|
discovery_path_requests = {} # A table for keeping track of path requests on behalf of other nodes
|
||||||
discovery_pr_tags = [] # A table for keeping track of tagged path requests
|
discovery_pr_tags = [] # A table for keeping track of tagged path requests
|
||||||
max_pr_tags = 32000 # Maximum amount of unique path request tags to remember
|
max_pr_tags = 32000 # Maximum amount of unique path request tags to remember
|
||||||
|
|
||||||
# Transport control destinations are used
|
# Transport control destinations are used
|
||||||
# for control purposes like path requests
|
# for control purposes like path requests
|
||||||
control_destinations = []
|
control_destinations = []
|
||||||
control_hashes = []
|
control_hashes = []
|
||||||
remote_management_allowed = []
|
|
||||||
|
|
||||||
# Interfaces for communicating with
|
# Interfaces for communicating with
|
||||||
# local clients connected to a shared
|
# local clients connected to a shared
|
||||||
# Reticulum instance
|
# Reticulum instance
|
||||||
local_client_interfaces = []
|
local_client_interfaces = []
|
||||||
|
|
||||||
local_client_rssi_cache = []
|
local_client_rssi_cache = []
|
||||||
local_client_snr_cache = []
|
local_client_snr_cache = []
|
||||||
local_client_q_cache = []
|
local_client_q_cache = []
|
||||||
LOCAL_CLIENT_CACHE_MAXSIZE = 512
|
LOCAL_CLIENT_CACHE_MAXSIZE = 512
|
||||||
|
|
||||||
pending_local_path_requests = {}
|
pending_local_path_requests = {}
|
||||||
|
|
||||||
start_time = None
|
start_time = None
|
||||||
jobs_locked = False
|
jobs_locked = False
|
||||||
jobs_running = False
|
jobs_running = False
|
||||||
job_interval = 0.250
|
job_interval = 0.250
|
||||||
links_last_checked = 0.0
|
links_last_checked = 0.0
|
||||||
links_check_interval = 1.0
|
links_check_interval = 1.0
|
||||||
receipts_last_checked = 0.0
|
receipts_last_checked = 0.0
|
||||||
receipts_check_interval = 1.0
|
receipts_check_interval = 1.0
|
||||||
announces_last_checked = 0.0
|
announces_last_checked = 0.0
|
||||||
announces_check_interval = 1.0
|
announces_check_interval = 1.0
|
||||||
hashlist_maxsize = 1000000
|
hashlist_maxsize = 1000000
|
||||||
tables_last_culled = 0.0
|
tables_last_culled = 0.0
|
||||||
tables_cull_interval = 5.0
|
tables_cull_interval = 5.0
|
||||||
interface_last_jobs = 0.0
|
interface_last_jobs = 0.0
|
||||||
interface_jobs_interval = 5.0
|
interface_jobs_interval = 5.0
|
||||||
|
|
||||||
identity = None
|
identity = None
|
||||||
|
|
||||||
@ -180,13 +179,6 @@ class Transport:
|
|||||||
Transport.control_destinations.append(Transport.tunnel_synthesize_handler)
|
Transport.control_destinations.append(Transport.tunnel_synthesize_handler)
|
||||||
Transport.control_hashes.append(Transport.tunnel_synthesize_destination.hash)
|
Transport.control_hashes.append(Transport.tunnel_synthesize_destination.hash)
|
||||||
|
|
||||||
if RNS.Reticulum.remote_management_enabled() and not Transport.owner.is_connected_to_shared_instance:
|
|
||||||
Transport.remote_management_destination = RNS.Destination(Transport.identity, RNS.Destination.IN, RNS.Destination.SINGLE, Transport.APP_NAME, "remote", "management")
|
|
||||||
Transport.remote_management_destination.register_request_handler("/status", response_generator = Transport.remote_status_handler, allow = RNS.Destination.ALLOW_LIST, allowed_list=Transport.remote_management_allowed)
|
|
||||||
Transport.control_destinations.append(Transport.remote_management_destination)
|
|
||||||
Transport.control_hashes.append(Transport.remote_management_destination.hash)
|
|
||||||
RNS.log("Enabled remote management on "+str(Transport.remote_management_destination), RNS.LOG_NOTICE)
|
|
||||||
|
|
||||||
Transport.jobs_running = False
|
Transport.jobs_running = False
|
||||||
thread = threading.Thread(target=Transport.jobloop, daemon=True)
|
thread = threading.Thread(target=Transport.jobloop, daemon=True)
|
||||||
thread.start()
|
thread.start()
|
||||||
@ -2255,25 +2247,6 @@ class Transport:
|
|||||||
packet.send()
|
packet.send()
|
||||||
Transport.path_requests[destination_hash] = time.time()
|
Transport.path_requests[destination_hash] = time.time()
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def remote_status_handler(path, data, request_id, link_id, remote_identity, requested_at):
|
|
||||||
if remote_identity != None:
|
|
||||||
response = None
|
|
||||||
try:
|
|
||||||
if isinstance(data, list) and len(data) > 0:
|
|
||||||
response = []
|
|
||||||
response.append(Transport.owner.get_interface_stats())
|
|
||||||
if data[0] == True:
|
|
||||||
response.append(Transport.owner.get_link_count())
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
RNS.log("An error occurred while processing remote status request from "+RNS.prettyhexrep(remote_identity), RNS.LOG_ERROR)
|
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def path_request_handler(data, packet):
|
def path_request_handler(data, packet):
|
||||||
try:
|
try:
|
||||||
|
@ -30,7 +30,7 @@ import argparse
|
|||||||
from RNS._version import __version__
|
from RNS._version import __version__
|
||||||
|
|
||||||
|
|
||||||
def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity, timeout, drop_queues, drop_via, max_hops):
|
def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity, timeout, drop_queues, drop_via):
|
||||||
if table:
|
if table:
|
||||||
destination_hash = None
|
destination_hash = None
|
||||||
if destination_hexhash != None:
|
if destination_hexhash != None:
|
||||||
@ -47,7 +47,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
||||||
table = sorted(reticulum.get_path_table(max_hops=max_hops), key=lambda e: (e["interface"], e["hops"]) )
|
table = sorted(reticulum.get_path_table(), key=lambda e: (e["interface"], e["hops"]) )
|
||||||
|
|
||||||
displayed = 0
|
displayed = 0
|
||||||
for path in table:
|
for path in table:
|
||||||
@ -255,16 +255,6 @@ def main():
|
|||||||
default=False
|
default=False
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"-m",
|
|
||||||
"--max",
|
|
||||||
action="store",
|
|
||||||
metavar="hops",
|
|
||||||
type=int,
|
|
||||||
help="maximum hops to filter path table by",
|
|
||||||
default=None
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-r",
|
"-r",
|
||||||
"--rates",
|
"--rates",
|
||||||
@ -337,7 +327,6 @@ def main():
|
|||||||
timeout = args.w,
|
timeout = args.w,
|
||||||
drop_queues = args.drop_announces,
|
drop_queues = args.drop_announces,
|
||||||
drop_via = args.drop_via,
|
drop_via = args.drop_via,
|
||||||
max_hops = args.max,
|
|
||||||
)
|
)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
@ -23,9 +23,6 @@
|
|||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
import RNS
|
import RNS
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from RNS._version import __version__
|
from RNS._version import __version__
|
||||||
@ -49,135 +46,22 @@ def size_str(num, suffix='B'):
|
|||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return "%.2f%s%s" % (num, last_unit, suffix)
|
||||||
|
|
||||||
request_result = None
|
def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=False, astats=False, lstats=False, sorting=None, sort_reverse=False):
|
||||||
request_concluded = False
|
|
||||||
def get_remote_status(destination_hash, include_lstats, identity, no_output=False, timeout=RNS.Transport.PATH_REQUEST_TIMEOUT):
|
|
||||||
global request_result, request_concluded
|
|
||||||
link_count = None
|
|
||||||
|
|
||||||
if not RNS.Transport.has_path(destination_hash):
|
|
||||||
if not no_output:
|
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested", end=" ")
|
|
||||||
sys.stdout.flush()
|
|
||||||
RNS.Transport.request_path(destination_hash)
|
|
||||||
pr_time = time.time()
|
|
||||||
while not RNS.Transport.has_path(destination_hash):
|
|
||||||
time.sleep(0.1)
|
|
||||||
if time.time() - pr_time > timeout:
|
|
||||||
if not no_output:
|
|
||||||
print("\r \r", end="")
|
|
||||||
print("Path request timed out")
|
|
||||||
exit(12)
|
|
||||||
|
|
||||||
remote_identity = RNS.Identity.recall(destination_hash)
|
|
||||||
|
|
||||||
def remote_link_closed(link):
|
|
||||||
if link.teardown_reason == RNS.Link.TIMEOUT:
|
|
||||||
if not no_output:
|
|
||||||
print("\r \r", end="")
|
|
||||||
print("The link timed out, exiting now")
|
|
||||||
elif link.teardown_reason == RNS.Link.DESTINATION_CLOSED:
|
|
||||||
if not no_output:
|
|
||||||
print("\r \r", end="")
|
|
||||||
print("The link was closed by the server, exiting now")
|
|
||||||
else:
|
|
||||||
if not no_output:
|
|
||||||
print("\r \r", end="")
|
|
||||||
print("Link closed unexpectedly, exiting now")
|
|
||||||
exit(10)
|
|
||||||
|
|
||||||
def request_failed(request_receipt):
|
|
||||||
global request_result, request_concluded
|
|
||||||
if not no_output:
|
|
||||||
print("\r \r", end="")
|
|
||||||
print("The remote status request failed. Likely authentication failure.")
|
|
||||||
request_concluded = True
|
|
||||||
|
|
||||||
def got_response(request_receipt):
|
|
||||||
global request_result, request_concluded
|
|
||||||
response = request_receipt.response
|
|
||||||
if isinstance(response, list):
|
|
||||||
status = response[0]
|
|
||||||
if len(response) > 1:
|
|
||||||
link_count = response[1]
|
|
||||||
else:
|
|
||||||
link_count = None
|
|
||||||
|
|
||||||
request_result = (status, link_count)
|
|
||||||
|
|
||||||
request_concluded = True
|
|
||||||
|
|
||||||
def remote_link_established(link):
|
|
||||||
if not no_output:
|
|
||||||
print("\r \r", end="")
|
|
||||||
print("Sending request...", end=" ")
|
|
||||||
sys.stdout.flush()
|
|
||||||
link.identify(identity)
|
|
||||||
link.request("/status", data = [include_lstats], response_callback = got_response, failed_callback = request_failed)
|
|
||||||
|
|
||||||
if not no_output:
|
|
||||||
print("\r \r", end="")
|
|
||||||
print("Establishing link with remote transport instance...", end=" ")
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
remote_destination = RNS.Destination(remote_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, "rnstransport", "remote", "management")
|
|
||||||
link = RNS.Link(remote_destination)
|
|
||||||
link.set_link_established_callback(remote_link_established)
|
|
||||||
link.set_link_closed_callback(remote_link_closed)
|
|
||||||
|
|
||||||
while not request_concluded:
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
if request_result != None:
|
|
||||||
print("\r \r", end="")
|
|
||||||
|
|
||||||
return request_result
|
|
||||||
|
|
||||||
def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=False, astats=False,
|
|
||||||
lstats=False, sorting=None, sort_reverse=False, remote=None, management_identity=None,
|
|
||||||
remote_timeout=RNS.Transport.PATH_REQUEST_TIMEOUT):
|
|
||||||
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
||||||
|
|
||||||
link_count = None
|
link_count = None
|
||||||
stats = None
|
if lstats:
|
||||||
if remote:
|
|
||||||
try:
|
try:
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
link_count = reticulum.get_link_count()
|
||||||
if len(remote) != dest_len:
|
|
||||||
raise ValueError("Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
|
||||||
try:
|
|
||||||
identity_hash = bytes.fromhex(remote)
|
|
||||||
destination_hash = RNS.Destination.hash_from_name_and_identity("rnstransport.remote.management", identity_hash)
|
|
||||||
except Exception as e:
|
|
||||||
raise ValueError("Invalid destination entered. Check your input.")
|
|
||||||
|
|
||||||
identity = RNS.Identity.from_file(os.path.expanduser(management_identity))
|
|
||||||
if identity == None:
|
|
||||||
raise ValueError("Could not load management identity from "+str(management_identity))
|
|
||||||
|
|
||||||
try:
|
|
||||||
remote_status = get_remote_status(destination_hash, lstats, identity, no_output=json, timeout=remote_timeout)
|
|
||||||
if remote_status != None:
|
|
||||||
stats, link_count = remote_status
|
|
||||||
except Exception as e:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(str(e))
|
|
||||||
exit(20)
|
|
||||||
|
|
||||||
else:
|
|
||||||
if lstats:
|
|
||||||
try:
|
|
||||||
link_count = reticulum.get_link_count()
|
|
||||||
except Exception as e:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
stats = reticulum.get_interface_stats()
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
stats = None
|
||||||
|
try:
|
||||||
|
stats = reticulum.get_interface_stats()
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
if stats != None:
|
if stats != None:
|
||||||
if json:
|
if json:
|
||||||
import json
|
import json
|
||||||
@ -343,8 +227,7 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
|
|||||||
print("\n Transport Instance "+RNS.prettyhexrep(stats["transport_id"])+" running")
|
print("\n Transport Instance "+RNS.prettyhexrep(stats["transport_id"])+" running")
|
||||||
if "probe_responder" in stats and stats["probe_responder"] != None:
|
if "probe_responder" in stats and stats["probe_responder"] != None:
|
||||||
print(" Probe responder at "+RNS.prettyhexrep(stats["probe_responder"])+ " active")
|
print(" Probe responder at "+RNS.prettyhexrep(stats["probe_responder"])+ " active")
|
||||||
if "transport_uptime" in stats and stats["transport_uptime"] != None:
|
print(" Uptime is "+RNS.prettytime(stats["transport_uptime"])+lstr)
|
||||||
print(" Uptime is "+RNS.prettytime(stats["transport_uptime"])+lstr)
|
|
||||||
else:
|
else:
|
||||||
if lstr != "":
|
if lstr != "":
|
||||||
print(f"\n{lstr}")
|
print(f"\n{lstr}")
|
||||||
@ -352,10 +235,7 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
|
|||||||
print("")
|
print("")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if not remote:
|
print("Could not get RNS status")
|
||||||
print("Could not get RNS status")
|
|
||||||
else:
|
|
||||||
print("Could not get RNS status from remote transport instance "+RNS.prettyhexrep(identity_hash))
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
try:
|
||||||
@ -412,33 +292,6 @@ def main():
|
|||||||
default=False
|
default=False
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"-R",
|
|
||||||
action="store",
|
|
||||||
metavar="hash",
|
|
||||||
help="transport identity hash of remote instance to get status from",
|
|
||||||
default=None,
|
|
||||||
type=str
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"-i",
|
|
||||||
action="store",
|
|
||||||
metavar="path",
|
|
||||||
help="path to identity used for remote management",
|
|
||||||
default=None,
|
|
||||||
type=str
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"-w",
|
|
||||||
action="store",
|
|
||||||
metavar="seconds",
|
|
||||||
type=float,
|
|
||||||
help="timeout before giving up on remote queries",
|
|
||||||
default=RNS.Transport.PATH_REQUEST_TIMEOUT
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument('-v', '--verbose', action='count', default=0)
|
parser.add_argument('-v', '--verbose', action='count', default=0)
|
||||||
|
|
||||||
parser.add_argument("filter", nargs="?", default=None, help="only display interfaces with names including filter", type=str)
|
parser.add_argument("filter", nargs="?", default=None, help="only display interfaces with names including filter", type=str)
|
||||||
@ -460,9 +313,6 @@ def main():
|
|||||||
lstats=args.link_stats,
|
lstats=args.link_stats,
|
||||||
sorting=args.sort,
|
sorting=args.sort,
|
||||||
sort_reverse=args.reverse,
|
sort_reverse=args.reverse,
|
||||||
remote=args.R,
|
|
||||||
management_identity=args.i,
|
|
||||||
remote_timeout=args.w,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
Loading…
Reference in New Issue
Block a user