Added JSON output to rnpath utility

This commit is contained in:
Mark Qvist 2024-08-29 14:51:38 +02:00
parent 7be6a0e000
commit 169d1921be
1 changed files with 110 additions and 59 deletions

View File

@ -79,9 +79,9 @@ def connect_remote(destination_hash, auth_identity, timeout, no_output = False):
link.set_link_established_callback(remote_link_established) link.set_link_established_callback(remote_link_established)
link.set_link_closed_callback(remote_link_closed) link.set_link_closed_callback(remote_link_closed)
def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity, timeout, def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity, timeout, drop_queues,
drop_queues, drop_via, max_hops, remote=None, management_identity=None, drop_via, max_hops, remote=None, management_identity=None, remote_timeout=RNS.Transport.PATH_REQUEST_TIMEOUT,
remote_timeout=RNS.Transport.PATH_REQUEST_TIMEOUT, no_output=False): no_output=False, json=False):
global remote_link, reticulum global remote_link, reticulum
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity) reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
if remote: if remote:
@ -148,19 +148,29 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
exit(10) exit(10)
displayed = 0 displayed = 0
for path in table: if json:
if destination_hash == None or destination_hash == path["hash"]: import json
displayed += 1 for p in table:
exp_str = RNS.timestamp_str(path["expires"]) for k in p:
if path["hops"] == 1: if isinstance(p[k], bytes):
m_str = " " p[k] = RNS.hexrep(p[k], delimit=False)
else:
m_str = "s"
print(RNS.prettyhexrep(path["hash"])+" is "+str(path["hops"])+" hop"+m_str+" away via "+RNS.prettyhexrep(path["via"])+" on "+path["interface"]+" expires "+RNS.timestamp_str(path["expires"]))
if destination_hash != None and displayed == 0: print(json.dumps(table))
print("No path known") exit()
sys.exit(1) else:
for path in table:
if destination_hash == None or destination_hash == path["hash"]:
displayed += 1
exp_str = RNS.timestamp_str(path["expires"])
if path["hops"] == 1:
m_str = " "
else:
m_str = "s"
print(RNS.prettyhexrep(path["hash"])+" is "+str(path["hops"])+" hop"+m_str+" away via "+RNS.prettyhexrep(path["via"])+" on "+path["interface"]+" expires "+RNS.timestamp_str(path["expires"]))
if destination_hash != None and displayed == 0:
print("No path known")
sys.exit(1)
elif rates: elif rates:
destination_hash = None destination_hash = None
@ -198,56 +208,78 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
exit(10) exit(10)
table = sorted(table, key=lambda e: e["last"]) table = sorted(table, key=lambda e: e["last"])
if len(table) == 0: if json:
print("No information available") import json
for p in table:
for k in p:
if isinstance(p[k], bytes):
p[k] = RNS.hexrep(p[k], delimit=False)
print(json.dumps(table))
exit()
else: else:
displayed = 0 if len(table) == 0:
for entry in table:
if destination_hash == None or destination_hash == entry["hash"]:
displayed += 1
try:
last_str = pretty_date(int(entry["last"]))
start_ts = entry["timestamps"][0]
span = max(time.time() - start_ts, 3600.0)
span_hours = span/3600.0
span_str = pretty_date(int(entry["timestamps"][0]))
hour_rate = round(len(entry["timestamps"])/span_hours, 3)
if hour_rate-int(hour_rate) == 0:
hour_rate = int(hour_rate)
if entry["rate_violations"] > 0:
if entry["rate_violations"] == 1:
s_str = ""
else:
s_str = "s"
rv_str = ", "+str(entry["rate_violations"])+" active rate violation"+s_str
else:
rv_str = ""
if entry["blocked_until"] > time.time():
bli = time.time()-(int(entry["blocked_until"])-time.time())
bl_str = ", new announces allowed in "+pretty_date(int(bli))
else:
bl_str = ""
print(RNS.prettyhexrep(entry["hash"])+" last heard "+last_str+" ago, "+str(hour_rate)+" announces/hour in the last "+span_str+rv_str+bl_str)
except Exception as e:
print("Error while processing entry for "+RNS.prettyhexrep(entry["hash"]))
print(str(e))
if destination_hash != None and displayed == 0:
print("No information available") print("No information available")
sys.exit(1)
else:
displayed = 0
for entry in table:
if destination_hash == None or destination_hash == entry["hash"]:
displayed += 1
try:
last_str = pretty_date(int(entry["last"]))
start_ts = entry["timestamps"][0]
span = max(time.time() - start_ts, 3600.0)
span_hours = span/3600.0
span_str = pretty_date(int(entry["timestamps"][0]))
hour_rate = round(len(entry["timestamps"])/span_hours, 3)
if hour_rate-int(hour_rate) == 0:
hour_rate = int(hour_rate)
if entry["rate_violations"] > 0:
if entry["rate_violations"] == 1:
s_str = ""
else:
s_str = "s"
rv_str = ", "+str(entry["rate_violations"])+" active rate violation"+s_str
else:
rv_str = ""
if entry["blocked_until"] > time.time():
bli = time.time()-(int(entry["blocked_until"])-time.time())
bl_str = ", new announces allowed in "+pretty_date(int(bli))
else:
bl_str = ""
print(RNS.prettyhexrep(entry["hash"])+" last heard "+last_str+" ago, "+str(hour_rate)+" announces/hour in the last "+span_str+rv_str+bl_str)
except Exception as e:
print("Error while processing entry for "+RNS.prettyhexrep(entry["hash"]))
print(str(e))
if destination_hash != None and displayed == 0:
print("No information available")
sys.exit(1)
elif drop_queues: elif drop_queues:
RNS.log("Dropping announce queues on all interfaces...") if remote_link:
if not no_output:
print("\r \r", end="")
print("Dropping announce queues on remote instances not yet implemented")
exit(255)
print("Dropping announce queues on all interfaces...")
reticulum.drop_announce_queues() reticulum.drop_announce_queues()
elif drop: elif drop:
if remote_link:
if not no_output:
print("\r \r", end="")
print("Dropping path on remote instances not yet implemented")
exit(255)
try: try:
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2 dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
if len(destination_hexhash) != dest_len: if len(destination_hexhash) != dest_len:
@ -266,8 +298,13 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
print("Unable to drop path to "+RNS.prettyhexrep(destination_hash)+". Does it exist?") print("Unable to drop path to "+RNS.prettyhexrep(destination_hash)+". Does it exist?")
sys.exit(1) sys.exit(1)
elif drop_via: elif drop_via:
if remote_link:
if not no_output:
print("\r \r", end="")
print("Dropping all paths via specific transport instance on remote instances yet not implemented")
exit(255)
try: try:
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2 dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
if len(destination_hexhash) != dest_len: if len(destination_hexhash) != dest_len:
@ -286,8 +323,13 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
print("Unable to drop paths via "+RNS.prettyhexrep(destination_hash)+". Does the transport instance exist?") print("Unable to drop paths via "+RNS.prettyhexrep(destination_hash)+". Does the transport instance exist?")
sys.exit(1) sys.exit(1)
else: else:
if remote_link:
if not no_output:
print("\r \r", end="")
print("Requesting paths on remote instances not implemented")
exit(255)
try: try:
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2 dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
if len(destination_hexhash) != dest_len: if len(destination_hexhash) != dest_len:
@ -437,6 +479,14 @@ def main():
help="timeout before giving up on remote queries", help="timeout before giving up on remote queries",
default=RNS.Transport.PATH_REQUEST_TIMEOUT default=RNS.Transport.PATH_REQUEST_TIMEOUT
) )
parser.add_argument(
"-j",
"--json",
action="store_true",
help="output in JSON format",
default=False
)
parser.add_argument( parser.add_argument(
"destination", "destination",
@ -474,6 +524,7 @@ def main():
remote=args.R, remote=args.R,
management_identity=args.i, management_identity=args.i,
remote_timeout=args.W, remote_timeout=args.W,
json=args.json,
) )
sys.exit(0) sys.exit(0)