mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-11-22 13:40:19 +00:00
Added path and rate tables to remote management
This commit is contained in:
parent
8ee11ac32c
commit
d3b8c1c829
@ -183,6 +183,7 @@ class Transport:
|
|||||||
if RNS.Reticulum.remote_management_enabled() and not Transport.owner.is_connected_to_shared_instance:
|
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 = 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.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.remote_management_destination.register_request_handler("/path", response_generator = Transport.remote_path_handler, allow = RNS.Destination.ALLOW_LIST, allowed_list=Transport.remote_management_allowed)
|
||||||
Transport.control_destinations.append(Transport.remote_management_destination)
|
Transport.control_destinations.append(Transport.remote_management_destination)
|
||||||
Transport.control_hashes.append(Transport.remote_management_destination.hash)
|
Transport.control_hashes.append(Transport.remote_management_destination.hash)
|
||||||
RNS.log("Enabled remote management on "+str(Transport.remote_management_destination), RNS.LOG_NOTICE)
|
RNS.log("Enabled remote management on "+str(Transport.remote_management_destination), RNS.LOG_NOTICE)
|
||||||
@ -2269,7 +2270,43 @@ class Transport:
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error occurred while processing remote status request from "+RNS.prettyhexrep(remote_identity), RNS.LOG_ERROR)
|
RNS.log("An error occurred while processing remote status request from "+str(remote_identity), RNS.LOG_ERROR)
|
||||||
|
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def remote_path_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:
|
||||||
|
command = data[0]
|
||||||
|
destination_hash = None
|
||||||
|
max_hops = None
|
||||||
|
if len(data) > 1:
|
||||||
|
destination_hash = data[1]
|
||||||
|
if len(data) > 2:
|
||||||
|
max_hops = data[2]
|
||||||
|
|
||||||
|
if command == "table":
|
||||||
|
table = Transport.owner.get_path_table(max_hops=max_hops)
|
||||||
|
response = []
|
||||||
|
for path in table:
|
||||||
|
if destination_hash == None or destination_hash == path["hash"]:
|
||||||
|
response.append(path)
|
||||||
|
|
||||||
|
elif command == "rates":
|
||||||
|
table = Transport.owner.get_rate_table()
|
||||||
|
response = []
|
||||||
|
for path in table:
|
||||||
|
if destination_hash == None or destination_hash == path["hash"]:
|
||||||
|
response.append(path)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("An error occurred while processing remote status request from "+str(remote_identity), 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)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
@ -23,14 +23,95 @@
|
|||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
import RNS
|
import RNS
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from RNS._version import __version__
|
from RNS._version import __version__
|
||||||
|
|
||||||
|
remote_link = None
|
||||||
|
def connect_remote(destination_hash, auth_identity, timeout, no_output = False):
|
||||||
|
global remote_link, reticulum
|
||||||
|
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 remote_link_established(link):
|
||||||
|
global remote_link
|
||||||
|
link.identify(auth_identity)
|
||||||
|
remote_link = link
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity, timeout,
|
||||||
|
drop_queues, drop_via, max_hops, remote=None, management_identity=None,
|
||||||
|
remote_timeout=RNS.Transport.PATH_REQUEST_TIMEOUT, no_output=False):
|
||||||
|
global remote_link, reticulum
|
||||||
|
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
||||||
|
if remote:
|
||||||
|
try:
|
||||||
|
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||||
|
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)
|
||||||
|
remote_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:
|
||||||
|
connect_remote(remote_hash, identity, remote_timeout, no_output)
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
exit(20)
|
||||||
|
|
||||||
|
while remote_link == None:
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
|
||||||
def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity, timeout, drop_queues, drop_via, max_hops):
|
|
||||||
if table:
|
if table:
|
||||||
destination_hash = None
|
destination_hash = None
|
||||||
if destination_hexhash != None:
|
if destination_hexhash != None:
|
||||||
@ -46,8 +127,25 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
print(str(e))
|
print(str(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
if not remote_link:
|
||||||
table = sorted(reticulum.get_path_table(max_hops=max_hops), key=lambda e: (e["interface"], e["hops"]) )
|
table = sorted(reticulum.get_path_table(max_hops=max_hops), key=lambda e: (e["interface"], e["hops"]) )
|
||||||
|
else:
|
||||||
|
if not no_output:
|
||||||
|
print("\r \r", end="")
|
||||||
|
print("Sending request...", end=" ")
|
||||||
|
sys.stdout.flush()
|
||||||
|
receipt = remote_link.request("/path", data = ["table", destination_hash, max_hops])
|
||||||
|
while not receipt.concluded():
|
||||||
|
time.sleep(0.1)
|
||||||
|
response = receipt.get_response()
|
||||||
|
if response:
|
||||||
|
table = response
|
||||||
|
print("\r \r", end="")
|
||||||
|
else:
|
||||||
|
if not no_output:
|
||||||
|
print("\r \r", end="")
|
||||||
|
print("The remote request failed. Likely authentication failure.")
|
||||||
|
exit(10)
|
||||||
|
|
||||||
displayed = 0
|
displayed = 0
|
||||||
for path in table:
|
for path in table:
|
||||||
@ -79,9 +177,27 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
print(str(e))
|
print(str(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
if not remote_link:
|
||||||
table = sorted(reticulum.get_rate_table(), key=lambda e: e["last"] )
|
table = reticulum.get_rate_table()
|
||||||
|
else:
|
||||||
|
if not no_output:
|
||||||
|
print("\r \r", end="")
|
||||||
|
print("Sending request...", end=" ")
|
||||||
|
sys.stdout.flush()
|
||||||
|
receipt = remote_link.request("/path", data = ["rates", destination_hash])
|
||||||
|
while not receipt.concluded():
|
||||||
|
time.sleep(0.1)
|
||||||
|
response = receipt.get_response()
|
||||||
|
if response:
|
||||||
|
table = response
|
||||||
|
print("\r \r", end="")
|
||||||
|
else:
|
||||||
|
if not no_output:
|
||||||
|
print("\r \r", end="")
|
||||||
|
print("The remote request failed. Likely authentication failure.")
|
||||||
|
exit(10)
|
||||||
|
|
||||||
|
table = sorted(table, key=lambda e: e["last"])
|
||||||
if len(table) == 0:
|
if len(table) == 0:
|
||||||
print("No information available")
|
print("No information available")
|
||||||
|
|
||||||
@ -128,7 +244,6 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
elif drop_queues:
|
elif drop_queues:
|
||||||
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
|
||||||
RNS.log("Dropping announce queues on all interfaces...")
|
RNS.log("Dropping announce queues on all interfaces...")
|
||||||
reticulum.drop_announce_queues()
|
reticulum.drop_announce_queues()
|
||||||
|
|
||||||
@ -145,9 +260,6 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
print(str(e))
|
print(str(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
|
||||||
|
|
||||||
if reticulum.drop_path(destination_hash):
|
if reticulum.drop_path(destination_hash):
|
||||||
print("Dropped path to "+RNS.prettyhexrep(destination_hash))
|
print("Dropped path to "+RNS.prettyhexrep(destination_hash))
|
||||||
else:
|
else:
|
||||||
@ -168,9 +280,6 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
print(str(e))
|
print(str(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
|
||||||
|
|
||||||
if reticulum.drop_all_via(destination_hash):
|
if reticulum.drop_all_via(destination_hash):
|
||||||
print("Dropped all paths via "+RNS.prettyhexrep(destination_hash))
|
print("Dropped all paths via "+RNS.prettyhexrep(destination_hash))
|
||||||
else:
|
else:
|
||||||
@ -191,9 +300,6 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
print(str(e))
|
print(str(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
|
|
||||||
|
|
||||||
if not RNS.Transport.has_path(destination_hash):
|
if not RNS.Transport.has_path(destination_hash):
|
||||||
RNS.Transport.request_path(destination_hash)
|
RNS.Transport.request_path(destination_hash)
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested ", end=" ")
|
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested ", end=" ")
|
||||||
@ -305,6 +411,33 @@ def main():
|
|||||||
default=RNS.Transport.PATH_REQUEST_TIMEOUT
|
default=RNS.Transport.PATH_REQUEST_TIMEOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-R",
|
||||||
|
action="store",
|
||||||
|
metavar="hash",
|
||||||
|
help="transport identity hash of remote instance to manage",
|
||||||
|
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(
|
parser.add_argument(
|
||||||
"destination",
|
"destination",
|
||||||
nargs="?",
|
nargs="?",
|
||||||
@ -338,6 +471,9 @@ def main():
|
|||||||
drop_queues = args.drop_announces,
|
drop_queues = args.drop_announces,
|
||||||
drop_via = args.drop_via,
|
drop_via = args.drop_via,
|
||||||
max_hops = args.max,
|
max_hops = args.max,
|
||||||
|
remote=args.R,
|
||||||
|
management_identity=args.i,
|
||||||
|
remote_timeout=args.W,
|
||||||
)
|
)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user