mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-11-22 13:40:19 +00:00
Compare commits
2 Commits
86d4028dc4
...
011448c22d
Author | SHA1 | Date | |
---|---|---|---|
|
011448c22d | ||
|
2a5a439921 |
@ -93,9 +93,7 @@ def announceLoop(destination_1, destination_2):
|
|||||||
# Send the announce including the app data
|
# Send the announce including the app data
|
||||||
destination_1.announce(app_data=fruit.encode("utf-8"))
|
destination_1.announce(app_data=fruit.encode("utf-8"))
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Sent announce from "+
|
f"Sent announce from {RNS.prettyhexrep(destination_1.hash)} ({destination_1.name})"
|
||||||
RNS.prettyhexrep(destination_1.hash)+
|
|
||||||
" ("+destination_1.name+")"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Randomly select a noble gas
|
# Randomly select a noble gas
|
||||||
@ -104,9 +102,7 @@ def announceLoop(destination_1, destination_2):
|
|||||||
# Send the announce including the app data
|
# Send the announce including the app data
|
||||||
destination_2.announce(app_data=noble_gas.encode("utf-8"))
|
destination_2.announce(app_data=noble_gas.encode("utf-8"))
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Sent announce from "+
|
f"Sent announce from {RNS.prettyhexrep(destination_2.hash)} ({destination_2.name})"
|
||||||
RNS.prettyhexrep(destination_2.hash)+
|
|
||||||
" ("+destination_2.name+")"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# We will need to define an announce handler class that
|
# We will need to define an announce handler class that
|
||||||
@ -126,14 +122,12 @@ class ExampleAnnounceHandler:
|
|||||||
# and cannot use wildcards.
|
# and cannot use wildcards.
|
||||||
def received_announce(self, destination_hash, announced_identity, app_data):
|
def received_announce(self, destination_hash, announced_identity, app_data):
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Received an announce from "+
|
f"Received an announce from {RNS.prettyhexrep(destination_hash)}"
|
||||||
RNS.prettyhexrep(destination_hash)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if app_data:
|
if app_data:
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"The announce contained the following app data: "+
|
f"The announce contained the following app data: {app_data.decode('utf-8')}"
|
||||||
app_data.decode("utf-8")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
|
@ -48,15 +48,13 @@ def program_setup(configpath, channel=None):
|
|||||||
def packet_callback(data, packet):
|
def packet_callback(data, packet):
|
||||||
# Simply print out the received data
|
# Simply print out the received data
|
||||||
print("")
|
print("")
|
||||||
print("Received data: "+data.decode("utf-8")+"\r\n> ", end="")
|
print(f"Received data: {data.decode('utf-8')}\r\n> ", end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
def broadcastLoop(destination):
|
def broadcastLoop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Broadcast example "+
|
f"Broadcast example {RNS.prettyhexrep(destination.hash)} running, enter text and hit enter to broadcast (Ctrl-C to quit)"
|
||||||
RNS.prettyhexrep(destination.hash)+
|
|
||||||
" running, enter text and hit enter to broadcast (Ctrl-C to quit)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# We enter a loop that runs until the users exits.
|
# We enter a loop that runs until the users exits.
|
||||||
|
@ -61,9 +61,7 @@ def server(configpath):
|
|||||||
def server_loop(destination):
|
def server_loop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Link buffer example "+
|
f"Link buffer example {RNS.prettyhexrep(destination.hash)} running, waiting for a connection."
|
||||||
RNS.prettyhexrep(destination.hash)+
|
|
||||||
" running, waiting for a connection."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
||||||
@ -75,7 +73,7 @@ def server_loop(destination):
|
|||||||
while True:
|
while True:
|
||||||
entered = input()
|
entered = input()
|
||||||
destination.announce()
|
destination.announce()
|
||||||
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Sent announce from {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
# When a client establishes a link to our server
|
# When a client establishes a link to our server
|
||||||
# destination, this function will be called with
|
# destination, this function will be called with
|
||||||
@ -120,9 +118,9 @@ def server_buffer_ready(ready_bytes: int):
|
|||||||
data = latest_buffer.read(ready_bytes)
|
data = latest_buffer.read(ready_bytes)
|
||||||
data = data.decode("utf-8")
|
data = data.decode("utf-8")
|
||||||
|
|
||||||
RNS.log("Received data over the buffer: " + data)
|
RNS.log(f"Received data over the buffer: {data}")
|
||||||
|
|
||||||
reply_message = "I received \""+data+"\" over the buffer"
|
reply_message = f"I received \"{data}\" over the buffer"
|
||||||
reply_message = reply_message.encode("utf-8")
|
reply_message = reply_message.encode("utf-8")
|
||||||
latest_buffer.write(reply_message)
|
latest_buffer.write(reply_message)
|
||||||
latest_buffer.flush()
|
latest_buffer.flush()
|
||||||
@ -151,7 +149,7 @@ def client(destination_hexhash, configpath):
|
|||||||
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:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2)
|
f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes)."
|
||||||
)
|
)
|
||||||
|
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
@ -223,7 +221,7 @@ def client_loop():
|
|||||||
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while sending data over the link buffer: "+str(e))
|
RNS.log(f"Error while sending data over the link buffer: {e}")
|
||||||
should_quit = True
|
should_quit = True
|
||||||
server_link.teardown()
|
server_link.teardown()
|
||||||
|
|
||||||
@ -262,7 +260,7 @@ def link_closed(link):
|
|||||||
def client_buffer_ready(ready_bytes: int):
|
def client_buffer_ready(ready_bytes: int):
|
||||||
global buffer
|
global buffer
|
||||||
data = buffer.read(ready_bytes)
|
data = buffer.read(ready_bytes)
|
||||||
RNS.log("Received data over the link buffer: " + data.decode("utf-8"))
|
RNS.log(f"Received data over the link buffer: {data.decode('utf-8')}")
|
||||||
print("> ", end=" ")
|
print("> ", end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
@ -124,9 +124,7 @@ def server(configpath):
|
|||||||
def server_loop(destination):
|
def server_loop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Link example "+
|
f"Link example {RNS.prettyhexrep(destination.hash)} running, waiting for a connection."
|
||||||
RNS.prettyhexrep(destination.hash)+
|
|
||||||
" running, waiting for a connection."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
||||||
@ -138,7 +136,7 @@ def server_loop(destination):
|
|||||||
while True:
|
while True:
|
||||||
entered = input()
|
entered = input()
|
||||||
destination.announce()
|
destination.announce()
|
||||||
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Sent announce from {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
# When a client establishes a link to our server
|
# When a client establishes a link to our server
|
||||||
# destination, this function will be called with
|
# destination, this function will be called with
|
||||||
@ -176,9 +174,9 @@ def server_message_received(message):
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
if isinstance(message, StringMessage):
|
if isinstance(message, StringMessage):
|
||||||
RNS.log("Received data on the link: " + message.data + " (message created at " + str(message.timestamp) + ")")
|
RNS.log(f"Received data on the link: {message.data} (message created at {message.timestamp})")
|
||||||
|
|
||||||
reply_message = StringMessage("I received \""+message.data+"\" over the link")
|
reply_message = StringMessage(f"I received \"{message.data}\" over the link")
|
||||||
latest_client_link.get_channel().send(reply_message)
|
latest_client_link.get_channel().send(reply_message)
|
||||||
|
|
||||||
# Incoming messages are sent to each message
|
# Incoming messages are sent to each message
|
||||||
@ -206,7 +204,7 @@ def client(destination_hexhash, configpath):
|
|||||||
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:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2)
|
f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes)."
|
||||||
)
|
)
|
||||||
|
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
@ -280,17 +278,14 @@ def client_loop():
|
|||||||
channel.send(message)
|
channel.send(message)
|
||||||
else:
|
else:
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Cannot send this packet, the data size of "+
|
f"Cannot send this packet, the data size of {packed_size} bytes exceeds the link packet MDU of {channel.MDU} bytes",
|
||||||
str(packed_size)+" bytes exceeds the link packet MDU of "+
|
|
||||||
str(channel.MDU)+" bytes",
|
|
||||||
RNS.LOG_ERROR
|
RNS.LOG_ERROR
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
RNS.log("Channel is not ready to send, please wait for " +
|
RNS.log(f"Channel is not ready to send, please wait for pending messages to complete.", RNS.LOG_ERROR)
|
||||||
"pending messages to complete.", RNS.LOG_ERROR)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while sending data over the link: "+str(e))
|
RNS.log(f"Error while sending data over the link: {e}")
|
||||||
should_quit = True
|
should_quit = True
|
||||||
server_link.teardown()
|
server_link.teardown()
|
||||||
|
|
||||||
@ -329,7 +324,7 @@ def link_closed(link):
|
|||||||
# simply print out the data.
|
# simply print out the data.
|
||||||
def client_message_received(message):
|
def client_message_received(message):
|
||||||
if isinstance(message, StringMessage):
|
if isinstance(message, StringMessage):
|
||||||
RNS.log("Received data on the link: " + message.data + " (message created at " + str(message.timestamp) + ")")
|
RNS.log(f"Received data on the link: {message.data} (message created at {message.timestamp})")
|
||||||
print("> ", end=" ")
|
print("> ", end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
@ -64,9 +64,7 @@ def server(configpath):
|
|||||||
def announceLoop(destination):
|
def announceLoop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Echo server "+
|
f"Echo server {RNS.prettyhexrep(destination.hash)} running, hit enter to manually send an announce (Ctrl-C to quit)"
|
||||||
RNS.prettyhexrep(destination.hash)+
|
|
||||||
" running, hit enter to manually send an announce (Ctrl-C to quit)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# We enter a loop that runs until the users exits.
|
# We enter a loop that runs until the users exits.
|
||||||
@ -76,7 +74,7 @@ def announceLoop(destination):
|
|||||||
while True:
|
while True:
|
||||||
entered = input()
|
entered = input()
|
||||||
destination.announce()
|
destination.announce()
|
||||||
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Sent announce from {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
|
|
||||||
def server_callback(message, packet):
|
def server_callback(message, packet):
|
||||||
@ -93,19 +91,19 @@ def server_callback(message, packet):
|
|||||||
reception_snr = reticulum.get_packet_snr(packet.packet_hash)
|
reception_snr = reticulum.get_packet_snr(packet.packet_hash)
|
||||||
|
|
||||||
if reception_rssi != None:
|
if reception_rssi != None:
|
||||||
reception_stats += " [RSSI "+str(reception_rssi)+" dBm]"
|
reception_stats += f" [RSSI {reception_rssi} dBm]"
|
||||||
|
|
||||||
if reception_snr != None:
|
if reception_snr != None:
|
||||||
reception_stats += " [SNR "+str(reception_snr)+" dBm]"
|
reception_stats += f" [SNR {reception_snr} dBm]"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if packet.rssi != None:
|
if packet.rssi != None:
|
||||||
reception_stats += " [RSSI "+str(packet.rssi)+" dBm]"
|
reception_stats += f" [RSSI {packet.rssi} dBm]"
|
||||||
|
|
||||||
if packet.snr != None:
|
if packet.snr != None:
|
||||||
reception_stats += " [SNR "+str(packet.snr)+" dB]"
|
reception_stats += f" [SNR {packet.snr} dB]"
|
||||||
|
|
||||||
RNS.log("Received packet from echo client, proof sent"+reception_stats)
|
RNS.log(f"Received packet from echo client, proof sent{reception_stats}")
|
||||||
|
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
@ -123,13 +121,13 @@ def client(destination_hexhash, configpath, timeout=None):
|
|||||||
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:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2)
|
f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes)."
|
||||||
)
|
)
|
||||||
|
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Invalid destination entered. Check your input!")
|
RNS.log("Invalid destination entered. Check your input!")
|
||||||
RNS.log(str(e)+"\n")
|
RNS.log(f"{e}\n")
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
# We must first initialise Reticulum
|
# We must first initialise Reticulum
|
||||||
@ -142,9 +140,7 @@ def client(destination_hexhash, configpath, timeout=None):
|
|||||||
|
|
||||||
# Tell the user that the client is ready!
|
# Tell the user that the client is ready!
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Echo client ready, hit enter to send echo request to "+
|
f"Echo client ready, hit enter to send echo request to {destination_hexhash} (Ctrl-C to quit)"
|
||||||
destination_hexhash+
|
|
||||||
" (Ctrl-C to quit)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# We enter a loop that runs until the user exits.
|
# We enter a loop that runs until the user exits.
|
||||||
@ -205,7 +201,7 @@ def client(destination_hexhash, configpath, timeout=None):
|
|||||||
packet_receipt.set_delivery_callback(packet_delivered)
|
packet_receipt.set_delivery_callback(packet_delivered)
|
||||||
|
|
||||||
# Tell the user that the echo request was sent
|
# Tell the user that the echo request was sent
|
||||||
RNS.log("Sent echo request to "+RNS.prettyhexrep(request_destination.hash))
|
RNS.log(f"Sent echo request to {RNS.prettyhexrep(request_destination.hash)}")
|
||||||
else:
|
else:
|
||||||
# If we do not know this destination, tell the
|
# If we do not know this destination, tell the
|
||||||
# user to wait for an announce to arrive.
|
# user to wait for an announce to arrive.
|
||||||
@ -222,10 +218,10 @@ def packet_delivered(receipt):
|
|||||||
rtt = receipt.get_rtt()
|
rtt = receipt.get_rtt()
|
||||||
if (rtt >= 1):
|
if (rtt >= 1):
|
||||||
rtt = round(rtt, 3)
|
rtt = round(rtt, 3)
|
||||||
rttstring = str(rtt)+" seconds"
|
rttstring = f"{rtt} seconds"
|
||||||
else:
|
else:
|
||||||
rtt = round(rtt*1000, 3)
|
rtt = round(rtt*1000, 3)
|
||||||
rttstring = str(rtt)+" milliseconds"
|
rttstring = f"{rtt} milliseconds"
|
||||||
|
|
||||||
reception_stats = ""
|
reception_stats = ""
|
||||||
if reticulum.is_connected_to_shared_instance:
|
if reticulum.is_connected_to_shared_instance:
|
||||||
@ -233,30 +229,27 @@ def packet_delivered(receipt):
|
|||||||
reception_snr = reticulum.get_packet_snr(receipt.proof_packet.packet_hash)
|
reception_snr = reticulum.get_packet_snr(receipt.proof_packet.packet_hash)
|
||||||
|
|
||||||
if reception_rssi != None:
|
if reception_rssi != None:
|
||||||
reception_stats += " [RSSI "+str(reception_rssi)+" dBm]"
|
reception_stats += f" [RSSI {reception_rssi} dBm]"
|
||||||
|
|
||||||
if reception_snr != None:
|
if reception_snr != None:
|
||||||
reception_stats += " [SNR "+str(reception_snr)+" dB]"
|
reception_stats += f" [SNR {reception_snr} dB]"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if receipt.proof_packet != None:
|
if receipt.proof_packet != None:
|
||||||
if receipt.proof_packet.rssi != None:
|
if receipt.proof_packet.rssi != None:
|
||||||
reception_stats += " [RSSI "+str(receipt.proof_packet.rssi)+" dBm]"
|
reception_stats += f" [RSSI {receipt.proof_packet.rssi} dBm]"
|
||||||
|
|
||||||
if receipt.proof_packet.snr != None:
|
if receipt.proof_packet.snr != None:
|
||||||
reception_stats += " [SNR "+str(receipt.proof_packet.snr)+" dB]"
|
reception_stats += f" [SNR {receipt.proof_packet.snr} dB]"
|
||||||
|
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Valid reply received from "+
|
f"Valid reply received from {RNS.prettyhexrep(receipt.destination.hash)}, round-trip time is {rttstring}{reception_stats}"
|
||||||
RNS.prettyhexrep(receipt.destination.hash)+
|
|
||||||
", round-trip time is "+rttstring+
|
|
||||||
reception_stats
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# This function is called if a packet times out.
|
# This function is called if a packet times out.
|
||||||
def packet_timed_out(receipt):
|
def packet_timed_out(receipt):
|
||||||
if receipt.status == RNS.PacketReceipt.FAILED:
|
if receipt.status == RNS.PacketReceipt.FAILED:
|
||||||
RNS.log("Packet "+RNS.prettyhexrep(receipt.hash)+" timed out")
|
RNS.log(f"Packet {RNS.prettyhexrep(receipt.hash)} timed out")
|
||||||
|
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
|
@ -73,7 +73,7 @@ def server(configpath, path):
|
|||||||
|
|
||||||
def announceLoop(destination):
|
def announceLoop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log("File server "+RNS.prettyhexrep(destination.hash)+" running")
|
RNS.log(f"File server {RNS.prettyhexrep(destination.hash)} running")
|
||||||
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
||||||
|
|
||||||
# We enter a loop that runs until the users exits.
|
# We enter a loop that runs until the users exits.
|
||||||
@ -83,7 +83,7 @@ def announceLoop(destination):
|
|||||||
while True:
|
while True:
|
||||||
entered = input()
|
entered = input()
|
||||||
destination.announce()
|
destination.announce()
|
||||||
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Sent announce from {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
# Here's a convenience function for listing all files
|
# Here's a convenience function for listing all files
|
||||||
# in our served directory
|
# in our served directory
|
||||||
@ -145,7 +145,7 @@ def client_request(message, packet):
|
|||||||
try:
|
try:
|
||||||
# If we have the requested file, we'll
|
# If we have the requested file, we'll
|
||||||
# read it and pack it as a resource
|
# read it and pack it as a resource
|
||||||
RNS.log("Client requested \""+filename+"\"")
|
RNS.log(f"Client requested \"{filename}\"")
|
||||||
file = open(os.path.join(serve_path, filename), "rb")
|
file = open(os.path.join(serve_path, filename), "rb")
|
||||||
|
|
||||||
file_resource = RNS.Resource(
|
file_resource = RNS.Resource(
|
||||||
@ -158,7 +158,7 @@ def client_request(message, packet):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
# If somethign went wrong, we close
|
# If somethign went wrong, we close
|
||||||
# the link
|
# the link
|
||||||
RNS.log("Error while reading file \""+filename+"\"", RNS.LOG_ERROR)
|
RNS.log(f"Error while reading file \"{filename}\"", RNS.LOG_ERROR)
|
||||||
packet.link.teardown()
|
packet.link.teardown()
|
||||||
raise e
|
raise e
|
||||||
else:
|
else:
|
||||||
@ -175,9 +175,9 @@ def resource_sending_concluded(resource):
|
|||||||
name = "resource"
|
name = "resource"
|
||||||
|
|
||||||
if resource.status == RNS.Resource.COMPLETE:
|
if resource.status == RNS.Resource.COMPLETE:
|
||||||
RNS.log("Done sending \""+name+"\" to client")
|
RNS.log(f"Done sending \"{name}\" to client")
|
||||||
elif resource.status == RNS.Resource.FAILED:
|
elif resource.status == RNS.Resource.FAILED:
|
||||||
RNS.log("Sending \""+name+"\" to client failed")
|
RNS.log(f"Sending \"{name}\" to client failed")
|
||||||
|
|
||||||
def list_delivered(receipt):
|
def list_delivered(receipt):
|
||||||
RNS.log("The file list was received by the client")
|
RNS.log("The file list was received by the client")
|
||||||
@ -218,7 +218,7 @@ def client(destination_hexhash, configpath):
|
|||||||
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:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2)
|
f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes)."
|
||||||
)
|
)
|
||||||
|
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
@ -293,7 +293,7 @@ def download(filename):
|
|||||||
request_packet.send()
|
request_packet.send()
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
print(("Requested \""+filename+"\" from server, waiting for download to begin..."))
|
print(f"Requested \"{filename}\" from server, waiting for download to begin...")
|
||||||
menu_mode = "download_started"
|
menu_mode = "download_started"
|
||||||
|
|
||||||
# This function runs a simple menu for the user
|
# This function runs a simple menu for the user
|
||||||
@ -363,7 +363,7 @@ def print_menu():
|
|||||||
while menu_mode == "downloading":
|
while menu_mode == "downloading":
|
||||||
global current_download
|
global current_download
|
||||||
percent = round(current_download.get_progress() * 100.0, 1)
|
percent = round(current_download.get_progress() * 100.0, 1)
|
||||||
print(("\rProgress: "+str(percent)+" % "), end=' ')
|
print(f'\rProgress: {percent} % ', end=' ')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
@ -383,15 +383,15 @@ def print_menu():
|
|||||||
# Print statistics
|
# Print statistics
|
||||||
hours, rem = divmod(download_time, 3600)
|
hours, rem = divmod(download_time, 3600)
|
||||||
minutes, seconds = divmod(rem, 60)
|
minutes, seconds = divmod(rem, 60)
|
||||||
timestring = "{:0>2}:{:0>2}:{:05.2f}".format(int(hours),int(minutes),seconds)
|
timestring = f"{int(hours):0>2}:{int(minutes):0>2}:{seconds:05.2f}"
|
||||||
print("")
|
print("")
|
||||||
print("")
|
print("")
|
||||||
print("--- Statistics -----")
|
print("--- Statistics -----")
|
||||||
print("\tTime taken : "+timestring)
|
print(f"\tTime taken : {timestring}")
|
||||||
print("\tFile size : "+size_str(file_size))
|
print(f"\tFile size : {size_str(file_size)}")
|
||||||
print("\tData transferred : "+size_str(transfer_size))
|
print(f"\tData transferred : {size_str(transfer_size)}")
|
||||||
print("\tEffective rate : "+size_str(file_size/download_time, suffix='b')+"/s")
|
print(f"\tEffective rate : {size_str(file_size / download_time, suffix='b')}/s")
|
||||||
print("\tTransfer rate : "+size_str(transfer_size/download_time, suffix='b')+"/s")
|
print(f"\tTransfer rate : {size_str(transfer_size / download_time, suffix='b')}/s")
|
||||||
print("")
|
print("")
|
||||||
print("The download completed! Press enter to return to the menu.")
|
print("The download completed! Press enter to return to the menu.")
|
||||||
print("")
|
print("")
|
||||||
@ -412,7 +412,7 @@ def print_filelist():
|
|||||||
global server_files
|
global server_files
|
||||||
print("Files on server:")
|
print("Files on server:")
|
||||||
for index,file in enumerate(server_files):
|
for index,file in enumerate(server_files):
|
||||||
print("\t("+str(index)+")\t"+file)
|
print(f"\t({index})\t{file}")
|
||||||
|
|
||||||
def filelist_received(filelist_data, packet):
|
def filelist_received(filelist_data, packet):
|
||||||
global server_files, menu_mode
|
global server_files, menu_mode
|
||||||
@ -509,7 +509,7 @@ def download_concluded(resource):
|
|||||||
counter = 0
|
counter = 0
|
||||||
while os.path.isfile(saved_filename):
|
while os.path.isfile(saved_filename):
|
||||||
counter += 1
|
counter += 1
|
||||||
saved_filename = current_filename+"."+str(counter)
|
saved_filename = f"{current_filename}.{counter}"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
file = open(saved_filename, "wb")
|
file = open(saved_filename, "wb")
|
||||||
@ -534,9 +534,9 @@ def size_str(num, suffix='B'):
|
|||||||
|
|
||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1024.0:
|
if abs(num) < 1024.0:
|
||||||
return "%3.2f %s%s" % (num, unit, suffix)
|
return f"{num:3.2f} {unit}{suffix}"
|
||||||
num /= 1024.0
|
num /= 1024.0
|
||||||
return "%.2f %s%s" % (num, last_unit, suffix)
|
return f"{num:.2f} {last_unit}{suffix}"
|
||||||
|
|
||||||
# A convenience function for clearing the screen
|
# A convenience function for clearing the screen
|
||||||
def clear_screen():
|
def clear_screen():
|
||||||
|
@ -53,9 +53,7 @@ def server(configpath):
|
|||||||
def server_loop(destination):
|
def server_loop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Link identification example "+
|
f"Link identification example {RNS.prettyhexrep(destination.hash)} running, waiting for a connection."
|
||||||
RNS.prettyhexrep(destination.hash)+
|
|
||||||
" running, waiting for a connection."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
||||||
@ -67,7 +65,7 @@ def server_loop(destination):
|
|||||||
while True:
|
while True:
|
||||||
entered = input()
|
entered = input()
|
||||||
destination.announce()
|
destination.announce()
|
||||||
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Sent announce from {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
# When a client establishes a link to our server
|
# When a client establishes a link to our server
|
||||||
# destination, this function will be called with
|
# destination, this function will be called with
|
||||||
@ -85,7 +83,7 @@ def client_disconnected(link):
|
|||||||
RNS.log("Client disconnected")
|
RNS.log("Client disconnected")
|
||||||
|
|
||||||
def remote_identified(link, identity):
|
def remote_identified(link, identity):
|
||||||
RNS.log("Remote identified as: "+str(identity))
|
RNS.log(f"Remote identified as: {identity}")
|
||||||
|
|
||||||
def server_packet_received(message, packet):
|
def server_packet_received(message, packet):
|
||||||
global latest_client_link
|
global latest_client_link
|
||||||
@ -100,9 +98,9 @@ def server_packet_received(message, packet):
|
|||||||
# that connected.
|
# that connected.
|
||||||
text = message.decode("utf-8")
|
text = message.decode("utf-8")
|
||||||
|
|
||||||
RNS.log("Received data from "+remote_peer+": "+text)
|
RNS.log(f"Received data from {remote_peer}: {text}")
|
||||||
|
|
||||||
reply_text = "I received \""+text+"\" over the link from "+remote_peer
|
reply_text = f"I received \"{text}\" over the link from {remote_peer}"
|
||||||
reply_data = reply_text.encode("utf-8")
|
reply_data = reply_text.encode("utf-8")
|
||||||
RNS.Packet(latest_client_link, reply_data).send()
|
RNS.Packet(latest_client_link, reply_data).send()
|
||||||
|
|
||||||
@ -127,7 +125,7 @@ def client(destination_hexhash, configpath):
|
|||||||
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:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2)
|
f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes)."
|
||||||
)
|
)
|
||||||
|
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
@ -141,8 +139,7 @@ def client(destination_hexhash, configpath):
|
|||||||
# Create a new client identity
|
# Create a new client identity
|
||||||
client_identity = RNS.Identity()
|
client_identity = RNS.Identity()
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Client created new identity "+
|
f"Client created new identity {client_identity}"
|
||||||
str(client_identity)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if we know a path to the destination
|
# Check if we know a path to the destination
|
||||||
@ -210,14 +207,12 @@ def client_loop():
|
|||||||
RNS.Packet(server_link, data).send()
|
RNS.Packet(server_link, data).send()
|
||||||
else:
|
else:
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Cannot send this packet, the data size of "+
|
f"Cannot send this packet, the data size of {len(data)} bytes exceeds the link packet MDU of {RNS.Link.MDU} bytes",
|
||||||
str(len(data))+" bytes exceeds the link packet MDU of "+
|
|
||||||
str(RNS.Link.MDU)+" bytes",
|
|
||||||
RNS.LOG_ERROR
|
RNS.LOG_ERROR
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while sending data over the link: "+str(e))
|
RNS.log(f"Error while sending data over the link: {e}")
|
||||||
should_quit = True
|
should_quit = True
|
||||||
server_link.teardown()
|
server_link.teardown()
|
||||||
|
|
||||||
@ -253,7 +248,7 @@ def link_closed(link):
|
|||||||
# simply print out the data.
|
# simply print out the data.
|
||||||
def client_packet_received(message, packet):
|
def client_packet_received(message, packet):
|
||||||
text = message.decode("utf-8")
|
text = message.decode("utf-8")
|
||||||
RNS.log("Received data on the link: "+text)
|
RNS.log(f"Received data on the link: {text}")
|
||||||
print("> ", end=" ")
|
print("> ", end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
@ -53,9 +53,7 @@ def server(configpath):
|
|||||||
def server_loop(destination):
|
def server_loop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Link example "+
|
f"Link example {RNS.prettyhexrep(destination.hash)} running, waiting for a connection."
|
||||||
RNS.prettyhexrep(destination.hash)+
|
|
||||||
" running, waiting for a connection."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
||||||
@ -67,7 +65,7 @@ def server_loop(destination):
|
|||||||
while True:
|
while True:
|
||||||
entered = input()
|
entered = input()
|
||||||
destination.announce()
|
destination.announce()
|
||||||
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Sent announce from {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
# When a client establishes a link to our server
|
# When a client establishes a link to our server
|
||||||
# destination, this function will be called with
|
# destination, this function will be called with
|
||||||
@ -90,9 +88,9 @@ def server_packet_received(message, packet):
|
|||||||
# it will all be directed to the last client
|
# it will all be directed to the last client
|
||||||
# that connected.
|
# that connected.
|
||||||
text = message.decode("utf-8")
|
text = message.decode("utf-8")
|
||||||
RNS.log("Received data on the link: "+text)
|
RNS.log(f"Received data on the link: {text}")
|
||||||
|
|
||||||
reply_text = "I received \""+text+"\" over the link"
|
reply_text = f"I received \"{text}\" over the link"
|
||||||
reply_data = reply_text.encode("utf-8")
|
reply_data = reply_text.encode("utf-8")
|
||||||
RNS.Packet(latest_client_link, reply_data).send()
|
RNS.Packet(latest_client_link, reply_data).send()
|
||||||
|
|
||||||
@ -113,7 +111,7 @@ def client(destination_hexhash, configpath):
|
|||||||
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:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2)
|
f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes)."
|
||||||
)
|
)
|
||||||
|
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
@ -189,14 +187,12 @@ def client_loop():
|
|||||||
RNS.Packet(server_link, data).send()
|
RNS.Packet(server_link, data).send()
|
||||||
else:
|
else:
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Cannot send this packet, the data size of "+
|
f"Cannot send this packet, the data size of {len(data)} bytes exceeds the link packet MDU of {RNS.Link.MDU} bytes",
|
||||||
str(len(data))+" bytes exceeds the link packet MDU of "+
|
|
||||||
str(RNS.Link.MDU)+" bytes",
|
|
||||||
RNS.LOG_ERROR
|
RNS.LOG_ERROR
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while sending data over the link: "+str(e))
|
RNS.log(f"Error while sending data over the link: {e}")
|
||||||
should_quit = True
|
should_quit = True
|
||||||
server_link.teardown()
|
server_link.teardown()
|
||||||
|
|
||||||
@ -230,7 +226,7 @@ def link_closed(link):
|
|||||||
# simply print out the data.
|
# simply print out the data.
|
||||||
def client_packet_received(message, packet):
|
def client_packet_received(message, packet):
|
||||||
text = message.decode("utf-8")
|
text = message.decode("utf-8")
|
||||||
RNS.log("Received data on the link: "+text)
|
RNS.log(f"Received data on the link: {text}")
|
||||||
print("> ", end=" ")
|
print("> ", end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
@ -51,9 +51,7 @@ def program_setup(configpath):
|
|||||||
def announceLoop(destination):
|
def announceLoop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Minimal example "+
|
f"Minimal example {RNS.prettyhexrep(destination.hash)} running, hit enter to manually send an announce (Ctrl-C to quit)"
|
||||||
RNS.prettyhexrep(destination.hash)+
|
|
||||||
" running, hit enter to manually send an announce (Ctrl-C to quit)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# We enter a loop that runs until the users exits.
|
# We enter a loop that runs until the users exits.
|
||||||
@ -63,7 +61,7 @@ def announceLoop(destination):
|
|||||||
while True:
|
while True:
|
||||||
entered = input()
|
entered = input()
|
||||||
destination.announce()
|
destination.announce()
|
||||||
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Sent announce from {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
|
@ -75,9 +75,7 @@ def server(configpath):
|
|||||||
def announceLoop(destination):
|
def announceLoop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Ratcheted echo server "+
|
f"Ratcheted echo server {RNS.prettyhexrep(destination.hash)} running, hit enter to manually send an announce (Ctrl-C to quit)"
|
||||||
RNS.prettyhexrep(destination.hash)+
|
|
||||||
" running, hit enter to manually send an announce (Ctrl-C to quit)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# We enter a loop that runs until the users exits.
|
# We enter a loop that runs until the users exits.
|
||||||
@ -87,7 +85,7 @@ def announceLoop(destination):
|
|||||||
while True:
|
while True:
|
||||||
entered = input()
|
entered = input()
|
||||||
destination.announce()
|
destination.announce()
|
||||||
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Sent announce from {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
|
|
||||||
def server_callback(message, packet):
|
def server_callback(message, packet):
|
||||||
@ -104,19 +102,19 @@ def server_callback(message, packet):
|
|||||||
reception_snr = reticulum.get_packet_snr(packet.packet_hash)
|
reception_snr = reticulum.get_packet_snr(packet.packet_hash)
|
||||||
|
|
||||||
if reception_rssi != None:
|
if reception_rssi != None:
|
||||||
reception_stats += " [RSSI "+str(reception_rssi)+" dBm]"
|
reception_stats += f" [RSSI {reception_rssi} dBm]"
|
||||||
|
|
||||||
if reception_snr != None:
|
if reception_snr != None:
|
||||||
reception_stats += " [SNR "+str(reception_snr)+" dBm]"
|
reception_stats += f" [SNR {reception_snr} dBm]"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if packet.rssi != None:
|
if packet.rssi != None:
|
||||||
reception_stats += " [RSSI "+str(packet.rssi)+" dBm]"
|
reception_stats += f" [RSSI {packet.rssi} dBm]"
|
||||||
|
|
||||||
if packet.snr != None:
|
if packet.snr != None:
|
||||||
reception_stats += " [SNR "+str(packet.snr)+" dB]"
|
reception_stats += f" [SNR {packet.snr} dB]"
|
||||||
|
|
||||||
RNS.log("Received packet from echo client, proof sent"+reception_stats)
|
RNS.log(f"Received packet from echo client, proof sent{reception_stats}")
|
||||||
|
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
@ -134,13 +132,13 @@ def client(destination_hexhash, configpath, timeout=None):
|
|||||||
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:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2)
|
f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes)."
|
||||||
)
|
)
|
||||||
|
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Invalid destination entered. Check your input!")
|
RNS.log("Invalid destination entered. Check your input!")
|
||||||
RNS.log(str(e)+"\n")
|
RNS.log(f"{e}\n")
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
# We must first initialise Reticulum
|
# We must first initialise Reticulum
|
||||||
@ -153,9 +151,7 @@ def client(destination_hexhash, configpath, timeout=None):
|
|||||||
|
|
||||||
# Tell the user that the client is ready!
|
# Tell the user that the client is ready!
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Echo client ready, hit enter to send echo request to "+
|
f"Echo client ready, hit enter to send echo request to {destination_hexhash} (Ctrl-C to quit)"
|
||||||
destination_hexhash+
|
|
||||||
" (Ctrl-C to quit)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# We enter a loop that runs until the user exits.
|
# We enter a loop that runs until the user exits.
|
||||||
@ -217,7 +213,7 @@ def client(destination_hexhash, configpath, timeout=None):
|
|||||||
packet_receipt.set_delivery_callback(packet_delivered)
|
packet_receipt.set_delivery_callback(packet_delivered)
|
||||||
|
|
||||||
# Tell the user that the echo request was sent
|
# Tell the user that the echo request was sent
|
||||||
RNS.log("Sent echo request to "+RNS.prettyhexrep(request_destination.hash))
|
RNS.log(f"Sent echo request to {RNS.prettyhexrep(request_destination.hash)}")
|
||||||
else:
|
else:
|
||||||
# If we do not know this destination, tell the
|
# If we do not know this destination, tell the
|
||||||
# user to wait for an announce to arrive.
|
# user to wait for an announce to arrive.
|
||||||
@ -234,10 +230,10 @@ def packet_delivered(receipt):
|
|||||||
rtt = receipt.get_rtt()
|
rtt = receipt.get_rtt()
|
||||||
if (rtt >= 1):
|
if (rtt >= 1):
|
||||||
rtt = round(rtt, 3)
|
rtt = round(rtt, 3)
|
||||||
rttstring = str(rtt)+" seconds"
|
rttstring = f"{rtt} seconds"
|
||||||
else:
|
else:
|
||||||
rtt = round(rtt*1000, 3)
|
rtt = round(rtt*1000, 3)
|
||||||
rttstring = str(rtt)+" milliseconds"
|
rttstring = f"{rtt} milliseconds"
|
||||||
|
|
||||||
reception_stats = ""
|
reception_stats = ""
|
||||||
if reticulum.is_connected_to_shared_instance:
|
if reticulum.is_connected_to_shared_instance:
|
||||||
@ -245,30 +241,27 @@ def packet_delivered(receipt):
|
|||||||
reception_snr = reticulum.get_packet_snr(receipt.proof_packet.packet_hash)
|
reception_snr = reticulum.get_packet_snr(receipt.proof_packet.packet_hash)
|
||||||
|
|
||||||
if reception_rssi != None:
|
if reception_rssi != None:
|
||||||
reception_stats += " [RSSI "+str(reception_rssi)+" dBm]"
|
reception_stats += f" [RSSI {reception_rssi} dBm]"
|
||||||
|
|
||||||
if reception_snr != None:
|
if reception_snr != None:
|
||||||
reception_stats += " [SNR "+str(reception_snr)+" dB]"
|
reception_stats += f" [SNR {reception_snr} dB]"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if receipt.proof_packet != None:
|
if receipt.proof_packet != None:
|
||||||
if receipt.proof_packet.rssi != None:
|
if receipt.proof_packet.rssi != None:
|
||||||
reception_stats += " [RSSI "+str(receipt.proof_packet.rssi)+" dBm]"
|
reception_stats += f" [RSSI {receipt.proof_packet.rssi} dBm]"
|
||||||
|
|
||||||
if receipt.proof_packet.snr != None:
|
if receipt.proof_packet.snr != None:
|
||||||
reception_stats += " [SNR "+str(receipt.proof_packet.snr)+" dB]"
|
reception_stats += f" [SNR {receipt.proof_packet.snr} dB]"
|
||||||
|
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Valid reply received from "+
|
f"Valid reply received from {RNS.prettyhexrep(receipt.destination.hash)}, round-trip time is {rttstring}{reception_stats}"
|
||||||
RNS.prettyhexrep(receipt.destination.hash)+
|
|
||||||
", round-trip time is "+rttstring+
|
|
||||||
reception_stats
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# This function is called if a packet times out.
|
# This function is called if a packet times out.
|
||||||
def packet_timed_out(receipt):
|
def packet_timed_out(receipt):
|
||||||
if receipt.status == RNS.PacketReceipt.FAILED:
|
if receipt.status == RNS.PacketReceipt.FAILED:
|
||||||
RNS.log("Packet "+RNS.prettyhexrep(receipt.hash)+" timed out")
|
RNS.log(f"Packet {RNS.prettyhexrep(receipt.hash)} timed out")
|
||||||
|
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
|
@ -24,7 +24,7 @@ APP_NAME = "example_utilities"
|
|||||||
latest_client_link = None
|
latest_client_link = None
|
||||||
|
|
||||||
def random_text_generator(path, data, request_id, link_id, remote_identity, requested_at):
|
def random_text_generator(path, data, request_id, link_id, remote_identity, requested_at):
|
||||||
RNS.log("Generating response to request "+RNS.prettyhexrep(request_id)+" on link "+RNS.prettyhexrep(link_id))
|
RNS.log(f"Generating response to request {RNS.prettyhexrep(request_id)} on link {RNS.prettyhexrep(link_id)}")
|
||||||
texts = ["They looked up", "On each full moon", "Becky was upset", "I’ll stay away from it", "The pet shop stocks everything"]
|
texts = ["They looked up", "On each full moon", "Becky was upset", "I’ll stay away from it", "The pet shop stocks everything"]
|
||||||
return texts[random.randint(0, len(texts)-1)]
|
return texts[random.randint(0, len(texts)-1)]
|
||||||
|
|
||||||
@ -67,9 +67,7 @@ def server(configpath):
|
|||||||
def server_loop(destination):
|
def server_loop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Request example "+
|
f"Request example {RNS.prettyhexrep(destination.hash)} running, waiting for a connection."
|
||||||
RNS.prettyhexrep(destination.hash)+
|
|
||||||
" running, waiting for a connection."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
||||||
@ -81,7 +79,7 @@ def server_loop(destination):
|
|||||||
while True:
|
while True:
|
||||||
entered = input()
|
entered = input()
|
||||||
destination.announce()
|
destination.announce()
|
||||||
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Sent announce from {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
# When a client establishes a link to our server
|
# When a client establishes a link to our server
|
||||||
# destination, this function will be called with
|
# destination, this function will be called with
|
||||||
@ -113,7 +111,7 @@ def client(destination_hexhash, configpath):
|
|||||||
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:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2)
|
f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes)."
|
||||||
)
|
)
|
||||||
|
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
@ -187,7 +185,7 @@ def client_loop():
|
|||||||
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while sending request over the link: "+str(e))
|
RNS.log(f"Error while sending request over the link: {e}")
|
||||||
should_quit = True
|
should_quit = True
|
||||||
server_link.teardown()
|
server_link.teardown()
|
||||||
|
|
||||||
@ -195,13 +193,13 @@ def got_response(request_receipt):
|
|||||||
request_id = request_receipt.request_id
|
request_id = request_receipt.request_id
|
||||||
response = request_receipt.response
|
response = request_receipt.response
|
||||||
|
|
||||||
RNS.log("Got response for request "+RNS.prettyhexrep(request_id)+": "+str(response))
|
RNS.log(f"Got response for request {RNS.prettyhexrep(request_id)}: {response}")
|
||||||
|
|
||||||
def request_received(request_receipt):
|
def request_received(request_receipt):
|
||||||
RNS.log("The request "+RNS.prettyhexrep(request_receipt.request_id)+" was received by the remote peer.")
|
RNS.log(f"The request {RNS.prettyhexrep(request_receipt.request_id)} was received by the remote peer.")
|
||||||
|
|
||||||
def request_failed(request_receipt):
|
def request_failed(request_receipt):
|
||||||
RNS.log("The request "+RNS.prettyhexrep(request_receipt.request_id)+" failed.")
|
RNS.log(f"The request {RNS.prettyhexrep(request_receipt.request_id)} failed.")
|
||||||
|
|
||||||
|
|
||||||
# This function is called when a link
|
# This function is called when a link
|
||||||
|
@ -62,9 +62,7 @@ def server(configpath):
|
|||||||
def server_loop(destination):
|
def server_loop(destination):
|
||||||
# Let the user know that everything is ready
|
# Let the user know that everything is ready
|
||||||
RNS.log(
|
RNS.log(
|
||||||
"Speedtest "+
|
f"Speedtest {RNS.prettyhexrep(destination.hash)} running, waiting for a connection."
|
||||||
RNS.prettyhexrep(destination.hash)+
|
|
||||||
" running, waiting for a connection."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
|
||||||
@ -76,7 +74,7 @@ def server_loop(destination):
|
|||||||
while True:
|
while True:
|
||||||
entered = input()
|
entered = input()
|
||||||
destination.announce()
|
destination.announce()
|
||||||
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Sent announce from {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
# When a client establishes a link to our server
|
# When a client establishes a link to our server
|
||||||
# destination, this function will be called with
|
# destination, this function will be called with
|
||||||
@ -108,9 +106,9 @@ def size_str(num, suffix='B'):
|
|||||||
|
|
||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1024.0:
|
if abs(num) < 1024.0:
|
||||||
return "%3.2f %s%s" % (num, unit, suffix)
|
return f"{num:3.2f} {unit}{suffix}"
|
||||||
num /= 1024.0
|
num /= 1024.0
|
||||||
return "%.2f %s%s" % (num, last_unit, suffix)
|
return f"{num:.2f} {last_unit}{suffix}"
|
||||||
|
|
||||||
|
|
||||||
def server_packet_received(message, packet):
|
def server_packet_received(message, packet):
|
||||||
@ -134,14 +132,14 @@ def server_packet_received(message, packet):
|
|||||||
download_time = last_packet_at-first_packet_at
|
download_time = last_packet_at-first_packet_at
|
||||||
hours, rem = divmod(download_time, 3600)
|
hours, rem = divmod(download_time, 3600)
|
||||||
minutes, seconds = divmod(rem, 60)
|
minutes, seconds = divmod(rem, 60)
|
||||||
timestring = "{:0>2}:{:0>2}:{:05.2f}".format(int(hours),int(minutes),seconds)
|
timestring = f"{int(hours):0>2}:{int(minutes):0>2}:{seconds:05.2f}"
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
print("")
|
print("")
|
||||||
print("--- Statistics -----")
|
print("--- Statistics -----")
|
||||||
print("\tTime taken : "+timestring)
|
print(f"\tTime taken : {timestring}")
|
||||||
print("\tData transferred : "+size_str(rcv_d))
|
print(f"\tData transferred : {size_str(rcv_d)}")
|
||||||
print("\tTransfer rate : "+size_str(rcv_d/download_time, suffix='b')+"/s")
|
print(f"\tTransfer rate : {size_str(rcv_d / download_time, suffix='b')}/s")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
@ -169,7 +167,7 @@ def client(destination_hexhash, configpath):
|
|||||||
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:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2)
|
f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes)."
|
||||||
)
|
)
|
||||||
|
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
@ -260,13 +258,13 @@ def link_established(link):
|
|||||||
download_time = ended-started
|
download_time = ended-started
|
||||||
hours, rem = divmod(download_time, 3600)
|
hours, rem = divmod(download_time, 3600)
|
||||||
minutes, seconds = divmod(rem, 60)
|
minutes, seconds = divmod(rem, 60)
|
||||||
timestring = "{:0>2}:{:0>2}:{:05.2f}".format(int(hours),int(minutes),seconds)
|
timestring = f"{int(hours):0>2}:{int(minutes):0>2}:{seconds:05.2f}"
|
||||||
print("")
|
print("")
|
||||||
print("")
|
print("")
|
||||||
print("--- Statistics -----")
|
print("--- Statistics -----")
|
||||||
print("\tTime taken : "+timestring)
|
print(f"\tTime taken : {timestring}")
|
||||||
print("\tData transferred : "+size_str(data_sent))
|
print(f"\tData transferred : {size_str(data_sent)}")
|
||||||
print("\tTransfer rate : "+size_str(data_sent/download_time, suffix='b')+"/s")
|
print(f"\tTransfer rate : {size_str(data_sent / download_time, suffix='b')}/s")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
@ -65,7 +65,7 @@ class StreamDataMessage(MessageBase):
|
|||||||
raise ValueError("stream_id must be 0-16383")
|
raise ValueError("stream_id must be 0-16383")
|
||||||
self.stream_id = stream_id
|
self.stream_id = stream_id
|
||||||
self.compressed = compressed
|
self.compressed = compressed
|
||||||
self.data = data or bytes()
|
self.data = data or b''
|
||||||
self.eof = eof
|
self.eof = eof
|
||||||
|
|
||||||
def pack(self) -> bytes:
|
def pack(self) -> bytes:
|
||||||
@ -73,7 +73,7 @@ class StreamDataMessage(MessageBase):
|
|||||||
raise ValueError("stream_id")
|
raise ValueError("stream_id")
|
||||||
|
|
||||||
header_val = (0x3fff & self.stream_id) | (0x8000 if self.eof else 0x0000) | (0x4000 if self.compressed > 0 else 0x0000)
|
header_val = (0x3fff & self.stream_id) | (0x8000 if self.eof else 0x0000) | (0x4000 if self.compressed > 0 else 0x0000)
|
||||||
return bytes(struct.pack(">H", header_val) + (self.data if self.data else bytes()))
|
return bytes(struct.pack(">H", header_val) + (self.data if self.data else b''))
|
||||||
|
|
||||||
def unpack(self, raw):
|
def unpack(self, raw):
|
||||||
self.stream_id = struct.unpack(">H", raw[:2])[0]
|
self.stream_id = struct.unpack(">H", raw[:2])[0]
|
||||||
@ -148,7 +148,7 @@ class RawChannelReader(RawIOBase, AbstractContextManager):
|
|||||||
try:
|
try:
|
||||||
threading.Thread(target=listener, name="Message Callback", args=[len(self._buffer)], daemon=True).start()
|
threading.Thread(target=listener, name="Message Callback", args=[len(self._buffer)], daemon=True).start()
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
RNS.log("Error calling RawChannelReader(" + str(self._stream_id) + ") callback: " + str(ex), RNS.LOG_ERROR)
|
RNS.log(f"Error calling RawChannelReader({self._stream_id}) callback: {ex}", RNS.LOG_ERROR)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -264,7 +264,7 @@ class RawChannelWriter(RawIOBase, AbstractContextManager):
|
|||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
|
|
||||||
self._eof = True
|
self._eof = True
|
||||||
self.write(bytes())
|
self.write(b'')
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
@ -168,7 +168,7 @@ class Envelope:
|
|||||||
Internal wrapper used to transport messages over a channel and
|
Internal wrapper used to transport messages over a channel and
|
||||||
track its state within the channel framework.
|
track its state within the channel framework.
|
||||||
"""
|
"""
|
||||||
def unpack(self, message_factories: dict[int, Type]) -> MessageBase:
|
def unpack(self, message_factories: dict[int, type]) -> MessageBase:
|
||||||
msgtype, self.sequence, length = struct.unpack(">HHH", self.raw[:6])
|
msgtype, self.sequence, length = struct.unpack(">HHH", self.raw[:6])
|
||||||
raw = self.raw[6:]
|
raw = self.raw[6:]
|
||||||
ctor = message_factories.get(msgtype, None)
|
ctor = message_factories.get(msgtype, None)
|
||||||
@ -282,7 +282,7 @@ class Channel(contextlib.AbstractContextManager):
|
|||||||
self._message_callbacks: [MessageCallbackType] = []
|
self._message_callbacks: [MessageCallbackType] = []
|
||||||
self._next_sequence = 0
|
self._next_sequence = 0
|
||||||
self._next_rx_sequence = 0
|
self._next_rx_sequence = 0
|
||||||
self._message_factories: dict[int, Type[MessageBase]] = {}
|
self._message_factories: dict[int, type[MessageBase]] = {}
|
||||||
self._max_tries = 5
|
self._max_tries = 5
|
||||||
self.fast_rate_rounds = 0
|
self.fast_rate_rounds = 0
|
||||||
self.medium_rate_rounds = 0
|
self.medium_rate_rounds = 0
|
||||||
@ -301,12 +301,12 @@ class Channel(contextlib.AbstractContextManager):
|
|||||||
def __enter__(self) -> Channel:
|
def __enter__(self) -> Channel:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None,
|
def __exit__(self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None,
|
||||||
__traceback: TracebackType | None) -> bool | None:
|
__traceback: TracebackType | None) -> bool | None:
|
||||||
self._shutdown()
|
self._shutdown()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def register_message_type(self, message_class: Type[MessageBase]):
|
def register_message_type(self, message_class: type[MessageBase]):
|
||||||
"""
|
"""
|
||||||
Register a message class for reception over a ``Channel``.
|
Register a message class for reception over a ``Channel``.
|
||||||
|
|
||||||
@ -316,7 +316,7 @@ class Channel(contextlib.AbstractContextManager):
|
|||||||
"""
|
"""
|
||||||
self._register_message_type(message_class, is_system_type=False)
|
self._register_message_type(message_class, is_system_type=False)
|
||||||
|
|
||||||
def _register_message_type(self, message_class: Type[MessageBase], *, is_system_type: bool = False):
|
def _register_message_type(self, message_class: type[MessageBase], *, is_system_type: bool = False):
|
||||||
with self._lock:
|
with self._lock:
|
||||||
if not issubclass(message_class, MessageBase):
|
if not issubclass(message_class, MessageBase):
|
||||||
raise ChannelException(CEType.ME_INVALID_MSG_TYPE,
|
raise ChannelException(CEType.ME_INVALID_MSG_TYPE,
|
||||||
@ -384,7 +384,7 @@ class Channel(contextlib.AbstractContextManager):
|
|||||||
for existing in ring:
|
for existing in ring:
|
||||||
|
|
||||||
if envelope.sequence == existing.sequence:
|
if envelope.sequence == existing.sequence:
|
||||||
RNS.log(f"Envelope: Emplacement of duplicate envelope with sequence "+str(envelope.sequence), RNS.LOG_EXTREME)
|
RNS.log(f"Envelope: Emplacement of duplicate envelope with sequence {envelope.sequence}", RNS.LOG_EXTREME)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if envelope.sequence < existing.sequence and not (self._next_rx_sequence - envelope.sequence) > (Channel.SEQ_MAX//2):
|
if envelope.sequence < existing.sequence and not (self._next_rx_sequence - envelope.sequence) > (Channel.SEQ_MAX//2):
|
||||||
@ -408,7 +408,7 @@ class Channel(contextlib.AbstractContextManager):
|
|||||||
if cb(message):
|
if cb(message):
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Channel "+str(self)+" experienced an error while running a message callback. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Channel {self} experienced an error while running a message callback. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def _receive(self, raw: bytes):
|
def _receive(self, raw: bytes):
|
||||||
try:
|
try:
|
||||||
@ -420,16 +420,16 @@ class Channel(contextlib.AbstractContextManager):
|
|||||||
window_overflow = (self._next_rx_sequence+Channel.WINDOW_MAX) % Channel.SEQ_MODULUS
|
window_overflow = (self._next_rx_sequence+Channel.WINDOW_MAX) % Channel.SEQ_MODULUS
|
||||||
if window_overflow < self._next_rx_sequence:
|
if window_overflow < self._next_rx_sequence:
|
||||||
if envelope.sequence > window_overflow:
|
if envelope.sequence > window_overflow:
|
||||||
RNS.log("Invalid packet sequence ("+str(envelope.sequence)+") received on channel "+str(self), RNS.LOG_EXTREME)
|
RNS.log(f"Invalid packet sequence ({envelope.sequence}) received on channel {self}", RNS.LOG_EXTREME)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
RNS.log("Invalid packet sequence ("+str(envelope.sequence)+") received on channel "+str(self), RNS.LOG_EXTREME)
|
RNS.log(f"Invalid packet sequence ({envelope.sequence}) received on channel {self}", RNS.LOG_EXTREME)
|
||||||
return
|
return
|
||||||
|
|
||||||
is_new = self._emplace_envelope(envelope, self._rx_ring)
|
is_new = self._emplace_envelope(envelope, self._rx_ring)
|
||||||
|
|
||||||
if not is_new:
|
if not is_new:
|
||||||
RNS.log("Duplicate message received on channel "+str(self), RNS.LOG_EXTREME)
|
RNS.log(f"Duplicate message received on channel {self}", RNS.LOG_EXTREME)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
with self._lock:
|
with self._lock:
|
||||||
@ -454,7 +454,7 @@ class Channel(contextlib.AbstractContextManager):
|
|||||||
self._run_callbacks(m)
|
self._run_callbacks(m)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error ocurred while receiving data on "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"An error ocurred while receiving data on {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def is_ready_to_send(self) -> bool:
|
def is_ready_to_send(self) -> bool:
|
||||||
"""
|
"""
|
||||||
@ -520,9 +520,9 @@ class Channel(contextlib.AbstractContextManager):
|
|||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Envelope not found in TX ring for "+str(self), RNS.LOG_EXTREME)
|
RNS.log(f"Envelope not found in TX ring for {self}", RNS.LOG_EXTREME)
|
||||||
if not envelope:
|
if not envelope:
|
||||||
RNS.log("Spurious message received on "+str(self), RNS.LOG_EXTREME)
|
RNS.log(f"Spurious message received on {self}", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
def _packet_delivered(self, packet: TPacket):
|
def _packet_delivered(self, packet: TPacket):
|
||||||
self._packet_tx_op(packet, lambda env: True)
|
self._packet_tx_op(packet, lambda env: True)
|
||||||
@ -541,7 +541,7 @@ class Channel(contextlib.AbstractContextManager):
|
|||||||
def _packet_timeout(self, packet: TPacket):
|
def _packet_timeout(self, packet: TPacket):
|
||||||
def retry_envelope(envelope: Envelope) -> bool:
|
def retry_envelope(envelope: Envelope) -> bool:
|
||||||
if envelope.tries >= self._max_tries:
|
if envelope.tries >= self._max_tries:
|
||||||
RNS.log("Retry count exceeded on "+str(self)+", tearing down Link.", RNS.LOG_ERROR)
|
RNS.log(f"Retry count exceeded on {self}, tearing down Link.", RNS.LOG_ERROR)
|
||||||
self._shutdown() # start on separate thread?
|
self._shutdown() # start on separate thread?
|
||||||
self._outlet.timed_out()
|
self._outlet.timed_out()
|
||||||
return True
|
return True
|
||||||
|
@ -48,7 +48,7 @@ class Fernet():
|
|||||||
raise ValueError("Token key cannot be None")
|
raise ValueError("Token key cannot be None")
|
||||||
|
|
||||||
if len(key) != 32:
|
if len(key) != 32:
|
||||||
raise ValueError("Token key must be 32 bytes, not "+str(len(key)))
|
raise ValueError(f"Token key must be 32 bytes, not {len(key)}")
|
||||||
|
|
||||||
self._signing_key = key[:16]
|
self._signing_key = key[:16]
|
||||||
self._encryption_key = key[16:]
|
self._encryption_key = key[16:]
|
||||||
@ -56,7 +56,7 @@ class Fernet():
|
|||||||
|
|
||||||
def verify_hmac(self, token):
|
def verify_hmac(self, token):
|
||||||
if len(token) <= 32:
|
if len(token) <= 32:
|
||||||
raise ValueError("Cannot verify HMAC on token of only "+str(len(token))+" bytes")
|
raise ValueError(f"Cannot verify HMAC on token of only {len(token)} bytes")
|
||||||
else:
|
else:
|
||||||
received_hmac = token[-32:]
|
received_hmac = token[-32:]
|
||||||
expected_hmac = HMAC.new(self._signing_key, token[:-32]).digest()
|
expected_hmac = HMAC.new(self._signing_key, token[:-32]).digest()
|
||||||
|
@ -37,7 +37,7 @@ class HMAC:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(key, (bytes, bytearray)):
|
if not isinstance(key, (bytes, bytearray)):
|
||||||
raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
|
raise TypeError(f"key: expected bytes or bytearray, but got {type(key).__name__!r}")
|
||||||
|
|
||||||
if not digestmod:
|
if not digestmod:
|
||||||
raise TypeError("Missing required parameter 'digestmod'.")
|
raise TypeError("Missing required parameter 'digestmod'.")
|
||||||
@ -60,13 +60,11 @@ class HMAC:
|
|||||||
if hasattr(self._inner, 'block_size'):
|
if hasattr(self._inner, 'block_size'):
|
||||||
blocksize = self._inner.block_size
|
blocksize = self._inner.block_size
|
||||||
if blocksize < 16:
|
if blocksize < 16:
|
||||||
_warnings.warn('block_size of %d seems too small; using our '
|
_warnings.warn(f'block_size of {int(blocksize)} seems too small; using our default of {int(self.blocksize)}.',
|
||||||
'default of %d.' % (blocksize, self.blocksize),
|
|
||||||
RuntimeWarning, 2)
|
RuntimeWarning, 2)
|
||||||
blocksize = self.blocksize
|
blocksize = self.blocksize
|
||||||
else:
|
else:
|
||||||
_warnings.warn('No block_size attribute on given digest object; '
|
_warnings.warn(f'No block_size attribute on given digest object; Assuming {int(self.blocksize)}.',
|
||||||
'Assuming %d.' % (self.blocksize),
|
|
||||||
RuntimeWarning, 2)
|
RuntimeWarning, 2)
|
||||||
blocksize = self.blocksize
|
blocksize = self.blocksize
|
||||||
|
|
||||||
|
@ -35,6 +35,6 @@ class PKCS7:
|
|||||||
l = len(data)
|
l = len(data)
|
||||||
n = data[-1]
|
n = data[-1]
|
||||||
if n > bs:
|
if n > bs:
|
||||||
raise ValueError("Cannot unpad, invalid padding length of "+str(n)+" bytes")
|
raise ValueError(f"Cannot unpad, invalid padding length of {n} bytes")
|
||||||
else:
|
else:
|
||||||
return data[:l-n]
|
return data[:l-n]
|
@ -35,4 +35,4 @@ def backend():
|
|||||||
elif PROVIDER == PROVIDER_INTERNAL:
|
elif PROVIDER == PROVIDER_INTERNAL:
|
||||||
return "internal"
|
return "internal"
|
||||||
elif PROVIDER == PROVIDER_PYCA:
|
elif PROVIDER == PROVIDER_PYCA:
|
||||||
return "openssl, PyCA "+str(pyca_v)
|
return f"openssl, PyCA {pyca_v}"
|
@ -28,7 +28,7 @@ import sys
|
|||||||
def new(m=None):
|
def new(m=None):
|
||||||
return sha256(m)
|
return sha256(m)
|
||||||
|
|
||||||
class sha256(object):
|
class sha256:
|
||||||
_k = (0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
_k = (0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||||
@ -59,7 +59,7 @@ class sha256(object):
|
|||||||
|
|
||||||
if m is not None:
|
if m is not None:
|
||||||
if type(m) is not bytes:
|
if type(m) is not bytes:
|
||||||
raise TypeError('%s() argument 1 must be bytes, not %s' % (self.__class__.__name__, type(m).__name__))
|
raise TypeError(f'{self.__class__.__name__}() argument 1 must be bytes, not {type(m).__name__}')
|
||||||
self.update(m)
|
self.update(m)
|
||||||
|
|
||||||
def _rotr(self, x, y):
|
def _rotr(self, x, y):
|
||||||
@ -100,7 +100,7 @@ class sha256(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if type(m) is not bytes:
|
if type(m) is not bytes:
|
||||||
raise TypeError('%s() argument 1 must be bytes, not %s' % (sys._getframe().f_code.co_name, type(m).__name__))
|
raise TypeError(f'{sys._getframe().f_code.co_name}() argument 1 must be bytes, not {type(m).__name__}')
|
||||||
|
|
||||||
self._buffer += m
|
self._buffer += m
|
||||||
self._counter += len(m)
|
self._counter += len(m)
|
||||||
|
@ -25,7 +25,7 @@ import copy, struct, sys
|
|||||||
def new(m=None):
|
def new(m=None):
|
||||||
return sha512(m)
|
return sha512(m)
|
||||||
|
|
||||||
class sha512(object):
|
class sha512:
|
||||||
_k = (0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
|
_k = (0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
|
||||||
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
|
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
|
||||||
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
|
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
|
||||||
@ -60,7 +60,7 @@ class sha512(object):
|
|||||||
|
|
||||||
if m is not None:
|
if m is not None:
|
||||||
if type(m) is not bytes:
|
if type(m) is not bytes:
|
||||||
raise TypeError('%s() argument 1 must be bytes, not %s' % (self.__class__.__name__, type(m).__name__))
|
raise TypeError(f'{self.__class__.__name__}() argument 1 must be bytes, not {type(m).__name__}')
|
||||||
self.update(m)
|
self.update(m)
|
||||||
|
|
||||||
def _rotr(self, x, y):
|
def _rotr(self, x, y):
|
||||||
@ -100,7 +100,7 @@ class sha512(object):
|
|||||||
if not m:
|
if not m:
|
||||||
return
|
return
|
||||||
if type(m) is not bytes:
|
if type(m) is not bytes:
|
||||||
raise TypeError('%s() argument 1 must be bytes, not %s' % (sys._getframe().f_code.co_name, type(m).__name__))
|
raise TypeError(f'{sys._getframe().f_code.co_name}() argument 1 must be bytes, not {type(m).__name__}')
|
||||||
|
|
||||||
self._buffer += m
|
self._buffer += m
|
||||||
self._counter += len(m)
|
self._counter += len(m)
|
||||||
|
@ -20,5 +20,5 @@ elif cp.PROVIDER == cp.PROVIDER_PYCA:
|
|||||||
from RNS.Cryptography.Proxies import Ed25519PrivateKeyProxy as Ed25519PrivateKey
|
from RNS.Cryptography.Proxies import Ed25519PrivateKeyProxy as Ed25519PrivateKey
|
||||||
from RNS.Cryptography.Proxies import Ed25519PublicKeyProxy as Ed25519PublicKey
|
from RNS.Cryptography.Proxies import Ed25519PublicKeyProxy as Ed25519PublicKey
|
||||||
|
|
||||||
modules = glob.glob(os.path.dirname(__file__)+"/*.py")
|
modules = glob.glob(f"{os.path.dirname(__file__)}/*.py")
|
||||||
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
||||||
|
@ -230,7 +230,7 @@ def test():
|
|||||||
print(f"Ciphertext Hex: {ciphertext_block.hex()}")
|
print(f"Ciphertext Hex: {ciphertext_block.hex()}")
|
||||||
print(f"Plaintext: {plaintext_block.decode()}")
|
print(f"Plaintext: {plaintext_block.decode()}")
|
||||||
assert plaintext_block == single_block_text
|
assert plaintext_block == single_block_text
|
||||||
print(bcolors.OK + "Single Block Test Passed Successfully" + bcolors.RESET)
|
print(f"{bcolors.OK}Single Block Test Passed Successfully{bcolors.RESET}")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
# test a less than a block length phrase
|
# test a less than a block length phrase
|
||||||
@ -246,7 +246,7 @@ def test():
|
|||||||
print(f"Ciphertext Hex: {ciphertext_short.hex()}")
|
print(f"Ciphertext Hex: {ciphertext_short.hex()}")
|
||||||
print(f"Plaintext: {plaintext_short.decode()}")
|
print(f"Plaintext: {plaintext_short.decode()}")
|
||||||
assert short_text == plaintext_short
|
assert short_text == plaintext_short
|
||||||
print(bcolors.OK + "Short Text Test Passed Successfully" + bcolors.RESET)
|
print(f"{bcolors.OK}Short Text Test Passed Successfully{bcolors.RESET}")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
# test an arbitrary length phrase
|
# test an arbitrary length phrase
|
||||||
@ -262,7 +262,7 @@ def test():
|
|||||||
print(f"Ciphertext Hex: {ciphertext.hex()}")
|
print(f"Ciphertext Hex: {ciphertext.hex()}")
|
||||||
print(f"Plaintext: {plaintext.decode()}")
|
print(f"Plaintext: {plaintext.decode()}")
|
||||||
assert text == plaintext
|
assert text == plaintext
|
||||||
print(bcolors.OK + "Arbitrary Length Text Test Passed Successfully" + bcolors.RESET)
|
print(f"{bcolors.OK}Arbitrary Length Text Test Passed Successfully{bcolors.RESET}")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ def encodepoint(P):
|
|||||||
assert 0 <= y < (1<<255) # always < 0x7fff..ff
|
assert 0 <= y < (1<<255) # always < 0x7fff..ff
|
||||||
if x & 1:
|
if x & 1:
|
||||||
y += 1<<255
|
y += 1<<255
|
||||||
return binascii.unhexlify("%064x" % y)[::-1]
|
return binascii.unhexlify(f"{y:064x}")[::-1]
|
||||||
|
|
||||||
def isoncurve(P):
|
def isoncurve(P):
|
||||||
x = P[0]
|
x = P[0]
|
||||||
@ -192,7 +192,7 @@ def password_to_scalar(pw):
|
|||||||
def scalar_to_bytes(y):
|
def scalar_to_bytes(y):
|
||||||
y = y % L
|
y = y % L
|
||||||
assert 0 <= y < 2**256
|
assert 0 <= y < 2**256
|
||||||
return binascii.unhexlify("%064x" % y)[::-1]
|
return binascii.unhexlify(f"{y:064x}")[::-1]
|
||||||
|
|
||||||
# Elements, of various orders
|
# Elements, of various orders
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ class BadPrefixError(Exception):
|
|||||||
def remove_prefix(s_bytes, prefix):
|
def remove_prefix(s_bytes, prefix):
|
||||||
assert(type(s_bytes) == type(prefix))
|
assert(type(s_bytes) == type(prefix))
|
||||||
if s_bytes[:len(prefix)] != prefix:
|
if s_bytes[:len(prefix)] != prefix:
|
||||||
raise BadPrefixError("did not see expected '%s' prefix" % (prefix,))
|
raise BadPrefixError(f"did not see expected '{prefix}' prefix")
|
||||||
return s_bytes[len(prefix):]
|
return s_bytes[len(prefix):]
|
||||||
|
|
||||||
def to_ascii(s_bytes, prefix="", encoding="base64"):
|
def to_ascii(s_bytes, prefix="", encoding="base64"):
|
||||||
@ -93,7 +93,7 @@ def from_ascii(s_ascii, prefix="", encoding="base64"):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
return s_bytes
|
return s_bytes
|
||||||
|
|
||||||
class SigningKey(object):
|
class SigningKey:
|
||||||
# this can only be used to reconstruct a key created by create_keypair().
|
# this can only be used to reconstruct a key created by create_keypair().
|
||||||
def __init__(self, sk_s, prefix="", encoding=None):
|
def __init__(self, sk_s, prefix="", encoding=None):
|
||||||
assert isinstance(sk_s, bytes)
|
assert isinstance(sk_s, bytes)
|
||||||
@ -150,7 +150,7 @@ class SigningKey(object):
|
|||||||
return to_ascii(sig_out, prefix, encoding)
|
return to_ascii(sig_out, prefix, encoding)
|
||||||
return prefix+sig_out
|
return prefix+sig_out
|
||||||
|
|
||||||
class VerifyingKey(object):
|
class VerifyingKey:
|
||||||
def __init__(self, vk_s, prefix="", encoding=None):
|
def __init__(self, vk_s, prefix="", encoding=None):
|
||||||
if not isinstance(prefix, bytes):
|
if not isinstance(prefix, bytes):
|
||||||
prefix = prefix.encode('ascii')
|
prefix = prefix.encode('ascii')
|
||||||
|
@ -78,16 +78,16 @@ def sign(skbytes, msg):
|
|||||||
"""Return just the signature, given the message and just the secret
|
"""Return just the signature, given the message and just the secret
|
||||||
key."""
|
key."""
|
||||||
if len(skbytes) != 32:
|
if len(skbytes) != 32:
|
||||||
raise ValueError("Bad signing key length %d" % len(skbytes))
|
raise ValueError(f"Bad signing key length {len(skbytes)}")
|
||||||
vkbytes = create_verifying_key(skbytes)
|
vkbytes = create_verifying_key(skbytes)
|
||||||
sig = signature(msg, skbytes, vkbytes)
|
sig = signature(msg, skbytes, vkbytes)
|
||||||
return sig
|
return sig
|
||||||
|
|
||||||
def verify(vkbytes, sig, msg):
|
def verify(vkbytes, sig, msg):
|
||||||
if len(vkbytes) != 32:
|
if len(vkbytes) != 32:
|
||||||
raise ValueError("Bad verifying key length %d" % len(vkbytes))
|
raise ValueError(f"Bad verifying key length {len(vkbytes)}")
|
||||||
if len(sig) != 64:
|
if len(sig) != 64:
|
||||||
raise ValueError("Bad signature length %d" % len(sig))
|
raise ValueError(f"Bad signature length {len(sig)}")
|
||||||
rc = checkvalid(sig, msg, vkbytes)
|
rc = checkvalid(sig, msg, vkbytes)
|
||||||
if not rc:
|
if not rc:
|
||||||
raise ValueError("rc != 0", rc)
|
raise ValueError("rc != 0", rc)
|
||||||
|
@ -96,10 +96,10 @@ class Destination:
|
|||||||
name = app_name
|
name = app_name
|
||||||
for aspect in aspects:
|
for aspect in aspects:
|
||||||
if "." in aspect: raise ValueError("Dots can't be used in aspects")
|
if "." in aspect: raise ValueError("Dots can't be used in aspects")
|
||||||
name += "." + aspect
|
name += f".{aspect}"
|
||||||
|
|
||||||
if identity != None:
|
if identity != None:
|
||||||
name += "." + identity.hexhash
|
name += f".{identity.hexhash}"
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ class Destination:
|
|||||||
"""
|
"""
|
||||||
:returns: A human-readable representation of the destination including addressable hash and full name.
|
:returns: A human-readable representation of the destination including addressable hash and full name.
|
||||||
"""
|
"""
|
||||||
return "<"+self.name+"/"+self.hexhash+">"
|
return f"<{self.name}/{self.hexhash}>"
|
||||||
|
|
||||||
def _clean_ratchets(self):
|
def _clean_ratchets(self):
|
||||||
if self.ratchets != None:
|
if self.ratchets != None:
|
||||||
@ -210,13 +210,13 @@ class Destination:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.ratchets = None
|
self.ratchets = None
|
||||||
self.ratchets_path = None
|
self.ratchets_path = None
|
||||||
raise OSError("Could not write ratchet file contents for "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
raise OSError(f"Could not write ratchet file contents for {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def rotate_ratchets(self):
|
def rotate_ratchets(self):
|
||||||
if self.ratchets != None:
|
if self.ratchets != None:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now > self.latest_ratchet_time+self.ratchet_interval:
|
if now > self.latest_ratchet_time+self.ratchet_interval:
|
||||||
RNS.log("Rotating ratchets for "+str(self), RNS.LOG_DEBUG)
|
RNS.log(f"Rotating ratchets for {self}", RNS.LOG_DEBUG)
|
||||||
new_ratchet = RNS.Identity._generate_ratchet()
|
new_ratchet = RNS.Identity._generate_ratchet()
|
||||||
self.ratchets.insert(0, new_ratchet)
|
self.ratchets.insert(0, new_ratchet)
|
||||||
self.latest_ratchet_time = now
|
self.latest_ratchet_time = now
|
||||||
@ -224,7 +224,7 @@ class Destination:
|
|||||||
self._persist_ratchets()
|
self._persist_ratchets()
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
raise SystemError("Cannot rotate ratchet on "+str(self)+", ratchets are not enabled")
|
raise SystemError(f"Cannot rotate ratchet on {self}, ratchets are not enabled")
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -262,7 +262,7 @@ class Destination:
|
|||||||
# received via multiple paths. The difference in reception time will
|
# received via multiple paths. The difference in reception time will
|
||||||
# potentially also be useful in determining characteristics of the
|
# potentially also be useful in determining characteristics of the
|
||||||
# multiple available paths, and to choose the best one.
|
# multiple available paths, and to choose the best one.
|
||||||
RNS.log("Using cached announce data for answering path request with tag "+RNS.prettyhexrep(tag), RNS.LOG_EXTREME)
|
RNS.log(f"Using cached announce data for answering path request with tag {RNS.prettyhexrep(tag)}", RNS.LOG_EXTREME)
|
||||||
announce_data = self.path_responses[tag][1]
|
announce_data = self.path_responses[tag][1]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -413,7 +413,7 @@ class Destination:
|
|||||||
try:
|
try:
|
||||||
self.callbacks.packet(plaintext, packet)
|
self.callbacks.packet(plaintext, packet)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing receive callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing receive callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def incoming_link_request(self, data, packet):
|
def incoming_link_request(self, data, packet):
|
||||||
if self.accept_link_requests:
|
if self.accept_link_requests:
|
||||||
@ -437,9 +437,9 @@ class Destination:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.ratchets = None
|
self.ratchets = None
|
||||||
self.ratchets_path = None
|
self.ratchets_path = None
|
||||||
raise OSError("Could not read ratchet file contents for "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
raise OSError(f"Could not read ratchet file contents for {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
else:
|
else:
|
||||||
RNS.log("No existing ratchet data found, initialising new ratchet file for "+str(self), RNS.LOG_DEBUG)
|
RNS.log(f"No existing ratchet data found, initialising new ratchet file for {self}", RNS.LOG_DEBUG)
|
||||||
self.ratchets = []
|
self.ratchets = []
|
||||||
self.ratchets_path = ratchets_path
|
self.ratchets_path = ratchets_path
|
||||||
self._persist_ratchets()
|
self._persist_ratchets()
|
||||||
@ -464,11 +464,11 @@ class Destination:
|
|||||||
self._reload_ratchets(ratchets_path)
|
self._reload_ratchets(ratchets_path)
|
||||||
|
|
||||||
# TODO: Remove at some point
|
# TODO: Remove at some point
|
||||||
RNS.log("Ratchets enabled on "+str(self), RNS.LOG_DEBUG)
|
RNS.log(f"Ratchets enabled on {self}", RNS.LOG_DEBUG)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("No ratchet file path specified for "+str(self))
|
raise ValueError(f"No ratchet file path specified for {self}")
|
||||||
|
|
||||||
def enforce_ratchets(self):
|
def enforce_ratchets(self):
|
||||||
"""
|
"""
|
||||||
@ -478,7 +478,7 @@ class Destination:
|
|||||||
"""
|
"""
|
||||||
if self.ratchets != None:
|
if self.ratchets != None:
|
||||||
self.__enforce_ratchets = True
|
self.__enforce_ratchets = True
|
||||||
RNS.log("Ratchets enforced on "+str(self), RNS.LOG_DEBUG)
|
RNS.log(f"Ratchets enforced on {self}", RNS.LOG_DEBUG)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
@ -586,7 +586,7 @@ class Destination:
|
|||||||
return self.prv.encrypt(plaintext)
|
return self.prv.encrypt(plaintext)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("The GROUP destination could not encrypt data", RNS.LOG_ERROR)
|
RNS.log("The GROUP destination could not encrypt data", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
else:
|
else:
|
||||||
raise ValueError("No private key held by GROUP destination. Did you create or load one?")
|
raise ValueError("No private key held by GROUP destination. Did you create or load one?")
|
||||||
|
|
||||||
@ -630,7 +630,7 @@ class Destination:
|
|||||||
return self.prv.decrypt(ciphertext)
|
return self.prv.decrypt(ciphertext)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("The GROUP destination could not decrypt data", RNS.LOG_ERROR)
|
RNS.log("The GROUP destination could not decrypt data", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
else:
|
else:
|
||||||
raise ValueError("No private key held by GROUP destination. Did you create or load one?")
|
raise ValueError("No private key held by GROUP destination. Did you create or load one?")
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ class Identity:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def remember(packet_hash, destination_hash, public_key, app_data = None):
|
def remember(packet_hash, destination_hash, public_key, app_data = None):
|
||||||
if len(public_key) != Identity.KEYSIZE//8:
|
if len(public_key) != Identity.KEYSIZE//8:
|
||||||
raise TypeError("Can't remember "+RNS.prettyhexrep(destination_hash)+", the public key size of "+str(len(public_key))+" is not valid.", RNS.LOG_ERROR)
|
raise TypeError(f"Can't remember {RNS.prettyhexrep(destination_hash)}, the public key size of {len(public_key)} is not valid.", RNS.LOG_ERROR)
|
||||||
else:
|
else:
|
||||||
Identity.known_destinations[destination_hash] = [time.time(), packet_hash, public_key, app_data]
|
Identity.known_destinations[destination_hash] = [time.time(), packet_hash, public_key, app_data]
|
||||||
|
|
||||||
@ -153,9 +153,9 @@ class Identity:
|
|||||||
save_start = time.time()
|
save_start = time.time()
|
||||||
|
|
||||||
storage_known_destinations = {}
|
storage_known_destinations = {}
|
||||||
if os.path.isfile(RNS.Reticulum.storagepath+"/known_destinations"):
|
if os.path.isfile(f"{RNS.Reticulum.storagepath}/known_destinations"):
|
||||||
try:
|
try:
|
||||||
file = open(RNS.Reticulum.storagepath+"/known_destinations","rb")
|
file = open(f"{RNS.Reticulum.storagepath}/known_destinations","rb")
|
||||||
storage_known_destinations = umsgpack.load(file)
|
storage_known_destinations = umsgpack.load(file)
|
||||||
file.close()
|
file.close()
|
||||||
except:
|
except:
|
||||||
@ -166,32 +166,32 @@ class Identity:
|
|||||||
if not destination_hash in Identity.known_destinations:
|
if not destination_hash in Identity.known_destinations:
|
||||||
Identity.known_destinations[destination_hash] = storage_known_destinations[destination_hash]
|
Identity.known_destinations[destination_hash] = storage_known_destinations[destination_hash]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Skipped recombining known destinations from disk, since an error occurred: "+str(e), RNS.LOG_WARNING)
|
RNS.log(f"Skipped recombining known destinations from disk, since an error occurred: {e}", RNS.LOG_WARNING)
|
||||||
|
|
||||||
RNS.log("Saving "+str(len(Identity.known_destinations))+" known destinations to storage...", RNS.LOG_DEBUG)
|
RNS.log(f"Saving {len(Identity.known_destinations)} known destinations to storage...", RNS.LOG_DEBUG)
|
||||||
file = open(RNS.Reticulum.storagepath+"/known_destinations","wb")
|
file = open(f"{RNS.Reticulum.storagepath}/known_destinations","wb")
|
||||||
umsgpack.dump(Identity.known_destinations, file)
|
umsgpack.dump(Identity.known_destinations, file)
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
save_time = time.time() - save_start
|
save_time = time.time() - save_start
|
||||||
if save_time < 1:
|
if save_time < 1:
|
||||||
time_str = str(round(save_time*1000,2))+"ms"
|
time_str = f"{round(save_time * 1000, 2)}ms"
|
||||||
else:
|
else:
|
||||||
time_str = str(round(save_time,2))+"s"
|
time_str = f"{round(save_time, 2)}s"
|
||||||
|
|
||||||
RNS.log("Saved known destinations to storage in "+time_str, RNS.LOG_DEBUG)
|
RNS.log(f"Saved known destinations to storage in {time_str}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while saving known destinations to disk, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while saving known destinations to disk, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.trace_exception(e)
|
RNS.trace_exception(e)
|
||||||
|
|
||||||
Identity.saving_known_destinations = False
|
Identity.saving_known_destinations = False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_known_destinations():
|
def load_known_destinations():
|
||||||
if os.path.isfile(RNS.Reticulum.storagepath+"/known_destinations"):
|
if os.path.isfile(f"{RNS.Reticulum.storagepath}/known_destinations"):
|
||||||
try:
|
try:
|
||||||
file = open(RNS.Reticulum.storagepath+"/known_destinations","rb")
|
file = open(f"{RNS.Reticulum.storagepath}/known_destinations","rb")
|
||||||
loaded_known_destinations = umsgpack.load(file)
|
loaded_known_destinations = umsgpack.load(file)
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ class Identity:
|
|||||||
if len(known_destination) == RNS.Reticulum.TRUNCATED_HASHLENGTH//8:
|
if len(known_destination) == RNS.Reticulum.TRUNCATED_HASHLENGTH//8:
|
||||||
Identity.known_destinations[known_destination] = loaded_known_destinations[known_destination]
|
Identity.known_destinations[known_destination] = loaded_known_destinations[known_destination]
|
||||||
|
|
||||||
RNS.log("Loaded "+str(len(Identity.known_destinations))+" known destination from storage", RNS.LOG_VERBOSE)
|
RNS.log(f"Loaded {len(Identity.known_destinations)} known destination from storage", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error loading known destinations from disk, file will be recreated on exit", RNS.LOG_ERROR)
|
RNS.log("Error loading known destinations from disk, file will be recreated on exit", RNS.LOG_ERROR)
|
||||||
@ -278,7 +278,7 @@ class Identity:
|
|||||||
hexhash = RNS.hexrep(destination_hash, delimit=False)
|
hexhash = RNS.hexrep(destination_hash, delimit=False)
|
||||||
ratchet_data = {"ratchet": ratchet, "received": time.time()}
|
ratchet_data = {"ratchet": ratchet, "received": time.time()}
|
||||||
|
|
||||||
ratchetdir = RNS.Reticulum.storagepath+"/ratchets"
|
ratchetdir = f"{RNS.Reticulum.storagepath}/ratchets"
|
||||||
|
|
||||||
if not os.path.isdir(ratchetdir):
|
if not os.path.isdir(ratchetdir):
|
||||||
os.makedirs(ratchetdir)
|
os.makedirs(ratchetdir)
|
||||||
@ -303,7 +303,7 @@ class Identity:
|
|||||||
RNS.log("Cleaning ratchets...", RNS.LOG_DEBUG)
|
RNS.log("Cleaning ratchets...", RNS.LOG_DEBUG)
|
||||||
try:
|
try:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
ratchetdir = RNS.Reticulum.storagepath+"/ratchets"
|
ratchetdir = f"{RNS.Reticulum.storagepath}/ratchets"
|
||||||
if os.path.isdir(ratchetdir):
|
if os.path.isdir(ratchetdir):
|
||||||
for filename in os.listdir(ratchetdir):
|
for filename in os.listdir(ratchetdir):
|
||||||
try:
|
try:
|
||||||
@ -326,7 +326,7 @@ class Identity:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def get_ratchet(destination_hash):
|
def get_ratchet(destination_hash):
|
||||||
if not destination_hash in Identity.known_ratchets:
|
if not destination_hash in Identity.known_ratchets:
|
||||||
ratchetdir = RNS.Reticulum.storagepath+"/ratchets"
|
ratchetdir = f"{RNS.Reticulum.storagepath}/ratchets"
|
||||||
hexhash = RNS.hexrep(destination_hash, delimit=False)
|
hexhash = RNS.hexrep(destination_hash, delimit=False)
|
||||||
ratchet_path = f"{ratchetdir}/{hexhash}"
|
ratchet_path = f"{ratchetdir}/{hexhash}"
|
||||||
if os.path.isfile(ratchet_path):
|
if os.path.isfile(ratchet_path):
|
||||||
@ -417,19 +417,19 @@ class Identity:
|
|||||||
if packet.rssi != None or packet.snr != None:
|
if packet.rssi != None or packet.snr != None:
|
||||||
signal_str = " ["
|
signal_str = " ["
|
||||||
if packet.rssi != None:
|
if packet.rssi != None:
|
||||||
signal_str += "RSSI "+str(packet.rssi)+"dBm"
|
signal_str += f"RSSI {packet.rssi}dBm"
|
||||||
if packet.snr != None:
|
if packet.snr != None:
|
||||||
signal_str += ", "
|
signal_str += ", "
|
||||||
if packet.snr != None:
|
if packet.snr != None:
|
||||||
signal_str += "SNR "+str(packet.snr)+"dB"
|
signal_str += f"SNR {packet.snr}dB"
|
||||||
signal_str += "]"
|
signal_str += "]"
|
||||||
else:
|
else:
|
||||||
signal_str = ""
|
signal_str = ""
|
||||||
|
|
||||||
if hasattr(packet, "transport_id") and packet.transport_id != None:
|
if hasattr(packet, "transport_id") and packet.transport_id != None:
|
||||||
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" "+str(packet.hops)+" hops away, received via "+RNS.prettyhexrep(packet.transport_id)+" on "+str(packet.receiving_interface)+signal_str, RNS.LOG_EXTREME)
|
RNS.log(f"Valid announce for {RNS.prettyhexrep(destination_hash)} {packet.hops} hops away, received via {RNS.prettyhexrep(packet.transport_id)} on {packet.receiving_interface}{signal_str}", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" "+str(packet.hops)+" hops away, received on "+str(packet.receiving_interface)+signal_str, RNS.LOG_EXTREME)
|
RNS.log(f"Valid announce for {RNS.prettyhexrep(destination_hash)} {packet.hops} hops away, received on {packet.receiving_interface}{signal_str}", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
if ratchet:
|
if ratchet:
|
||||||
Identity._remember_ratchet(destination_hash, ratchet)
|
Identity._remember_ratchet(destination_hash, ratchet)
|
||||||
@ -437,16 +437,16 @@ class Identity:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Received invalid announce for "+RNS.prettyhexrep(destination_hash)+": Destination mismatch.", RNS.LOG_DEBUG)
|
RNS.log(f"Received invalid announce for {RNS.prettyhexrep(destination_hash)}: Destination mismatch.", RNS.LOG_DEBUG)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Received invalid announce for "+RNS.prettyhexrep(destination_hash)+": Invalid signature.", RNS.LOG_DEBUG)
|
RNS.log(f"Received invalid announce for {RNS.prettyhexrep(destination_hash)}: Invalid signature.", RNS.LOG_DEBUG)
|
||||||
del announced_identity
|
del announced_identity
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error occurred while validating announce. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error occurred while validating announce. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -505,8 +505,8 @@ class Identity:
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while saving identity to "+str(path), RNS.LOG_ERROR)
|
RNS.log(f"Error while saving identity to {path}", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e))
|
RNS.log(f"The contained exception was: {e}")
|
||||||
|
|
||||||
def __init__(self,create_keys=True):
|
def __init__(self,create_keys=True):
|
||||||
# Initialize keys to none
|
# Initialize keys to none
|
||||||
@ -541,7 +541,7 @@ class Identity:
|
|||||||
|
|
||||||
self.update_hashes()
|
self.update_hashes()
|
||||||
|
|
||||||
RNS.log("Identity keys created for "+RNS.prettyhexrep(self.hash), RNS.LOG_VERBOSE)
|
RNS.log(f"Identity keys created for {RNS.prettyhexrep(self.hash)}", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
def get_private_key(self):
|
def get_private_key(self):
|
||||||
"""
|
"""
|
||||||
@ -581,7 +581,7 @@ class Identity:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise e
|
raise e
|
||||||
RNS.log("Failed to load identity key", RNS.LOG_ERROR)
|
RNS.log("Failed to load identity key", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def load_public_key(self, pub_bytes):
|
def load_public_key(self, pub_bytes):
|
||||||
@ -600,7 +600,7 @@ class Identity:
|
|||||||
|
|
||||||
self.update_hashes()
|
self.update_hashes()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while loading public key, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while loading public key, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def update_hashes(self):
|
def update_hashes(self):
|
||||||
self.hash = Identity.truncated_hash(self.get_public_key())
|
self.hash = Identity.truncated_hash(self.get_public_key())
|
||||||
@ -613,8 +613,8 @@ class Identity:
|
|||||||
return self.load_private_key(prv_bytes)
|
return self.load_private_key(prv_bytes)
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while loading identity from "+str(path), RNS.LOG_ERROR)
|
RNS.log(f"Error while loading identity from {path}", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def get_salt(self):
|
def get_salt(self):
|
||||||
return self.hash
|
return self.hash
|
||||||
@ -697,7 +697,7 @@ class Identity:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
if enforce_ratchets and plaintext == None:
|
if enforce_ratchets and plaintext == None:
|
||||||
RNS.log("Decryption with ratchet enforcement by "+RNS.prettyhexrep(self.hash)+" failed. Dropping packet.", RNS.LOG_DEBUG)
|
RNS.log(f"Decryption with ratchet enforcement by {RNS.prettyhexrep(self.hash)} failed. Dropping packet.", RNS.LOG_DEBUG)
|
||||||
if ratchet_id_receiver:
|
if ratchet_id_receiver:
|
||||||
ratchet_id_receiver.latest_ratchet_id = None
|
ratchet_id_receiver.latest_ratchet_id = None
|
||||||
return None
|
return None
|
||||||
@ -717,7 +717,7 @@ class Identity:
|
|||||||
ratchet_id_receiver.latest_ratchet_id = None
|
ratchet_id_receiver.latest_ratchet_id = None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Decryption by "+RNS.prettyhexrep(self.hash)+" failed: "+str(e), RNS.LOG_DEBUG)
|
RNS.log(f"Decryption by {RNS.prettyhexrep(self.hash)} failed: {e}", RNS.LOG_DEBUG)
|
||||||
if ratchet_id_receiver:
|
if ratchet_id_receiver:
|
||||||
ratchet_id_receiver.latest_ratchet_id = None
|
ratchet_id_receiver.latest_ratchet_id = None
|
||||||
|
|
||||||
@ -741,7 +741,7 @@ class Identity:
|
|||||||
try:
|
try:
|
||||||
return self.sig_prv.sign(message)
|
return self.sig_prv.sign(message)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("The identity "+str(self)+" could not sign the requested message. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The identity {self} could not sign the requested message. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
else:
|
else:
|
||||||
raise KeyError("Signing failed because identity does not hold a private key")
|
raise KeyError("Signing failed because identity does not hold a private key")
|
||||||
|
@ -87,7 +87,7 @@ class AX25KISSInterface(Interface):
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.src_call = callsign.upper().encode("ascii")
|
self.src_call = callsign.upper().encode("ascii")
|
||||||
self.src_ssid = ssid
|
self.src_ssid = ssid
|
||||||
self.dst_call = "APZRNS".encode("ascii")
|
self.dst_call = b"APZRNS"
|
||||||
self.dst_ssid = 0
|
self.dst_ssid = 0
|
||||||
self.port = port
|
self.port = port
|
||||||
self.speed = speed
|
self.speed = speed
|
||||||
@ -105,10 +105,10 @@ class AX25KISSInterface(Interface):
|
|||||||
self.flow_control_locked = time.time()
|
self.flow_control_locked = time.time()
|
||||||
|
|
||||||
if (len(self.src_call) < 3 or len(self.src_call) > 6):
|
if (len(self.src_call) < 3 or len(self.src_call) > 6):
|
||||||
raise ValueError("Invalid callsign for "+str(self))
|
raise ValueError(f"Invalid callsign for {self}")
|
||||||
|
|
||||||
if (self.src_ssid < 0 or self.src_ssid > 15):
|
if (self.src_ssid < 0 or self.src_ssid > 15):
|
||||||
raise ValueError("Invalid SSID for "+str(self))
|
raise ValueError(f"Invalid SSID for {self}")
|
||||||
|
|
||||||
self.preamble = preamble if preamble != None else 350;
|
self.preamble = preamble if preamble != None else 350;
|
||||||
self.txtail = txtail if txtail != None else 20;
|
self.txtail = txtail if txtail != None else 20;
|
||||||
@ -124,16 +124,16 @@ class AX25KISSInterface(Interface):
|
|||||||
try:
|
try:
|
||||||
self.open_port()
|
self.open_port()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not open serial port for interface "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Could not open serial port for interface {self}", RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not open serial port")
|
raise OSError("Could not open serial port")
|
||||||
|
|
||||||
def open_port(self):
|
def open_port(self):
|
||||||
RNS.log("Opening serial port "+self.port+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Opening serial port {self.port}...", RNS.LOG_VERBOSE)
|
||||||
self.serial = self.pyserial.Serial(
|
self.serial = self.pyserial.Serial(
|
||||||
port = self.port,
|
port = self.port,
|
||||||
baudrate = self.speed,
|
baudrate = self.speed,
|
||||||
@ -155,7 +155,7 @@ class AX25KISSInterface(Interface):
|
|||||||
thread.daemon = True
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
self.online = True
|
self.online = True
|
||||||
RNS.log("Serial port "+self.port+" is now open")
|
RNS.log(f"Serial port {self.port} is now open")
|
||||||
RNS.log("Configuring AX.25 KISS interface parameters...")
|
RNS.log("Configuring AX.25 KISS interface parameters...")
|
||||||
self.setPreamble(self.preamble)
|
self.setPreamble(self.preamble)
|
||||||
self.setTxTail(self.txtail)
|
self.setTxTail(self.txtail)
|
||||||
@ -176,7 +176,7 @@ class AX25KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXDELAY])+bytes([preamble])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXDELAY])+bytes([preamble])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure AX.25 KISS interface preamble to "+str(preamble_ms)+" (command value "+str(preamble)+")")
|
raise OSError(f"Could not configure AX.25 KISS interface preamble to {preamble_ms} (command value {preamble})")
|
||||||
|
|
||||||
def setTxTail(self, txtail):
|
def setTxTail(self, txtail):
|
||||||
txtail_ms = txtail
|
txtail_ms = txtail
|
||||||
@ -189,7 +189,7 @@ class AX25KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXTAIL])+bytes([txtail])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXTAIL])+bytes([txtail])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure AX.25 KISS interface TX tail to "+str(txtail_ms)+" (command value "+str(txtail)+")")
|
raise OSError(f"Could not configure AX.25 KISS interface TX tail to {txtail_ms} (command value {txtail})")
|
||||||
|
|
||||||
def setPersistence(self, persistence):
|
def setPersistence(self, persistence):
|
||||||
if persistence < 0:
|
if persistence < 0:
|
||||||
@ -200,7 +200,7 @@ class AX25KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_P])+bytes([persistence])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_P])+bytes([persistence])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure AX.25 KISS interface persistence to "+str(persistence))
|
raise OSError(f"Could not configure AX.25 KISS interface persistence to {persistence}")
|
||||||
|
|
||||||
def setSlotTime(self, slottime):
|
def setSlotTime(self, slottime):
|
||||||
slottime_ms = slottime
|
slottime_ms = slottime
|
||||||
@ -213,16 +213,16 @@ class AX25KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_SLOTTIME])+bytes([slottime])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_SLOTTIME])+bytes([slottime])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure AX.25 KISS interface slot time to "+str(slottime_ms)+" (command value "+str(slottime)+")")
|
raise OSError(f"Could not configure AX.25 KISS interface slot time to {slottime_ms} (command value {slottime})")
|
||||||
|
|
||||||
def setFlowControl(self, flow_control):
|
def setFlowControl(self, flow_control):
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_READY])+bytes([0x01])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_READY])+bytes([0x01])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
if (flow_control):
|
if (flow_control):
|
||||||
raise IOError("Could not enable AX.25 KISS interface flow control")
|
raise OSError("Could not enable AX.25 KISS interface flow control")
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not enable AX.25 KISS interface flow control")
|
raise OSError("Could not enable AX.25 KISS interface flow control")
|
||||||
|
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
@ -270,7 +270,7 @@ class AX25KISSInterface(Interface):
|
|||||||
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
|
||||||
raise IOError("AX.25 interface only wrote "+str(written)+" bytes of "+str(len(kiss_frame)))
|
raise OSError(f"AX.25 interface only wrote {written} bytes of {len(kiss_frame)}")
|
||||||
else:
|
else:
|
||||||
self.queue(data)
|
self.queue(data)
|
||||||
|
|
||||||
@ -336,13 +336,13 @@ class AX25KISSInterface(Interface):
|
|||||||
if self.flow_control:
|
if self.flow_control:
|
||||||
if not self.interface_ready:
|
if not self.interface_ready:
|
||||||
if time.time() > self.flow_control_locked + self.flow_control_timeout:
|
if time.time() > self.flow_control_locked + self.flow_control_timeout:
|
||||||
RNS.log("Interface "+str(self)+" is unlocking flow control due to time-out. This should not happen. Your hardware might have missed a flow-control READY command, or maybe it does not support flow-control.", RNS.LOG_WARNING)
|
RNS.log(f"Interface {self} is unlocking flow control due to time-out. This should not happen. Your hardware might have missed a flow-control READY command, or maybe it does not support flow-control.", RNS.LOG_WARNING)
|
||||||
self.process_queue()
|
self.process_queue()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"A serial port error occurred, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
RNS.log(f"The interface {self} experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if RNS.Reticulum.panic_on_interface_error:
|
if RNS.Reticulum.panic_on_interface_error:
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
@ -357,17 +357,17 @@ class AX25KISSInterface(Interface):
|
|||||||
while not self.online:
|
while not self.online:
|
||||||
try:
|
try:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Attempting to reconnect serial port {self.port} for {self}...", RNS.LOG_VERBOSE)
|
||||||
self.open_port()
|
self.open_port()
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while reconnecting port, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
RNS.log("Reconnected serial port for "+str(self))
|
RNS.log(f"Reconnected serial port for {self}")
|
||||||
|
|
||||||
def should_ingress_limit(self):
|
def should_ingress_limit(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "AX25KISSInterface["+self.name+"]"
|
return f"AX25KISSInterface[{self.name}]"
|
@ -125,17 +125,17 @@ class KISSInterface(Interface):
|
|||||||
try:
|
try:
|
||||||
self.open_port()
|
self.open_port()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not open serial port "+self.port, RNS.LOG_ERROR)
|
RNS.log(f"Could not open serial port {self.port}", RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not open serial port")
|
raise OSError("Could not open serial port")
|
||||||
|
|
||||||
|
|
||||||
def open_port(self):
|
def open_port(self):
|
||||||
RNS.log("Opening serial port "+self.port+"...")
|
RNS.log(f"Opening serial port {self.port}...")
|
||||||
# Get device parameters
|
# Get device parameters
|
||||||
from usb4a import usb
|
from usb4a import usb
|
||||||
device = usb.get_usb_device(self.port)
|
device = usb.get_usb_device(self.port)
|
||||||
@ -147,7 +147,7 @@ class KISSInterface(Interface):
|
|||||||
proxy = self.pyserial.get_serial_port
|
proxy = self.pyserial.get_serial_port
|
||||||
if vid == 0x1A86 and pid == 0x55D4:
|
if vid == 0x1A86 and pid == 0x55D4:
|
||||||
# Force CDC driver for Qinheng CH34x
|
# Force CDC driver for Qinheng CH34x
|
||||||
RNS.log(str(self)+" using CDC driver for "+RNS.hexrep(vid)+":"+RNS.hexrep(pid), RNS.LOG_DEBUG)
|
RNS.log(f"{self} using CDC driver for {RNS.hexrep(vid)}:{RNS.hexrep(pid)}", RNS.LOG_DEBUG)
|
||||||
from usbserial4a.cdcacmserial4a import CdcAcmSerial
|
from usbserial4a.cdcacmserial4a import CdcAcmSerial
|
||||||
proxy = CdcAcmSerial
|
proxy = CdcAcmSerial
|
||||||
|
|
||||||
@ -186,9 +186,9 @@ class KISSInterface(Interface):
|
|||||||
self.serial.USB_READ_TIMEOUT_MILLIS = 100
|
self.serial.USB_READ_TIMEOUT_MILLIS = 100
|
||||||
self.serial.timeout = 0.1
|
self.serial.timeout = 0.1
|
||||||
|
|
||||||
RNS.log(str(self)+" USB read buffer size set to "+RNS.prettysize(self.serial.DEFAULT_READ_BUFFER_SIZE), RNS.LOG_DEBUG)
|
RNS.log(f"{self} USB read buffer size set to {RNS.prettysize(self.serial.DEFAULT_READ_BUFFER_SIZE)}", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self)+" USB read timeout set to "+str(self.serial.USB_READ_TIMEOUT_MILLIS)+"ms", RNS.LOG_DEBUG)
|
RNS.log(f"{self} USB read timeout set to {self.serial.USB_READ_TIMEOUT_MILLIS}ms", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self)+" USB write timeout set to "+str(self.serial.USB_WRITE_TIMEOUT_MILLIS)+"ms", RNS.LOG_DEBUG)
|
RNS.log(f"{self} USB write timeout set to {self.serial.USB_WRITE_TIMEOUT_MILLIS}ms", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
def configure_device(self):
|
def configure_device(self):
|
||||||
# Allow time for interface to initialise before config
|
# Allow time for interface to initialise before config
|
||||||
@ -197,7 +197,7 @@ class KISSInterface(Interface):
|
|||||||
thread.daemon = True
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
self.online = True
|
self.online = True
|
||||||
RNS.log("Serial port "+self.port+" is now open")
|
RNS.log(f"Serial port {self.port} is now open")
|
||||||
RNS.log("Configuring KISS interface parameters...")
|
RNS.log("Configuring KISS interface parameters...")
|
||||||
self.setPreamble(self.preamble)
|
self.setPreamble(self.preamble)
|
||||||
self.setTxTail(self.txtail)
|
self.setTxTail(self.txtail)
|
||||||
@ -218,7 +218,7 @@ class KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXDELAY])+bytes([preamble])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXDELAY])+bytes([preamble])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure KISS interface preamble to "+str(preamble_ms)+" (command value "+str(preamble)+")")
|
raise OSError(f"Could not configure KISS interface preamble to {preamble_ms} (command value {preamble})")
|
||||||
|
|
||||||
def setTxTail(self, txtail):
|
def setTxTail(self, txtail):
|
||||||
txtail_ms = txtail
|
txtail_ms = txtail
|
||||||
@ -231,7 +231,7 @@ class KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXTAIL])+bytes([txtail])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXTAIL])+bytes([txtail])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure KISS interface TX tail to "+str(txtail_ms)+" (command value "+str(txtail)+")")
|
raise OSError(f"Could not configure KISS interface TX tail to {txtail_ms} (command value {txtail})")
|
||||||
|
|
||||||
def setPersistence(self, persistence):
|
def setPersistence(self, persistence):
|
||||||
if persistence < 0:
|
if persistence < 0:
|
||||||
@ -242,7 +242,7 @@ class KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_P])+bytes([persistence])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_P])+bytes([persistence])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure KISS interface persistence to "+str(persistence))
|
raise OSError(f"Could not configure KISS interface persistence to {persistence}")
|
||||||
|
|
||||||
def setSlotTime(self, slottime):
|
def setSlotTime(self, slottime):
|
||||||
slottime_ms = slottime
|
slottime_ms = slottime
|
||||||
@ -255,16 +255,16 @@ class KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_SLOTTIME])+bytes([slottime])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_SLOTTIME])+bytes([slottime])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure KISS interface slot time to "+str(slottime_ms)+" (command value "+str(slottime)+")")
|
raise OSError(f"Could not configure KISS interface slot time to {slottime_ms} (command value {slottime})")
|
||||||
|
|
||||||
def setFlowControl(self, flow_control):
|
def setFlowControl(self, flow_control):
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_READY])+bytes([0x01])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_READY])+bytes([0x01])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
if (flow_control):
|
if (flow_control):
|
||||||
raise IOError("Could not enable KISS interface flow control")
|
raise OSError("Could not enable KISS interface flow control")
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not enable KISS interface flow control")
|
raise OSError("Could not enable KISS interface flow control")
|
||||||
|
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
@ -295,7 +295,7 @@ class KISSInterface(Interface):
|
|||||||
self.first_tx = time.time()
|
self.first_tx = time.time()
|
||||||
|
|
||||||
if written != len(frame):
|
if written != len(frame):
|
||||||
raise IOError("Serial interface only wrote "+str(written)+" bytes of "+str(len(data)))
|
raise OSError(f"Serial interface only wrote {written} bytes of {len(data)}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.queue(data)
|
self.queue(data)
|
||||||
@ -365,20 +365,20 @@ class KISSInterface(Interface):
|
|||||||
if self.flow_control:
|
if self.flow_control:
|
||||||
if not self.interface_ready:
|
if not self.interface_ready:
|
||||||
if time.time() > self.flow_control_locked + self.flow_control_timeout:
|
if time.time() > self.flow_control_locked + self.flow_control_timeout:
|
||||||
RNS.log("Interface "+str(self)+" is unlocking flow control due to time-out. This should not happen. Your hardware might have missed a flow-control READY command, or maybe it does not support flow-control.", RNS.LOG_WARNING)
|
RNS.log(f"Interface {self} is unlocking flow control due to time-out. This should not happen. Your hardware might have missed a flow-control READY command, or maybe it does not support flow-control.", RNS.LOG_WARNING)
|
||||||
self.process_queue()
|
self.process_queue()
|
||||||
|
|
||||||
if self.beacon_i != None and self.beacon_d != None:
|
if self.beacon_i != None and self.beacon_d != None:
|
||||||
if self.first_tx != None:
|
if self.first_tx != None:
|
||||||
if time.time() > self.first_tx + self.beacon_i:
|
if time.time() > self.first_tx + self.beacon_i:
|
||||||
RNS.log("Interface "+str(self)+" is transmitting beacon data: "+str(self.beacon_d.decode("utf-8")), RNS.LOG_DEBUG)
|
RNS.log(f"Interface {self} is transmitting beacon data: {self.beacon_d.decode('utf-8')}", RNS.LOG_DEBUG)
|
||||||
self.first_tx = None
|
self.first_tx = None
|
||||||
self.processOutgoing(self.beacon_d)
|
self.processOutgoing(self.beacon_d)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"A serial port error occurred, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
RNS.log(f"The interface {self} experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if RNS.Reticulum.panic_on_interface_error:
|
if RNS.Reticulum.panic_on_interface_error:
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
@ -393,17 +393,17 @@ class KISSInterface(Interface):
|
|||||||
while not self.online:
|
while not self.online:
|
||||||
try:
|
try:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Attempting to reconnect serial port {self.port} for {self}...", RNS.LOG_VERBOSE)
|
||||||
self.open_port()
|
self.open_port()
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while reconnecting port, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
RNS.log("Reconnected serial port for "+str(self))
|
RNS.log(f"Reconnected serial port for {self}")
|
||||||
|
|
||||||
def should_ingress_limit(self):
|
def should_ingress_limit(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "KISSInterface["+self.name+"]"
|
return f"KISSInterface[{self.name}]"
|
@ -172,7 +172,7 @@ class AndroidBluetoothManager():
|
|||||||
try:
|
try:
|
||||||
self.rfcomm_socket = device.createRfcommSocketToServiceRecord(self.bt_rfcomm_service_record)
|
self.rfcomm_socket = device.createRfcommSocketToServiceRecord(self.bt_rfcomm_service_record)
|
||||||
if self.rfcomm_socket == None:
|
if self.rfcomm_socket == None:
|
||||||
raise IOError("Bluetooth stack returned no socket object")
|
raise OSError("Bluetooth stack returned no socket object")
|
||||||
else:
|
else:
|
||||||
if not self.rfcomm_socket.isConnected():
|
if not self.rfcomm_socket.isConnected():
|
||||||
try:
|
try:
|
||||||
@ -181,13 +181,13 @@ class AndroidBluetoothManager():
|
|||||||
self.rfcomm_writer = self.rfcomm_socket.getOutputStream()
|
self.rfcomm_writer = self.rfcomm_socket.getOutputStream()
|
||||||
self.connected = True
|
self.connected = True
|
||||||
self.connected_device = device
|
self.connected_device = device
|
||||||
RNS.log("Bluetooth device "+str(self.connected_device.getName())+" "+str(self.connected_device.getAddress())+" connected.")
|
RNS.log(f"Bluetooth device {self.connected_device.getName()} {self.connected_device.getAddress()} connected.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise IOError("The Bluetooth RFcomm socket could not be connected: "+str(e))
|
raise OSError(f"The Bluetooth RFcomm socket could not be connected: {e}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not create and connect Bluetooth RFcomm socket for "+str(device.getName())+" "+str(device.getAddress()), RNS.LOG_EXTREME)
|
RNS.log(f"Could not create and connect Bluetooth RFcomm socket for {device.getName()} {device.getAddress()}", RNS.LOG_EXTREME)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_EXTREME)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.connected:
|
if self.connected:
|
||||||
@ -209,7 +209,7 @@ class AndroidBluetoothManager():
|
|||||||
|
|
||||||
def read(self, len = None):
|
def read(self, len = None):
|
||||||
if self.connection_failed:
|
if self.connection_failed:
|
||||||
raise IOError("Bluetooth connection failed")
|
raise OSError("Bluetooth connection failed")
|
||||||
else:
|
else:
|
||||||
if self.connected and self.rfcomm_reader != None:
|
if self.connected and self.rfcomm_reader != None:
|
||||||
available = self.rfcomm_reader.available()
|
available = self.rfcomm_reader.available()
|
||||||
@ -223,7 +223,7 @@ class AndroidBluetoothManager():
|
|||||||
else:
|
else:
|
||||||
return bytes([])
|
return bytes([])
|
||||||
else:
|
else:
|
||||||
raise IOError("No RFcomm socket available")
|
raise OSError("No RFcomm socket available")
|
||||||
|
|
||||||
def write(self, data):
|
def write(self, data):
|
||||||
try:
|
try:
|
||||||
@ -231,7 +231,7 @@ class AndroidBluetoothManager():
|
|||||||
self.rfcomm_writer.flush()
|
self.rfcomm_writer.flush()
|
||||||
return len(data)
|
return len(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Bluetooth connection failed for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Bluetooth connection failed for {self}", RNS.LOG_ERROR)
|
||||||
self.connection_failed = True
|
self.connection_failed = True
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -274,7 +274,7 @@ class RNodeInterface(Interface):
|
|||||||
bluetooth_state = 0x00
|
bluetooth_state = 0x00
|
||||||
|
|
||||||
if port != None:
|
if port != None:
|
||||||
RNS.log("Opening serial port "+port+"...")
|
RNS.log(f"Opening serial port {port}...")
|
||||||
# Get device parameters
|
# Get device parameters
|
||||||
from usb4a import usb
|
from usb4a import usb
|
||||||
device = usb.get_usb_device(port)
|
device = usb.get_usb_device(port)
|
||||||
@ -287,7 +287,7 @@ class RNodeInterface(Interface):
|
|||||||
proxy = pyserial.get_serial_port
|
proxy = pyserial.get_serial_port
|
||||||
if vid == 0x1A86 and pid == 0x55D4:
|
if vid == 0x1A86 and pid == 0x55D4:
|
||||||
# Force CDC driver for Qinheng CH34x
|
# Force CDC driver for Qinheng CH34x
|
||||||
RNS.log("Using CDC driver for "+RNS.hexrep(vid)+":"+RNS.hexrep(pid), RNS.LOG_DEBUG)
|
RNS.log(f"Using CDC driver for {RNS.hexrep(vid)}:{RNS.hexrep(pid)}", RNS.LOG_DEBUG)
|
||||||
from usbserial4a.cdcacmserial4a import CdcAcmSerial
|
from usbserial4a.cdcacmserial4a import CdcAcmSerial
|
||||||
proxy = CdcAcmSerial
|
proxy = CdcAcmSerial
|
||||||
|
|
||||||
@ -466,31 +466,31 @@ class RNodeInterface(Interface):
|
|||||||
|
|
||||||
self.validcfg = True
|
self.validcfg = True
|
||||||
if (self.frequency < RNodeInterface.FREQ_MIN or self.frequency > RNodeInterface.FREQ_MAX):
|
if (self.frequency < RNodeInterface.FREQ_MIN or self.frequency > RNodeInterface.FREQ_MAX):
|
||||||
RNS.log("Invalid frequency configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid frequency configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.txpower < 0 or self.txpower > 22):
|
if (self.txpower < 0 or self.txpower > 22):
|
||||||
RNS.log("Invalid TX power configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid TX power configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.bandwidth < 7800 or self.bandwidth > 500000):
|
if (self.bandwidth < 7800 or self.bandwidth > 500000):
|
||||||
RNS.log("Invalid bandwidth configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid bandwidth configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.sf < 5 or self.sf > 12):
|
if (self.sf < 5 or self.sf > 12):
|
||||||
RNS.log("Invalid spreading factor configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid spreading factor configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.cr < 5 or self.cr > 8):
|
if (self.cr < 5 or self.cr > 8):
|
||||||
RNS.log("Invalid coding rate configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid coding rate configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.st_alock and (self.st_alock < 0.0 or self.st_alock > 100.0)):
|
if (self.st_alock and (self.st_alock < 0.0 or self.st_alock > 100.0)):
|
||||||
RNS.log("Invalid short-term airtime limit configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid short-term airtime limit configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.lt_alock and (self.lt_alock < 0.0 or self.lt_alock > 100.0)):
|
if (self.lt_alock and (self.lt_alock < 0.0 or self.lt_alock > 100.0)):
|
||||||
RNS.log("Invalid long-term airtime limit configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid long-term airtime limit configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if id_interval != None and id_callsign != None:
|
if id_interval != None and id_callsign != None:
|
||||||
@ -499,14 +499,14 @@ class RNodeInterface(Interface):
|
|||||||
self.id_callsign = id_callsign.encode("utf-8")
|
self.id_callsign = id_callsign.encode("utf-8")
|
||||||
self.id_interval = id_interval
|
self.id_interval = id_interval
|
||||||
else:
|
else:
|
||||||
RNS.log("The encoded ID callsign for "+str(self)+" exceeds the max length of "+str(RNodeInterface.CALLSIGN_MAX_LEN)+" bytes.", RNS.LOG_ERROR)
|
RNS.log(f"The encoded ID callsign for {self} exceeds the max length of {RNodeInterface.CALLSIGN_MAX_LEN} bytes.", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
else:
|
else:
|
||||||
self.id_interval = None
|
self.id_interval = None
|
||||||
self.id_callsign = None
|
self.id_callsign = None
|
||||||
|
|
||||||
if (not self.validcfg):
|
if (not self.validcfg):
|
||||||
raise ValueError("The configuration for "+str(self)+" contains errors, interface is offline")
|
raise ValueError(f"The configuration for {self} contains errors, interface is offline")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.open_port()
|
self.open_port()
|
||||||
@ -515,18 +515,18 @@ class RNodeInterface(Interface):
|
|||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not open serial port")
|
raise OSError("Could not open serial port")
|
||||||
elif self.bt_manager != None:
|
elif self.bt_manager != None:
|
||||||
if self.bt_manager.connected:
|
if self.bt_manager.connected:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not connect to any Bluetooth devices")
|
raise OSError("Could not connect to any Bluetooth devices")
|
||||||
else:
|
else:
|
||||||
raise IOError("Neither serial port nor Bluetooth devices available")
|
raise OSError("Neither serial port nor Bluetooth devices available")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not open serial port for interface "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Could not open serial port for interface {self}", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
if len(self.hw_errors) == 0:
|
if len(self.hw_errors) == 0:
|
||||||
RNS.log("Reticulum will attempt to bring up this interface periodically", RNS.LOG_ERROR)
|
RNS.log("Reticulum will attempt to bring up this interface periodically", RNS.LOG_ERROR)
|
||||||
thread = threading.Thread(target=self.reconnect_port, daemon=True).start()
|
thread = threading.Thread(target=self.reconnect_port, daemon=True).start()
|
||||||
@ -538,7 +538,7 @@ class RNodeInterface(Interface):
|
|||||||
elif self.bt_manager != None:
|
elif self.bt_manager != None:
|
||||||
return self.bt_manager.read()
|
return self.bt_manager.read()
|
||||||
else:
|
else:
|
||||||
raise IOError("No ports available for reading")
|
raise OSError("No ports available for reading")
|
||||||
|
|
||||||
def write_mux(self, data):
|
def write_mux(self, data):
|
||||||
if self.serial != None:
|
if self.serial != None:
|
||||||
@ -551,7 +551,7 @@ class RNodeInterface(Interface):
|
|||||||
self.last_port_io = time.time()
|
self.last_port_io = time.time()
|
||||||
return written
|
return written
|
||||||
else:
|
else:
|
||||||
raise IOError("No ports available for writing")
|
raise OSError("No ports available for writing")
|
||||||
|
|
||||||
# def reset_ble(self):
|
# def reset_ble(self):
|
||||||
# RNS.log(f"Clearing previous connection instance: "+str(self.ble))
|
# RNS.log(f"Clearing previous connection instance: "+str(self.ble))
|
||||||
@ -565,7 +565,7 @@ class RNodeInterface(Interface):
|
|||||||
def open_port(self):
|
def open_port(self):
|
||||||
if not self.use_ble:
|
if not self.use_ble:
|
||||||
if self.port != None:
|
if self.port != None:
|
||||||
RNS.log("Opening serial port "+self.port+"...")
|
RNS.log(f"Opening serial port {self.port}...")
|
||||||
# Get device parameters
|
# Get device parameters
|
||||||
from usb4a import usb
|
from usb4a import usb
|
||||||
device = usb.get_usb_device(self.port)
|
device = usb.get_usb_device(self.port)
|
||||||
@ -577,7 +577,7 @@ class RNodeInterface(Interface):
|
|||||||
proxy = self.pyserial.get_serial_port
|
proxy = self.pyserial.get_serial_port
|
||||||
if vid == 0x1A86 and pid == 0x55D4:
|
if vid == 0x1A86 and pid == 0x55D4:
|
||||||
# Force CDC driver for Qinheng CH34x
|
# Force CDC driver for Qinheng CH34x
|
||||||
RNS.log(str(self)+" using CDC driver for "+RNS.hexrep(vid)+":"+RNS.hexrep(pid), RNS.LOG_DEBUG)
|
RNS.log(f"{self} using CDC driver for {RNS.hexrep(vid)}:{RNS.hexrep(pid)}", RNS.LOG_DEBUG)
|
||||||
from usbserial4a.cdcacmserial4a import CdcAcmSerial
|
from usbserial4a.cdcacmserial4a import CdcAcmSerial
|
||||||
proxy = CdcAcmSerial
|
proxy = CdcAcmSerial
|
||||||
|
|
||||||
@ -616,9 +616,9 @@ class RNodeInterface(Interface):
|
|||||||
self.serial.USB_READ_TIMEOUT_MILLIS = 100
|
self.serial.USB_READ_TIMEOUT_MILLIS = 100
|
||||||
self.serial.timeout = 0.1
|
self.serial.timeout = 0.1
|
||||||
|
|
||||||
RNS.log(str(self)+" USB read buffer size set to "+RNS.prettysize(self.serial.DEFAULT_READ_BUFFER_SIZE), RNS.LOG_DEBUG)
|
RNS.log(f"{self} USB read buffer size set to {RNS.prettysize(self.serial.DEFAULT_READ_BUFFER_SIZE)}", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self)+" USB read timeout set to "+str(self.serial.USB_READ_TIMEOUT_MILLIS)+"ms", RNS.LOG_DEBUG)
|
RNS.log(f"{self} USB read timeout set to {self.serial.USB_READ_TIMEOUT_MILLIS}ms", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self)+" USB write timeout set to "+str(self.serial.USB_WRITE_TIMEOUT_MILLIS)+"ms", RNS.LOG_DEBUG)
|
RNS.log(f"{self} USB write timeout set to {self.serial.USB_WRITE_TIMEOUT_MILLIS}ms", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
elif self.allow_bluetooth:
|
elif self.allow_bluetooth:
|
||||||
if self.bt_manager == None:
|
if self.bt_manager == None:
|
||||||
@ -660,17 +660,17 @@ class RNodeInterface(Interface):
|
|||||||
RNS.log(f"RNode detect timed out over {self.port}", RNS.LOG_ERROR)
|
RNS.log(f"RNode detect timed out over {self.port}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if not self.detected:
|
if not self.detected:
|
||||||
raise IOError("Could not detect device")
|
raise OSError("Could not detect device")
|
||||||
else:
|
else:
|
||||||
if self.platform == KISS.PLATFORM_ESP32 or self.platform == KISS.PLATFORM_NRF52:
|
if self.platform == KISS.PLATFORM_ESP32 or self.platform == KISS.PLATFORM_NRF52:
|
||||||
self.display = True
|
self.display = True
|
||||||
|
|
||||||
if not self.firmware_ok:
|
if not self.firmware_ok:
|
||||||
raise IOError("Invalid device firmware")
|
raise OSError("Invalid device firmware")
|
||||||
|
|
||||||
if self.serial != None and self.port != None:
|
if self.serial != None and self.port != None:
|
||||||
self.timeout = 200
|
self.timeout = 200
|
||||||
RNS.log("Serial port "+self.port+" is now open")
|
RNS.log(f"Serial port {self.port} is now open")
|
||||||
|
|
||||||
if self.bt_manager != None and self.bt_manager.connected:
|
if self.bt_manager != None and self.bt_manager.connected:
|
||||||
self.timeout = 1500
|
self.timeout = 1500
|
||||||
@ -680,11 +680,11 @@ class RNodeInterface(Interface):
|
|||||||
self.initRadio()
|
self.initRadio()
|
||||||
if (self.validateRadioState()):
|
if (self.validateRadioState()):
|
||||||
self.interface_ready = True
|
self.interface_ready = True
|
||||||
RNS.log(str(self)+" is configured and powered up")
|
RNS.log(f"{self} is configured and powered up")
|
||||||
sleep(0.3)
|
sleep(0.3)
|
||||||
self.online = True
|
self.online = True
|
||||||
else:
|
else:
|
||||||
RNS.log("After configuring "+str(self)+", the reported radio parameters did not match your configuration.", RNS.LOG_ERROR)
|
RNS.log(f"After configuring {self}, the reported radio parameters did not match your configuration.", RNS.LOG_ERROR)
|
||||||
RNS.log("Make sure that your hardware actually supports the parameters specified in the configuration", RNS.LOG_ERROR)
|
RNS.log("Make sure that your hardware actually supports the parameters specified in the configuration", RNS.LOG_ERROR)
|
||||||
RNS.log("Aborting RNode startup", RNS.LOG_ERROR)
|
RNS.log("Aborting RNode startup", RNS.LOG_ERROR)
|
||||||
|
|
||||||
@ -693,7 +693,7 @@ class RNodeInterface(Interface):
|
|||||||
if self.bt_manager != None:
|
if self.bt_manager != None:
|
||||||
self.bt_manager.close()
|
self.bt_manager.close()
|
||||||
|
|
||||||
raise IOError("RNode interface did not pass configuration validation")
|
raise OSError("RNode interface did not pass configuration validation")
|
||||||
|
|
||||||
|
|
||||||
def initRadio(self):
|
def initRadio(self):
|
||||||
@ -728,45 +728,45 @@ class RNodeInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_DETECT, KISS.DETECT_REQ, KISS.FEND, KISS.CMD_FW_VERSION, 0x00, KISS.FEND, KISS.CMD_PLATFORM, 0x00, KISS.FEND, KISS.CMD_MCU, 0x00, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_DETECT, KISS.DETECT_REQ, KISS.FEND, KISS.CMD_FW_VERSION, 0x00, KISS.FEND, KISS.CMD_PLATFORM, 0x00, KISS.FEND, KISS.CMD_MCU, 0x00, KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while detecting hardware for "+str(self))
|
raise OSError(f"An IO error occurred while detecting hardware for {self}")
|
||||||
|
|
||||||
def leave(self):
|
def leave(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_LEAVE, 0xFF, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_LEAVE, 0xFF, KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while sending host left command to device")
|
raise OSError("An IO error occurred while sending host left command to device")
|
||||||
|
|
||||||
def enable_bluetooth(self):
|
def enable_bluetooth(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_BT_CTRL, 0x01, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_BT_CTRL, 0x01, KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while sending bluetooth enable command to device")
|
raise OSError("An IO error occurred while sending bluetooth enable command to device")
|
||||||
|
|
||||||
def disable_bluetooth(self):
|
def disable_bluetooth(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_BT_CTRL, 0x00, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_BT_CTRL, 0x00, KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while sending bluetooth disable command to device")
|
raise OSError("An IO error occurred while sending bluetooth disable command to device")
|
||||||
|
|
||||||
def bluetooth_pair(self):
|
def bluetooth_pair(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_BT_CTRL, 0x02, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_BT_CTRL, 0x02, KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while sending bluetooth pair command to device")
|
raise OSError("An IO error occurred while sending bluetooth pair command to device")
|
||||||
|
|
||||||
def enable_external_framebuffer(self):
|
def enable_external_framebuffer(self):
|
||||||
if self.display != None:
|
if self.display != None:
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x01, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x01, KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while enabling external framebuffer on device")
|
raise OSError("An IO error occurred while enabling external framebuffer on device")
|
||||||
|
|
||||||
def disable_external_framebuffer(self):
|
def disable_external_framebuffer(self):
|
||||||
if self.display != None:
|
if self.display != None:
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x00, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x00, KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while disabling external framebuffer on device")
|
raise OSError("An IO error occurred while disabling external framebuffer on device")
|
||||||
|
|
||||||
FB_PIXEL_WIDTH = 64
|
FB_PIXEL_WIDTH = 64
|
||||||
FB_BITS_PER_PIXEL = 1
|
FB_BITS_PER_PIXEL = 1
|
||||||
@ -791,13 +791,13 @@ class RNodeInterface(Interface):
|
|||||||
|
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while writing framebuffer data device")
|
raise OSError("An IO error occurred while writing framebuffer data device")
|
||||||
|
|
||||||
def hard_reset(self):
|
def hard_reset(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_RESET, 0xf8, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_RESET, 0xf8, KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while restarting device")
|
raise OSError("An IO error occurred while restarting device")
|
||||||
sleep(4.0);
|
sleep(4.0);
|
||||||
|
|
||||||
def setFrequency(self):
|
def setFrequency(self):
|
||||||
@ -810,7 +810,7 @@ class RNodeInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_FREQUENCY])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_FREQUENCY])+data+bytes([KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring frequency for "+str(self))
|
raise OSError(f"An IO error occurred while configuring frequency for {self}")
|
||||||
|
|
||||||
def setBandwidth(self):
|
def setBandwidth(self):
|
||||||
c1 = self.bandwidth >> 24
|
c1 = self.bandwidth >> 24
|
||||||
@ -822,28 +822,28 @@ class RNodeInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_BANDWIDTH])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_BANDWIDTH])+data+bytes([KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring bandwidth for "+str(self))
|
raise OSError(f"An IO error occurred while configuring bandwidth for {self}")
|
||||||
|
|
||||||
def setTXPower(self):
|
def setTXPower(self):
|
||||||
txp = bytes([self.txpower])
|
txp = bytes([self.txpower])
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXPOWER])+txp+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXPOWER])+txp+bytes([KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring TX power for "+str(self))
|
raise OSError(f"An IO error occurred while configuring TX power for {self}")
|
||||||
|
|
||||||
def setSpreadingFactor(self):
|
def setSpreadingFactor(self):
|
||||||
sf = bytes([self.sf])
|
sf = bytes([self.sf])
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_SF])+sf+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_SF])+sf+bytes([KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring spreading factor for "+str(self))
|
raise OSError(f"An IO error occurred while configuring spreading factor for {self}")
|
||||||
|
|
||||||
def setCodingRate(self):
|
def setCodingRate(self):
|
||||||
cr = bytes([self.cr])
|
cr = bytes([self.cr])
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_CR])+cr+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_CR])+cr+bytes([KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring coding rate for "+str(self))
|
raise OSError(f"An IO error occurred while configuring coding rate for {self}")
|
||||||
|
|
||||||
def setSTALock(self):
|
def setSTALock(self):
|
||||||
if self.st_alock != None:
|
if self.st_alock != None:
|
||||||
@ -855,7 +855,7 @@ class RNodeInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_ST_ALOCK])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_ST_ALOCK])+data+bytes([KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring short-term airtime limit for "+str(self))
|
raise OSError(f"An IO error occurred while configuring short-term airtime limit for {self}")
|
||||||
|
|
||||||
def setLTALock(self):
|
def setLTALock(self):
|
||||||
if self.lt_alock != None:
|
if self.lt_alock != None:
|
||||||
@ -867,14 +867,14 @@ class RNodeInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_LT_ALOCK])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_LT_ALOCK])+data+bytes([KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring long-term airtime limit for "+str(self))
|
raise OSError(f"An IO error occurred while configuring long-term airtime limit for {self}")
|
||||||
|
|
||||||
def setRadioState(self, state):
|
def setRadioState(self, state):
|
||||||
self.state = state
|
self.state = state
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_RADIO_STATE])+bytes([state])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_RADIO_STATE])+bytes([state])+bytes([KISS.FEND])
|
||||||
written = self.write_mux(kiss_command)
|
written = self.write_mux(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring radio state for "+str(self))
|
raise OSError(f"An IO error occurred while configuring radio state for {self}")
|
||||||
|
|
||||||
def validate_firmware(self):
|
def validate_firmware(self):
|
||||||
if (self.maj_version > RNodeInterface.REQUIRED_FW_VER_MAJ):
|
if (self.maj_version > RNodeInterface.REQUIRED_FW_VER_MAJ):
|
||||||
@ -887,17 +887,17 @@ class RNodeInterface(Interface):
|
|||||||
if self.firmware_ok:
|
if self.firmware_ok:
|
||||||
return
|
return
|
||||||
|
|
||||||
RNS.log("The firmware version of the connected RNode is "+str(self.maj_version)+"."+str(self.min_version), RNS.LOG_ERROR)
|
RNS.log(f"The firmware version of the connected RNode is {self.maj_version}.{self.min_version}", RNS.LOG_ERROR)
|
||||||
RNS.log("This version of Reticulum requires at least version "+str(RNodeInterface.REQUIRED_FW_VER_MAJ)+"."+str(RNodeInterface.REQUIRED_FW_VER_MIN), RNS.LOG_ERROR)
|
RNS.log(f"This version of Reticulum requires at least version {RNodeInterface.REQUIRED_FW_VER_MAJ}.{RNodeInterface.REQUIRED_FW_VER_MIN}", RNS.LOG_ERROR)
|
||||||
RNS.log("Please update your RNode firmware with rnodeconf from https://github.com/markqvist/reticulum/")
|
RNS.log("Please update your RNode firmware with rnodeconf from https://github.com/markqvist/reticulum/")
|
||||||
error_description = "The firmware version of the connected RNode is "+str(self.maj_version)+"."+str(self.min_version)+". "
|
error_description = f"The firmware version of the connected RNode is {self.maj_version}.{self.min_version}. "
|
||||||
error_description += "This version of Reticulum requires at least version "+str(RNodeInterface.REQUIRED_FW_VER_MAJ)+"."+str(RNodeInterface.REQUIRED_FW_VER_MIN)+". "
|
error_description += f"This version of Reticulum requires at least version {RNodeInterface.REQUIRED_FW_VER_MAJ}.{RNodeInterface.REQUIRED_FW_VER_MIN}. "
|
||||||
error_description += "Please update your RNode firmware with rnodeconf from: https://github.com/markqvist/rnodeconfigutil/"
|
error_description += "Please update your RNode firmware with rnodeconf from: https://github.com/markqvist/rnodeconfigutil/"
|
||||||
self.hw_errors.append({"error": KISS.ERROR_INVALID_FIRMWARE, "description": error_description})
|
self.hw_errors.append({"error": KISS.ERROR_INVALID_FIRMWARE, "description": error_description})
|
||||||
|
|
||||||
|
|
||||||
def validateRadioState(self):
|
def validateRadioState(self):
|
||||||
RNS.log("Waiting for radio configuration validation for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Waiting for radio configuration validation for {self}...", RNS.LOG_VERBOSE)
|
||||||
if not self.platform == KISS.PLATFORM_ESP32:
|
if not self.platform == KISS.PLATFORM_ESP32:
|
||||||
sleep(1.00);
|
sleep(1.00);
|
||||||
else:
|
else:
|
||||||
@ -937,7 +937,7 @@ class RNodeInterface(Interface):
|
|||||||
try:
|
try:
|
||||||
self.bitrate = self.r_sf * ( (4.0/self.r_cr) / (math.pow(2,self.r_sf)/(self.r_bandwidth/1000)) ) * 1000
|
self.bitrate = self.r_sf * ( (4.0/self.r_cr) / (math.pow(2,self.r_sf)/(self.r_bandwidth/1000)) ) * 1000
|
||||||
self.bitrate_kbps = round(self.bitrate/1000.0, 2)
|
self.bitrate_kbps = round(self.bitrate/1000.0, 2)
|
||||||
RNS.log(str(self)+" On-air bitrate is now "+str(self.bitrate_kbps)+ " kbps", RNS.LOG_VERBOSE)
|
RNS.log(f"{self} On-air bitrate is now {self.bitrate_kbps} kbps", RNS.LOG_VERBOSE)
|
||||||
except:
|
except:
|
||||||
self.bitrate = 0
|
self.bitrate = 0
|
||||||
|
|
||||||
@ -969,7 +969,7 @@ class RNodeInterface(Interface):
|
|||||||
self.txb += datalen
|
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 OSError(f"Serial interface only wrote {written} bytes of {len(data)}")
|
||||||
else:
|
else:
|
||||||
self.queue(data)
|
self.queue(data)
|
||||||
|
|
||||||
@ -1042,7 +1042,7 @@ class RNodeInterface(Interface):
|
|||||||
command_buffer = command_buffer+bytes([byte])
|
command_buffer = command_buffer+bytes([byte])
|
||||||
if (len(command_buffer) == 4):
|
if (len(command_buffer) == 4):
|
||||||
self.r_frequency = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
self.r_frequency = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
||||||
RNS.log(str(self)+" Radio reporting frequency is "+str(self.r_frequency/1000000.0)+" MHz", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting frequency is {self.r_frequency / 1000000.0} MHz", RNS.LOG_DEBUG)
|
||||||
self.updateBitrate()
|
self.updateBitrate()
|
||||||
|
|
||||||
elif (command == KISS.CMD_BANDWIDTH):
|
elif (command == KISS.CMD_BANDWIDTH):
|
||||||
@ -1058,26 +1058,26 @@ class RNodeInterface(Interface):
|
|||||||
command_buffer = command_buffer+bytes([byte])
|
command_buffer = command_buffer+bytes([byte])
|
||||||
if (len(command_buffer) == 4):
|
if (len(command_buffer) == 4):
|
||||||
self.r_bandwidth = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
self.r_bandwidth = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
||||||
RNS.log(str(self)+" Radio reporting bandwidth is "+str(self.r_bandwidth/1000.0)+" KHz", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting bandwidth is {self.r_bandwidth / 1000.0} KHz", RNS.LOG_DEBUG)
|
||||||
self.updateBitrate()
|
self.updateBitrate()
|
||||||
|
|
||||||
elif (command == KISS.CMD_TXPOWER):
|
elif (command == KISS.CMD_TXPOWER):
|
||||||
self.r_txpower = byte
|
self.r_txpower = byte
|
||||||
RNS.log(str(self)+" Radio reporting TX power is "+str(self.r_txpower)+" dBm", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting TX power is {self.r_txpower} dBm", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_SF):
|
elif (command == KISS.CMD_SF):
|
||||||
self.r_sf = byte
|
self.r_sf = byte
|
||||||
RNS.log(str(self)+" Radio reporting spreading factor is "+str(self.r_sf), RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting spreading factor is {self.r_sf}", RNS.LOG_DEBUG)
|
||||||
self.updateBitrate()
|
self.updateBitrate()
|
||||||
elif (command == KISS.CMD_CR):
|
elif (command == KISS.CMD_CR):
|
||||||
self.r_cr = byte
|
self.r_cr = byte
|
||||||
RNS.log(str(self)+" Radio reporting coding rate is "+str(self.r_cr), RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting coding rate is {self.r_cr}", RNS.LOG_DEBUG)
|
||||||
self.updateBitrate()
|
self.updateBitrate()
|
||||||
elif (command == KISS.CMD_RADIO_STATE):
|
elif (command == KISS.CMD_RADIO_STATE):
|
||||||
self.r_state = byte
|
self.r_state = byte
|
||||||
if self.r_state:
|
if self.r_state:
|
||||||
RNS.log(str(self)+" Radio reporting state is online", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting state is online", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self)+" Radio reporting state is offline", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting state is offline", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
elif (command == KISS.CMD_RADIO_LOCK):
|
elif (command == KISS.CMD_RADIO_LOCK):
|
||||||
self.r_lock = byte
|
self.r_lock = byte
|
||||||
@ -1156,7 +1156,7 @@ class RNodeInterface(Interface):
|
|||||||
if (len(command_buffer) == 2):
|
if (len(command_buffer) == 2):
|
||||||
at = command_buffer[0] << 8 | command_buffer[1]
|
at = command_buffer[0] << 8 | command_buffer[1]
|
||||||
self.r_st_alock = at/100.0
|
self.r_st_alock = at/100.0
|
||||||
RNS.log(str(self)+" Radio reporting short-term airtime limit is "+str(self.r_st_alock)+"%", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting short-term airtime limit is {self.r_st_alock}%", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_LT_ALOCK):
|
elif (command == KISS.CMD_LT_ALOCK):
|
||||||
if (byte == KISS.FESC):
|
if (byte == KISS.FESC):
|
||||||
escape = True
|
escape = True
|
||||||
@ -1171,7 +1171,7 @@ class RNodeInterface(Interface):
|
|||||||
if (len(command_buffer) == 2):
|
if (len(command_buffer) == 2):
|
||||||
at = command_buffer[0] << 8 | command_buffer[1]
|
at = command_buffer[0] << 8 | command_buffer[1]
|
||||||
self.r_lt_alock = at/100.0
|
self.r_lt_alock = at/100.0
|
||||||
RNS.log(str(self)+" Radio reporting long-term airtime limit is "+str(self.r_lt_alock)+"%", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting long-term airtime limit is {self.r_lt_alock}%", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_STAT_CHTM):
|
elif (command == KISS.CMD_STAT_CHTM):
|
||||||
if (byte == KISS.FESC):
|
if (byte == KISS.FESC):
|
||||||
escape = True
|
escape = True
|
||||||
@ -1217,9 +1217,9 @@ class RNodeInterface(Interface):
|
|||||||
self.r_preamble_symbols = prs
|
self.r_preamble_symbols = prs
|
||||||
self.r_premable_time_ms = prt
|
self.r_premable_time_ms = prt
|
||||||
self.r_csma_slot_time_ms = cst
|
self.r_csma_slot_time_ms = cst
|
||||||
RNS.log(str(self)+" Radio reporting symbol time is "+str(round(self.r_symbol_time_ms,2))+"ms (at "+str(self.r_symbol_rate)+" baud)", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting symbol time is {round(self.r_symbol_time_ms, 2)}ms (at {self.r_symbol_rate} baud)", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self)+" Radio reporting preamble is "+str(self.r_preamble_symbols)+" symbols ("+str(self.r_premable_time_ms)+"ms)", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting preamble is {self.r_preamble_symbols} symbols ({self.r_premable_time_ms}ms)", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self)+" Radio reporting CSMA slot time is "+str(self.r_csma_slot_time_ms)+"ms", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting CSMA slot time is {self.r_csma_slot_time_ms}ms", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_STAT_BAT):
|
elif (command == KISS.CMD_STAT_BAT):
|
||||||
if (byte == KISS.FESC):
|
if (byte == KISS.FESC):
|
||||||
escape = True
|
escape = True
|
||||||
@ -1247,26 +1247,26 @@ class RNodeInterface(Interface):
|
|||||||
self.mcu = byte
|
self.mcu = byte
|
||||||
elif (command == KISS.CMD_ERROR):
|
elif (command == KISS.CMD_ERROR):
|
||||||
if (byte == KISS.ERROR_INITRADIO):
|
if (byte == KISS.ERROR_INITRADIO):
|
||||||
RNS.log(str(self)+" hardware initialisation error (code "+RNS.hexrep(byte)+")", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware initialisation error (code {RNS.hexrep(byte)})", RNS.LOG_ERROR)
|
||||||
raise IOError("Radio initialisation failure")
|
raise OSError("Radio initialisation failure")
|
||||||
elif (byte == KISS.ERROR_TXFAILED):
|
elif (byte == KISS.ERROR_TXFAILED):
|
||||||
RNS.log(str(self)+" hardware TX error (code "+RNS.hexrep(byte)+")", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware TX error (code {RNS.hexrep(byte)})", RNS.LOG_ERROR)
|
||||||
raise IOError("Hardware transmit failure")
|
raise OSError("Hardware transmit failure")
|
||||||
elif (byte == KISS.ERROR_MEMORY_LOW):
|
elif (byte == KISS.ERROR_MEMORY_LOW):
|
||||||
RNS.log(str(self)+" hardware error (code "+RNS.hexrep(byte)+"): Memory exhausted", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware error (code {RNS.hexrep(byte)}): Memory exhausted", RNS.LOG_ERROR)
|
||||||
self.hw_errors.append({"error": KISS.ERROR_MEMORY_LOW, "description": "Memory exhausted on connected device"})
|
self.hw_errors.append({"error": KISS.ERROR_MEMORY_LOW, "description": "Memory exhausted on connected device"})
|
||||||
elif (byte == KISS.ERROR_MODEM_TIMEOUT):
|
elif (byte == KISS.ERROR_MODEM_TIMEOUT):
|
||||||
RNS.log(str(self)+" hardware error (code "+RNS.hexrep(byte)+"): Modem communication timed out", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware error (code {RNS.hexrep(byte)}): Modem communication timed out", RNS.LOG_ERROR)
|
||||||
self.hw_errors.append({"error": KISS.ERROR_MODEM_TIMEOUT, "description": "Modem communication timed out on connected device"})
|
self.hw_errors.append({"error": KISS.ERROR_MODEM_TIMEOUT, "description": "Modem communication timed out on connected device"})
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self)+" hardware error (code "+RNS.hexrep(byte)+")", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware error (code {RNS.hexrep(byte)})", RNS.LOG_ERROR)
|
||||||
raise IOError("Unknown hardware failure")
|
raise OSError("Unknown hardware failure")
|
||||||
elif (command == KISS.CMD_RESET):
|
elif (command == KISS.CMD_RESET):
|
||||||
if (byte == 0xF8):
|
if (byte == 0xF8):
|
||||||
if self.platform == KISS.PLATFORM_ESP32:
|
if self.platform == KISS.PLATFORM_ESP32:
|
||||||
if self.online:
|
if self.online:
|
||||||
RNS.log("Detected reset while device was online, reinitialising device...", RNS.LOG_ERROR)
|
RNS.log("Detected reset while device was online, reinitialising device...", RNS.LOG_ERROR)
|
||||||
raise IOError("ESP32 reset")
|
raise OSError("ESP32 reset")
|
||||||
elif (command == KISS.CMD_READY):
|
elif (command == KISS.CMD_READY):
|
||||||
self.process_queue()
|
self.process_queue()
|
||||||
elif (command == KISS.CMD_DETECT):
|
elif (command == KISS.CMD_DETECT):
|
||||||
@ -1278,7 +1278,7 @@ class RNodeInterface(Interface):
|
|||||||
if got == 0:
|
if got == 0:
|
||||||
time_since_last = int(time.time()*1000) - last_read_ms
|
time_since_last = int(time.time()*1000) - last_read_ms
|
||||||
if len(data_buffer) > 0 and time_since_last > self.timeout:
|
if len(data_buffer) > 0 and time_since_last > self.timeout:
|
||||||
RNS.log(str(self)+" serial read timeout in command "+str(command), RNS.LOG_WARNING)
|
RNS.log(f"{self} serial read timeout in command {command}", RNS.LOG_WARNING)
|
||||||
data_buffer = b""
|
data_buffer = b""
|
||||||
in_frame = False
|
in_frame = False
|
||||||
command = KISS.CMD_UNKNOWN
|
command = KISS.CMD_UNKNOWN
|
||||||
@ -1287,22 +1287,22 @@ class RNodeInterface(Interface):
|
|||||||
if self.id_interval != None and self.id_callsign != None:
|
if self.id_interval != None and self.id_callsign != None:
|
||||||
if self.first_tx != None:
|
if self.first_tx != None:
|
||||||
if time.time() > self.first_tx + self.id_interval:
|
if time.time() > self.first_tx + self.id_interval:
|
||||||
RNS.log("Interface "+str(self)+" is transmitting beacon data: "+str(self.id_callsign.decode("utf-8")), RNS.LOG_DEBUG)
|
RNS.log(f"Interface {self} is transmitting beacon data: {self.id_callsign.decode('utf-8')}", RNS.LOG_DEBUG)
|
||||||
self.processOutgoing(self.id_callsign)
|
self.processOutgoing(self.id_callsign)
|
||||||
|
|
||||||
if (time.time() - self.last_port_io > self.port_io_timeout):
|
if (time.time() - self.last_port_io > self.port_io_timeout):
|
||||||
self.detect()
|
self.detect()
|
||||||
|
|
||||||
if (time.time() - self.last_port_io > self.port_io_timeout*3):
|
if (time.time() - self.last_port_io > self.port_io_timeout*3):
|
||||||
raise IOError("Connected port for "+str(self)+" became unresponsive")
|
raise OSError(f"Connected port for {self} became unresponsive")
|
||||||
|
|
||||||
if self.bt_manager != None:
|
if self.bt_manager != None:
|
||||||
sleep(0.08)
|
sleep(0.08)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("A serial port occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"A serial port occurred, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
RNS.log(f"The interface {self} experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if RNS.Reticulum.panic_on_interface_error:
|
if RNS.Reticulum.panic_on_interface_error:
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
@ -1330,10 +1330,10 @@ class RNodeInterface(Interface):
|
|||||||
try:
|
try:
|
||||||
time.sleep(self.reconnect_w)
|
time.sleep(self.reconnect_w)
|
||||||
if self.serial != None and self.port != None:
|
if self.serial != None and self.port != None:
|
||||||
RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_EXTREME)
|
RNS.log(f"Attempting to reconnect serial port {self.port} for {self}...", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
if self.bt_manager != None:
|
if self.bt_manager != None:
|
||||||
RNS.log("Attempting to reconnect Bluetooth device for "+str(self)+"...", RNS.LOG_EXTREME)
|
RNS.log(f"Attempting to reconnect Bluetooth device for {self}...", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
self.open_port()
|
self.open_port()
|
||||||
|
|
||||||
@ -1352,10 +1352,10 @@ class RNodeInterface(Interface):
|
|||||||
self.enable_external_framebuffer()
|
self.enable_external_framebuffer()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while reconnecting RNode, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while reconnecting RNode, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if self.online:
|
if self.online:
|
||||||
RNS.log("Reconnected serial port for "+str(self))
|
RNS.log(f"Reconnected serial port for {self}")
|
||||||
|
|
||||||
def detach(self):
|
def detach(self):
|
||||||
self.detached = True
|
self.detached = True
|
||||||
@ -1399,7 +1399,7 @@ class RNodeInterface(Interface):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "RNodeInterface["+str(self.name)+"]"
|
return f"RNodeInterface[{self.name}]"
|
||||||
|
|
||||||
class BLEConnection(BluetoothDispatcher):
|
class BLEConnection(BluetoothDispatcher):
|
||||||
UART_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
|
UART_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
|
||||||
@ -1472,7 +1472,7 @@ class BLEConnection(BluetoothDispatcher):
|
|||||||
RNS.trace_exception(e)
|
RNS.trace_exception(e)
|
||||||
|
|
||||||
def __init__(self, owner=None, target_name=None, target_bt_addr=None):
|
def __init__(self, owner=None, target_name=None, target_bt_addr=None):
|
||||||
super(BLEConnection, self).__init__()
|
super().__init__()
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
self.target_name = target_name
|
self.target_name = target_name
|
||||||
self.target_bt_addr = target_bt_addr
|
self.target_bt_addr = target_bt_addr
|
||||||
|
@ -98,17 +98,17 @@ class SerialInterface(Interface):
|
|||||||
try:
|
try:
|
||||||
self.open_port()
|
self.open_port()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not open serial port for interface "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Could not open serial port for interface {self}", RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not open serial port")
|
raise OSError("Could not open serial port")
|
||||||
|
|
||||||
|
|
||||||
def open_port(self):
|
def open_port(self):
|
||||||
RNS.log("Opening serial port "+self.port+"...")
|
RNS.log(f"Opening serial port {self.port}...")
|
||||||
# Get device parameters
|
# Get device parameters
|
||||||
from usb4a import usb
|
from usb4a import usb
|
||||||
device = usb.get_usb_device(self.port)
|
device = usb.get_usb_device(self.port)
|
||||||
@ -120,7 +120,7 @@ class SerialInterface(Interface):
|
|||||||
proxy = self.pyserial.get_serial_port
|
proxy = self.pyserial.get_serial_port
|
||||||
if vid == 0x1A86 and pid == 0x55D4:
|
if vid == 0x1A86 and pid == 0x55D4:
|
||||||
# Force CDC driver for Qinheng CH34x
|
# Force CDC driver for Qinheng CH34x
|
||||||
RNS.log(str(self)+" using CDC driver for "+RNS.hexrep(vid)+":"+RNS.hexrep(pid), RNS.LOG_DEBUG)
|
RNS.log(f"{self} using CDC driver for {RNS.hexrep(vid)}:{RNS.hexrep(pid)}", RNS.LOG_DEBUG)
|
||||||
from usbserial4a.cdcacmserial4a import CdcAcmSerial
|
from usbserial4a.cdcacmserial4a import CdcAcmSerial
|
||||||
proxy = CdcAcmSerial
|
proxy = CdcAcmSerial
|
||||||
|
|
||||||
@ -159,9 +159,9 @@ class SerialInterface(Interface):
|
|||||||
self.serial.USB_READ_TIMEOUT_MILLIS = 100
|
self.serial.USB_READ_TIMEOUT_MILLIS = 100
|
||||||
self.serial.timeout = 0.1
|
self.serial.timeout = 0.1
|
||||||
|
|
||||||
RNS.log(str(self)+" USB read buffer size set to "+RNS.prettysize(self.serial.DEFAULT_READ_BUFFER_SIZE), RNS.LOG_DEBUG)
|
RNS.log(f"{self} USB read buffer size set to {RNS.prettysize(self.serial.DEFAULT_READ_BUFFER_SIZE)}", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self)+" USB read timeout set to "+str(self.serial.USB_READ_TIMEOUT_MILLIS)+"ms", RNS.LOG_DEBUG)
|
RNS.log(f"{self} USB read timeout set to {self.serial.USB_READ_TIMEOUT_MILLIS}ms", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self)+" USB write timeout set to "+str(self.serial.USB_WRITE_TIMEOUT_MILLIS)+"ms", RNS.LOG_DEBUG)
|
RNS.log(f"{self} USB write timeout set to {self.serial.USB_WRITE_TIMEOUT_MILLIS}ms", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
def configure_device(self):
|
def configure_device(self):
|
||||||
sleep(0.5)
|
sleep(0.5)
|
||||||
@ -169,7 +169,7 @@ class SerialInterface(Interface):
|
|||||||
thread.daemon = True
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
self.online = True
|
self.online = True
|
||||||
RNS.log("Serial port "+self.port+" is now open", RNS.LOG_VERBOSE)
|
RNS.log(f"Serial port {self.port} is now open", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
@ -184,7 +184,7 @@ class SerialInterface(Interface):
|
|||||||
written = self.serial.write(data)
|
written = self.serial.write(data)
|
||||||
self.txb += len(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 OSError(f"Serial interface only wrote {written} bytes of {len(data)}")
|
||||||
|
|
||||||
def readLoop(self):
|
def readLoop(self):
|
||||||
try:
|
try:
|
||||||
@ -228,8 +228,8 @@ class SerialInterface(Interface):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"A serial port error occurred, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
RNS.log(f"The interface {self} experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if RNS.Reticulum.panic_on_interface_error:
|
if RNS.Reticulum.panic_on_interface_error:
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
@ -244,17 +244,17 @@ class SerialInterface(Interface):
|
|||||||
while not self.online:
|
while not self.online:
|
||||||
try:
|
try:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Attempting to reconnect serial port {self.port} for {self}...", RNS.LOG_VERBOSE)
|
||||||
self.open_port()
|
self.open_port()
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while reconnecting port, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
RNS.log("Reconnected serial port for "+str(self))
|
RNS.log(f"Reconnected serial port for {self}")
|
||||||
|
|
||||||
def should_ingress_limit(self):
|
def should_ingress_limit(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "SerialInterface["+self.name+"]"
|
return f"SerialInterface[{self.name}]"
|
||||||
|
@ -23,5 +23,5 @@
|
|||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
|
|
||||||
modules = glob.glob(os.path.dirname(__file__)+"/*.py")
|
modules = glob.glob(f"{os.path.dirname(__file__)}/*.py")
|
||||||
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
@ -35,7 +35,7 @@ import RNS
|
|||||||
class AutoInterface(Interface):
|
class AutoInterface(Interface):
|
||||||
DEFAULT_DISCOVERY_PORT = 29716
|
DEFAULT_DISCOVERY_PORT = 29716
|
||||||
DEFAULT_DATA_PORT = 42671
|
DEFAULT_DATA_PORT = 42671
|
||||||
DEFAULT_GROUP_ID = "reticulum".encode("utf-8")
|
DEFAULT_GROUP_ID = b"reticulum"
|
||||||
|
|
||||||
SCOPE_LINK = "2"
|
SCOPE_LINK = "2"
|
||||||
SCOPE_ADMIN = "4"
|
SCOPE_ADMIN = "4"
|
||||||
@ -169,32 +169,32 @@ class AutoInterface(Interface):
|
|||||||
|
|
||||||
self.group_hash = RNS.Identity.full_hash(self.group_id)
|
self.group_hash = RNS.Identity.full_hash(self.group_id)
|
||||||
g = self.group_hash
|
g = self.group_hash
|
||||||
#gt = "{:02x}".format(g[1]+(g[0]<<8))
|
#gt = f"{g[1] + (g[0] << 8):02x}"
|
||||||
gt = "0"
|
gt = "0"
|
||||||
gt += ":"+"{:02x}".format(g[3]+(g[2]<<8))
|
gt += f":{g[3] + (g[2] << 8):02x}"
|
||||||
gt += ":"+"{:02x}".format(g[5]+(g[4]<<8))
|
gt += f":{g[5] + (g[4] << 8):02x}"
|
||||||
gt += ":"+"{:02x}".format(g[7]+(g[6]<<8))
|
gt += f":{g[7] + (g[6] << 8):02x}"
|
||||||
gt += ":"+"{:02x}".format(g[9]+(g[8]<<8))
|
gt += f":{g[9] + (g[8] << 8):02x}"
|
||||||
gt += ":"+"{:02x}".format(g[11]+(g[10]<<8))
|
gt += f":{g[11] + (g[10] << 8):02x}"
|
||||||
gt += ":"+"{:02x}".format(g[13]+(g[12]<<8))
|
gt += f":{g[13] + (g[12] << 8):02x}"
|
||||||
self.mcast_discovery_address = "ff"+self.multicast_address_type+self.discovery_scope+":"+gt
|
self.mcast_discovery_address = f"ff{self.multicast_address_type}{self.discovery_scope}:{gt}"
|
||||||
|
|
||||||
suitable_interfaces = 0
|
suitable_interfaces = 0
|
||||||
for ifname in self.list_interfaces():
|
for ifname in self.list_interfaces():
|
||||||
try:
|
try:
|
||||||
if RNS.vendor.platformutils.is_darwin() and ifname in AutoInterface.DARWIN_IGNORE_IFS and not ifname in self.allowed_interfaces:
|
if RNS.vendor.platformutils.is_darwin() and ifname in AutoInterface.DARWIN_IGNORE_IFS and not ifname in self.allowed_interfaces:
|
||||||
RNS.log(str(self)+" skipping Darwin AWDL or tethering interface "+str(ifname), RNS.LOG_EXTREME)
|
RNS.log(f"{self} skipping Darwin AWDL or tethering interface {ifname}", RNS.LOG_EXTREME)
|
||||||
elif RNS.vendor.platformutils.is_darwin() and ifname == "lo0":
|
elif RNS.vendor.platformutils.is_darwin() and ifname == "lo0":
|
||||||
RNS.log(str(self)+" skipping Darwin loopback interface "+str(ifname), RNS.LOG_EXTREME)
|
RNS.log(f"{self} skipping Darwin loopback interface {ifname}", RNS.LOG_EXTREME)
|
||||||
elif RNS.vendor.platformutils.is_android() and ifname in AutoInterface.ANDROID_IGNORE_IFS and not ifname in self.allowed_interfaces:
|
elif RNS.vendor.platformutils.is_android() and ifname in AutoInterface.ANDROID_IGNORE_IFS and not ifname in self.allowed_interfaces:
|
||||||
RNS.log(str(self)+" skipping Android system interface "+str(ifname), RNS.LOG_EXTREME)
|
RNS.log(f"{self} skipping Android system interface {ifname}", RNS.LOG_EXTREME)
|
||||||
elif ifname in self.ignored_interfaces:
|
elif ifname in self.ignored_interfaces:
|
||||||
RNS.log(str(self)+" ignoring disallowed interface "+str(ifname), RNS.LOG_EXTREME)
|
RNS.log(f"{self} ignoring disallowed interface {ifname}", RNS.LOG_EXTREME)
|
||||||
elif ifname in AutoInterface.ALL_IGNORE_IFS:
|
elif ifname in AutoInterface.ALL_IGNORE_IFS:
|
||||||
RNS.log(str(self)+" skipping interface "+str(ifname), RNS.LOG_EXTREME)
|
RNS.log(f"{self} skipping interface {ifname}", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
if len(self.allowed_interfaces) > 0 and not ifname in self.allowed_interfaces:
|
if len(self.allowed_interfaces) > 0 and not ifname in self.allowed_interfaces:
|
||||||
RNS.log(str(self)+" ignoring interface "+str(ifname)+" since it was not allowed", RNS.LOG_EXTREME)
|
RNS.log(f"{self} ignoring interface {ifname} since it was not allowed", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
addresses = self.list_addresses(ifname)
|
addresses = self.list_addresses(ifname)
|
||||||
if self.netinfo.AF_INET6 in addresses:
|
if self.netinfo.AF_INET6 in addresses:
|
||||||
@ -213,10 +213,10 @@ class AutoInterface(Interface):
|
|||||||
RNS.log(f"{self} Selecting link-local address {link_local_addr} for interface {ifname}", RNS.LOG_EXTREME)
|
RNS.log(f"{self} Selecting link-local address {link_local_addr} for interface {ifname}", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
if link_local_addr == None:
|
if link_local_addr == None:
|
||||||
RNS.log(str(self)+" No link-local IPv6 address configured for "+str(ifname)+", skipping interface", RNS.LOG_EXTREME)
|
RNS.log(f"{self} No link-local IPv6 address configured for {ifname}, skipping interface", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
mcast_addr = self.mcast_discovery_address
|
mcast_addr = self.mcast_discovery_address
|
||||||
RNS.log(str(self)+" Creating multicast discovery listener on "+str(ifname)+" with address "+str(mcast_addr), RNS.LOG_EXTREME)
|
RNS.log(f"{self} Creating multicast discovery listener on {ifname} with address {mcast_addr}", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
# Struct with interface index
|
# Struct with interface index
|
||||||
if_struct = struct.pack("I", self.interface_name_to_index(ifname))
|
if_struct = struct.pack("I", self.interface_name_to_index(ifname))
|
||||||
@ -243,7 +243,7 @@ class AutoInterface(Interface):
|
|||||||
else:
|
else:
|
||||||
|
|
||||||
if self.discovery_scope == AutoInterface.SCOPE_LINK:
|
if self.discovery_scope == AutoInterface.SCOPE_LINK:
|
||||||
addr_info = socket.getaddrinfo(mcast_addr+"%"+ifname, self.discovery_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
addr_info = socket.getaddrinfo(f"{mcast_addr}%{ifname}", self.discovery_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
else:
|
else:
|
||||||
addr_info = socket.getaddrinfo(mcast_addr, self.discovery_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
addr_info = socket.getaddrinfo(mcast_addr, self.discovery_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ class AutoInterface(Interface):
|
|||||||
RNS.log(f"Could not configure the system interface {ifname} for use with {self}, skipping it. The contained exception was: {e}", RNS.LOG_ERROR)
|
RNS.log(f"Could not configure the system interface {ifname} for use with {self}, skipping it. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if suitable_interfaces == 0:
|
if suitable_interfaces == 0:
|
||||||
RNS.log(str(self)+" could not autoconfigure. This interface currently provides no connectivity.", RNS.LOG_WARNING)
|
RNS.log(f"{self} could not autoconfigure. This interface currently provides no connectivity.", RNS.LOG_WARNING)
|
||||||
else:
|
else:
|
||||||
self.receives = True
|
self.receives = True
|
||||||
|
|
||||||
@ -277,13 +277,13 @@ class AutoInterface(Interface):
|
|||||||
self.bitrate = AutoInterface.BITRATE_GUESS
|
self.bitrate = AutoInterface.BITRATE_GUESS
|
||||||
|
|
||||||
peering_wait = self.announce_interval*1.2
|
peering_wait = self.announce_interval*1.2
|
||||||
RNS.log(str(self)+" discovering peers for "+str(round(peering_wait, 2))+" seconds...", RNS.LOG_VERBOSE)
|
RNS.log(f"{self} discovering peers for {round(peering_wait, 2)} seconds...", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
socketserver.UDPServer.address_family = socket.AF_INET6
|
socketserver.UDPServer.address_family = socket.AF_INET6
|
||||||
|
|
||||||
for ifname in self.adopted_interfaces:
|
for ifname in self.adopted_interfaces:
|
||||||
local_addr = self.adopted_interfaces[ifname]+"%"+str(self.interface_name_to_index(ifname))
|
local_addr = f"{self.adopted_interfaces[ifname]}%{self.interface_name_to_index(ifname)}"
|
||||||
addr_info = socket.getaddrinfo(local_addr, self.data_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
addr_info = socket.getaddrinfo(local_addr, self.data_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
address = addr_info[0][4]
|
address = addr_info[0][4]
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ class AutoInterface(Interface):
|
|||||||
if data == expected_hash:
|
if data == expected_hash:
|
||||||
self.add_peer(ipv6_src[0], ifname)
|
self.add_peer(ipv6_src[0], ifname)
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self)+" received peering packet on "+str(ifname)+" from "+str(ipv6_src[0])+", but authentication hash was incorrect.", RNS.LOG_DEBUG)
|
RNS.log(f"{self} received peering packet on {ifname} from {ipv6_src[0]}, but authentication hash was incorrect.", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
def peer_jobs(self):
|
def peer_jobs(self):
|
||||||
while True:
|
while True:
|
||||||
@ -335,7 +335,7 @@ class AutoInterface(Interface):
|
|||||||
# Remove any timed out peers
|
# Remove any timed out peers
|
||||||
for peer_addr in timed_out_peers:
|
for peer_addr in timed_out_peers:
|
||||||
removed_peer = self.peers.pop(peer_addr)
|
removed_peer = self.peers.pop(peer_addr)
|
||||||
RNS.log(str(self)+" removed peer "+str(peer_addr)+" on "+str(removed_peer[0]), RNS.LOG_DEBUG)
|
RNS.log(f"{self} removed peer {peer_addr} on {removed_peer[0]}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
for ifname in self.adopted_interfaces:
|
for ifname in self.adopted_interfaces:
|
||||||
# Check that the link-local address has not changed
|
# Check that the link-local address has not changed
|
||||||
@ -349,25 +349,25 @@ class AutoInterface(Interface):
|
|||||||
link_local_addr = self.descope_linklocal(address["addr"])
|
link_local_addr = self.descope_linklocal(address["addr"])
|
||||||
if link_local_addr != self.adopted_interfaces[ifname]:
|
if link_local_addr != self.adopted_interfaces[ifname]:
|
||||||
old_link_local_address = self.adopted_interfaces[ifname]
|
old_link_local_address = self.adopted_interfaces[ifname]
|
||||||
RNS.log("Replacing link-local address "+str(old_link_local_address)+" for "+str(ifname)+" with "+str(link_local_addr), RNS.LOG_DEBUG)
|
RNS.log(f"Replacing link-local address {old_link_local_address} for {ifname} with {link_local_addr}", RNS.LOG_DEBUG)
|
||||||
self.adopted_interfaces[ifname] = link_local_addr
|
self.adopted_interfaces[ifname] = link_local_addr
|
||||||
self.link_local_addresses.append(link_local_addr)
|
self.link_local_addresses.append(link_local_addr)
|
||||||
|
|
||||||
if old_link_local_address in self.link_local_addresses:
|
if old_link_local_address in self.link_local_addresses:
|
||||||
self.link_local_addresses.remove(old_link_local_address)
|
self.link_local_addresses.remove(old_link_local_address)
|
||||||
|
|
||||||
local_addr = link_local_addr+"%"+ifname
|
local_addr = f"{link_local_addr}%{ifname}"
|
||||||
addr_info = socket.getaddrinfo(local_addr, self.data_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
addr_info = socket.getaddrinfo(local_addr, self.data_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
listen_address = addr_info[0][4]
|
listen_address = addr_info[0][4]
|
||||||
|
|
||||||
if ifname in self.interface_servers:
|
if ifname in self.interface_servers:
|
||||||
RNS.log("Shutting down previous UDP listener for "+str(self)+" "+str(ifname), RNS.LOG_DEBUG)
|
RNS.log(f"Shutting down previous UDP listener for {self} {ifname}", RNS.LOG_DEBUG)
|
||||||
previous_server = self.interface_servers[ifname]
|
previous_server = self.interface_servers[ifname]
|
||||||
def shutdown_server():
|
def shutdown_server():
|
||||||
previous_server.shutdown()
|
previous_server.shutdown()
|
||||||
threading.Thread(target=shutdown_server, daemon=True).start()
|
threading.Thread(target=shutdown_server, daemon=True).start()
|
||||||
|
|
||||||
RNS.log("Starting new UDP listener for "+str(self)+" "+str(ifname), RNS.LOG_DEBUG)
|
RNS.log(f"Starting new UDP listener for {self} {ifname}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
udp_server = socketserver.UDPServer(listen_address, self.handler_factory(self.processIncoming))
|
udp_server = socketserver.UDPServer(listen_address, self.handler_factory(self.processIncoming))
|
||||||
self.interface_servers[ifname] = udp_server
|
self.interface_servers[ifname] = udp_server
|
||||||
@ -379,7 +379,7 @@ class AutoInterface(Interface):
|
|||||||
self.carrier_changed = True
|
self.carrier_changed = True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not get device information while updating link-local addresses for "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Could not get device information while updating link-local addresses for {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
# Check multicast echo timeouts
|
# Check multicast echo timeouts
|
||||||
last_multicast_echo = 0
|
last_multicast_echo = 0
|
||||||
@ -389,12 +389,12 @@ class AutoInterface(Interface):
|
|||||||
if now - last_multicast_echo > self.multicast_echo_timeout:
|
if now - last_multicast_echo > self.multicast_echo_timeout:
|
||||||
if ifname in self.timed_out_interfaces and self.timed_out_interfaces[ifname] == False:
|
if ifname in self.timed_out_interfaces and self.timed_out_interfaces[ifname] == False:
|
||||||
self.carrier_changed = True
|
self.carrier_changed = True
|
||||||
RNS.log("Multicast echo timeout for "+str(ifname)+". Carrier lost.", RNS.LOG_WARNING)
|
RNS.log(f"Multicast echo timeout for {ifname}. Carrier lost.", RNS.LOG_WARNING)
|
||||||
self.timed_out_interfaces[ifname] = True
|
self.timed_out_interfaces[ifname] = True
|
||||||
else:
|
else:
|
||||||
if ifname in self.timed_out_interfaces and self.timed_out_interfaces[ifname] == True:
|
if ifname in self.timed_out_interfaces and self.timed_out_interfaces[ifname] == True:
|
||||||
self.carrier_changed = True
|
self.carrier_changed = True
|
||||||
RNS.log(str(self)+" Carrier recovered on "+str(ifname), RNS.LOG_WARNING)
|
RNS.log(f"{self} Carrier recovered on {ifname}", RNS.LOG_WARNING)
|
||||||
self.timed_out_interfaces[ifname] = False
|
self.timed_out_interfaces[ifname] = False
|
||||||
|
|
||||||
|
|
||||||
@ -417,7 +417,7 @@ class AutoInterface(Interface):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if (ifname in self.timed_out_interfaces and self.timed_out_interfaces[ifname] == False) or not ifname in self.timed_out_interfaces:
|
if (ifname in self.timed_out_interfaces and self.timed_out_interfaces[ifname] == False) or not ifname in self.timed_out_interfaces:
|
||||||
RNS.log(str(self)+" Detected possible carrier loss on "+str(ifname)+": "+str(e), RNS.LOG_WARNING)
|
RNS.log(f"{self} Detected possible carrier loss on {ifname}: {e}", RNS.LOG_WARNING)
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -431,12 +431,12 @@ class AutoInterface(Interface):
|
|||||||
if ifname != None:
|
if ifname != None:
|
||||||
self.multicast_echoes[ifname] = time.time()
|
self.multicast_echoes[ifname] = time.time()
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self)+" received multicast echo on unexpected interface "+str(ifname), RNS.LOG_WARNING)
|
RNS.log(f"{self} received multicast echo on unexpected interface {ifname}", RNS.LOG_WARNING)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if not addr in self.peers:
|
if not addr in self.peers:
|
||||||
self.peers[addr] = [ifname, time.time()]
|
self.peers[addr] = [ifname, time.time()]
|
||||||
RNS.log(str(self)+" added peer "+str(addr)+" on "+str(ifname), RNS.LOG_DEBUG)
|
RNS.log(f"{self} added peer {addr} on {ifname}", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
self.refresh_peer(addr)
|
self.refresh_peer(addr)
|
||||||
|
|
||||||
@ -464,12 +464,12 @@ class AutoInterface(Interface):
|
|||||||
if self.outbound_udp_socket == None:
|
if self.outbound_udp_socket == None:
|
||||||
self.outbound_udp_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
self.outbound_udp_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
|
|
||||||
peer_addr = str(peer)+"%"+str(self.interface_name_to_index(self.peers[peer][0]))
|
peer_addr = f"{peer}%{self.interface_name_to_index(self.peers[peer][0])}"
|
||||||
addr_info = socket.getaddrinfo(peer_addr, self.data_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
addr_info = socket.getaddrinfo(peer_addr, self.data_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
self.outbound_udp_socket.sendto(data, addr_info[0][4])
|
self.outbound_udp_socket.sendto(data, addr_info[0][4])
|
||||||
|
|
||||||
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(f"Could not transmit on {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
|
||||||
self.txb += len(data)
|
self.txb += len(data)
|
||||||
@ -481,7 +481,7 @@ class AutoInterface(Interface):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "AutoInterface["+self.name+"]"
|
return f"AutoInterface[{self.name}]"
|
||||||
|
|
||||||
class AutoInterfaceHandler(socketserver.BaseRequestHandler):
|
class AutoInterfaceHandler(socketserver.BaseRequestHandler):
|
||||||
def __init__(self, callback, *args, **keys):
|
def __init__(self, callback, *args, **keys):
|
||||||
|
@ -90,7 +90,7 @@ class I2PController:
|
|||||||
|
|
||||||
time.sleep(0.10)
|
time.sleep(0.10)
|
||||||
if self.loop == None:
|
if self.loop == None:
|
||||||
RNS.log("Could not get event loop for "+str(self)+", waiting for event loop to appear", RNS.LOG_VERBOSE)
|
RNS.log(f"Could not get event loop for {self}, waiting for event loop to appear", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
while self.loop == None:
|
while self.loop == None:
|
||||||
self.loop = asyncio.get_event_loop()
|
self.loop = asyncio.get_event_loop()
|
||||||
@ -101,7 +101,7 @@ class I2PController:
|
|||||||
self.loop.run_forever()
|
self.loop.run_forever()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.ready = False
|
self.ready = False
|
||||||
RNS.log("Exception on event loop for "+str(self)+": "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Exception on event loop for {self}: {e}", RNS.LOG_ERROR)
|
||||||
finally:
|
finally:
|
||||||
self.loop.close()
|
self.loop.close()
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ class I2PController:
|
|||||||
if not self.client_tunnels[i2p_destination]:
|
if not self.client_tunnels[i2p_destination]:
|
||||||
try:
|
try:
|
||||||
async def tunnel_up():
|
async def tunnel_up():
|
||||||
RNS.log("Bringing up I2P tunnel to "+str(owner)+", this may take a while...", RNS.LOG_INFO)
|
RNS.log(f"Bringing up I2P tunnel to {owner}, this may take a while...", RNS.LOG_INFO)
|
||||||
tunnel = self.i2plib.ClientTunnel(i2p_destination, owner.local_addr, sam_address=self.sam_address, loop=self.loop)
|
tunnel = self.i2plib.ClientTunnel(i2p_destination, owner.local_addr, sam_address=self.sam_address, loop=self.loop)
|
||||||
self.i2plib_tunnels[i2p_destination] = tunnel
|
self.i2plib_tunnels[i2p_destination] = tunnel
|
||||||
await tunnel.run()
|
await tunnel.run()
|
||||||
@ -145,7 +145,7 @@ class I2PController:
|
|||||||
result = asyncio.run_coroutine_threadsafe(tunnel_up(), self.loop).result()
|
result = asyncio.run_coroutine_threadsafe(tunnel_up(), self.loop).result()
|
||||||
|
|
||||||
if not i2p_destination in self.i2plib_tunnels:
|
if not i2p_destination in self.i2plib_tunnels:
|
||||||
raise IOError("No tunnel control instance was created")
|
raise OSError("No tunnel control instance was created")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
tn = self.i2plib_tunnels[i2p_destination]
|
tn = self.i2plib_tunnels[i2p_destination]
|
||||||
@ -167,19 +167,19 @@ class I2PController:
|
|||||||
try:
|
try:
|
||||||
owner.socket.shutdown(socket.SHUT_RDWR)
|
owner.socket.shutdown(socket.SHUT_RDWR)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while shutting down socket for "+str(owner)+": "+str(e))
|
RNS.log(f"Error while shutting down socket for {owner}: {e}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
owner.socket.close()
|
owner.socket.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while closing socket for "+str(owner)+": "+str(e))
|
RNS.log(f"Error while closing socket for {owner}: {e}")
|
||||||
self.client_tunnels[i2p_destination] = True
|
self.client_tunnels[i2p_destination] = True
|
||||||
owner.awaiting_i2p_tunnel = False
|
owner.awaiting_i2p_tunnel = False
|
||||||
|
|
||||||
RNS.log(str(owner)+" tunnel setup complete", RNS.LOG_VERBOSE)
|
RNS.log(f"{owner} tunnel setup complete", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise IOError("Got no status response from SAM API")
|
raise OSError("Got no status response from SAM API")
|
||||||
|
|
||||||
except ConnectionRefusedError as e:
|
except ConnectionRefusedError as e:
|
||||||
raise e
|
raise e
|
||||||
@ -188,7 +188,7 @@ class I2PController:
|
|||||||
raise e
|
raise e
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Unexpected error type from I2P SAM: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Unexpected error type from I2P SAM: {e}", RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -197,16 +197,16 @@ class I2PController:
|
|||||||
i2p_exception = i2ptunnel.status["exception"]
|
i2p_exception = i2ptunnel.status["exception"]
|
||||||
|
|
||||||
if i2ptunnel.status["setup_ran"] == False:
|
if i2ptunnel.status["setup_ran"] == False:
|
||||||
RNS.log(str(self)+" I2P tunnel setup did not complete", RNS.LOG_ERROR)
|
RNS.log(f"{self} I2P tunnel setup did not complete", RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.stop_tunnel(i2ptunnel)
|
self.stop_tunnel(i2ptunnel)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
elif i2p_exception != None:
|
elif i2p_exception != None:
|
||||||
RNS.log("An error ocurred while setting up I2P tunnel to "+str(i2p_destination), RNS.LOG_ERROR)
|
RNS.log(f"An error ocurred while setting up I2P tunnel to {i2p_destination}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.CantReachPeer):
|
if isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.CantReachPeer):
|
||||||
RNS.log("The I2P daemon can't reach peer "+str(i2p_destination), RNS.LOG_ERROR)
|
RNS.log(f"The I2P daemon can't reach peer {i2p_destination}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.DuplicatedDest):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.DuplicatedDest):
|
||||||
RNS.log("The I2P daemon reported that the destination is already in use", RNS.LOG_ERROR)
|
RNS.log("The I2P daemon reported that the destination is already in use", RNS.LOG_ERROR)
|
||||||
@ -218,19 +218,19 @@ class I2PController:
|
|||||||
RNS.log("The I2P daemon reported that the stream session ID doesn't exist", RNS.LOG_ERROR)
|
RNS.log("The I2P daemon reported that the stream session ID doesn't exist", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.InvalidKey):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.InvalidKey):
|
||||||
RNS.log("The I2P daemon reported that the key for "+str(i2p_destination)+" is invalid", RNS.LOG_ERROR)
|
RNS.log(f"The I2P daemon reported that the key for {i2p_destination} is invalid", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.KeyNotFound):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.KeyNotFound):
|
||||||
RNS.log("The I2P daemon could not find the key for "+str(i2p_destination), RNS.LOG_ERROR)
|
RNS.log(f"The I2P daemon could not find the key for {i2p_destination}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.PeerNotFound):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.PeerNotFound):
|
||||||
RNS.log("The I2P daemon mould not find the peer "+str(i2p_destination), RNS.LOG_ERROR)
|
RNS.log(f"The I2P daemon mould not find the peer {i2p_destination}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.I2PError):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.I2PError):
|
||||||
RNS.log("The I2P daemon experienced an unspecified error", RNS.LOG_ERROR)
|
RNS.log("The I2P daemon experienced an unspecified error", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.Timeout):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.Timeout):
|
||||||
RNS.log("I2P daemon timed out while setting up client tunnel to "+str(i2p_destination), RNS.LOG_ERROR)
|
RNS.log(f"I2P daemon timed out while setting up client tunnel to {i2p_destination}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
RNS.log("Resetting I2P tunnel and retrying later", RNS.LOG_ERROR)
|
RNS.log("Resetting I2P tunnel and retrying later", RNS.LOG_ERROR)
|
||||||
|
|
||||||
@ -238,13 +238,13 @@ class I2PController:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
elif i2ptunnel.status["setup_failed"] == True:
|
elif i2ptunnel.status["setup_failed"] == True:
|
||||||
RNS.log(str(self)+" Unspecified I2P tunnel setup error, resetting I2P tunnel", RNS.LOG_ERROR)
|
RNS.log(f"{self} Unspecified I2P tunnel setup error, resetting I2P tunnel", RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.stop_tunnel(i2ptunnel)
|
self.stop_tunnel(i2ptunnel)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self)+" Got no status from SAM API, resetting I2P tunnel", RNS.LOG_ERROR)
|
RNS.log(f"{self} Got no status from SAM API, resetting I2P tunnel", RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.stop_tunnel(i2ptunnel)
|
self.stop_tunnel(i2ptunnel)
|
||||||
return False
|
return False
|
||||||
@ -259,11 +259,11 @@ class I2PController:
|
|||||||
|
|
||||||
# Old format
|
# Old format
|
||||||
i2p_dest_hash_of = RNS.Identity.full_hash(RNS.Identity.full_hash(owner.name.encode("utf-8")))
|
i2p_dest_hash_of = RNS.Identity.full_hash(RNS.Identity.full_hash(owner.name.encode("utf-8")))
|
||||||
i2p_keyfile_of = self.storagepath+"/"+RNS.hexrep(i2p_dest_hash_of, delimit=False)+".i2p"
|
i2p_keyfile_of = f"{self.storagepath}/{RNS.hexrep(i2p_dest_hash_of, delimit=False)}.i2p"
|
||||||
|
|
||||||
# New format
|
# New format
|
||||||
i2p_dest_hash_nf = RNS.Identity.full_hash(RNS.Identity.full_hash(owner.name.encode("utf-8"))+RNS.Identity.full_hash(RNS.Transport.identity.hash))
|
i2p_dest_hash_nf = RNS.Identity.full_hash(RNS.Identity.full_hash(owner.name.encode("utf-8"))+RNS.Identity.full_hash(RNS.Transport.identity.hash))
|
||||||
i2p_keyfile_nf = self.storagepath+"/"+RNS.hexrep(i2p_dest_hash_nf, delimit=False)+".i2p"
|
i2p_keyfile_nf = f"{self.storagepath}/{RNS.hexrep(i2p_dest_hash_nf, delimit=False)}.i2p"
|
||||||
|
|
||||||
# Use old format if a key is already present
|
# Use old format if a key is already present
|
||||||
if os.path.isfile(i2p_keyfile_of):
|
if os.path.isfile(i2p_keyfile_of):
|
||||||
@ -279,7 +279,7 @@ class I2PController:
|
|||||||
key_file.write(i2p_dest.private_key.base64)
|
key_file.write(i2p_dest.private_key.base64)
|
||||||
key_file.close()
|
key_file.close()
|
||||||
else:
|
else:
|
||||||
key_file = open(i2p_keyfile, "r")
|
key_file = open(i2p_keyfile)
|
||||||
prvd = key_file.read()
|
prvd = key_file.read()
|
||||||
key_file.close()
|
key_file.close()
|
||||||
i2p_dest = self.i2plib.Destination(data=prvd, has_private_key=True)
|
i2p_dest = self.i2plib.Destination(data=prvd, has_private_key=True)
|
||||||
@ -294,12 +294,12 @@ class I2PController:
|
|||||||
if self.server_tunnels[i2p_b32] == False:
|
if self.server_tunnels[i2p_b32] == False:
|
||||||
try:
|
try:
|
||||||
async def tunnel_up():
|
async def tunnel_up():
|
||||||
RNS.log(str(owner)+" Bringing up I2P endpoint, this may take a while...", RNS.LOG_INFO)
|
RNS.log(f"{owner} Bringing up I2P endpoint, this may take a while...", RNS.LOG_INFO)
|
||||||
tunnel = self.i2plib.ServerTunnel((owner.bind_ip, owner.bind_port), loop=self.loop, destination=i2p_dest, sam_address=self.sam_address)
|
tunnel = self.i2plib.ServerTunnel((owner.bind_ip, owner.bind_port), loop=self.loop, destination=i2p_dest, sam_address=self.sam_address)
|
||||||
self.i2plib_tunnels[i2p_b32] = tunnel
|
self.i2plib_tunnels[i2p_b32] = tunnel
|
||||||
await tunnel.run()
|
await tunnel.run()
|
||||||
owner.online = True
|
owner.online = True
|
||||||
RNS.log(str(owner)+ " endpoint setup complete. Now reachable at: "+str(i2p_dest.base32)+".b32.i2p", RNS.LOG_VERBOSE)
|
RNS.log(f"{owner} endpoint setup complete. Now reachable at: {i2p_dest.base32}.b32.i2p", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
asyncio.run_coroutine_threadsafe(tunnel_up(), self.loop).result()
|
asyncio.run_coroutine_threadsafe(tunnel_up(), self.loop).result()
|
||||||
self.server_tunnels[i2p_b32] = True
|
self.server_tunnels[i2p_b32] = True
|
||||||
@ -313,7 +313,7 @@ class I2PController:
|
|||||||
i2p_exception = i2ptunnel.status["exception"]
|
i2p_exception = i2ptunnel.status["exception"]
|
||||||
|
|
||||||
if i2ptunnel.status["setup_ran"] == False:
|
if i2ptunnel.status["setup_ran"] == False:
|
||||||
RNS.log(str(self)+" I2P tunnel setup did not complete", RNS.LOG_ERROR)
|
RNS.log(f"{self} I2P tunnel setup did not complete", RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.stop_tunnel(i2ptunnel)
|
self.stop_tunnel(i2ptunnel)
|
||||||
return False
|
return False
|
||||||
@ -322,7 +322,7 @@ class I2PController:
|
|||||||
RNS.log("An error ocurred while setting up I2P tunnel", RNS.LOG_ERROR)
|
RNS.log("An error ocurred while setting up I2P tunnel", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.CantReachPeer):
|
if isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.CantReachPeer):
|
||||||
RNS.log("The I2P daemon can't reach peer "+str(i2p_destination), RNS.LOG_ERROR)
|
RNS.log(f"The I2P daemon can't reach peer {i2p_destination}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.DuplicatedDest):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.DuplicatedDest):
|
||||||
RNS.log("The I2P daemon reported that the destination is already in use", RNS.LOG_ERROR)
|
RNS.log("The I2P daemon reported that the destination is already in use", RNS.LOG_ERROR)
|
||||||
@ -334,19 +334,19 @@ class I2PController:
|
|||||||
RNS.log("The I2P daemon reported that the stream session ID doesn't exist", RNS.LOG_ERROR)
|
RNS.log("The I2P daemon reported that the stream session ID doesn't exist", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.InvalidKey):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.InvalidKey):
|
||||||
RNS.log("The I2P daemon reported that the key for "+str(i2p_destination)+" is invalid", RNS.LOG_ERROR)
|
RNS.log(f"The I2P daemon reported that the key for {i2p_destination} is invalid", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.KeyNotFound):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.KeyNotFound):
|
||||||
RNS.log("The I2P daemon could not find the key for "+str(i2p_destination), RNS.LOG_ERROR)
|
RNS.log(f"The I2P daemon could not find the key for {i2p_destination}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.PeerNotFound):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.PeerNotFound):
|
||||||
RNS.log("The I2P daemon mould not find the peer "+str(i2p_destination), RNS.LOG_ERROR)
|
RNS.log(f"The I2P daemon mould not find the peer {i2p_destination}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.I2PError):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.I2PError):
|
||||||
RNS.log("The I2P daemon experienced an unspecified error", RNS.LOG_ERROR)
|
RNS.log("The I2P daemon experienced an unspecified error", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.Timeout):
|
elif isinstance(i2p_exception, RNS.vendor.i2plib.exceptions.Timeout):
|
||||||
RNS.log("I2P daemon timed out while setting up client tunnel to "+str(i2p_destination), RNS.LOG_ERROR)
|
RNS.log(f"I2P daemon timed out while setting up client tunnel to {i2p_destination}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
RNS.log("Resetting I2P tunnel and retrying later", RNS.LOG_ERROR)
|
RNS.log("Resetting I2P tunnel and retrying later", RNS.LOG_ERROR)
|
||||||
|
|
||||||
@ -354,13 +354,13 @@ class I2PController:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
elif i2ptunnel.status["setup_failed"] == True:
|
elif i2ptunnel.status["setup_failed"] == True:
|
||||||
RNS.log(str(self)+" Unspecified I2P tunnel setup error, resetting I2P tunnel", RNS.LOG_ERROR)
|
RNS.log(f"{self} Unspecified I2P tunnel setup error, resetting I2P tunnel", RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.stop_tunnel(i2ptunnel)
|
self.stop_tunnel(i2ptunnel)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self)+" Got no status from SAM API, resetting I2P tunnel", RNS.LOG_ERROR)
|
RNS.log(f"{self} Got no status from SAM API, resetting I2P tunnel", RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.stop_tunnel(i2ptunnel)
|
self.stop_tunnel(i2ptunnel)
|
||||||
return False
|
return False
|
||||||
@ -475,11 +475,11 @@ class I2PInterfacePeer(Interface):
|
|||||||
self.target_port = self.bind_port
|
self.target_port = self.bind_port
|
||||||
|
|
||||||
if not self.parent_interface.i2p.client_tunnel(self, target_i2p_dest):
|
if not self.parent_interface.i2p.client_tunnel(self, target_i2p_dest):
|
||||||
RNS.log(str(self)+" I2P control process experienced an error, requesting new tunnel...", RNS.LOG_ERROR)
|
RNS.log(f"{self} I2P control process experienced an error, requesting new tunnel...", RNS.LOG_ERROR)
|
||||||
self.awaiting_i2p_tunnel = True
|
self.awaiting_i2p_tunnel = True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while while configuring "+str(self)+": "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while while configuring {self}: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("Check that I2P is installed and running, and that SAM is enabled. Retrying tunnel setup later.", RNS.LOG_ERROR)
|
RNS.log("Check that I2P is installed and running, and that SAM is enabled. Retrying tunnel setup later.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
time.sleep(8)
|
time.sleep(8)
|
||||||
@ -532,16 +532,16 @@ class I2PInterfacePeer(Interface):
|
|||||||
if socket != None:
|
if socket != None:
|
||||||
target_socket.shutdown(socket.SHUT_RDWR)
|
target_socket.shutdown(socket.SHUT_RDWR)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while shutting down socket for "+str(self)+": "+str(e))
|
RNS.log(f"Error while shutting down socket for {self}: {e}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if socket != None:
|
if socket != None:
|
||||||
target_socket.close()
|
target_socket.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while closing socket for "+str(self)+": "+str(e))
|
RNS.log(f"Error while closing socket for {self}: {e}")
|
||||||
|
|
||||||
def detach(self):
|
def detach(self):
|
||||||
RNS.log("Detaching "+str(self), RNS.LOG_DEBUG)
|
RNS.log(f"Detaching {self}", RNS.LOG_DEBUG)
|
||||||
if self.socket != None:
|
if self.socket != None:
|
||||||
if hasattr(self.socket, "close"):
|
if hasattr(self.socket, "close"):
|
||||||
if callable(self.socket.close):
|
if callable(self.socket.close):
|
||||||
@ -550,12 +550,12 @@ class I2PInterfacePeer(Interface):
|
|||||||
try:
|
try:
|
||||||
self.socket.shutdown(socket.SHUT_RDWR)
|
self.socket.shutdown(socket.SHUT_RDWR)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while shutting down socket for "+str(self)+": "+str(e))
|
RNS.log(f"Error while shutting down socket for {self}: {e}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while closing socket for "+str(self)+": "+str(e))
|
RNS.log(f"Error while closing socket for {self}: {e}")
|
||||||
|
|
||||||
self.socket = None
|
self.socket = None
|
||||||
|
|
||||||
@ -568,8 +568,8 @@ class I2PInterfacePeer(Interface):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
if initial:
|
if initial:
|
||||||
if not self.awaiting_i2p_tunnel:
|
if not self.awaiting_i2p_tunnel:
|
||||||
RNS.log("Initial connection for "+str(self)+" could not be established: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Initial connection for {self} could not be established: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("Leaving unconnected and retrying connection in "+str(I2PInterfacePeer.RECONNECT_WAIT)+" seconds.", RNS.LOG_ERROR)
|
RNS.log(f"Leaving unconnected and retrying connection in {I2PInterfacePeer.RECONNECT_WAIT} seconds.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -600,7 +600,7 @@ class I2PInterfacePeer(Interface):
|
|||||||
attempts += 1
|
attempts += 1
|
||||||
|
|
||||||
if self.max_reconnect_tries != None and attempts > self.max_reconnect_tries:
|
if self.max_reconnect_tries != None and attempts > self.max_reconnect_tries:
|
||||||
RNS.log("Max reconnection attempts reached for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Max reconnection attempts reached for {self}", RNS.LOG_ERROR)
|
||||||
self.teardown()
|
self.teardown()
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -609,12 +609,12 @@ class I2PInterfacePeer(Interface):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if not self.awaiting_i2p_tunnel:
|
if not self.awaiting_i2p_tunnel:
|
||||||
RNS.log("Connection attempt for "+str(self)+" failed: "+str(e), RNS.LOG_DEBUG)
|
RNS.log(f"Connection attempt for {self} failed: {e}", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self)+" still waiting for I2P tunnel to appear", RNS.LOG_VERBOSE)
|
RNS.log(f"{self} still waiting for I2P tunnel to appear", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
if not self.never_connected:
|
if not self.never_connected:
|
||||||
RNS.log(str(self)+" Re-established connection via I2P tunnel", RNS.LOG_INFO)
|
RNS.log(f"{self} Re-established connection via I2P tunnel", RNS.LOG_INFO)
|
||||||
|
|
||||||
self.reconnecting = False
|
self.reconnecting = False
|
||||||
thread = threading.Thread(target=self.read_loop)
|
thread = threading.Thread(target=self.read_loop)
|
||||||
@ -625,7 +625,7 @@ class I2PInterfacePeer(Interface):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Attempt to reconnect on a non-initiator I2P interface. This should not happen.", RNS.LOG_ERROR)
|
RNS.log("Attempt to reconnect on a non-initiator I2P interface. This should not happen.", RNS.LOG_ERROR)
|
||||||
raise IOError("Attempt to reconnect on a non-initiator I2P interface")
|
raise OSError("Attempt to reconnect on a non-initiator I2P interface")
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
self.rxb += len(data)
|
self.rxb += len(data)
|
||||||
@ -656,8 +656,8 @@ class I2PInterfacePeer(Interface):
|
|||||||
self.parent_interface.txb += len(data)
|
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(f"Exception occurred while transmitting via {self}, tearing down interface", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
self.teardown()
|
self.teardown()
|
||||||
|
|
||||||
|
|
||||||
@ -683,7 +683,7 @@ class I2PInterfacePeer(Interface):
|
|||||||
if self.socket != None:
|
if self.socket != None:
|
||||||
self.socket.sendall(bytes([HDLC.FLAG, HDLC.FLAG]))
|
self.socket.sendall(bytes([HDLC.FLAG, HDLC.FLAG]))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error ocurred while sending I2P keepalive. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"An error ocurred while sending I2P keepalive. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
self.shutdown_socket(self.socket)
|
self.shutdown_socket(self.socket)
|
||||||
should_run = False
|
should_run = False
|
||||||
|
|
||||||
@ -693,12 +693,12 @@ class I2PInterfacePeer(Interface):
|
|||||||
try:
|
try:
|
||||||
self.socket.shutdown(socket.SHUT_RDWR)
|
self.socket.shutdown(socket.SHUT_RDWR)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while shutting down socket for "+str(self)+": "+str(e))
|
RNS.log(f"Error while shutting down socket for {self}: {e}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while closing socket for "+str(self)+": "+str(e))
|
RNS.log(f"Error while closing socket for {self}: {e}")
|
||||||
|
|
||||||
should_run = False
|
should_run = False
|
||||||
|
|
||||||
@ -782,10 +782,10 @@ class I2PInterfacePeer(Interface):
|
|||||||
self.wd_reset = False
|
self.wd_reset = False
|
||||||
|
|
||||||
if self.initiator and not self.detached:
|
if self.initiator and not self.detached:
|
||||||
RNS.log("Socket for "+str(self)+" was closed, attempting to reconnect...", RNS.LOG_WARNING)
|
RNS.log(f"Socket for {self} was closed, attempting to reconnect...", RNS.LOG_WARNING)
|
||||||
self.reconnect()
|
self.reconnect()
|
||||||
else:
|
else:
|
||||||
RNS.log("Socket for remote client "+str(self)+" was closed.", RNS.LOG_VERBOSE)
|
RNS.log(f"Socket for remote client {self} was closed.", RNS.LOG_VERBOSE)
|
||||||
self.teardown()
|
self.teardown()
|
||||||
|
|
||||||
break
|
break
|
||||||
@ -793,7 +793,7 @@ class I2PInterfacePeer(Interface):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("An interface error occurred for "+str(self)+", the contained exception was: "+str(e), RNS.LOG_WARNING)
|
RNS.log(f"An interface error occurred for {self}, the contained exception was: {e}", RNS.LOG_WARNING)
|
||||||
|
|
||||||
if self.initiator:
|
if self.initiator:
|
||||||
RNS.log("Attempting to reconnect...", RNS.LOG_WARNING)
|
RNS.log("Attempting to reconnect...", RNS.LOG_WARNING)
|
||||||
@ -803,12 +803,12 @@ class I2PInterfacePeer(Interface):
|
|||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
if self.initiator and not self.detached:
|
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(f"The interface {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()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("The interface "+str(self)+" is being torn down.", RNS.LOG_VERBOSE)
|
RNS.log(f"The interface {self} is being torn down.", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
self.online = False
|
self.online = False
|
||||||
self.OUT = False
|
self.OUT = False
|
||||||
@ -824,7 +824,7 @@ class I2PInterfacePeer(Interface):
|
|||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "I2PInterfacePeer["+str(self.name)+"]"
|
return f"I2PInterfacePeer[{self.name}]"
|
||||||
|
|
||||||
|
|
||||||
class I2PInterface(Interface):
|
class I2PInterface(Interface):
|
||||||
@ -895,11 +895,11 @@ class I2PInterface(Interface):
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
if not self.i2p.server_tunnel(self):
|
if not self.i2p.server_tunnel(self):
|
||||||
RNS.log(str(self)+" I2P control process experienced an error, requesting new tunnel...", RNS.LOG_ERROR)
|
RNS.log(f"{self} I2P control process experienced an error, requesting new tunnel...", RNS.LOG_ERROR)
|
||||||
self.online = False
|
self.online = False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while while configuring "+str(self)+": "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while while configuring {self}: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("Check that I2P is installed and running, and that SAM is enabled. Retrying tunnel setup later.", RNS.LOG_ERROR)
|
RNS.log("Check that I2P is installed and running, and that SAM is enabled. Retrying tunnel setup later.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
time.sleep(15)
|
time.sleep(15)
|
||||||
@ -911,7 +911,7 @@ class I2PInterface(Interface):
|
|||||||
|
|
||||||
if peers != None:
|
if peers != None:
|
||||||
for peer_addr in peers:
|
for peer_addr in peers:
|
||||||
interface_name = self.name+" to "+peer_addr
|
interface_name = f"{self.name} to {peer_addr}"
|
||||||
peer_interface = I2PInterfacePeer(self, self.owner, interface_name, peer_addr)
|
peer_interface = I2PInterfacePeer(self, self.owner, interface_name, peer_addr)
|
||||||
peer_interface.OUT = True
|
peer_interface.OUT = True
|
||||||
peer_interface.IN = True
|
peer_interface.IN = True
|
||||||
@ -921,7 +921,7 @@ class I2PInterface(Interface):
|
|||||||
|
|
||||||
def incoming_connection(self, handler):
|
def incoming_connection(self, handler):
|
||||||
RNS.log("Accepting incoming I2P connection", RNS.LOG_VERBOSE)
|
RNS.log("Accepting incoming I2P connection", RNS.LOG_VERBOSE)
|
||||||
interface_name = "Connected peer on "+self.name
|
interface_name = f"Connected peer on {self.name}"
|
||||||
spawned_interface = I2PInterfacePeer(self, self.owner, interface_name, connected_socket=handler.request)
|
spawned_interface = I2PInterfacePeer(self, self.owner, interface_name, connected_socket=handler.request)
|
||||||
spawned_interface.OUT = True
|
spawned_interface.OUT = True
|
||||||
spawned_interface.IN = True
|
spawned_interface.IN = True
|
||||||
@ -954,7 +954,7 @@ class I2PInterface(Interface):
|
|||||||
spawned_interface.announce_rate_penalty = self.announce_rate_penalty
|
spawned_interface.announce_rate_penalty = self.announce_rate_penalty
|
||||||
spawned_interface.mode = self.mode
|
spawned_interface.mode = self.mode
|
||||||
spawned_interface.HW_MTU = self.HW_MTU
|
spawned_interface.HW_MTU = self.HW_MTU
|
||||||
RNS.log("Spawned new I2PInterface Peer: "+str(spawned_interface), RNS.LOG_VERBOSE)
|
RNS.log(f"Spawned new I2PInterface Peer: {spawned_interface}", RNS.LOG_VERBOSE)
|
||||||
RNS.Transport.interfaces.append(spawned_interface)
|
RNS.Transport.interfaces.append(spawned_interface)
|
||||||
self.clients += 1
|
self.clients += 1
|
||||||
spawned_interface.read_loop()
|
spawned_interface.read_loop()
|
||||||
@ -969,11 +969,11 @@ class I2PInterface(Interface):
|
|||||||
if from_spawned: self.oa_freq_deque.append(time.time())
|
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(f"Detaching {self}", RNS.LOG_DEBUG)
|
||||||
self.i2p.stop()
|
self.i2p.stop()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "I2PInterface["+self.name+"]"
|
return f"I2PInterface[{self.name}]"
|
||||||
|
|
||||||
class I2PInterfaceHandler(socketserver.BaseRequestHandler):
|
class I2PInterfaceHandler(socketserver.BaseRequestHandler):
|
||||||
def __init__(self, callback, *args, **keys):
|
def __init__(self, callback, *args, **keys):
|
||||||
|
@ -140,7 +140,7 @@ class Interface:
|
|||||||
selected_announce_packet = announce_packet
|
selected_announce_packet = announce_packet
|
||||||
|
|
||||||
if selected_announce_packet != None:
|
if selected_announce_packet != None:
|
||||||
RNS.log("Releasing held announce packet "+str(selected_announce_packet)+" from "+str(self), RNS.LOG_EXTREME)
|
RNS.log(f"Releasing held announce packet {selected_announce_packet} from {self}", RNS.LOG_EXTREME)
|
||||||
self.ic_held_release = time.time() + self.ic_held_release_interval
|
self.ic_held_release = time.time() + self.ic_held_release_interval
|
||||||
self.held_announces.pop(selected_announce_packet.destination_hash)
|
self.held_announces.pop(selected_announce_packet.destination_hash)
|
||||||
def release():
|
def release():
|
||||||
@ -148,8 +148,8 @@ class Interface:
|
|||||||
threading.Thread(target=release, daemon=True).start()
|
threading.Thread(target=release, daemon=True).start()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error occurred while processing held announces for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"An error occurred while processing held announces for {self}", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def received_announce(self):
|
def received_announce(self):
|
||||||
self.ia_freq_deque.append(time.time())
|
self.ia_freq_deque.append(time.time())
|
||||||
@ -234,7 +234,7 @@ class Interface:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.announce_queue = []
|
self.announce_queue = []
|
||||||
RNS.log("Error while processing announce queue on "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while processing announce queue on {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("The announce queue for this interface has been cleared.", RNS.LOG_ERROR)
|
RNS.log("The announce queue for this interface has been cleared.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def detach(self):
|
def detach(self):
|
||||||
|
@ -113,17 +113,17 @@ class KISSInterface(Interface):
|
|||||||
try:
|
try:
|
||||||
self.open_port()
|
self.open_port()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not open serial port "+self.port, RNS.LOG_ERROR)
|
RNS.log(f"Could not open serial port {self.port}", RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not open serial port")
|
raise OSError("Could not open serial port")
|
||||||
|
|
||||||
|
|
||||||
def open_port(self):
|
def open_port(self):
|
||||||
RNS.log("Opening serial port "+self.port+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Opening serial port {self.port}...", RNS.LOG_VERBOSE)
|
||||||
self.serial = self.pyserial.Serial(
|
self.serial = self.pyserial.Serial(
|
||||||
port = self.port,
|
port = self.port,
|
||||||
baudrate = self.speed,
|
baudrate = self.speed,
|
||||||
@ -146,7 +146,7 @@ class KISSInterface(Interface):
|
|||||||
thread.daemon = True
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
self.online = True
|
self.online = True
|
||||||
RNS.log("Serial port "+self.port+" is now open")
|
RNS.log(f"Serial port {self.port} is now open")
|
||||||
RNS.log("Configuring KISS interface parameters...")
|
RNS.log("Configuring KISS interface parameters...")
|
||||||
self.setPreamble(self.preamble)
|
self.setPreamble(self.preamble)
|
||||||
self.setTxTail(self.txtail)
|
self.setTxTail(self.txtail)
|
||||||
@ -168,7 +168,7 @@ class KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXDELAY])+bytes([preamble])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXDELAY])+bytes([preamble])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure KISS interface preamble to "+str(preamble_ms)+" (command value "+str(preamble)+")")
|
raise OSError(f"Could not configure KISS interface preamble to {preamble_ms} (command value {preamble})")
|
||||||
|
|
||||||
def setTxTail(self, txtail):
|
def setTxTail(self, txtail):
|
||||||
txtail_ms = txtail
|
txtail_ms = txtail
|
||||||
@ -181,7 +181,7 @@ class KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXTAIL])+bytes([txtail])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXTAIL])+bytes([txtail])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure KISS interface TX tail to "+str(txtail_ms)+" (command value "+str(txtail)+")")
|
raise OSError(f"Could not configure KISS interface TX tail to {txtail_ms} (command value {txtail})")
|
||||||
|
|
||||||
def setPersistence(self, persistence):
|
def setPersistence(self, persistence):
|
||||||
if persistence < 0:
|
if persistence < 0:
|
||||||
@ -192,7 +192,7 @@ class KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_P])+bytes([persistence])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_P])+bytes([persistence])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure KISS interface persistence to "+str(persistence))
|
raise OSError(f"Could not configure KISS interface persistence to {persistence}")
|
||||||
|
|
||||||
def setSlotTime(self, slottime):
|
def setSlotTime(self, slottime):
|
||||||
slottime_ms = slottime
|
slottime_ms = slottime
|
||||||
@ -205,16 +205,16 @@ class KISSInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_SLOTTIME])+bytes([slottime])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_SLOTTIME])+bytes([slottime])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("Could not configure KISS interface slot time to "+str(slottime_ms)+" (command value "+str(slottime)+")")
|
raise OSError(f"Could not configure KISS interface slot time to {slottime_ms} (command value {slottime})")
|
||||||
|
|
||||||
def setFlowControl(self, flow_control):
|
def setFlowControl(self, flow_control):
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_READY])+bytes([0x01])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_READY])+bytes([0x01])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
if (flow_control):
|
if (flow_control):
|
||||||
raise IOError("Could not enable KISS interface flow control")
|
raise OSError("Could not enable KISS interface flow control")
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not enable KISS interface flow control")
|
raise OSError("Could not enable KISS interface flow control")
|
||||||
|
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
@ -244,7 +244,7 @@ class KISSInterface(Interface):
|
|||||||
self.first_tx = time.time()
|
self.first_tx = time.time()
|
||||||
|
|
||||||
if written != len(frame):
|
if written != len(frame):
|
||||||
raise IOError("Serial interface only wrote "+str(written)+" bytes of "+str(len(data)))
|
raise OSError(f"Serial interface only wrote {written} bytes of {len(data)}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.queue(data)
|
self.queue(data)
|
||||||
@ -311,20 +311,20 @@ class KISSInterface(Interface):
|
|||||||
if self.flow_control:
|
if self.flow_control:
|
||||||
if not self.interface_ready:
|
if not self.interface_ready:
|
||||||
if time.time() > self.flow_control_locked + self.flow_control_timeout:
|
if time.time() > self.flow_control_locked + self.flow_control_timeout:
|
||||||
RNS.log("Interface "+str(self)+" is unlocking flow control due to time-out. This should not happen. Your hardware might have missed a flow-control READY command, or maybe it does not support flow-control.", RNS.LOG_WARNING)
|
RNS.log(f"Interface {self} is unlocking flow control due to time-out. This should not happen. Your hardware might have missed a flow-control READY command, or maybe it does not support flow-control.", RNS.LOG_WARNING)
|
||||||
self.process_queue()
|
self.process_queue()
|
||||||
|
|
||||||
if self.beacon_i != None and self.beacon_d != None:
|
if self.beacon_i != None and self.beacon_d != None:
|
||||||
if self.first_tx != None:
|
if self.first_tx != None:
|
||||||
if time.time() > self.first_tx + self.beacon_i:
|
if time.time() > self.first_tx + self.beacon_i:
|
||||||
RNS.log("Interface "+str(self)+" is transmitting beacon data: "+str(self.beacon_d.decode("utf-8")), RNS.LOG_DEBUG)
|
RNS.log(f"Interface {self} is transmitting beacon data: {self.beacon_d.decode('utf-8')}", RNS.LOG_DEBUG)
|
||||||
self.first_tx = None
|
self.first_tx = None
|
||||||
self.processOutgoing(self.beacon_d)
|
self.processOutgoing(self.beacon_d)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"A serial port error occurred, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
RNS.log(f"The interface {self} experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if RNS.Reticulum.panic_on_interface_error:
|
if RNS.Reticulum.panic_on_interface_error:
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
@ -339,17 +339,17 @@ class KISSInterface(Interface):
|
|||||||
while not self.online:
|
while not self.online:
|
||||||
try:
|
try:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Attempting to reconnect serial port {self.port} for {self}...", RNS.LOG_VERBOSE)
|
||||||
self.open_port()
|
self.open_port()
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while reconnecting port, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
RNS.log("Reconnected serial port for "+str(self))
|
RNS.log(f"Reconnected serial port for {self}")
|
||||||
|
|
||||||
def should_ingress_limit(self):
|
def should_ingress_limit(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "KISSInterface["+self.name+"]"
|
return f"KISSInterface[{self.name}]"
|
@ -133,10 +133,10 @@ class LocalClientInterface(Interface):
|
|||||||
self.connect()
|
self.connect()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Connection attempt for "+str(self)+" failed: "+str(e), RNS.LOG_DEBUG)
|
RNS.log(f"Connection attempt for {self} failed: {e}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
if not self.never_connected:
|
if not self.never_connected:
|
||||||
RNS.log("Reconnected socket for "+str(self)+".", RNS.LOG_INFO)
|
RNS.log(f"Reconnected socket for {self}.", RNS.LOG_INFO)
|
||||||
|
|
||||||
self.reconnecting = False
|
self.reconnecting = False
|
||||||
thread = threading.Thread(target=self.read_loop)
|
thread = threading.Thread(target=self.read_loop)
|
||||||
@ -149,7 +149,7 @@ class LocalClientInterface(Interface):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Attempt to reconnect on a non-initiator shared local interface. This should not happen.", RNS.LOG_ERROR)
|
RNS.log("Attempt to reconnect on a non-initiator shared local interface. This should not happen.", RNS.LOG_ERROR)
|
||||||
raise IOError("Attempt to reconnect on a non-initiator local interface")
|
raise OSError("Attempt to reconnect on a non-initiator local interface")
|
||||||
|
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
@ -188,8 +188,8 @@ class LocalClientInterface(Interface):
|
|||||||
self.parent_interface.txb += len(data)
|
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(f"Exception occurred while transmitting via {self}, tearing down interface", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
self.teardown()
|
self.teardown()
|
||||||
|
|
||||||
|
|
||||||
@ -226,7 +226,7 @@ class LocalClientInterface(Interface):
|
|||||||
else:
|
else:
|
||||||
self.online = False
|
self.online = False
|
||||||
if self.is_connected_to_shared_instance and not self.detached:
|
if self.is_connected_to_shared_instance and not self.detached:
|
||||||
RNS.log("Socket for "+str(self)+" was closed, attempting to reconnect...", RNS.LOG_WARNING)
|
RNS.log(f"Socket for {self} was closed, attempting to reconnect...", RNS.LOG_WARNING)
|
||||||
RNS.Transport.shared_connection_disappeared()
|
RNS.Transport.shared_connection_disappeared()
|
||||||
self.reconnect()
|
self.reconnect()
|
||||||
else:
|
else:
|
||||||
@ -237,26 +237,26 @@ class LocalClientInterface(Interface):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("An interface error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"An interface error occurred, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("Tearing down "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Tearing down {self}", RNS.LOG_ERROR)
|
||||||
self.teardown()
|
self.teardown()
|
||||||
|
|
||||||
def detach(self):
|
def detach(self):
|
||||||
if self.socket != None:
|
if self.socket != None:
|
||||||
if hasattr(self.socket, "close"):
|
if hasattr(self.socket, "close"):
|
||||||
if callable(self.socket.close):
|
if callable(self.socket.close):
|
||||||
RNS.log("Detaching "+str(self), RNS.LOG_DEBUG)
|
RNS.log(f"Detaching {self}", RNS.LOG_DEBUG)
|
||||||
self.detached = True
|
self.detached = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.socket.shutdown(socket.SHUT_RDWR)
|
self.socket.shutdown(socket.SHUT_RDWR)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while shutting down socket for "+str(self)+": "+str(e))
|
RNS.log(f"Error while shutting down socket for {self}: {e}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while closing socket for "+str(self)+": "+str(e))
|
RNS.log(f"Error while closing socket for {self}: {e}")
|
||||||
|
|
||||||
self.socket = None
|
self.socket = None
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ class LocalClientInterface(Interface):
|
|||||||
RNS.Transport.owner._should_persist_data()
|
RNS.Transport.owner._should_persist_data()
|
||||||
|
|
||||||
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(f"The interface {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()
|
||||||
|
|
||||||
@ -288,7 +288,7 @@ class LocalClientInterface(Interface):
|
|||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "LocalInterface["+str(self.target_port)+"]"
|
return f"LocalInterface[{self.target_port}]"
|
||||||
|
|
||||||
|
|
||||||
class LocalServerInterface(Interface):
|
class LocalServerInterface(Interface):
|
||||||
@ -360,7 +360,7 @@ class LocalServerInterface(Interface):
|
|||||||
if from_spawned: self.oa_freq_deque.append(time.time())
|
if from_spawned: self.oa_freq_deque.append(time.time())
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Shared Instance["+str(self.bind_port)+"]"
|
return f"Shared Instance[{self.bind_port}]"
|
||||||
|
|
||||||
class LocalInterfaceHandler(socketserver.BaseRequestHandler):
|
class LocalInterfaceHandler(socketserver.BaseRequestHandler):
|
||||||
def __init__(self, callback, *args, **keys):
|
def __init__(self, callback, *args, **keys):
|
||||||
|
@ -72,17 +72,17 @@ class PipeInterface(Interface):
|
|||||||
self.open_pipe()
|
self.open_pipe()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could connect pipe for interface "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Could connect pipe for interface {self}", RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
if self.pipe_is_open:
|
if self.pipe_is_open:
|
||||||
self.configure_pipe()
|
self.configure_pipe()
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not connect pipe")
|
raise OSError("Could not connect pipe")
|
||||||
|
|
||||||
|
|
||||||
def open_pipe(self):
|
def open_pipe(self):
|
||||||
RNS.log("Connecting subprocess pipe for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Connecting subprocess pipe for {self}...", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.process = subprocess.Popen(shlex.split(self.command), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
self.process = subprocess.Popen(shlex.split(self.command), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
@ -98,7 +98,7 @@ class PipeInterface(Interface):
|
|||||||
thread.daemon = True
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
self.online = True
|
self.online = True
|
||||||
RNS.log("Subprocess pipe for "+str(self)+" is now connected", RNS.LOG_VERBOSE)
|
RNS.log(f"Subprocess pipe for {self} is now connected", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
@ -113,7 +113,7 @@ class PipeInterface(Interface):
|
|||||||
self.process.stdin.flush()
|
self.process.stdin.flush()
|
||||||
self.txb += len(data)
|
self.txb += len(data)
|
||||||
if written != len(data):
|
if written != len(data):
|
||||||
raise IOError("Pipe interface only wrote "+str(written)+" bytes of "+str(len(data)))
|
raise OSError(f"Pipe interface only wrote {written} bytes of {len(data)}")
|
||||||
|
|
||||||
|
|
||||||
def readLoop(self):
|
def readLoop(self):
|
||||||
@ -150,7 +150,7 @@ class PipeInterface(Interface):
|
|||||||
escape = False
|
escape = False
|
||||||
data_buffer = data_buffer+bytes([byte])
|
data_buffer = data_buffer+bytes([byte])
|
||||||
|
|
||||||
RNS.log("Subprocess terminated on "+str(self))
|
RNS.log(f"Subprocess terminated on {self}")
|
||||||
self.process.kill()
|
self.process.kill()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -160,8 +160,8 @@ class PipeInterface(Interface):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
RNS.log("A pipe error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"A pipe error occurred, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
RNS.log(f"The interface {self} experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if RNS.Reticulum.panic_on_interface_error:
|
if RNS.Reticulum.panic_on_interface_error:
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
@ -175,14 +175,14 @@ class PipeInterface(Interface):
|
|||||||
while not self.online:
|
while not self.online:
|
||||||
try:
|
try:
|
||||||
time.sleep(self.respawn_delay)
|
time.sleep(self.respawn_delay)
|
||||||
RNS.log("Attempting to respawn subprocess for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Attempting to respawn subprocess for {self}...", RNS.LOG_VERBOSE)
|
||||||
self.open_pipe()
|
self.open_pipe()
|
||||||
if self.pipe_is_open:
|
if self.pipe_is_open:
|
||||||
self.configure_pipe()
|
self.configure_pipe()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while spawning subprocess, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while spawning subprocess, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
RNS.log("Reconnected pipe for "+str(self))
|
RNS.log(f"Reconnected pipe for {self}")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "PipeInterface["+self.name+"]"
|
return f"PipeInterface[{self.name}]"
|
||||||
|
@ -211,31 +211,31 @@ class RNodeInterface(Interface):
|
|||||||
|
|
||||||
self.validcfg = True
|
self.validcfg = True
|
||||||
if (self.frequency < RNodeInterface.FREQ_MIN or self.frequency > RNodeInterface.FREQ_MAX):
|
if (self.frequency < RNodeInterface.FREQ_MIN or self.frequency > RNodeInterface.FREQ_MAX):
|
||||||
RNS.log("Invalid frequency configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid frequency configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.txpower < 0 or self.txpower > 22):
|
if (self.txpower < 0 or self.txpower > 22):
|
||||||
RNS.log("Invalid TX power configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid TX power configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.bandwidth < 7800 or self.bandwidth > 1625000):
|
if (self.bandwidth < 7800 or self.bandwidth > 1625000):
|
||||||
RNS.log("Invalid bandwidth configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid bandwidth configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.sf < 5 or self.sf > 12):
|
if (self.sf < 5 or self.sf > 12):
|
||||||
RNS.log("Invalid spreading factor configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid spreading factor configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.cr < 5 or self.cr > 8):
|
if (self.cr < 5 or self.cr > 8):
|
||||||
RNS.log("Invalid coding rate configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid coding rate configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.st_alock and (self.st_alock < 0.0 or self.st_alock > 100.0)):
|
if (self.st_alock and (self.st_alock < 0.0 or self.st_alock > 100.0)):
|
||||||
RNS.log("Invalid short-term airtime limit configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid short-term airtime limit configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.lt_alock and (self.lt_alock < 0.0 or self.lt_alock > 100.0)):
|
if (self.lt_alock and (self.lt_alock < 0.0 or self.lt_alock > 100.0)):
|
||||||
RNS.log("Invalid long-term airtime limit configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid long-term airtime limit configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if id_interval != None and id_callsign != None:
|
if id_interval != None and id_callsign != None:
|
||||||
@ -244,14 +244,14 @@ class RNodeInterface(Interface):
|
|||||||
self.id_callsign = id_callsign.encode("utf-8")
|
self.id_callsign = id_callsign.encode("utf-8")
|
||||||
self.id_interval = id_interval
|
self.id_interval = id_interval
|
||||||
else:
|
else:
|
||||||
RNS.log("The encoded ID callsign for "+str(self)+" exceeds the max length of "+str(RNodeInterface.CALLSIGN_MAX_LEN)+" bytes.", RNS.LOG_ERROR)
|
RNS.log(f"The encoded ID callsign for {self} exceeds the max length of {RNodeInterface.CALLSIGN_MAX_LEN} bytes.", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
else:
|
else:
|
||||||
self.id_interval = None
|
self.id_interval = None
|
||||||
self.id_callsign = None
|
self.id_callsign = None
|
||||||
|
|
||||||
if (not self.validcfg):
|
if (not self.validcfg):
|
||||||
raise ValueError("The configuration for "+str(self)+" contains errors, interface is offline")
|
raise ValueError(f"The configuration for {self} contains errors, interface is offline")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.open_port()
|
self.open_port()
|
||||||
@ -259,11 +259,11 @@ class RNodeInterface(Interface):
|
|||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not open serial port")
|
raise OSError("Could not open serial port")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not open serial port for interface "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Could not open serial port for interface {self}", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("Reticulum will attempt to bring up this interface periodically", RNS.LOG_ERROR)
|
RNS.log("Reticulum will attempt to bring up this interface periodically", RNS.LOG_ERROR)
|
||||||
if not self.detached and not self.reconnecting:
|
if not self.detached and not self.reconnecting:
|
||||||
thread = threading.Thread(target=self.reconnect_port)
|
thread = threading.Thread(target=self.reconnect_port)
|
||||||
@ -273,7 +273,7 @@ class RNodeInterface(Interface):
|
|||||||
|
|
||||||
def open_port(self):
|
def open_port(self):
|
||||||
if not self.use_ble:
|
if not self.use_ble:
|
||||||
RNS.log("Opening serial port "+self.port+"...")
|
RNS.log(f"Opening serial port {self.port}...")
|
||||||
self.serial = self.pyserial.Serial(
|
self.serial = self.pyserial.Serial(
|
||||||
port = self.port,
|
port = self.port,
|
||||||
baudrate = self.speed,
|
baudrate = self.speed,
|
||||||
@ -327,22 +327,22 @@ class RNodeInterface(Interface):
|
|||||||
RNS.log(f"RNode detect timed out over {self.port}", RNS.LOG_ERROR)
|
RNS.log(f"RNode detect timed out over {self.port}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if not self.detected:
|
if not self.detected:
|
||||||
RNS.log("Could not detect device for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Could not detect device for {self}", RNS.LOG_ERROR)
|
||||||
self.serial.close()
|
self.serial.close()
|
||||||
else:
|
else:
|
||||||
if self.platform == KISS.PLATFORM_ESP32 or self.platform == KISS.PLATFORM_NRF52:
|
if self.platform == KISS.PLATFORM_ESP32 or self.platform == KISS.PLATFORM_NRF52:
|
||||||
self.display = True
|
self.display = True
|
||||||
|
|
||||||
RNS.log("Serial port "+self.port+" is now open")
|
RNS.log(f"Serial port {self.port} is now open")
|
||||||
RNS.log("Configuring RNode interface...", RNS.LOG_VERBOSE)
|
RNS.log("Configuring RNode interface...", RNS.LOG_VERBOSE)
|
||||||
self.initRadio()
|
self.initRadio()
|
||||||
if (self.validateRadioState()):
|
if (self.validateRadioState()):
|
||||||
self.interface_ready = True
|
self.interface_ready = True
|
||||||
RNS.log(str(self)+" is configured and powered up")
|
RNS.log(f"{self} is configured and powered up")
|
||||||
sleep(0.3)
|
sleep(0.3)
|
||||||
self.online = True
|
self.online = True
|
||||||
else:
|
else:
|
||||||
RNS.log("After configuring "+str(self)+", the reported radio parameters did not match your configuration.", RNS.LOG_ERROR)
|
RNS.log(f"After configuring {self}, the reported radio parameters did not match your configuration.", RNS.LOG_ERROR)
|
||||||
RNS.log("Make sure that your hardware actually supports the parameters specified in the configuration", RNS.LOG_ERROR)
|
RNS.log("Make sure that your hardware actually supports the parameters specified in the configuration", RNS.LOG_ERROR)
|
||||||
RNS.log("Aborting RNode startup", RNS.LOG_ERROR)
|
RNS.log("Aborting RNode startup", RNS.LOG_ERROR)
|
||||||
self.serial.close()
|
self.serial.close()
|
||||||
@ -365,27 +365,27 @@ class RNodeInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_DETECT, KISS.DETECT_REQ, KISS.FEND, KISS.CMD_FW_VERSION, 0x00, KISS.FEND, KISS.CMD_PLATFORM, 0x00, KISS.FEND, KISS.CMD_MCU, 0x00, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_DETECT, KISS.DETECT_REQ, KISS.FEND, KISS.CMD_FW_VERSION, 0x00, KISS.FEND, KISS.CMD_PLATFORM, 0x00, KISS.FEND, KISS.CMD_MCU, 0x00, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while detecting hardware for "+str(self))
|
raise OSError(f"An IO error occurred while detecting hardware for {self}")
|
||||||
|
|
||||||
def leave(self):
|
def leave(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_LEAVE, 0xFF, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_LEAVE, 0xFF, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while sending host left command to device")
|
raise OSError("An IO error occurred while sending host left command to device")
|
||||||
|
|
||||||
def enable_external_framebuffer(self):
|
def enable_external_framebuffer(self):
|
||||||
if self.display != None:
|
if self.display != None:
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x01, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x01, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while enabling external framebuffer on device")
|
raise OSError("An IO error occurred while enabling external framebuffer on device")
|
||||||
|
|
||||||
def disable_external_framebuffer(self):
|
def disable_external_framebuffer(self):
|
||||||
if self.display != None:
|
if self.display != None:
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x00, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x00, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while disabling external framebuffer on device")
|
raise OSError("An IO error occurred while disabling external framebuffer on device")
|
||||||
|
|
||||||
FB_PIXEL_WIDTH = 64
|
FB_PIXEL_WIDTH = 64
|
||||||
FB_BITS_PER_PIXEL = 1
|
FB_BITS_PER_PIXEL = 1
|
||||||
@ -409,13 +409,13 @@ class RNodeInterface(Interface):
|
|||||||
|
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while writing framebuffer data device")
|
raise OSError("An IO error occurred while writing framebuffer data device")
|
||||||
|
|
||||||
def hard_reset(self):
|
def hard_reset(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_RESET, 0xf8, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_RESET, 0xf8, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while restarting device")
|
raise OSError("An IO error occurred while restarting device")
|
||||||
sleep(2.25);
|
sleep(2.25);
|
||||||
|
|
||||||
def setFrequency(self):
|
def setFrequency(self):
|
||||||
@ -428,7 +428,7 @@ class RNodeInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_FREQUENCY])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_FREQUENCY])+data+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring frequency for "+str(self))
|
raise OSError(f"An IO error occurred while configuring frequency for {self}")
|
||||||
|
|
||||||
def setBandwidth(self):
|
def setBandwidth(self):
|
||||||
c1 = self.bandwidth >> 24
|
c1 = self.bandwidth >> 24
|
||||||
@ -440,28 +440,28 @@ class RNodeInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_BANDWIDTH])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_BANDWIDTH])+data+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring bandwidth for "+str(self))
|
raise OSError(f"An IO error occurred while configuring bandwidth for {self}")
|
||||||
|
|
||||||
def setTXPower(self):
|
def setTXPower(self):
|
||||||
txp = bytes([self.txpower])
|
txp = bytes([self.txpower])
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXPOWER])+txp+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_TXPOWER])+txp+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring TX power for "+str(self))
|
raise OSError(f"An IO error occurred while configuring TX power for {self}")
|
||||||
|
|
||||||
def setSpreadingFactor(self):
|
def setSpreadingFactor(self):
|
||||||
sf = bytes([self.sf])
|
sf = bytes([self.sf])
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_SF])+sf+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_SF])+sf+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring spreading factor for "+str(self))
|
raise OSError(f"An IO error occurred while configuring spreading factor for {self}")
|
||||||
|
|
||||||
def setCodingRate(self):
|
def setCodingRate(self):
|
||||||
cr = bytes([self.cr])
|
cr = bytes([self.cr])
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_CR])+cr+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_CR])+cr+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring coding rate for "+str(self))
|
raise OSError(f"An IO error occurred while configuring coding rate for {self}")
|
||||||
|
|
||||||
def setSTALock(self):
|
def setSTALock(self):
|
||||||
if self.st_alock != None:
|
if self.st_alock != None:
|
||||||
@ -473,7 +473,7 @@ class RNodeInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_ST_ALOCK])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_ST_ALOCK])+data+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring short-term airtime limit for "+str(self))
|
raise OSError(f"An IO error occurred while configuring short-term airtime limit for {self}")
|
||||||
|
|
||||||
def setLTALock(self):
|
def setLTALock(self):
|
||||||
if self.lt_alock != None:
|
if self.lt_alock != None:
|
||||||
@ -485,14 +485,14 @@ class RNodeInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_LT_ALOCK])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_LT_ALOCK])+data+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring long-term airtime limit for "+str(self))
|
raise OSError(f"An IO error occurred while configuring long-term airtime limit for {self}")
|
||||||
|
|
||||||
def setRadioState(self, state):
|
def setRadioState(self, state):
|
||||||
self.state = state
|
self.state = state
|
||||||
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_RADIO_STATE])+bytes([state])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_RADIO_STATE])+bytes([state])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring radio state for "+str(self))
|
raise OSError(f"An IO error occurred while configuring radio state for {self}")
|
||||||
|
|
||||||
def validate_firmware(self):
|
def validate_firmware(self):
|
||||||
if (self.maj_version > RNodeInterface.REQUIRED_FW_VER_MAJ):
|
if (self.maj_version > RNodeInterface.REQUIRED_FW_VER_MAJ):
|
||||||
@ -505,14 +505,14 @@ class RNodeInterface(Interface):
|
|||||||
if self.firmware_ok:
|
if self.firmware_ok:
|
||||||
return
|
return
|
||||||
|
|
||||||
RNS.log("The firmware version of the connected RNode is "+str(self.maj_version)+"."+str(self.min_version), RNS.LOG_ERROR)
|
RNS.log(f"The firmware version of the connected RNode is {self.maj_version}.{self.min_version}", RNS.LOG_ERROR)
|
||||||
RNS.log("This version of Reticulum requires at least version "+str(RNodeInterface.REQUIRED_FW_VER_MAJ)+"."+str(RNodeInterface.REQUIRED_FW_VER_MIN), RNS.LOG_ERROR)
|
RNS.log(f"This version of Reticulum requires at least version {RNodeInterface.REQUIRED_FW_VER_MAJ}.{RNodeInterface.REQUIRED_FW_VER_MIN}", RNS.LOG_ERROR)
|
||||||
RNS.log("Please update your RNode firmware with rnodeconf from https://github.com/markqvist/rnodeconfigutil/")
|
RNS.log("Please update your RNode firmware with rnodeconf from https://github.com/markqvist/rnodeconfigutil/")
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
|
|
||||||
|
|
||||||
def validateRadioState(self):
|
def validateRadioState(self):
|
||||||
RNS.log("Waiting for radio configuration validation for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Waiting for radio configuration validation for {self}...", RNS.LOG_VERBOSE)
|
||||||
sleep(0.25);
|
sleep(0.25);
|
||||||
|
|
||||||
self.validcfg = True
|
self.validcfg = True
|
||||||
@ -542,7 +542,7 @@ class RNodeInterface(Interface):
|
|||||||
try:
|
try:
|
||||||
self.bitrate = self.r_sf * ( (4.0/self.r_cr) / (math.pow(2,self.r_sf)/(self.r_bandwidth/1000)) ) * 1000
|
self.bitrate = self.r_sf * ( (4.0/self.r_cr) / (math.pow(2,self.r_sf)/(self.r_bandwidth/1000)) ) * 1000
|
||||||
self.bitrate_kbps = round(self.bitrate/1000.0, 2)
|
self.bitrate_kbps = round(self.bitrate/1000.0, 2)
|
||||||
RNS.log(str(self)+" On-air bitrate is now "+str(self.bitrate_kbps)+ " kbps", RNS.LOG_VERBOSE)
|
RNS.log(f"{self} On-air bitrate is now {self.bitrate_kbps} kbps", RNS.LOG_VERBOSE)
|
||||||
except:
|
except:
|
||||||
self.bitrate = 0
|
self.bitrate = 0
|
||||||
|
|
||||||
@ -573,7 +573,7 @@ class RNodeInterface(Interface):
|
|||||||
self.txb += datalen
|
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 OSError(f"Serial interface only wrote {written} bytes of {len(data)}")
|
||||||
else:
|
else:
|
||||||
self.queue(data)
|
self.queue(data)
|
||||||
|
|
||||||
@ -639,7 +639,7 @@ class RNodeInterface(Interface):
|
|||||||
command_buffer = command_buffer+bytes([byte])
|
command_buffer = command_buffer+bytes([byte])
|
||||||
if (len(command_buffer) == 4):
|
if (len(command_buffer) == 4):
|
||||||
self.r_frequency = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
self.r_frequency = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
||||||
RNS.log(str(self)+" Radio reporting frequency is "+str(self.r_frequency/1000000.0)+" MHz", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting frequency is {self.r_frequency / 1000000.0} MHz", RNS.LOG_DEBUG)
|
||||||
self.updateBitrate()
|
self.updateBitrate()
|
||||||
|
|
||||||
elif (command == KISS.CMD_BANDWIDTH):
|
elif (command == KISS.CMD_BANDWIDTH):
|
||||||
@ -655,26 +655,26 @@ class RNodeInterface(Interface):
|
|||||||
command_buffer = command_buffer+bytes([byte])
|
command_buffer = command_buffer+bytes([byte])
|
||||||
if (len(command_buffer) == 4):
|
if (len(command_buffer) == 4):
|
||||||
self.r_bandwidth = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
self.r_bandwidth = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
||||||
RNS.log(str(self)+" Radio reporting bandwidth is "+str(self.r_bandwidth/1000.0)+" KHz", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting bandwidth is {self.r_bandwidth / 1000.0} KHz", RNS.LOG_DEBUG)
|
||||||
self.updateBitrate()
|
self.updateBitrate()
|
||||||
|
|
||||||
elif (command == KISS.CMD_TXPOWER):
|
elif (command == KISS.CMD_TXPOWER):
|
||||||
self.r_txpower = byte
|
self.r_txpower = byte
|
||||||
RNS.log(str(self)+" Radio reporting TX power is "+str(self.r_txpower)+" dBm", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting TX power is {self.r_txpower} dBm", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_SF):
|
elif (command == KISS.CMD_SF):
|
||||||
self.r_sf = byte
|
self.r_sf = byte
|
||||||
RNS.log(str(self)+" Radio reporting spreading factor is "+str(self.r_sf), RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting spreading factor is {self.r_sf}", RNS.LOG_DEBUG)
|
||||||
self.updateBitrate()
|
self.updateBitrate()
|
||||||
elif (command == KISS.CMD_CR):
|
elif (command == KISS.CMD_CR):
|
||||||
self.r_cr = byte
|
self.r_cr = byte
|
||||||
RNS.log(str(self)+" Radio reporting coding rate is "+str(self.r_cr), RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting coding rate is {self.r_cr}", RNS.LOG_DEBUG)
|
||||||
self.updateBitrate()
|
self.updateBitrate()
|
||||||
elif (command == KISS.CMD_RADIO_STATE):
|
elif (command == KISS.CMD_RADIO_STATE):
|
||||||
self.r_state = byte
|
self.r_state = byte
|
||||||
if self.r_state:
|
if self.r_state:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self)+" Radio reporting state is offline", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting state is offline", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
elif (command == KISS.CMD_RADIO_LOCK):
|
elif (command == KISS.CMD_RADIO_LOCK):
|
||||||
self.r_lock = byte
|
self.r_lock = byte
|
||||||
@ -752,7 +752,7 @@ class RNodeInterface(Interface):
|
|||||||
if (len(command_buffer) == 2):
|
if (len(command_buffer) == 2):
|
||||||
at = command_buffer[0] << 8 | command_buffer[1]
|
at = command_buffer[0] << 8 | command_buffer[1]
|
||||||
self.r_st_alock = at/100.0
|
self.r_st_alock = at/100.0
|
||||||
RNS.log(str(self)+" Radio reporting short-term airtime limit is "+str(self.r_st_alock)+"%", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting short-term airtime limit is {self.r_st_alock}%", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_LT_ALOCK):
|
elif (command == KISS.CMD_LT_ALOCK):
|
||||||
if (byte == KISS.FESC):
|
if (byte == KISS.FESC):
|
||||||
escape = True
|
escape = True
|
||||||
@ -767,7 +767,7 @@ class RNodeInterface(Interface):
|
|||||||
if (len(command_buffer) == 2):
|
if (len(command_buffer) == 2):
|
||||||
at = command_buffer[0] << 8 | command_buffer[1]
|
at = command_buffer[0] << 8 | command_buffer[1]
|
||||||
self.r_lt_alock = at/100.0
|
self.r_lt_alock = at/100.0
|
||||||
RNS.log(str(self)+" Radio reporting long-term airtime limit is "+str(self.r_lt_alock)+"%", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting long-term airtime limit is {self.r_lt_alock}%", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_STAT_CHTM):
|
elif (command == KISS.CMD_STAT_CHTM):
|
||||||
if (byte == KISS.FESC):
|
if (byte == KISS.FESC):
|
||||||
escape = True
|
escape = True
|
||||||
@ -813,9 +813,9 @@ class RNodeInterface(Interface):
|
|||||||
self.r_preamble_symbols = prs
|
self.r_preamble_symbols = prs
|
||||||
self.r_premable_time_ms = prt
|
self.r_premable_time_ms = prt
|
||||||
self.r_csma_slot_time_ms = cst
|
self.r_csma_slot_time_ms = cst
|
||||||
RNS.log(str(self)+" Radio reporting symbol time is "+str(round(self.r_symbol_time_ms,2))+"ms (at "+str(self.r_symbol_rate)+" baud)", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting symbol time is {round(self.r_symbol_time_ms, 2)}ms (at {self.r_symbol_rate} baud)", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self)+" Radio reporting preamble is "+str(self.r_preamble_symbols)+" symbols ("+str(self.r_premable_time_ms)+"ms)", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting preamble is {self.r_preamble_symbols} symbols ({self.r_premable_time_ms}ms)", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self)+" Radio reporting CSMA slot time is "+str(self.r_csma_slot_time_ms)+"ms", RNS.LOG_DEBUG)
|
RNS.log(f"{self} Radio reporting CSMA slot time is {self.r_csma_slot_time_ms}ms", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_STAT_BAT):
|
elif (command == KISS.CMD_STAT_BAT):
|
||||||
if (byte == KISS.FESC):
|
if (byte == KISS.FESC):
|
||||||
escape = True
|
escape = True
|
||||||
@ -843,26 +843,26 @@ class RNodeInterface(Interface):
|
|||||||
self.mcu = byte
|
self.mcu = byte
|
||||||
elif (command == KISS.CMD_ERROR):
|
elif (command == KISS.CMD_ERROR):
|
||||||
if (byte == KISS.ERROR_INITRADIO):
|
if (byte == KISS.ERROR_INITRADIO):
|
||||||
RNS.log(str(self)+" hardware initialisation error (code "+RNS.hexrep(byte)+")", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware initialisation error (code {RNS.hexrep(byte)})", RNS.LOG_ERROR)
|
||||||
raise IOError("Radio initialisation failure")
|
raise OSError("Radio initialisation failure")
|
||||||
elif (byte == KISS.ERROR_TXFAILED):
|
elif (byte == KISS.ERROR_TXFAILED):
|
||||||
RNS.log(str(self)+" hardware TX error (code "+RNS.hexrep(byte)+")", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware TX error (code {RNS.hexrep(byte)})", RNS.LOG_ERROR)
|
||||||
raise IOError("Hardware transmit failure")
|
raise OSError("Hardware transmit failure")
|
||||||
elif (byte == KISS.ERROR_MEMORY_LOW):
|
elif (byte == KISS.ERROR_MEMORY_LOW):
|
||||||
RNS.log(str(self)+" hardware error (code "+RNS.hexrep(byte)+"): Memory exhausted", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware error (code {RNS.hexrep(byte)}): Memory exhausted", RNS.LOG_ERROR)
|
||||||
self.hw_errors.append({"error": KISS.ERROR_MEMORY_LOW, "description": "Memory exhausted on connected device"})
|
self.hw_errors.append({"error": KISS.ERROR_MEMORY_LOW, "description": "Memory exhausted on connected device"})
|
||||||
elif (byte == KISS.ERROR_MODEM_TIMEOUT):
|
elif (byte == KISS.ERROR_MODEM_TIMEOUT):
|
||||||
RNS.log(str(self)+" hardware error (code "+RNS.hexrep(byte)+"): Modem communication timed out", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware error (code {RNS.hexrep(byte)}): Modem communication timed out", RNS.LOG_ERROR)
|
||||||
self.hw_errors.append({"error": KISS.ERROR_MODEM_TIMEOUT, "description": "Modem communication timed out on connected device"})
|
self.hw_errors.append({"error": KISS.ERROR_MODEM_TIMEOUT, "description": "Modem communication timed out on connected device"})
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self)+" hardware error (code "+RNS.hexrep(byte)+")", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware error (code {RNS.hexrep(byte)})", RNS.LOG_ERROR)
|
||||||
raise IOError("Unknown hardware failure")
|
raise OSError("Unknown hardware failure")
|
||||||
elif (command == KISS.CMD_RESET):
|
elif (command == KISS.CMD_RESET):
|
||||||
if (byte == 0xF8):
|
if (byte == 0xF8):
|
||||||
if self.platform == KISS.PLATFORM_ESP32:
|
if self.platform == KISS.PLATFORM_ESP32:
|
||||||
if self.online:
|
if self.online:
|
||||||
RNS.log("Detected reset while device was online, reinitialising device...", RNS.LOG_ERROR)
|
RNS.log("Detected reset while device was online, reinitialising device...", RNS.LOG_ERROR)
|
||||||
raise IOError("ESP32 reset")
|
raise OSError("ESP32 reset")
|
||||||
elif (command == KISS.CMD_READY):
|
elif (command == KISS.CMD_READY):
|
||||||
self.process_queue()
|
self.process_queue()
|
||||||
elif (command == KISS.CMD_DETECT):
|
elif (command == KISS.CMD_DETECT):
|
||||||
@ -874,7 +874,7 @@ class RNodeInterface(Interface):
|
|||||||
else:
|
else:
|
||||||
time_since_last = int(time.time()*1000) - last_read_ms
|
time_since_last = int(time.time()*1000) - last_read_ms
|
||||||
if len(data_buffer) > 0 and time_since_last > self.timeout:
|
if len(data_buffer) > 0 and time_since_last > self.timeout:
|
||||||
RNS.log(str(self)+" serial read timeout in command "+str(command), RNS.LOG_WARNING)
|
RNS.log(f"{self} serial read timeout in command {command}", RNS.LOG_WARNING)
|
||||||
data_buffer = b""
|
data_buffer = b""
|
||||||
in_frame = False
|
in_frame = False
|
||||||
command = KISS.CMD_UNKNOWN
|
command = KISS.CMD_UNKNOWN
|
||||||
@ -883,15 +883,15 @@ class RNodeInterface(Interface):
|
|||||||
if self.id_interval != None and self.id_callsign != None:
|
if self.id_interval != None and self.id_callsign != None:
|
||||||
if self.first_tx != None:
|
if self.first_tx != None:
|
||||||
if time.time() > self.first_tx + self.id_interval:
|
if time.time() > self.first_tx + self.id_interval:
|
||||||
RNS.log("Interface "+str(self)+" is transmitting beacon data: "+str(self.id_callsign.decode("utf-8")), RNS.LOG_DEBUG)
|
RNS.log(f"Interface {self} is transmitting beacon data: {self.id_callsign.decode('utf-8')}", RNS.LOG_DEBUG)
|
||||||
self.processOutgoing(self.id_callsign)
|
self.processOutgoing(self.id_callsign)
|
||||||
|
|
||||||
sleep(0.08)
|
sleep(0.08)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"A serial port error occurred, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
RNS.log(f"The interface {self} experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if RNS.Reticulum.panic_on_interface_error:
|
if RNS.Reticulum.panic_on_interface_error:
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
@ -912,16 +912,16 @@ class RNodeInterface(Interface):
|
|||||||
while not self.online and not self.detached:
|
while not self.online and not self.detached:
|
||||||
try:
|
try:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Attempting to reconnect serial port {self.port} for {self}...", RNS.LOG_VERBOSE)
|
||||||
self.open_port()
|
self.open_port()
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while reconnecting port, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.reconnecting = False
|
self.reconnecting = False
|
||||||
if self.online:
|
if self.online:
|
||||||
RNS.log("Reconnected serial port for "+str(self))
|
RNS.log(f"Reconnected serial port for {self}")
|
||||||
|
|
||||||
def detach(self):
|
def detach(self):
|
||||||
self.detached = True
|
self.detached = True
|
||||||
@ -965,7 +965,7 @@ class RNodeInterface(Interface):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "RNodeInterface["+str(self.name)+"]"
|
return f"RNodeInterface[{self.name}]"
|
||||||
|
|
||||||
class BLEConnection():
|
class BLEConnection():
|
||||||
UART_SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
|
UART_SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||||
|
@ -241,14 +241,14 @@ class RNodeMultiInterface(Interface):
|
|||||||
self.id_callsign = id_callsign.encode("utf-8")
|
self.id_callsign = id_callsign.encode("utf-8")
|
||||||
self.id_interval = id_interval
|
self.id_interval = id_interval
|
||||||
else:
|
else:
|
||||||
RNS.log("The encoded ID callsign for "+str(self)+" exceeds the max length of "+str(RNodeMultiInterface.CALLSIGN_MAX_LEN)+" bytes.", RNS.LOG_ERROR)
|
RNS.log(f"The encoded ID callsign for {self} exceeds the max length of {RNodeMultiInterface.CALLSIGN_MAX_LEN} bytes.", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
else:
|
else:
|
||||||
self.id_interval = None
|
self.id_interval = None
|
||||||
self.id_callsign = None
|
self.id_callsign = None
|
||||||
|
|
||||||
if (not self.validcfg):
|
if (not self.validcfg):
|
||||||
raise ValueError("The configuration for "+str(self)+" contains errors, interface is offline")
|
raise ValueError(f"The configuration for {self} contains errors, interface is offline")
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
try:
|
try:
|
||||||
@ -257,11 +257,11 @@ class RNodeMultiInterface(Interface):
|
|||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not open serial port")
|
raise OSError("Could not open serial port")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not open serial port for interface "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Could not open serial port for interface {self}", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("Reticulum will attempt to bring up this interface periodically", RNS.LOG_ERROR)
|
RNS.log("Reticulum will attempt to bring up this interface periodically", RNS.LOG_ERROR)
|
||||||
if not self.detached and not self.reconnecting:
|
if not self.detached and not self.reconnecting:
|
||||||
thread = threading.Thread(target=self.reconnect_port)
|
thread = threading.Thread(target=self.reconnect_port)
|
||||||
@ -269,7 +269,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def open_port(self):
|
def open_port(self):
|
||||||
RNS.log("Opening serial port "+self.port+"...")
|
RNS.log(f"Opening serial port {self.port}...")
|
||||||
self.serial = self.pyserial.Serial(
|
self.serial = self.pyserial.Serial(
|
||||||
port = self.port,
|
port = self.port,
|
||||||
baudrate = self.speed,
|
baudrate = self.speed,
|
||||||
@ -296,13 +296,13 @@ class RNodeMultiInterface(Interface):
|
|||||||
sleep(0.2)
|
sleep(0.2)
|
||||||
|
|
||||||
if not self.detected:
|
if not self.detected:
|
||||||
RNS.log("Could not detect device for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Could not detect device for {self}", RNS.LOG_ERROR)
|
||||||
self.serial.close()
|
self.serial.close()
|
||||||
else:
|
else:
|
||||||
if self.platform == KISS.PLATFORM_ESP32 or self.platform == KISS.PLATFORM_NRF52:
|
if self.platform == KISS.PLATFORM_ESP32 or self.platform == KISS.PLATFORM_NRF52:
|
||||||
self.display = True
|
self.display = True
|
||||||
|
|
||||||
RNS.log("Serial port "+self.port+" is now open")
|
RNS.log(f"Serial port {self.port} is now open")
|
||||||
RNS.log("Creating subinterfaces...", RNS.LOG_VERBOSE)
|
RNS.log("Creating subinterfaces...", RNS.LOG_VERBOSE)
|
||||||
for subint in self.subint_config:
|
for subint in self.subint_config:
|
||||||
subint_vport = int(subint[1])
|
subint_vport = int(subint[1])
|
||||||
@ -333,38 +333,38 @@ class RNodeMultiInterface(Interface):
|
|||||||
interface.HW_MTU = self.HW_MTU
|
interface.HW_MTU = self.HW_MTU
|
||||||
interface.detected = True
|
interface.detected = True
|
||||||
RNS.Transport.interfaces.append(interface)
|
RNS.Transport.interfaces.append(interface)
|
||||||
RNS.log("Spawned new RNode subinterface: "+str(interface), RNS.LOG_VERBOSE)
|
RNS.log(f"Spawned new RNode subinterface: {interface}", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
self.clients += 1
|
self.clients += 1
|
||||||
else:
|
else:
|
||||||
raise ValueError("Virtual port \""+subint[1]+"\" for subinterface "+subint[0]+" does not exist on "+self.name)
|
raise ValueError(f"Virtual port \"{subint[1]}\" for subinterface {subint[0]} does not exist on {self.name}")
|
||||||
self.online = True
|
self.online = True
|
||||||
|
|
||||||
def detect(self):
|
def detect(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_DETECT, KISS.DETECT_REQ, KISS.FEND, KISS.CMD_FW_VERSION, 0x00, KISS.FEND, KISS.CMD_PLATFORM, 0x00, KISS.FEND, KISS.CMD_MCU, 0x00, KISS.FEND, KISS.CMD_INTERFACES, 0x00, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_DETECT, KISS.DETECT_REQ, KISS.FEND, KISS.CMD_FW_VERSION, 0x00, KISS.FEND, KISS.CMD_PLATFORM, 0x00, KISS.FEND, KISS.CMD_MCU, 0x00, KISS.FEND, KISS.CMD_INTERFACES, 0x00, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while detecting hardware for "+str(self))
|
raise OSError(f"An IO error occurred while detecting hardware for {self}")
|
||||||
|
|
||||||
def leave(self):
|
def leave(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_LEAVE, 0xFF, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_LEAVE, 0xFF, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while sending host left command to device")
|
raise OSError("An IO error occurred while sending host left command to device")
|
||||||
|
|
||||||
def enable_external_framebuffer(self):
|
def enable_external_framebuffer(self):
|
||||||
if self.display != None:
|
if self.display != None:
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x01, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x01, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while enabling external framebuffer on device")
|
raise OSError("An IO error occurred while enabling external framebuffer on device")
|
||||||
|
|
||||||
def disable_external_framebuffer(self):
|
def disable_external_framebuffer(self):
|
||||||
if self.display != None:
|
if self.display != None:
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x00, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_FB_EXT, 0x00, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while disabling external framebuffer on device")
|
raise OSError("An IO error occurred while disabling external framebuffer on device")
|
||||||
|
|
||||||
FB_PIXEL_WIDTH = 64
|
FB_PIXEL_WIDTH = 64
|
||||||
FB_BITS_PER_PIXEL = 1
|
FB_BITS_PER_PIXEL = 1
|
||||||
@ -388,13 +388,13 @@ class RNodeMultiInterface(Interface):
|
|||||||
|
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while writing framebuffer data device")
|
raise OSError("An IO error occurred while writing framebuffer data device")
|
||||||
|
|
||||||
def hard_reset(self):
|
def hard_reset(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_RESET, 0xf8, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_RESET, 0xf8, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while restarting device")
|
raise OSError("An IO error occurred while restarting device")
|
||||||
sleep(2.25);
|
sleep(2.25);
|
||||||
|
|
||||||
def setFrequency(self, frequency, interface):
|
def setFrequency(self, frequency, interface):
|
||||||
@ -407,7 +407,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_FREQUENCY])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_FREQUENCY])+data+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring frequency for "+str(self))
|
raise OSError(f"An IO error occurred while configuring frequency for {self}")
|
||||||
self.selected_index = interface.index
|
self.selected_index = interface.index
|
||||||
|
|
||||||
def setBandwidth(self, bandwidth, interface):
|
def setBandwidth(self, bandwidth, interface):
|
||||||
@ -420,7 +420,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_BANDWIDTH])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_BANDWIDTH])+data+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring bandwidth for "+str(self))
|
raise OSError(f"An IO error occurred while configuring bandwidth for {self}")
|
||||||
self.selected_index = interface.index
|
self.selected_index = interface.index
|
||||||
|
|
||||||
def setTXPower(self, txpower, interface):
|
def setTXPower(self, txpower, interface):
|
||||||
@ -428,7 +428,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_TXPOWER])+txp+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_TXPOWER])+txp+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring TX power for "+str(self))
|
raise OSError(f"An IO error occurred while configuring TX power for {self}")
|
||||||
self.selected_index = interface.index
|
self.selected_index = interface.index
|
||||||
|
|
||||||
def setSpreadingFactor(self, sf, interface):
|
def setSpreadingFactor(self, sf, interface):
|
||||||
@ -436,7 +436,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_SF])+sf+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_SF])+sf+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring spreading factor for "+str(self))
|
raise OSError(f"An IO error occurred while configuring spreading factor for {self}")
|
||||||
self.selected_index = interface.index
|
self.selected_index = interface.index
|
||||||
|
|
||||||
def setCodingRate(self, cr, interface):
|
def setCodingRate(self, cr, interface):
|
||||||
@ -444,7 +444,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_CR])+cr+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_CR])+cr+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring coding rate for "+str(self))
|
raise OSError(f"An IO error occurred while configuring coding rate for {self}")
|
||||||
self.selected_index = interface.index
|
self.selected_index = interface.index
|
||||||
|
|
||||||
def setSTALock(self, st_alock, interface):
|
def setSTALock(self, st_alock, interface):
|
||||||
@ -457,7 +457,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_ST_ALOCK])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_ST_ALOCK])+data+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring short-term airtime limit for "+str(self))
|
raise OSError(f"An IO error occurred while configuring short-term airtime limit for {self}")
|
||||||
self.selected_index = interface.index
|
self.selected_index = interface.index
|
||||||
|
|
||||||
def setLTALock(self, lt_alock, interface):
|
def setLTALock(self, lt_alock, interface):
|
||||||
@ -470,7 +470,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_LT_ALOCK])+data+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_LT_ALOCK])+data+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring long-term airtime limit for "+str(self))
|
raise OSError(f"An IO error occurred while configuring long-term airtime limit for {self}")
|
||||||
self.selected_index = interface.index
|
self.selected_index = interface.index
|
||||||
|
|
||||||
def setRadioState(self, state, interface):
|
def setRadioState(self, state, interface):
|
||||||
@ -478,7 +478,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_RADIO_STATE])+bytes([state])+bytes([KISS.FEND])
|
kiss_command = bytes([KISS.FEND])+bytes([interface.sel_cmd])+bytes([KISS.FEND])+bytes([KISS.FEND])+bytes([KISS.CMD_RADIO_STATE])+bytes([state])+bytes([KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while configuring radio state for "+str(self))
|
raise OSError(f"An IO error occurred while configuring radio state for {self}")
|
||||||
self.selected_index = interface.index
|
self.selected_index = interface.index
|
||||||
|
|
||||||
def validate_firmware(self):
|
def validate_firmware(self):
|
||||||
@ -489,8 +489,8 @@ class RNodeMultiInterface(Interface):
|
|||||||
if self.firmware_ok:
|
if self.firmware_ok:
|
||||||
return
|
return
|
||||||
|
|
||||||
RNS.log("The firmware version of the connected RNode is "+str(self.maj_version)+"."+str(self.min_version), RNS.LOG_ERROR)
|
RNS.log(f"The firmware version of the connected RNode is {self.maj_version}.{self.min_version}", RNS.LOG_ERROR)
|
||||||
RNS.log("This version of Reticulum requires at least version "+str(RNodeMultiInterface.REQUIRED_FW_VER_MAJ)+"."+str(RNodeMultiInterface.REQUIRED_FW_VER_MIN), RNS.LOG_ERROR)
|
RNS.log(f"This version of Reticulum requires at least version {RNodeMultiInterface.REQUIRED_FW_VER_MAJ}.{RNodeMultiInterface.REQUIRED_FW_VER_MIN}", RNS.LOG_ERROR)
|
||||||
RNS.log("Please update your RNode firmware with rnodeconf from https://github.com/markqvist/Reticulum/RNS/Utilities/rnodeconf.py")
|
RNS.log("Please update your RNode firmware with rnodeconf from https://github.com/markqvist/Reticulum/RNS/Utilities/rnodeconf.py")
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
|
|
||||||
@ -506,7 +506,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
self.txb += len(data)
|
self.txb += len(data)
|
||||||
|
|
||||||
if written != len(frame):
|
if written != len(frame):
|
||||||
raise IOError("Serial interface only wrote "+str(written)+" bytes of "+str(len(data)))
|
raise OSError(f"Serial interface only wrote {written} bytes of {len(data)}")
|
||||||
|
|
||||||
def received_announce(self, from_spawned=False):
|
def received_announce(self, from_spawned=False):
|
||||||
if from_spawned: self.ia_freq_deque.append(time.time())
|
if from_spawned: self.ia_freq_deque.append(time.time())
|
||||||
@ -589,7 +589,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
command_buffer = command_buffer+bytes([byte])
|
command_buffer = command_buffer+bytes([byte])
|
||||||
if (len(command_buffer) == 4):
|
if (len(command_buffer) == 4):
|
||||||
self.subinterfaces[self.selected_index].r_frequency = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
self.subinterfaces[self.selected_index].r_frequency = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting frequency is "+str(self.subinterfaces[self.selected_index].r_frequency/1000000.0)+" MHz", RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting frequency is {self.subinterfaces[self.selected_index].r_frequency / 1000000.0} MHz", RNS.LOG_DEBUG)
|
||||||
self.subinterfaces[self.selected_index].updateBitrate()
|
self.subinterfaces[self.selected_index].updateBitrate()
|
||||||
|
|
||||||
elif (command == KISS.CMD_BANDWIDTH):
|
elif (command == KISS.CMD_BANDWIDTH):
|
||||||
@ -605,20 +605,20 @@ class RNodeMultiInterface(Interface):
|
|||||||
command_buffer = command_buffer+bytes([byte])
|
command_buffer = command_buffer+bytes([byte])
|
||||||
if (len(command_buffer) == 4):
|
if (len(command_buffer) == 4):
|
||||||
self.subinterfaces[self.selected_index].r_bandwidth = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
self.subinterfaces[self.selected_index].r_bandwidth = command_buffer[0] << 24 | command_buffer[1] << 16 | command_buffer[2] << 8 | command_buffer[3]
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting bandwidth is "+str(self.subinterfaces[self.selected_index].r_bandwidth/1000.0)+" KHz", RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting bandwidth is {self.subinterfaces[self.selected_index].r_bandwidth / 1000.0} KHz", RNS.LOG_DEBUG)
|
||||||
self.subinterfaces[self.selected_index].updateBitrate()
|
self.subinterfaces[self.selected_index].updateBitrate()
|
||||||
|
|
||||||
elif (command == KISS.CMD_TXPOWER):
|
elif (command == KISS.CMD_TXPOWER):
|
||||||
txp = byte - 256 if byte > 127 else byte
|
txp = byte - 256 if byte > 127 else byte
|
||||||
self.subinterfaces[self.selected_index].r_txpower = txp
|
self.subinterfaces[self.selected_index].r_txpower = txp
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting TX power is "+str(self.subinterfaces[self.selected_index].r_txpower)+" dBm", RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting TX power is {self.subinterfaces[self.selected_index].r_txpower} dBm", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_SF):
|
elif (command == KISS.CMD_SF):
|
||||||
self.subinterfaces[self.selected_index].r_sf = byte
|
self.subinterfaces[self.selected_index].r_sf = byte
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting spreading factor is "+str(self.subinterfaces[self.selected_index].r_sf), RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting spreading factor is {self.subinterfaces[self.selected_index].r_sf}", RNS.LOG_DEBUG)
|
||||||
self.subinterfaces[self.selected_index].updateBitrate()
|
self.subinterfaces[self.selected_index].updateBitrate()
|
||||||
elif (command == KISS.CMD_CR):
|
elif (command == KISS.CMD_CR):
|
||||||
self.subinterfaces[self.selected_index].r_cr = byte
|
self.subinterfaces[self.selected_index].r_cr = byte
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting coding rate is "+str(self.subinterfaces[self.selected_index].r_cr), RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting coding rate is {self.subinterfaces[self.selected_index].r_cr}", RNS.LOG_DEBUG)
|
||||||
self.subinterfaces[self.selected_index].updateBitrate()
|
self.subinterfaces[self.selected_index].updateBitrate()
|
||||||
elif (command == KISS.CMD_RADIO_STATE):
|
elif (command == KISS.CMD_RADIO_STATE):
|
||||||
self.subinterfaces[self.selected_index].r_state = byte
|
self.subinterfaces[self.selected_index].r_state = byte
|
||||||
@ -626,7 +626,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
pass
|
pass
|
||||||
#RNS.log(str(self)+" Radio reporting state is online", RNS.LOG_DEBUG)
|
#RNS.log(str(self)+" Radio reporting state is online", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting state is offline", RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting state is offline", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
elif (command == KISS.CMD_RADIO_LOCK):
|
elif (command == KISS.CMD_RADIO_LOCK):
|
||||||
self.subinterfaces[self.selected_index].r_lock = byte
|
self.subinterfaces[self.selected_index].r_lock = byte
|
||||||
@ -705,7 +705,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
if (len(command_buffer) == 2):
|
if (len(command_buffer) == 2):
|
||||||
at = command_buffer[0] << 8 | command_buffer[1]
|
at = command_buffer[0] << 8 | command_buffer[1]
|
||||||
self.subinterfaces[self.selected_index].r_st_alock = at/100.0
|
self.subinterfaces[self.selected_index].r_st_alock = at/100.0
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting short-term airtime limit is "+str(self.subinterfaces[self.selected_index].r_st_alock)+"%", RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting short-term airtime limit is {self.subinterfaces[self.selected_index].r_st_alock}%", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_LT_ALOCK):
|
elif (command == KISS.CMD_LT_ALOCK):
|
||||||
if (byte == KISS.FESC):
|
if (byte == KISS.FESC):
|
||||||
escape = True
|
escape = True
|
||||||
@ -720,7 +720,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
if (len(command_buffer) == 2):
|
if (len(command_buffer) == 2):
|
||||||
at = command_buffer[0] << 8 | command_buffer[1]
|
at = command_buffer[0] << 8 | command_buffer[1]
|
||||||
self.subinterfaces[self.selected_index].r_lt_alock = at/100.0
|
self.subinterfaces[self.selected_index].r_lt_alock = at/100.0
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting long-term airtime limit is "+str(self.subinterfaces[self.selected_index].r_lt_alock)+"%", RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting long-term airtime limit is {self.subinterfaces[self.selected_index].r_lt_alock}%", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_STAT_CHTM):
|
elif (command == KISS.CMD_STAT_CHTM):
|
||||||
if (byte == KISS.FESC):
|
if (byte == KISS.FESC):
|
||||||
escape = True
|
escape = True
|
||||||
@ -766,9 +766,9 @@ class RNodeMultiInterface(Interface):
|
|||||||
self.subinterfaces[self.selected_index].r_preamble_symbols = prs
|
self.subinterfaces[self.selected_index].r_preamble_symbols = prs
|
||||||
self.subinterfaces[self.selected_index].r_premable_time_ms = prt
|
self.subinterfaces[self.selected_index].r_premable_time_ms = prt
|
||||||
self.subinterfaces[self.selected_index].r_csma_slot_time_ms = cst
|
self.subinterfaces[self.selected_index].r_csma_slot_time_ms = cst
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting symbol time is "+str(round(self.subinterfaces[self.selected_index].r_symbol_time_ms,2))+"ms (at "+str(self.subinterfaces[self.selected_index].r_symbol_rate)+" baud)", RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting symbol time is {round(self.subinterfaces[self.selected_index].r_symbol_time_ms, 2)}ms (at {self.subinterfaces[self.selected_index].r_symbol_rate} baud)", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting preamble is "+str(self.subinterfaces[self.selected_index].r_preamble_symbols)+" symbols ("+str(self.subinterfaces[self.selected_index].r_premable_time_ms)+"ms)", RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting preamble is {self.subinterfaces[self.selected_index].r_preamble_symbols} symbols ({self.subinterfaces[self.selected_index].r_premable_time_ms}ms)", RNS.LOG_DEBUG)
|
||||||
RNS.log(str(self.subinterfaces[self.selected_index])+" Radio reporting CSMA slot time is "+str(self.subinterfaces[self.selected_index].r_csma_slot_time_ms)+"ms", RNS.LOG_DEBUG)
|
RNS.log(f"{self.subinterfaces[self.selected_index]} Radio reporting CSMA slot time is {self.subinterfaces[self.selected_index].r_csma_slot_time_ms}ms", RNS.LOG_DEBUG)
|
||||||
elif (command == KISS.CMD_RANDOM):
|
elif (command == KISS.CMD_RANDOM):
|
||||||
self.r_random = byte
|
self.r_random = byte
|
||||||
elif (command == KISS.CMD_PLATFORM):
|
elif (command == KISS.CMD_PLATFORM):
|
||||||
@ -777,20 +777,20 @@ class RNodeMultiInterface(Interface):
|
|||||||
self.mcu = byte
|
self.mcu = byte
|
||||||
elif (command == KISS.CMD_ERROR):
|
elif (command == KISS.CMD_ERROR):
|
||||||
if (byte == KISS.ERROR_INITRADIO):
|
if (byte == KISS.ERROR_INITRADIO):
|
||||||
RNS.log(str(self)+" hardware initialisation error (code "+RNS.hexrep(byte)+")", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware initialisation error (code {RNS.hexrep(byte)})", RNS.LOG_ERROR)
|
||||||
raise IOError("Radio initialisation failure")
|
raise OSError("Radio initialisation failure")
|
||||||
elif (byte == KISS.ERROR_TXFAILED):
|
elif (byte == KISS.ERROR_TXFAILED):
|
||||||
RNS.log(str(self)+" hardware TX error (code "+RNS.hexrep(byte)+")", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware TX error (code {RNS.hexrep(byte)})", RNS.LOG_ERROR)
|
||||||
raise IOError("Hardware transmit failure")
|
raise OSError("Hardware transmit failure")
|
||||||
else:
|
else:
|
||||||
RNS.log(str(self)+" hardware error (code "+RNS.hexrep(byte)+")", RNS.LOG_ERROR)
|
RNS.log(f"{self} hardware error (code {RNS.hexrep(byte)})", RNS.LOG_ERROR)
|
||||||
raise IOError("Unknown hardware failure")
|
raise OSError("Unknown hardware failure")
|
||||||
elif (command == KISS.CMD_RESET):
|
elif (command == KISS.CMD_RESET):
|
||||||
if (byte == 0xF8):
|
if (byte == 0xF8):
|
||||||
if self.platform == KISS.PLATFORM_ESP32:
|
if self.platform == KISS.PLATFORM_ESP32:
|
||||||
if self.online:
|
if self.online:
|
||||||
RNS.log("Detected reset while device was online, reinitialising device...", RNS.LOG_ERROR)
|
RNS.log("Detected reset while device was online, reinitialising device...", RNS.LOG_ERROR)
|
||||||
raise IOError("ESP32 reset")
|
raise OSError("ESP32 reset")
|
||||||
elif (command == KISS.CMD_READY):
|
elif (command == KISS.CMD_READY):
|
||||||
self.process_queue()
|
self.process_queue()
|
||||||
elif (command == KISS.CMD_DETECT):
|
elif (command == KISS.CMD_DETECT):
|
||||||
@ -808,7 +808,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
else:
|
else:
|
||||||
time_since_last = int(time.time()*1000) - last_read_ms
|
time_since_last = int(time.time()*1000) - last_read_ms
|
||||||
if len(data_buffer) > 0 and time_since_last > self.timeout:
|
if len(data_buffer) > 0 and time_since_last > self.timeout:
|
||||||
RNS.log(str(self)+" serial read timeout in command "+str(command), RNS.LOG_WARNING)
|
RNS.log(f"{self} serial read timeout in command {command}", RNS.LOG_WARNING)
|
||||||
data_buffer = b""
|
data_buffer = b""
|
||||||
in_frame = False
|
in_frame = False
|
||||||
command = KISS.CMD_UNKNOWN
|
command = KISS.CMD_UNKNOWN
|
||||||
@ -824,14 +824,14 @@ class RNodeMultiInterface(Interface):
|
|||||||
self.subinterfaces[interface.index].processOutgoing(self.id_callsign)
|
self.subinterfaces[interface.index].processOutgoing(self.id_callsign)
|
||||||
|
|
||||||
if interface_available:
|
if interface_available:
|
||||||
RNS.log("Interface "+str(self)+" is transmitting beacon data on all subinterfaces: "+str(self.id_callsign.decode("utf-8")), RNS.LOG_DEBUG)
|
RNS.log(f"Interface {self} is transmitting beacon data on all subinterfaces: {self.id_callsign.decode('utf-8')}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
sleep(0.08)
|
sleep(0.08)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"A serial port error occurred, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
RNS.log(f"The interface {self} experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if RNS.Reticulum.panic_on_interface_error:
|
if RNS.Reticulum.panic_on_interface_error:
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
@ -854,16 +854,16 @@ class RNodeMultiInterface(Interface):
|
|||||||
while not self.online and not self.detached:
|
while not self.online and not self.detached:
|
||||||
try:
|
try:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Attempting to reconnect serial port {self.port} for {self}...", RNS.LOG_VERBOSE)
|
||||||
self.open_port()
|
self.open_port()
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while reconnecting port, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.reconnecting = False
|
self.reconnecting = False
|
||||||
if self.online:
|
if self.online:
|
||||||
RNS.log("Reconnected serial port for "+str(self))
|
RNS.log(f"Reconnected serial port for {self}")
|
||||||
|
|
||||||
def detach(self):
|
def detach(self):
|
||||||
self.detached = True
|
self.detached = True
|
||||||
@ -890,7 +890,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
interface.process_queue()
|
interface.process_queue()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "RNodeMultiInterface["+str(self.name)+"]"
|
return f"RNodeMultiInterface[{self.name}]"
|
||||||
|
|
||||||
class RNodeSubInterface(Interface):
|
class RNodeSubInterface(Interface):
|
||||||
LOW_FREQ_MIN = 137000000
|
LOW_FREQ_MIN = 137000000
|
||||||
@ -1019,42 +1019,42 @@ class RNodeSubInterface(Interface):
|
|||||||
self.validcfg = True
|
self.validcfg = True
|
||||||
if (self.interface_type == "SX126X" or self.interface_type == "SX127X"):
|
if (self.interface_type == "SX126X" or self.interface_type == "SX127X"):
|
||||||
if (self.frequency < RNodeSubInterface.LOW_FREQ_MIN or self.frequency > RNodeSubInterface.LOW_FREQ_MAX):
|
if (self.frequency < RNodeSubInterface.LOW_FREQ_MIN or self.frequency > RNodeSubInterface.LOW_FREQ_MAX):
|
||||||
RNS.log("Invalid frequency configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid frequency configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
elif (self.interface_type == "SX128X"):
|
elif (self.interface_type == "SX128X"):
|
||||||
if (self.frequency < RNodeSubInterface.HIGH_FREQ_MIN or self.frequency > RNodeSubInterface.HIGH_FREQ_MAX):
|
if (self.frequency < RNodeSubInterface.HIGH_FREQ_MIN or self.frequency > RNodeSubInterface.HIGH_FREQ_MAX):
|
||||||
RNS.log("Invalid frequency configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid frequency configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
else:
|
else:
|
||||||
RNS.log("Invalid interface type configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid interface type configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.txpower < -9 or self.txpower > 27):
|
if (self.txpower < -9 or self.txpower > 27):
|
||||||
RNS.log("Invalid TX power configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid TX power configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.bandwidth < 7800 or self.bandwidth > 1625000):
|
if (self.bandwidth < 7800 or self.bandwidth > 1625000):
|
||||||
RNS.log("Invalid bandwidth configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid bandwidth configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.sf < 5 or self.sf > 12):
|
if (self.sf < 5 or self.sf > 12):
|
||||||
RNS.log("Invalid spreading factor configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid spreading factor configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.cr < 5 or self.cr > 8):
|
if (self.cr < 5 or self.cr > 8):
|
||||||
RNS.log("Invalid coding rate configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid coding rate configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.st_alock and (self.st_alock < 0.0 or self.st_alock > 100.0)):
|
if (self.st_alock and (self.st_alock < 0.0 or self.st_alock > 100.0)):
|
||||||
RNS.log("Invalid short-term airtime limit configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid short-term airtime limit configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (self.lt_alock and (self.lt_alock < 0.0 or self.lt_alock > 100.0)):
|
if (self.lt_alock and (self.lt_alock < 0.0 or self.lt_alock > 100.0)):
|
||||||
RNS.log("Invalid long-term airtime limit configured for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Invalid long-term airtime limit configured for {self}", RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
if (not self.validcfg):
|
if (not self.validcfg):
|
||||||
raise ValueError("The configuration for "+str(self)+" contains errors, interface is offline")
|
raise ValueError(f"The configuration for {self} contains errors, interface is offline")
|
||||||
|
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
|
|
||||||
@ -1068,15 +1068,15 @@ class RNodeSubInterface(Interface):
|
|||||||
self.r_lock = None
|
self.r_lock = None
|
||||||
sleep(2.0)
|
sleep(2.0)
|
||||||
|
|
||||||
RNS.log("Configuring RNode subinterface "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Configuring RNode subinterface {self}...", RNS.LOG_VERBOSE)
|
||||||
self.initRadio()
|
self.initRadio()
|
||||||
if (self.validateRadioState()):
|
if (self.validateRadioState()):
|
||||||
self.interface_ready = True
|
self.interface_ready = True
|
||||||
RNS.log(str(self)+" is configured and powered up")
|
RNS.log(f"{self} is configured and powered up")
|
||||||
sleep(0.3)
|
sleep(0.3)
|
||||||
self.online = True
|
self.online = True
|
||||||
else:
|
else:
|
||||||
RNS.log("After configuring "+str(self)+", the reported radio parameters did not match your configuration.", RNS.LOG_ERROR)
|
RNS.log(f"After configuring {self}, the reported radio parameters did not match your configuration.", RNS.LOG_ERROR)
|
||||||
RNS.log("Make sure that your hardware actually supports the parameters specified in the configuration", RNS.LOG_ERROR)
|
RNS.log("Make sure that your hardware actually supports the parameters specified in the configuration", RNS.LOG_ERROR)
|
||||||
RNS.log("Aborting RNode startup", RNS.LOG_ERROR)
|
RNS.log("Aborting RNode startup", RNS.LOG_ERROR)
|
||||||
|
|
||||||
@ -1093,7 +1093,7 @@ class RNodeSubInterface(Interface):
|
|||||||
self.state = KISS.RADIO_STATE_ON
|
self.state = KISS.RADIO_STATE_ON
|
||||||
|
|
||||||
def validateRadioState(self):
|
def validateRadioState(self):
|
||||||
RNS.log("Waiting for radio configuration validation for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Waiting for radio configuration validation for {self}...", RNS.LOG_VERBOSE)
|
||||||
sleep(0.25);
|
sleep(0.25);
|
||||||
|
|
||||||
self.validcfg = True
|
self.validcfg = True
|
||||||
@ -1123,7 +1123,7 @@ class RNodeSubInterface(Interface):
|
|||||||
try:
|
try:
|
||||||
self.bitrate = self.r_sf * ( (4.0/self.r_cr) / (math.pow(2,self.r_sf)/(self.r_bandwidth/1000)) ) * 1000
|
self.bitrate = self.r_sf * ( (4.0/self.r_cr) / (math.pow(2,self.r_sf)/(self.r_bandwidth/1000)) ) * 1000
|
||||||
self.bitrate_kbps = round(self.bitrate/1000.0, 2)
|
self.bitrate_kbps = round(self.bitrate/1000.0, 2)
|
||||||
RNS.log(str(self)+" On-air bitrate is now "+str(self.bitrate_kbps)+ " kbps", RNS.LOG_VERBOSE)
|
RNS.log(f"{self} On-air bitrate is now {self.bitrate_kbps} kbps", RNS.LOG_VERBOSE)
|
||||||
except:
|
except:
|
||||||
self.bitrate = 0
|
self.bitrate = 0
|
||||||
|
|
||||||
@ -1162,4 +1162,4 @@ class RNodeSubInterface(Interface):
|
|||||||
self.interface_ready = True
|
self.interface_ready = True
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.parent_interface.name+"["+self.name+"]"
|
return f"{self.parent_interface.name}[{self.name}]"
|
||||||
|
@ -86,17 +86,17 @@ class SerialInterface(Interface):
|
|||||||
try:
|
try:
|
||||||
self.open_port()
|
self.open_port()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not open serial port for interface "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Could not open serial port for interface {self}", RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
else:
|
else:
|
||||||
raise IOError("Could not open serial port")
|
raise OSError("Could not open serial port")
|
||||||
|
|
||||||
|
|
||||||
def open_port(self):
|
def open_port(self):
|
||||||
RNS.log("Opening serial port "+self.port+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Opening serial port {self.port}...", RNS.LOG_VERBOSE)
|
||||||
self.serial = self.pyserial.Serial(
|
self.serial = self.pyserial.Serial(
|
||||||
port = self.port,
|
port = self.port,
|
||||||
baudrate = self.speed,
|
baudrate = self.speed,
|
||||||
@ -118,7 +118,7 @@ class SerialInterface(Interface):
|
|||||||
thread.daemon = True
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
self.online = True
|
self.online = True
|
||||||
RNS.log("Serial port "+self.port+" is now open", RNS.LOG_VERBOSE)
|
RNS.log(f"Serial port {self.port} is now open", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
@ -132,7 +132,7 @@ class SerialInterface(Interface):
|
|||||||
written = self.serial.write(data)
|
written = self.serial.write(data)
|
||||||
self.txb += len(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 OSError(f"Serial interface only wrote {written} bytes of {len(data)}")
|
||||||
|
|
||||||
|
|
||||||
def readLoop(self):
|
def readLoop(self):
|
||||||
@ -175,8 +175,8 @@ class SerialInterface(Interface):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"A serial port error occurred, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
RNS.log(f"The interface {self} experienced an unrecoverable error and is now offline.", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if RNS.Reticulum.panic_on_interface_error:
|
if RNS.Reticulum.panic_on_interface_error:
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
@ -191,17 +191,17 @@ class SerialInterface(Interface):
|
|||||||
while not self.online:
|
while not self.online:
|
||||||
try:
|
try:
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
RNS.log("Attempting to reconnect serial port "+str(self.port)+" for "+str(self)+"...", RNS.LOG_VERBOSE)
|
RNS.log(f"Attempting to reconnect serial port {self.port} for {self}...", RNS.LOG_VERBOSE)
|
||||||
self.open_port()
|
self.open_port()
|
||||||
if self.serial.is_open:
|
if self.serial.is_open:
|
||||||
self.configure_device()
|
self.configure_device()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while reconnecting port, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while reconnecting port, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
RNS.log("Reconnected serial port for "+str(self))
|
RNS.log(f"Reconnected serial port for {self}")
|
||||||
|
|
||||||
def should_ingress_limit(self):
|
def should_ingress_limit(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "SerialInterface["+self.name+"]"
|
return f"SerialInterface[{self.name}]"
|
||||||
|
@ -180,25 +180,25 @@ class TCPClientInterface(Interface):
|
|||||||
if self.socket != None:
|
if self.socket != None:
|
||||||
if hasattr(self.socket, "close"):
|
if hasattr(self.socket, "close"):
|
||||||
if callable(self.socket.close):
|
if callable(self.socket.close):
|
||||||
RNS.log("Detaching "+str(self), RNS.LOG_DEBUG)
|
RNS.log(f"Detaching {self}", RNS.LOG_DEBUG)
|
||||||
self.detached = True
|
self.detached = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.socket.shutdown(socket.SHUT_RDWR)
|
self.socket.shutdown(socket.SHUT_RDWR)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while shutting down socket for "+str(self)+": "+str(e))
|
RNS.log(f"Error while shutting down socket for {self}: {e}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while closing socket for "+str(self)+": "+str(e))
|
RNS.log(f"Error while closing socket for {self}: {e}")
|
||||||
|
|
||||||
self.socket = None
|
self.socket = None
|
||||||
|
|
||||||
def connect(self, initial=False):
|
def connect(self, initial=False):
|
||||||
try:
|
try:
|
||||||
if initial:
|
if initial:
|
||||||
RNS.log("Establishing TCP connection for "+str(self)+"...", RNS.LOG_DEBUG)
|
RNS.log(f"Establishing TCP connection for {self}...", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.socket.settimeout(TCPClientInterface.INITIAL_CONNECT_TIMEOUT)
|
self.socket.settimeout(TCPClientInterface.INITIAL_CONNECT_TIMEOUT)
|
||||||
@ -208,12 +208,12 @@ class TCPClientInterface(Interface):
|
|||||||
self.online = True
|
self.online = True
|
||||||
|
|
||||||
if initial:
|
if initial:
|
||||||
RNS.log("TCP connection for "+str(self)+" established", RNS.LOG_DEBUG)
|
RNS.log(f"TCP connection for {self} established", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if initial:
|
if initial:
|
||||||
RNS.log("Initial connection for "+str(self)+" could not be established: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Initial connection for {self} could not be established: {e}", RNS.LOG_ERROR)
|
||||||
RNS.log("Leaving unconnected and retrying connection in "+str(TCPClientInterface.RECONNECT_WAIT)+" seconds.", RNS.LOG_ERROR)
|
RNS.log(f"Leaving unconnected and retrying connection in {TCPClientInterface.RECONNECT_WAIT} seconds.", RNS.LOG_ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -241,7 +241,7 @@ class TCPClientInterface(Interface):
|
|||||||
attempts += 1
|
attempts += 1
|
||||||
|
|
||||||
if self.max_reconnect_tries != None and attempts > self.max_reconnect_tries:
|
if self.max_reconnect_tries != None and attempts > self.max_reconnect_tries:
|
||||||
RNS.log("Max reconnection attempts reached for "+str(self), RNS.LOG_ERROR)
|
RNS.log(f"Max reconnection attempts reached for {self}", RNS.LOG_ERROR)
|
||||||
self.teardown()
|
self.teardown()
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -249,10 +249,10 @@ class TCPClientInterface(Interface):
|
|||||||
self.connect()
|
self.connect()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Connection attempt for "+str(self)+" failed: "+str(e), RNS.LOG_DEBUG)
|
RNS.log(f"Connection attempt for {self} failed: {e}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
if not self.never_connected:
|
if not self.never_connected:
|
||||||
RNS.log("Reconnected socket for "+str(self)+".", RNS.LOG_INFO)
|
RNS.log(f"Reconnected socket for {self}.", RNS.LOG_INFO)
|
||||||
|
|
||||||
self.reconnecting = False
|
self.reconnecting = False
|
||||||
thread = threading.Thread(target=self.read_loop)
|
thread = threading.Thread(target=self.read_loop)
|
||||||
@ -263,7 +263,7 @@ class TCPClientInterface(Interface):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Attempt to reconnect on a non-initiator TCP interface. This should not happen.", RNS.LOG_ERROR)
|
RNS.log("Attempt to reconnect on a non-initiator TCP interface. This should not happen.", RNS.LOG_ERROR)
|
||||||
raise IOError("Attempt to reconnect on a non-initiator TCP interface")
|
raise OSError("Attempt to reconnect on a non-initiator TCP interface")
|
||||||
|
|
||||||
def processIncoming(self, data):
|
def processIncoming(self, data):
|
||||||
self.rxb += len(data)
|
self.rxb += len(data)
|
||||||
@ -292,8 +292,8 @@ class TCPClientInterface(Interface):
|
|||||||
self.parent_interface.txb += len(data)
|
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(f"Exception occurred while transmitting via {self}, tearing down interface", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
self.teardown()
|
self.teardown()
|
||||||
|
|
||||||
|
|
||||||
@ -361,10 +361,10 @@ class TCPClientInterface(Interface):
|
|||||||
else:
|
else:
|
||||||
self.online = False
|
self.online = False
|
||||||
if self.initiator and not self.detached:
|
if self.initiator and not self.detached:
|
||||||
RNS.log("The socket for "+str(self)+" was closed, attempting to reconnect...", RNS.LOG_WARNING)
|
RNS.log(f"The socket for {self} was closed, attempting to reconnect...", RNS.LOG_WARNING)
|
||||||
self.reconnect()
|
self.reconnect()
|
||||||
else:
|
else:
|
||||||
RNS.log("The socket for remote client "+str(self)+" was closed.", RNS.LOG_VERBOSE)
|
RNS.log(f"The socket for remote client {self} was closed.", RNS.LOG_VERBOSE)
|
||||||
self.teardown()
|
self.teardown()
|
||||||
|
|
||||||
break
|
break
|
||||||
@ -372,7 +372,7 @@ class TCPClientInterface(Interface):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.online = False
|
self.online = False
|
||||||
RNS.log("An interface error occurred for "+str(self)+", the contained exception was: "+str(e), RNS.LOG_WARNING)
|
RNS.log(f"An interface error occurred for {self}, the contained exception was: {e}", RNS.LOG_WARNING)
|
||||||
|
|
||||||
if self.initiator:
|
if self.initiator:
|
||||||
RNS.log("Attempting to reconnect...", RNS.LOG_WARNING)
|
RNS.log("Attempting to reconnect...", RNS.LOG_WARNING)
|
||||||
@ -382,12 +382,12 @@ class TCPClientInterface(Interface):
|
|||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
if self.initiator and not self.detached:
|
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(f"The interface {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()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("The interface "+str(self)+" is being torn down.", RNS.LOG_VERBOSE)
|
RNS.log(f"The interface {self} is being torn down.", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
self.online = False
|
self.online = False
|
||||||
self.OUT = False
|
self.OUT = False
|
||||||
@ -402,7 +402,7 @@ class TCPClientInterface(Interface):
|
|||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "TCPInterface["+str(self.name)+"/"+str(self.target_ip)+":"+str(self.target_port)+"]"
|
return f"TCPInterface[{self.name}/{self.target_ip}:{self.target_port}]"
|
||||||
|
|
||||||
|
|
||||||
class TCPServerInterface(Interface):
|
class TCPServerInterface(Interface):
|
||||||
@ -466,7 +466,7 @@ class TCPServerInterface(Interface):
|
|||||||
|
|
||||||
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)
|
||||||
interface_name = "Client on "+self.name
|
interface_name = f"Client on {self.name}"
|
||||||
spawned_interface = TCPClientInterface(self.owner, interface_name, target_ip=None, target_port=None, connected_socket=handler.request, i2p_tunneled=self.i2p_tunneled)
|
spawned_interface = TCPClientInterface(self.owner, interface_name, target_ip=None, target_port=None, connected_socket=handler.request, i2p_tunneled=self.i2p_tunneled)
|
||||||
spawned_interface.OUT = self.OUT
|
spawned_interface.OUT = self.OUT
|
||||||
spawned_interface.IN = self.IN
|
spawned_interface.IN = self.IN
|
||||||
@ -501,7 +501,7 @@ class TCPServerInterface(Interface):
|
|||||||
spawned_interface.mode = self.mode
|
spawned_interface.mode = self.mode
|
||||||
spawned_interface.HW_MTU = self.HW_MTU
|
spawned_interface.HW_MTU = self.HW_MTU
|
||||||
spawned_interface.online = True
|
spawned_interface.online = True
|
||||||
RNS.log("Spawned new TCPClient Interface: "+str(spawned_interface), RNS.LOG_VERBOSE)
|
RNS.log(f"Spawned new TCPClient Interface: {spawned_interface}", RNS.LOG_VERBOSE)
|
||||||
RNS.Transport.interfaces.append(spawned_interface)
|
RNS.Transport.interfaces.append(spawned_interface)
|
||||||
self.clients += 1
|
self.clients += 1
|
||||||
spawned_interface.read_loop()
|
spawned_interface.read_loop()
|
||||||
@ -521,17 +521,17 @@ class TCPServerInterface(Interface):
|
|||||||
if hasattr(self.server, "shutdown"):
|
if hasattr(self.server, "shutdown"):
|
||||||
if callable(self.server.shutdown):
|
if callable(self.server.shutdown):
|
||||||
try:
|
try:
|
||||||
RNS.log("Detaching "+str(self), RNS.LOG_DEBUG)
|
RNS.log(f"Detaching {self}", RNS.LOG_DEBUG)
|
||||||
self.server.shutdown()
|
self.server.shutdown()
|
||||||
self.detached = True
|
self.detached = True
|
||||||
self.server = None
|
self.server = None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while shutting down server for "+str(self)+": "+str(e))
|
RNS.log(f"Error while shutting down server for {self}: {e}")
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "TCPServerInterface["+self.name+"/"+self.bind_ip+":"+str(self.bind_port)+"]"
|
return f"TCPServerInterface[{self.name}/{self.bind_ip}:{self.bind_port}]"
|
||||||
|
|
||||||
|
|
||||||
class TCPInterfaceHandler(socketserver.BaseRequestHandler):
|
class TCPInterfaceHandler(socketserver.BaseRequestHandler):
|
||||||
|
@ -101,11 +101,11 @@ class UDPInterface(Interface):
|
|||||||
self.txb += len(data)
|
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(f"Could not transmit on {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "UDPInterface["+self.name+"/"+self.bind_ip+":"+str(self.bind_port)+"]"
|
return f"UDPInterface[{self.name}/{self.bind_ip}:{self.bind_port}]"
|
||||||
|
|
||||||
class UDPInterfaceHandler(socketserver.BaseRequestHandler):
|
class UDPInterfaceHandler(socketserver.BaseRequestHandler):
|
||||||
def __init__(self, callback, *args, **keys):
|
def __init__(self, callback, *args, **keys):
|
||||||
|
@ -24,5 +24,5 @@ import os
|
|||||||
import glob
|
import glob
|
||||||
import RNS.Interfaces.Android
|
import RNS.Interfaces.Android
|
||||||
|
|
||||||
modules = glob.glob(os.path.dirname(__file__)+"/*.py")
|
modules = glob.glob(f"{os.path.dirname(__file__)}/*.py")
|
||||||
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
||||||
|
74
RNS/Link.py
74
RNS/Link.py
@ -115,8 +115,8 @@ class Link:
|
|||||||
link.destination = packet.destination
|
link.destination = packet.destination
|
||||||
link.establishment_timeout = Link.ESTABLISHMENT_TIMEOUT_PER_HOP * max(1, packet.hops) + Link.KEEPALIVE
|
link.establishment_timeout = Link.ESTABLISHMENT_TIMEOUT_PER_HOP * max(1, packet.hops) + Link.KEEPALIVE
|
||||||
link.establishment_cost += len(packet.raw)
|
link.establishment_cost += len(packet.raw)
|
||||||
RNS.log("Validating link request "+RNS.prettyhexrep(link.link_id), RNS.LOG_VERBOSE)
|
RNS.log(f"Validating link request {RNS.prettyhexrep(link.link_id)}", RNS.LOG_VERBOSE)
|
||||||
RNS.log(f"Establishment timeout is {RNS.prettytime(link.establishment_timeout)} for incoming link request "+RNS.prettyhexrep(link.link_id), RNS.LOG_EXTREME)
|
RNS.log(f"Establishment timeout is {RNS.prettytime(link.establishment_timeout)} for incoming link request {RNS.prettyhexrep(link.link_id)}", RNS.LOG_EXTREME)
|
||||||
link.handshake()
|
link.handshake()
|
||||||
link.attached_interface = packet.receiving_interface
|
link.attached_interface = packet.receiving_interface
|
||||||
link.prove()
|
link.prove()
|
||||||
@ -125,12 +125,12 @@ class Link:
|
|||||||
link.last_inbound = time.time()
|
link.last_inbound = time.time()
|
||||||
link.start_watchdog()
|
link.start_watchdog()
|
||||||
|
|
||||||
RNS.log("Incoming link request "+str(link)+" accepted on "+str(link.attached_interface), RNS.LOG_DEBUG)
|
RNS.log(f"Incoming link request {link} accepted on {link.attached_interface}", RNS.LOG_DEBUG)
|
||||||
return link
|
return link
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Validating link request failed", RNS.LOG_VERBOSE)
|
RNS.log("Validating link request failed", RNS.LOG_VERBOSE)
|
||||||
RNS.log("exc: "+str(e))
|
RNS.log(f"exc: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -219,8 +219,8 @@ class Link:
|
|||||||
self.start_watchdog()
|
self.start_watchdog()
|
||||||
self.packet.send()
|
self.packet.send()
|
||||||
self.had_outbound()
|
self.had_outbound()
|
||||||
RNS.log("Link request "+RNS.prettyhexrep(self.link_id)+" sent to "+str(self.destination), RNS.LOG_DEBUG)
|
RNS.log(f"Link request {RNS.prettyhexrep(self.link_id)} sent to {self.destination}", RNS.LOG_DEBUG)
|
||||||
RNS.log(f"Establishment timeout is {RNS.prettytime(self.establishment_timeout)} for link request "+RNS.prettyhexrep(self.link_id), RNS.LOG_EXTREME)
|
RNS.log(f"Establishment timeout is {RNS.prettytime(self.establishment_timeout)} for link request {RNS.prettyhexrep(self.link_id)}", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
|
|
||||||
def load_peer(self, peer_pub_bytes, peer_sig_pub_bytes):
|
def load_peer(self, peer_pub_bytes, peer_sig_pub_bytes):
|
||||||
@ -249,7 +249,7 @@ class Link:
|
|||||||
context=self.get_context(),
|
context=self.get_context(),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
RNS.log("Handshake attempt on "+str(self)+" with invalid state "+str(self.status), RNS.LOG_ERROR)
|
RNS.log(f"Handshake attempt on {self} with invalid state {self.status}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
|
||||||
def prove(self):
|
def prove(self):
|
||||||
@ -291,7 +291,7 @@ class Link:
|
|||||||
|
|
||||||
if self.destination.identity.validate(signature, signed_data):
|
if self.destination.identity.validate(signature, signed_data):
|
||||||
if self.status != Link.HANDSHAKE:
|
if self.status != Link.HANDSHAKE:
|
||||||
raise IOError("Invalid link state for proof validation: "+str(self.status))
|
raise OSError(f"Invalid link state for proof validation: {self.status}")
|
||||||
|
|
||||||
self.rtt = time.time() - self.request_time
|
self.rtt = time.time() - self.request_time
|
||||||
self.attached_interface = packet.receiving_interface
|
self.attached_interface = packet.receiving_interface
|
||||||
@ -300,7 +300,7 @@ class Link:
|
|||||||
self.activated_at = time.time()
|
self.activated_at = time.time()
|
||||||
self.last_proof = self.activated_at
|
self.last_proof = self.activated_at
|
||||||
RNS.Transport.activate_link(self)
|
RNS.Transport.activate_link(self)
|
||||||
RNS.log("Link "+str(self)+" established with "+str(self.destination)+", RTT is "+str(round(self.rtt, 3))+"s", RNS.LOG_VERBOSE)
|
RNS.log(f"Link {self} established with {self.destination}, RTT is {round(self.rtt, 3)}s", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
if self.rtt != None and self.establishment_cost != None and self.rtt > 0 and self.establishment_cost > 0:
|
if self.rtt != None and self.establishment_cost != None and self.rtt > 0 and self.establishment_cost > 0:
|
||||||
self.establishment_rate = self.establishment_cost/self.rtt
|
self.establishment_rate = self.establishment_cost/self.rtt
|
||||||
@ -315,12 +315,12 @@ class Link:
|
|||||||
thread.daemon = True
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
else:
|
else:
|
||||||
RNS.log("Invalid link proof signature received by "+str(self)+". Ignoring.", RNS.LOG_DEBUG)
|
RNS.log(f"Invalid link proof signature received by {self}. Ignoring.", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.status = Link.CLOSED
|
self.status = Link.CLOSED
|
||||||
RNS.log("An error ocurred while validating link request proof on "+str(self)+".", RNS.LOG_ERROR)
|
RNS.log(f"An error ocurred while validating link request proof on {self}.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
|
||||||
def identify(self, identity):
|
def identify(self, identity):
|
||||||
@ -380,7 +380,7 @@ class Link:
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
request_id = RNS.Identity.truncated_hash(packed_request)
|
request_id = RNS.Identity.truncated_hash(packed_request)
|
||||||
RNS.log("Sending request "+RNS.prettyhexrep(request_id)+" as resource.", RNS.LOG_DEBUG)
|
RNS.log(f"Sending request {RNS.prettyhexrep(request_id)} as resource.", RNS.LOG_DEBUG)
|
||||||
request_resource = RNS.Resource(packed_request, self, request_id = request_id, is_response = False, timeout = timeout)
|
request_resource = RNS.Resource(packed_request, self, request_id = request_id, is_response = False, timeout = timeout)
|
||||||
|
|
||||||
return RequestReceipt(
|
return RequestReceipt(
|
||||||
@ -411,10 +411,10 @@ class Link:
|
|||||||
if self.owner.callbacks.link_established != None:
|
if self.owner.callbacks.link_established != None:
|
||||||
self.owner.callbacks.link_established(self)
|
self.owner.callbacks.link_established(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error occurred in external link establishment callback. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error occurred in external link establishment callback. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error occurred while processing RTT packet, tearing down link. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error occurred while processing RTT packet, tearing down link. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
self.teardown()
|
self.teardown()
|
||||||
|
|
||||||
def track_phy_stats(self, track):
|
def track_phy_stats(self, track):
|
||||||
@ -563,7 +563,7 @@ class Link:
|
|||||||
try:
|
try:
|
||||||
self.callbacks.link_closed(self)
|
self.callbacks.link_closed(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing link closed callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing link closed callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
|
||||||
def start_watchdog(self):
|
def start_watchdog(self):
|
||||||
@ -634,7 +634,7 @@ class Link:
|
|||||||
if sleep_time == 0:
|
if sleep_time == 0:
|
||||||
RNS.log("Warning! Link watchdog sleep time of 0!", RNS.LOG_ERROR)
|
RNS.log("Warning! Link watchdog sleep time of 0!", RNS.LOG_ERROR)
|
||||||
if sleep_time == None or sleep_time < 0:
|
if sleep_time == None or sleep_time < 0:
|
||||||
RNS.log("Timing error! Tearing down link "+str(self)+" now.", RNS.LOG_ERROR)
|
RNS.log(f"Timing error! Tearing down link {self} now.", RNS.LOG_ERROR)
|
||||||
self.teardown()
|
self.teardown()
|
||||||
sleep_time = 0.1
|
sleep_time = 0.1
|
||||||
|
|
||||||
@ -683,7 +683,7 @@ class Link:
|
|||||||
allowed = True
|
allowed = True
|
||||||
|
|
||||||
if allowed:
|
if allowed:
|
||||||
RNS.log("Handling request "+RNS.prettyhexrep(request_id)+" for: "+str(path), RNS.LOG_DEBUG)
|
RNS.log(f"Handling request {RNS.prettyhexrep(request_id)} for: {path}", RNS.LOG_DEBUG)
|
||||||
if len(inspect.signature(response_generator).parameters) == 5:
|
if len(inspect.signature(response_generator).parameters) == 5:
|
||||||
response = response_generator(path, request_data, request_id, self.__remote_identity, requested_at)
|
response = response_generator(path, request_data, request_id, self.__remote_identity, requested_at)
|
||||||
elif len(inspect.signature(response_generator).parameters) == 6:
|
elif len(inspect.signature(response_generator).parameters) == 6:
|
||||||
@ -700,7 +700,7 @@ class Link:
|
|||||||
response_resource = RNS.Resource(packed_response, self, request_id = request_id, is_response = True)
|
response_resource = RNS.Resource(packed_response, self, request_id = request_id, is_response = True)
|
||||||
else:
|
else:
|
||||||
identity_string = str(self.get_remote_identity()) if self.get_remote_identity() != None else "<Unknown>"
|
identity_string = str(self.get_remote_identity()) if self.get_remote_identity() != None else "<Unknown>"
|
||||||
RNS.log("Request "+RNS.prettyhexrep(request_id)+" from "+identity_string+" not allowed for: "+str(path), RNS.LOG_DEBUG)
|
RNS.log(f"Request {RNS.prettyhexrep(request_id)} from {identity_string} not allowed for: {path}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
def handle_response(self, request_id, response_data, response_size, response_transfer_size):
|
def handle_response(self, request_id, response_data, response_size, response_transfer_size):
|
||||||
if self.status == Link.ACTIVE:
|
if self.status == Link.ACTIVE:
|
||||||
@ -715,7 +715,7 @@ class Link:
|
|||||||
pending_request.response_transfer_size += response_transfer_size
|
pending_request.response_transfer_size += response_transfer_size
|
||||||
pending_request.response_received(response_data)
|
pending_request.response_received(response_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error occurred while handling response. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error occurred while handling response. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -732,7 +732,7 @@ class Link:
|
|||||||
|
|
||||||
self.handle_request(request_id, request_data)
|
self.handle_request(request_id, request_data)
|
||||||
else:
|
else:
|
||||||
RNS.log("Incoming request resource failed with status: "+RNS.hexrep([resource.status]), RNS.LOG_DEBUG)
|
RNS.log(f"Incoming request resource failed with status: {RNS.hexrep([resource.status])}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
def response_resource_concluded(self, resource):
|
def response_resource_concluded(self, resource):
|
||||||
if resource.status == RNS.Resource.COMPLETE:
|
if resource.status == RNS.Resource.COMPLETE:
|
||||||
@ -743,7 +743,7 @@ class Link:
|
|||||||
|
|
||||||
self.handle_response(request_id, response_data, resource.total_size, resource.size)
|
self.handle_response(request_id, response_data, resource.total_size, resource.size)
|
||||||
else:
|
else:
|
||||||
RNS.log("Incoming response resource failed with status: "+RNS.hexrep([resource.status]), RNS.LOG_DEBUG)
|
RNS.log(f"Incoming response resource failed with status: {RNS.hexrep([resource.status])}", RNS.LOG_DEBUG)
|
||||||
for pending_request in self.pending_requests:
|
for pending_request in self.pending_requests:
|
||||||
if pending_request.request_id == resource.request_id:
|
if pending_request.request_id == resource.request_id:
|
||||||
pending_request.request_timed_out(None)
|
pending_request.request_timed_out(None)
|
||||||
@ -794,7 +794,7 @@ class Link:
|
|||||||
packet.prove()
|
packet.prove()
|
||||||
should_query = True
|
should_query = True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing proof request callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing proof request callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.__update_phy_stats(packet, query_shared=should_query)
|
self.__update_phy_stats(packet, query_shared=should_query)
|
||||||
|
|
||||||
@ -814,7 +814,7 @@ class Link:
|
|||||||
try:
|
try:
|
||||||
self.callbacks.remote_identified(self, self.__remote_identity)
|
self.callbacks.remote_identified(self, self.__remote_identity)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing remote identified callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing remote identified callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.__update_phy_stats(packet, query_shared=True)
|
self.__update_phy_stats(packet, query_shared=True)
|
||||||
|
|
||||||
@ -827,7 +827,7 @@ class Link:
|
|||||||
self.handle_request(request_id, unpacked_request)
|
self.handle_request(request_id, unpacked_request)
|
||||||
self.__update_phy_stats(packet, query_shared=True)
|
self.__update_phy_stats(packet, query_shared=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error occurred while handling request. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error occurred while handling request. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif packet.context == RNS.Packet.RESPONSE:
|
elif packet.context == RNS.Packet.RESPONSE:
|
||||||
try:
|
try:
|
||||||
@ -840,7 +840,7 @@ class Link:
|
|||||||
self.handle_response(request_id, response_data, transfer_size, transfer_size)
|
self.handle_response(request_id, response_data, transfer_size, transfer_size)
|
||||||
self.__update_phy_stats(packet, query_shared=True)
|
self.__update_phy_stats(packet, query_shared=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error occurred while handling response. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error occurred while handling response. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
elif packet.context == RNS.Packet.LRRTT:
|
elif packet.context == RNS.Packet.LRRTT:
|
||||||
if not self.initiator:
|
if not self.initiator:
|
||||||
@ -883,7 +883,7 @@ class Link:
|
|||||||
if self.callbacks.resource(resource_advertisement):
|
if self.callbacks.resource(resource_advertisement):
|
||||||
RNS.Resource.accept(packet, self.callbacks.resource_concluded)
|
RNS.Resource.accept(packet, self.callbacks.resource_concluded)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing resource accept callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing resource accept callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
elif self.resource_strategy == Link.ACCEPT_ALL:
|
elif self.resource_strategy == Link.ACCEPT_ALL:
|
||||||
RNS.Resource.accept(packet, self.callbacks.resource_concluded)
|
RNS.Resource.accept(packet, self.callbacks.resource_concluded)
|
||||||
|
|
||||||
@ -970,13 +970,13 @@ class Link:
|
|||||||
try:
|
try:
|
||||||
self.fernet = Fernet(self.derived_key)
|
self.fernet = Fernet(self.derived_key)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not instantiate Fernet while performin encryption on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Could not instantiate Fernet while performin encryption on link {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
return self.fernet.encrypt(plaintext)
|
return self.fernet.encrypt(plaintext)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Encryption on link "+str(self)+" failed. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Encryption on link {self} failed. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
|
||||||
@ -988,7 +988,7 @@ class Link:
|
|||||||
return self.fernet.decrypt(ciphertext)
|
return self.fernet.decrypt(ciphertext)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Decryption failed on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Decryption failed on link {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -1169,7 +1169,7 @@ class RequestReceipt():
|
|||||||
|
|
||||||
def request_resource_concluded(self, resource):
|
def request_resource_concluded(self, resource):
|
||||||
if resource.status == RNS.Resource.COMPLETE:
|
if resource.status == RNS.Resource.COMPLETE:
|
||||||
RNS.log("Request "+RNS.prettyhexrep(self.request_id)+" successfully sent as resource.", RNS.LOG_DEBUG)
|
RNS.log(f"Request {RNS.prettyhexrep(self.request_id)} successfully sent as resource.", RNS.LOG_DEBUG)
|
||||||
if self.started_at == None:
|
if self.started_at == None:
|
||||||
self.started_at = time.time()
|
self.started_at = time.time()
|
||||||
self.status = RequestReceipt.DELIVERED
|
self.status = RequestReceipt.DELIVERED
|
||||||
@ -1178,7 +1178,7 @@ class RequestReceipt():
|
|||||||
response_timeout_thread.daemon = True
|
response_timeout_thread.daemon = True
|
||||||
response_timeout_thread.start()
|
response_timeout_thread.start()
|
||||||
else:
|
else:
|
||||||
RNS.log("Sending request "+RNS.prettyhexrep(self.request_id)+" as resource failed with status: "+RNS.hexrep([resource.status]), RNS.LOG_DEBUG)
|
RNS.log(f"Sending request {RNS.prettyhexrep(self.request_id)} as resource failed with status: {RNS.hexrep([resource.status])}", RNS.LOG_DEBUG)
|
||||||
self.status = RequestReceipt.FAILED
|
self.status = RequestReceipt.FAILED
|
||||||
self.concluded_at = time.time()
|
self.concluded_at = time.time()
|
||||||
self.link.pending_requests.remove(self)
|
self.link.pending_requests.remove(self)
|
||||||
@ -1187,7 +1187,7 @@ class RequestReceipt():
|
|||||||
try:
|
try:
|
||||||
self.callbacks.failed(self)
|
self.callbacks.failed(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing request failed callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing request failed callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
|
||||||
def __response_timeout_job(self):
|
def __response_timeout_job(self):
|
||||||
@ -1208,7 +1208,7 @@ class RequestReceipt():
|
|||||||
try:
|
try:
|
||||||
self.callbacks.failed(self)
|
self.callbacks.failed(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing request timed out callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing request timed out callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
|
||||||
def response_resource_progress(self, resource):
|
def response_resource_progress(self, resource):
|
||||||
@ -1229,7 +1229,7 @@ class RequestReceipt():
|
|||||||
try:
|
try:
|
||||||
self.callbacks.progress(self)
|
self.callbacks.progress(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing response progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing response progress callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
else:
|
else:
|
||||||
resource.cancel()
|
resource.cancel()
|
||||||
|
|
||||||
@ -1252,13 +1252,13 @@ class RequestReceipt():
|
|||||||
try:
|
try:
|
||||||
self.callbacks.progress(self)
|
self.callbacks.progress(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing response progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing response progress callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if self.callbacks.response != None:
|
if self.callbacks.response != None:
|
||||||
try:
|
try:
|
||||||
self.callbacks.response(self)
|
self.callbacks.response(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing response received callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing response received callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def get_request_id(self):
|
def get_request_id(self):
|
||||||
"""
|
"""
|
||||||
|
@ -208,14 +208,14 @@ class Packet:
|
|||||||
# Announce packets are not encrypted
|
# Announce packets are not encrypted
|
||||||
self.ciphertext = self.data
|
self.ciphertext = self.data
|
||||||
else:
|
else:
|
||||||
raise IOError("Packet with header type 2 must have a transport ID")
|
raise OSError("Packet with header type 2 must have a transport ID")
|
||||||
|
|
||||||
|
|
||||||
self.header += bytes([self.context])
|
self.header += bytes([self.context])
|
||||||
self.raw = self.header + self.ciphertext
|
self.raw = self.header + self.ciphertext
|
||||||
|
|
||||||
if len(self.raw) > self.MTU:
|
if len(self.raw) > self.MTU:
|
||||||
raise IOError("Packet size of "+str(len(self.raw))+" exceeds MTU of "+str(self.MTU)+" bytes")
|
raise OSError(f"Packet size of {len(self.raw)} exceeds MTU of {self.MTU} bytes")
|
||||||
|
|
||||||
self.packed = True
|
self.packed = True
|
||||||
self.update_hash()
|
self.update_hash()
|
||||||
@ -250,7 +250,7 @@ class Packet:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Received malformed packet, dropping it. The contained exception was: "+str(e), RNS.LOG_EXTREME)
|
RNS.log(f"Received malformed packet, dropping it. The contained exception was: {e}", RNS.LOG_EXTREME)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def send(self):
|
def send(self):
|
||||||
@ -262,7 +262,7 @@ class Packet:
|
|||||||
if not self.sent:
|
if not self.sent:
|
||||||
if self.destination.type == RNS.Destination.LINK:
|
if self.destination.type == RNS.Destination.LINK:
|
||||||
if self.destination.status == RNS.Link.CLOSED:
|
if self.destination.status == RNS.Link.CLOSED:
|
||||||
raise IOError("Attempt to transmit over a closed link")
|
raise OSError("Attempt to transmit over a closed link")
|
||||||
else:
|
else:
|
||||||
self.destination.last_outbound = time.time()
|
self.destination.last_outbound = time.time()
|
||||||
self.destination.tx += 1
|
self.destination.tx += 1
|
||||||
@ -280,7 +280,7 @@ class Packet:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise IOError("Packet was already sent")
|
raise OSError("Packet was already sent")
|
||||||
|
|
||||||
def resend(self):
|
def resend(self):
|
||||||
"""
|
"""
|
||||||
@ -301,7 +301,7 @@ class Packet:
|
|||||||
self.receipt = None
|
self.receipt = None
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
raise IOError("Packet was not sent yet")
|
raise OSError("Packet was not sent yet")
|
||||||
|
|
||||||
def prove(self, destination=None):
|
def prove(self, destination=None):
|
||||||
if self.fromPacked and hasattr(self, "destination") and self.destination:
|
if self.fromPacked and hasattr(self, "destination") and self.destination:
|
||||||
@ -419,8 +419,8 @@ class PacketReceipt:
|
|||||||
try:
|
try:
|
||||||
self.callbacks.delivery(self)
|
self.callbacks.delivery(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error occurred while evaluating external delivery callback for "+str(link), RNS.LOG_ERROR)
|
RNS.log(f"An error occurred while evaluating external delivery callback for {link}", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.trace_exception(e)
|
RNS.trace_exception(e)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@ -465,7 +465,7 @@ class PacketReceipt:
|
|||||||
try:
|
try:
|
||||||
self.callbacks.delivery(self)
|
self.callbacks.delivery(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing proof validated callback. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing proof validated callback. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@ -489,7 +489,7 @@ class PacketReceipt:
|
|||||||
try:
|
try:
|
||||||
self.callbacks.delivery(self)
|
self.callbacks.delivery(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing proof validated callback. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing proof validated callback. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
@ -172,7 +172,7 @@ class Resource:
|
|||||||
resource.window_flexibility = Resource.WINDOW_FLEXIBILITY
|
resource.window_flexibility = Resource.WINDOW_FLEXIBILITY
|
||||||
resource.last_activity = time.time()
|
resource.last_activity = time.time()
|
||||||
|
|
||||||
resource.storagepath = RNS.Reticulum.resourcepath+"/"+resource.original_hash.hex()
|
resource.storagepath = f"{RNS.Reticulum.resourcepath}/{resource.original_hash.hex()}"
|
||||||
resource.segment_index = adv.i
|
resource.segment_index = adv.i
|
||||||
resource.total_segments = adv.l
|
resource.total_segments = adv.l
|
||||||
if adv.l > 1:
|
if adv.l > 1:
|
||||||
@ -194,7 +194,7 @@ class Resource:
|
|||||||
try:
|
try:
|
||||||
resource.link.callbacks.resource_started(resource)
|
resource.link.callbacks.resource_started(resource)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing resource started callback from "+str(resource)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing resource started callback from {resource}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
resource.hashmap_update(0, resource.hashmap_raw)
|
resource.hashmap_update(0, resource.hashmap_raw)
|
||||||
|
|
||||||
@ -203,7 +203,7 @@ class Resource:
|
|||||||
return resource
|
return resource
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Ignoring resource advertisement for "+RNS.prettyhexrep(resource.hash)+", resource already transferring", RNS.LOG_DEBUG)
|
RNS.log(f"Ignoring resource advertisement for {RNS.prettyhexrep(resource.hash)}, resource already transferring", RNS.LOG_DEBUG)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -309,7 +309,7 @@ class Resource:
|
|||||||
if (auto_compress and len(self.uncompressed_data) <= Resource.AUTO_COMPRESS_MAX_SIZE):
|
if (auto_compress and len(self.uncompressed_data) <= Resource.AUTO_COMPRESS_MAX_SIZE):
|
||||||
RNS.log("Compressing resource data...", RNS.LOG_DEBUG)
|
RNS.log("Compressing resource data...", RNS.LOG_DEBUG)
|
||||||
self.compressed_data = bz2.compress(self.uncompressed_data)
|
self.compressed_data = bz2.compress(self.uncompressed_data)
|
||||||
RNS.log("Compression completed in "+str(round(time.time()-compression_began, 3))+" seconds", RNS.LOG_DEBUG)
|
RNS.log(f"Compression completed in {round(time.time() - compression_began, 3)} seconds", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
self.compressed_data = self.uncompressed_data
|
self.compressed_data = self.uncompressed_data
|
||||||
|
|
||||||
@ -318,7 +318,7 @@ class Resource:
|
|||||||
|
|
||||||
if (self.compressed_size < self.uncompressed_size and auto_compress):
|
if (self.compressed_size < self.uncompressed_size and auto_compress):
|
||||||
saved_bytes = len(self.uncompressed_data) - len(self.compressed_data)
|
saved_bytes = len(self.uncompressed_data) - len(self.compressed_data)
|
||||||
RNS.log("Compression saved "+str(saved_bytes)+" bytes, sending compressed", RNS.LOG_DEBUG)
|
RNS.log(f"Compression saved {saved_bytes} bytes, sending compressed", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
self.data = b""
|
self.data = b""
|
||||||
self.data += RNS.Identity.get_random_hash()[:Resource.RANDOM_HASH_SIZE]
|
self.data += RNS.Identity.get_random_hash()[:Resource.RANDOM_HASH_SIZE]
|
||||||
@ -352,7 +352,7 @@ class Resource:
|
|||||||
hashmap_ok = False
|
hashmap_ok = False
|
||||||
while not hashmap_ok:
|
while not hashmap_ok:
|
||||||
hashmap_computation_began = time.time()
|
hashmap_computation_began = time.time()
|
||||||
RNS.log("Starting resource hashmap computation with "+str(hashmap_entries)+" entries...", RNS.LOG_DEBUG)
|
RNS.log(f"Starting resource hashmap computation with {hashmap_entries} entries...", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
self.random_hash = RNS.Identity.get_random_hash()[:Resource.RANDOM_HASH_SIZE]
|
self.random_hash = RNS.Identity.get_random_hash()[:Resource.RANDOM_HASH_SIZE]
|
||||||
self.hash = RNS.Identity.full_hash(data+self.random_hash)
|
self.hash = RNS.Identity.full_hash(data+self.random_hash)
|
||||||
@ -388,7 +388,7 @@ class Resource:
|
|||||||
self.hashmap += part.map_hash
|
self.hashmap += part.map_hash
|
||||||
self.parts.append(part)
|
self.parts.append(part)
|
||||||
|
|
||||||
RNS.log("Hashmap computation concluded in "+str(round(time.time()-hashmap_computation_began, 3))+" seconds", RNS.LOG_DEBUG)
|
RNS.log(f"Hashmap computation concluded in {round(time.time() - hashmap_computation_began, 3)} seconds", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
if advertise:
|
if advertise:
|
||||||
self.advertise()
|
self.advertise()
|
||||||
@ -447,9 +447,9 @@ class Resource:
|
|||||||
self.status = Resource.ADVERTISED
|
self.status = Resource.ADVERTISED
|
||||||
self.retries_left = self.max_adv_retries
|
self.retries_left = self.max_adv_retries
|
||||||
self.link.register_outgoing_resource(self)
|
self.link.register_outgoing_resource(self)
|
||||||
RNS.log("Sent resource advertisement for "+RNS.prettyhexrep(self.hash), RNS.LOG_DEBUG)
|
RNS.log(f"Sent resource advertisement for {RNS.prettyhexrep(self.hash)}", RNS.LOG_DEBUG)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not advertise resource, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Could not advertise resource, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
self.cancel()
|
self.cancel()
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -487,7 +487,7 @@ class Resource:
|
|||||||
self.adv_sent = self.last_activity
|
self.adv_sent = self.last_activity
|
||||||
sleep_time = 0.001
|
sleep_time = 0.001
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not resend advertisement packet, cancelling resource. The contained exception was: "+str(e), RNS.LOG_VERBOSE)
|
RNS.log(f"Could not resend advertisement packet, cancelling resource. The contained exception was: {e}", RNS.LOG_VERBOSE)
|
||||||
self.cancel()
|
self.cancel()
|
||||||
|
|
||||||
|
|
||||||
@ -508,7 +508,7 @@ class Resource:
|
|||||||
if sleep_time < 0:
|
if sleep_time < 0:
|
||||||
if self.retries_left > 0:
|
if self.retries_left > 0:
|
||||||
ms = "" if self.outstanding_parts == 1 else "s"
|
ms = "" if self.outstanding_parts == 1 else "s"
|
||||||
RNS.log("Timed out waiting for "+str(self.outstanding_parts)+" part"+ms+", requesting retry", RNS.LOG_DEBUG)
|
RNS.log(f"Timed out waiting for {self.outstanding_parts} part{ms}, requesting retry", RNS.LOG_DEBUG)
|
||||||
if self.window > self.window_min:
|
if self.window > self.window_min:
|
||||||
self.window -= 1
|
self.window -= 1
|
||||||
if self.window_max > self.window_min:
|
if self.window_max > self.window_min:
|
||||||
@ -591,7 +591,7 @@ class Resource:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while assembling received resource.", RNS.LOG_ERROR)
|
RNS.log("Error while assembling received resource.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
self.status = Resource.CORRUPT
|
self.status = Resource.CORRUPT
|
||||||
|
|
||||||
self.link.resource_concluded(self)
|
self.link.resource_concluded(self)
|
||||||
@ -602,7 +602,7 @@ class Resource:
|
|||||||
try:
|
try:
|
||||||
self.callback(self)
|
self.callback(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing resource assembled callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing resource assembled callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if hasattr(self.data, "close") and callable(self.data.close):
|
if hasattr(self.data, "close") and callable(self.data.close):
|
||||||
@ -614,7 +614,7 @@ class Resource:
|
|||||||
RNS.log("Error while cleaning up resource files, the contained exception was:", RNS.LOG_ERROR)
|
RNS.log("Error while cleaning up resource files, the contained exception was:", RNS.LOG_ERROR)
|
||||||
RNS.log(str(e))
|
RNS.log(str(e))
|
||||||
else:
|
else:
|
||||||
RNS.log("Resource segment "+str(self.segment_index)+" of "+str(self.total_segments)+" received, waiting for next segment to be announced", RNS.LOG_DEBUG)
|
RNS.log(f"Resource segment {self.segment_index} of {self.total_segments} received, waiting for next segment to be announced", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
|
|
||||||
def prove(self):
|
def prove(self):
|
||||||
@ -626,7 +626,7 @@ class Resource:
|
|||||||
proof_packet.send()
|
proof_packet.send()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not send proof packet, cancelling resource", RNS.LOG_DEBUG)
|
RNS.log("Could not send proof packet, cancelling resource", RNS.LOG_DEBUG)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_DEBUG)
|
||||||
self.cancel()
|
self.cancel()
|
||||||
|
|
||||||
def __prepare_next_segment(self):
|
def __prepare_next_segment(self):
|
||||||
@ -657,7 +657,7 @@ class Resource:
|
|||||||
try:
|
try:
|
||||||
self.callback(self)
|
self.callback(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing resource concluded callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing resource concluded callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
finally:
|
finally:
|
||||||
try:
|
try:
|
||||||
if hasattr(self, "input_file"):
|
if hasattr(self, "input_file"):
|
||||||
@ -665,7 +665,7 @@ class Resource:
|
|||||||
self.input_file.close()
|
self.input_file.close()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while closing resource input file: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while closing resource input file: {e}", RNS.LOG_ERROR)
|
||||||
else:
|
else:
|
||||||
# Otherwise we'll recursively create the
|
# Otherwise we'll recursively create the
|
||||||
# next segment of the resource
|
# next segment of the resource
|
||||||
@ -742,7 +742,7 @@ class Resource:
|
|||||||
try:
|
try:
|
||||||
self.__progress_callback(self)
|
self.__progress_callback(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing progress callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
@ -830,7 +830,7 @@ class Resource:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not send resource request packet, cancelling resource", RNS.LOG_DEBUG)
|
RNS.log("Could not send resource request packet, cancelling resource", RNS.LOG_DEBUG)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_DEBUG)
|
||||||
self.cancel()
|
self.cancel()
|
||||||
|
|
||||||
# Called on outgoing resource to make it send more data
|
# Called on outgoing resource to make it send more data
|
||||||
@ -876,7 +876,7 @@ class Resource:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Resource could not send parts, cancelling transfer!", RNS.LOG_DEBUG)
|
RNS.log("Resource could not send parts, cancelling transfer!", RNS.LOG_DEBUG)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_DEBUG)
|
||||||
self.cancel()
|
self.cancel()
|
||||||
|
|
||||||
if wants_more_hashmap:
|
if wants_more_hashmap:
|
||||||
@ -915,7 +915,7 @@ class Resource:
|
|||||||
self.last_activity = time.time()
|
self.last_activity = time.time()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not send resource HMU packet, cancelling resource", RNS.LOG_DEBUG)
|
RNS.log("Could not send resource HMU packet, cancelling resource", RNS.LOG_DEBUG)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_DEBUG)
|
||||||
self.cancel()
|
self.cancel()
|
||||||
|
|
||||||
if self.sent_parts == len(self.parts):
|
if self.sent_parts == len(self.parts):
|
||||||
@ -925,7 +925,7 @@ class Resource:
|
|||||||
try:
|
try:
|
||||||
self.__progress_callback(self)
|
self.__progress_callback(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing progress callback from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
"""
|
"""
|
||||||
@ -939,7 +939,7 @@ class Resource:
|
|||||||
cancel_packet = RNS.Packet(self.link, self.hash, context=RNS.Packet.RESOURCE_ICL)
|
cancel_packet = RNS.Packet(self.link, self.hash, context=RNS.Packet.RESOURCE_ICL)
|
||||||
cancel_packet.send()
|
cancel_packet.send()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not send resource cancel packet, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Could not send resource cancel packet, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
self.link.cancel_outgoing_resource(self)
|
self.link.cancel_outgoing_resource(self)
|
||||||
else:
|
else:
|
||||||
self.link.cancel_incoming_resource(self)
|
self.link.cancel_incoming_resource(self)
|
||||||
@ -949,7 +949,7 @@ class Resource:
|
|||||||
self.link.resource_concluded(self)
|
self.link.resource_concluded(self)
|
||||||
self.callback(self)
|
self.callback(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing callbacks on resource cancel from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing callbacks on resource cancel from {self}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def set_callback(self, callback):
|
def set_callback(self, callback):
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
@ -1015,7 +1015,7 @@ class Resource:
|
|||||||
return self.compressed
|
return self.compressed
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "<"+RNS.hexrep(self.hash,delimit=False)+"/"+RNS.hexrep(self.link.link_id,delimit=False)+">"
|
return f"<{RNS.hexrep(self.hash, delimit=False)}/{RNS.hexrep(self.link.link_id, delimit=False)}>"
|
||||||
|
|
||||||
|
|
||||||
class ResourceAdvertisement:
|
class ResourceAdvertisement:
|
||||||
|
@ -203,20 +203,20 @@ class Reticulum:
|
|||||||
else:
|
else:
|
||||||
if os.path.isdir("/etc/reticulum") and os.path.isfile("/etc/reticulum/config"):
|
if os.path.isdir("/etc/reticulum") and os.path.isfile("/etc/reticulum/config"):
|
||||||
Reticulum.configdir = "/etc/reticulum"
|
Reticulum.configdir = "/etc/reticulum"
|
||||||
elif os.path.isdir(Reticulum.userdir+"/.config/reticulum") and os.path.isfile(Reticulum.userdir+"/.config/reticulum/config"):
|
elif os.path.isdir(f"{Reticulum.userdir}/.config/reticulum") and os.path.isfile(f"{Reticulum.userdir}/.config/reticulum/config"):
|
||||||
Reticulum.configdir = Reticulum.userdir+"/.config/reticulum"
|
Reticulum.configdir = f"{Reticulum.userdir}/.config/reticulum"
|
||||||
else:
|
else:
|
||||||
Reticulum.configdir = Reticulum.userdir+"/.reticulum"
|
Reticulum.configdir = f"{Reticulum.userdir}/.reticulum"
|
||||||
|
|
||||||
if logdest == RNS.LOG_FILE:
|
if logdest == RNS.LOG_FILE:
|
||||||
RNS.logdest = RNS.LOG_FILE
|
RNS.logdest = RNS.LOG_FILE
|
||||||
RNS.logfile = Reticulum.configdir+"/logfile"
|
RNS.logfile = f"{Reticulum.configdir}/logfile"
|
||||||
|
|
||||||
Reticulum.configpath = Reticulum.configdir+"/config"
|
Reticulum.configpath = f"{Reticulum.configdir}/config"
|
||||||
Reticulum.storagepath = Reticulum.configdir+"/storage"
|
Reticulum.storagepath = f"{Reticulum.configdir}/storage"
|
||||||
Reticulum.cachepath = Reticulum.configdir+"/storage/cache"
|
Reticulum.cachepath = f"{Reticulum.configdir}/storage/cache"
|
||||||
Reticulum.resourcepath = Reticulum.configdir+"/storage/resources"
|
Reticulum.resourcepath = f"{Reticulum.configdir}/storage/resources"
|
||||||
Reticulum.identitypath = Reticulum.configdir+"/storage/identities"
|
Reticulum.identitypath = f"{Reticulum.configdir}/storage/identities"
|
||||||
|
|
||||||
Reticulum.__transport_enabled = False
|
Reticulum.__transport_enabled = False
|
||||||
Reticulum.__remote_management_enabled = False
|
Reticulum.__remote_management_enabled = False
|
||||||
@ -266,17 +266,17 @@ class Reticulum:
|
|||||||
try:
|
try:
|
||||||
self.config = ConfigObj(self.configpath)
|
self.config = ConfigObj(self.configpath)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not parse the configuration at "+self.configpath, RNS.LOG_ERROR)
|
RNS.log(f"Could not parse the configuration at {self.configpath}", RNS.LOG_ERROR)
|
||||||
RNS.log("Check your configuration file for errors!", RNS.LOG_ERROR)
|
RNS.log("Check your configuration file for errors!", RNS.LOG_ERROR)
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
else:
|
else:
|
||||||
RNS.log("Could not load config file, creating default configuration file...")
|
RNS.log("Could not load config file, creating default configuration file...")
|
||||||
self.__create_default_config()
|
self.__create_default_config()
|
||||||
RNS.log("Default config file created. Make any necessary changes in "+Reticulum.configdir+"/config and restart Reticulum if needed.")
|
RNS.log(f"Default config file created. Make any necessary changes in {Reticulum.configdir}/config and restart Reticulum if needed.")
|
||||||
time.sleep(1.5)
|
time.sleep(1.5)
|
||||||
|
|
||||||
self.__apply_config()
|
self.__apply_config()
|
||||||
RNS.log("Configuration loaded from "+self.configpath, RNS.LOG_VERBOSE)
|
RNS.log(f"Configuration loaded from {self.configpath}", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
RNS.Identity.load_known_destinations()
|
RNS.Identity.load_known_destinations()
|
||||||
|
|
||||||
@ -331,7 +331,7 @@ class Reticulum:
|
|||||||
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(f"Started shared instance interface: {interface}", RNS.LOG_DEBUG)
|
||||||
self.__start_jobs()
|
self.__start_jobs()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -353,10 +353,10 @@ class Reticulum:
|
|||||||
Reticulum.__transport_enabled = False
|
Reticulum.__transport_enabled = False
|
||||||
Reticulum.__remote_management_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(f"Connected to locally available Reticulum instance via: {interface}", RNS.LOG_DEBUG)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Local shared instance appears to be running, but it could not be connected", RNS.LOG_ERROR)
|
RNS.log("Local shared instance appears to be running, but it could not be connected", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
self.is_shared_instance = False
|
self.is_shared_instance = False
|
||||||
self.is_standalone_instance = True
|
self.is_standalone_instance = True
|
||||||
self.is_connected_to_shared_instance = False
|
self.is_connected_to_shared_instance = False
|
||||||
@ -411,11 +411,11 @@ class Reticulum:
|
|||||||
for hexhash in v:
|
for hexhash in v:
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||||
if len(hexhash) != dest_len:
|
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))
|
raise ValueError(f"Identity hash length for remote management ACL {hexhash} is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
allowed_hash = bytes.fromhex(hexhash)
|
allowed_hash = bytes.fromhex(hexhash)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError("Invalid identity hash for remote management ACL: "+str(hexhash))
|
raise ValueError(f"Invalid identity hash for remote management ACL: {hexhash}")
|
||||||
|
|
||||||
if not allowed_hash in RNS.Transport.remote_management_allowed:
|
if not allowed_hash in RNS.Transport.remote_management_allowed:
|
||||||
RNS.Transport.remote_management_allowed.append(allowed_hash)
|
RNS.Transport.remote_management_allowed.append(allowed_hash)
|
||||||
@ -658,7 +658,7 @@ class Reticulum:
|
|||||||
interface.OUT = True
|
interface.OUT = True
|
||||||
|
|
||||||
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
||||||
RNS.log(str(interface)+" does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
RNS.log(f"{interface} does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
||||||
interface_mode = Interface.Interface.MODE_FULL
|
interface_mode = Interface.Interface.MODE_FULL
|
||||||
|
|
||||||
interface.mode = interface_mode
|
interface.mode = interface_mode
|
||||||
@ -695,7 +695,7 @@ class Reticulum:
|
|||||||
interface.OUT = True
|
interface.OUT = True
|
||||||
|
|
||||||
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
||||||
RNS.log(str(interface)+" does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
RNS.log(f"{interface} does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
||||||
interface_mode = Interface.Interface.MODE_FULL
|
interface_mode = Interface.Interface.MODE_FULL
|
||||||
|
|
||||||
interface.mode = interface_mode
|
interface.mode = interface_mode
|
||||||
@ -732,7 +732,7 @@ class Reticulum:
|
|||||||
interface.OUT = True
|
interface.OUT = True
|
||||||
|
|
||||||
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
||||||
RNS.log(str(interface)+" does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
RNS.log(f"{interface} does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
||||||
interface_mode = Interface.Interface.MODE_FULL
|
interface_mode = Interface.Interface.MODE_FULL
|
||||||
|
|
||||||
interface.mode = interface_mode
|
interface.mode = interface_mode
|
||||||
@ -1029,17 +1029,17 @@ class Reticulum:
|
|||||||
|
|
||||||
# if no subinterfaces are defined
|
# if no subinterfaces are defined
|
||||||
if count == 0:
|
if count == 0:
|
||||||
raise ValueError("No subinterfaces configured for "+name)
|
raise ValueError(f"No subinterfaces configured for {name}")
|
||||||
# if no subinterfaces are enabled
|
# if no subinterfaces are enabled
|
||||||
elif enabled_count == 0:
|
elif enabled_count == 0:
|
||||||
raise ValueError("No subinterfaces enabled for "+name)
|
raise ValueError(f"No subinterfaces enabled for {name}")
|
||||||
|
|
||||||
id_interval = int(c["id_interval"]) if "id_interval" in c else None
|
id_interval = int(c["id_interval"]) if "id_interval" in c else None
|
||||||
id_callsign = c["id_callsign"] if "id_callsign" in c else None
|
id_callsign = c["id_callsign"] if "id_callsign" in c else None
|
||||||
port = c["port"] if "port" in c else None
|
port = c["port"] if "port" in c else None
|
||||||
|
|
||||||
if port == None:
|
if port == None:
|
||||||
raise ValueError("No port specified for "+name)
|
raise ValueError(f"No port specified for {name}")
|
||||||
|
|
||||||
interface = RNodeMultiInterface.RNodeMultiInterface(
|
interface = RNodeMultiInterface.RNodeMultiInterface(
|
||||||
RNS.Transport,
|
RNS.Transport,
|
||||||
@ -1106,14 +1106,14 @@ class Reticulum:
|
|||||||
interface.start()
|
interface.start()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Skipping disabled interface \""+name+"\"", RNS.LOG_DEBUG)
|
RNS.log(f"Skipping disabled interface \"{name}\"", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
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(f"The interface \"{name}\" could not be created. Check your configuration file for errors!", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
else:
|
else:
|
||||||
RNS.log("The interface name \""+name+"\" was already used. Check your configuration file for errors!", RNS.LOG_ERROR)
|
RNS.log(f"The interface name \"{name}\" was already used. Check your configuration file for errors!", RNS.LOG_ERROR)
|
||||||
RNS.panic()
|
RNS.panic()
|
||||||
|
|
||||||
RNS.log("System interfaces are ready", RNS.LOG_VERBOSE)
|
RNS.log("System interfaces are ready", RNS.LOG_VERBOSE)
|
||||||
@ -1181,27 +1181,27 @@ class Reticulum:
|
|||||||
for filename in os.listdir(self.resourcepath):
|
for filename in os.listdir(self.resourcepath):
|
||||||
try:
|
try:
|
||||||
if len(filename) == (RNS.Identity.HASHLENGTH//8)*2:
|
if len(filename) == (RNS.Identity.HASHLENGTH//8)*2:
|
||||||
filepath = self.resourcepath + "/" + filename
|
filepath = f"{self.resourcepath}/{filename}"
|
||||||
mtime = os.path.getmtime(filepath)
|
mtime = os.path.getmtime(filepath)
|
||||||
age = now - mtime
|
age = now - mtime
|
||||||
if age > Reticulum.RESOURCE_CACHE:
|
if age > Reticulum.RESOURCE_CACHE:
|
||||||
os.unlink(filepath)
|
os.unlink(filepath)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while cleaning resources cache, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while cleaning resources cache, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
# Clean packet caches
|
# Clean packet caches
|
||||||
for filename in os.listdir(self.cachepath):
|
for filename in os.listdir(self.cachepath):
|
||||||
try:
|
try:
|
||||||
if len(filename) == (RNS.Identity.HASHLENGTH//8)*2:
|
if len(filename) == (RNS.Identity.HASHLENGTH//8)*2:
|
||||||
filepath = self.cachepath + "/" + filename
|
filepath = f"{self.cachepath}/{filename}"
|
||||||
mtime = os.path.getmtime(filepath)
|
mtime = os.path.getmtime(filepath)
|
||||||
age = now - mtime
|
age = now - mtime
|
||||||
if age > RNS.Transport.DESTINATION_TIMEOUT:
|
if age > RNS.Transport.DESTINATION_TIMEOUT:
|
||||||
os.unlink(filepath)
|
os.unlink(filepath)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while cleaning resources cache, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while cleaning resources cache, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def __create_default_config(self):
|
def __create_default_config(self):
|
||||||
self.config = ConfigObj(__default_rns_config__)
|
self.config = ConfigObj(__default_rns_config__)
|
||||||
@ -1266,7 +1266,7 @@ class Reticulum:
|
|||||||
rpc_connection.close()
|
rpc_connection.close()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error ocurred while handling RPC call from local client: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"An error ocurred while handling RPC call from local client: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
def get_interface_stats(self):
|
def get_interface_stats(self):
|
||||||
if self.is_connected_to_shared_instance:
|
if self.is_connected_to_shared_instance:
|
||||||
@ -1296,7 +1296,7 @@ class Reticulum:
|
|||||||
|
|
||||||
if hasattr(interface, "b32"):
|
if hasattr(interface, "b32"):
|
||||||
if interface.b32 != None:
|
if interface.b32 != None:
|
||||||
ifstats["i2p_b32"] = interface.b32+".b32.i2p"
|
ifstats["i2p_b32"] = f"{interface.b32}.b32.i2p"
|
||||||
else:
|
else:
|
||||||
ifstats["i2p_b32"] = None
|
ifstats["i2p_b32"] = None
|
||||||
|
|
||||||
@ -1485,12 +1485,12 @@ class Reticulum:
|
|||||||
|
|
||||||
if self.is_connected_to_shared_instance and hasattr(self, "_force_shared_instance_bitrate") and self._force_shared_instance_bitrate:
|
if self.is_connected_to_shared_instance and hasattr(self, "_force_shared_instance_bitrate") and self._force_shared_instance_bitrate:
|
||||||
simulated_latency = ((1/self._force_shared_instance_bitrate)*8)*RNS.Reticulum.MTU
|
simulated_latency = ((1/self._force_shared_instance_bitrate)*8)*RNS.Reticulum.MTU
|
||||||
RNS.log("Adding simulated latency of "+RNS.prettytime(simulated_latency)+" to first hop timeout", RNS.LOG_DEBUG)
|
RNS.log(f"Adding simulated latency of {RNS.prettytime(simulated_latency)} to first hop timeout", RNS.LOG_DEBUG)
|
||||||
response += simulated_latency
|
response += simulated_latency
|
||||||
|
|
||||||
return response
|
return response
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error occurred while getting first hop timeout from shared instance: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"An error occurred while getting first hop timeout from shared instance: {e}", RNS.LOG_ERROR)
|
||||||
return RNS.Reticulum.DEFAULT_PER_HOP_TIMEOUT
|
return RNS.Reticulum.DEFAULT_PER_HOP_TIMEOUT
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
262
RNS/Transport.py
262
RNS/Transport.py
@ -148,7 +148,7 @@ class Transport:
|
|||||||
Transport.owner = reticulum_instance
|
Transport.owner = reticulum_instance
|
||||||
|
|
||||||
if Transport.identity == None:
|
if Transport.identity == None:
|
||||||
transport_identity_path = RNS.Reticulum.storagepath+"/transport_identity"
|
transport_identity_path = f"{RNS.Reticulum.storagepath}/transport_identity"
|
||||||
if os.path.isfile(transport_identity_path):
|
if os.path.isfile(transport_identity_path):
|
||||||
Transport.identity = RNS.Identity.from_file(transport_identity_path)
|
Transport.identity = RNS.Identity.from_file(transport_identity_path)
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ class Transport:
|
|||||||
else:
|
else:
|
||||||
RNS.log("Loaded Transport Identity from storage", RNS.LOG_VERBOSE)
|
RNS.log("Loaded Transport Identity from storage", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
packet_hashlist_path = RNS.Reticulum.storagepath+"/packet_hashlist"
|
packet_hashlist_path = f"{RNS.Reticulum.storagepath}/packet_hashlist"
|
||||||
if not Transport.owner.is_connected_to_shared_instance:
|
if not Transport.owner.is_connected_to_shared_instance:
|
||||||
if os.path.isfile(packet_hashlist_path):
|
if os.path.isfile(packet_hashlist_path):
|
||||||
try:
|
try:
|
||||||
@ -167,7 +167,7 @@ class Transport:
|
|||||||
Transport.packet_hashlist = umsgpack.unpackb(file.read())
|
Transport.packet_hashlist = umsgpack.unpackb(file.read())
|
||||||
file.close()
|
file.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not load packet hashlist from storage, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Could not load packet hashlist from storage, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
# Create transport-specific destinations
|
# Create transport-specific destinations
|
||||||
Transport.path_request_destination = RNS.Destination(None, RNS.Destination.IN, RNS.Destination.PLAIN, Transport.APP_NAME, "path", "request")
|
Transport.path_request_destination = RNS.Destination(None, RNS.Destination.IN, RNS.Destination.PLAIN, Transport.APP_NAME, "path", "request")
|
||||||
@ -186,15 +186,15 @@ class Transport:
|
|||||||
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.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(f"Enabled remote management on {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()
|
||||||
|
|
||||||
if RNS.Reticulum.transport_enabled():
|
if RNS.Reticulum.transport_enabled():
|
||||||
destination_table_path = RNS.Reticulum.storagepath+"/destination_table"
|
destination_table_path = f"{RNS.Reticulum.storagepath}/destination_table"
|
||||||
tunnel_table_path = RNS.Reticulum.storagepath+"/tunnels"
|
tunnel_table_path = f"{RNS.Reticulum.storagepath}/tunnels"
|
||||||
|
|
||||||
if os.path.isfile(destination_table_path) and not Transport.owner.is_connected_to_shared_instance:
|
if os.path.isfile(destination_table_path) and not Transport.owner.is_connected_to_shared_instance:
|
||||||
serialised_destinations = []
|
serialised_destinations = []
|
||||||
@ -223,9 +223,9 @@ class Transport:
|
|||||||
# increased hop-count.
|
# increased hop-count.
|
||||||
announce_packet.hops += 1
|
announce_packet.hops += 1
|
||||||
Transport.destination_table[destination_hash] = [timestamp, received_from, hops, expires, random_blobs, receiving_interface, announce_packet]
|
Transport.destination_table[destination_hash] = [timestamp, received_from, hops, expires, random_blobs, receiving_interface, announce_packet]
|
||||||
RNS.log("Loaded path table entry for "+RNS.prettyhexrep(destination_hash)+" from storage", RNS.LOG_DEBUG)
|
RNS.log(f"Loaded path table entry for {RNS.prettyhexrep(destination_hash)} from storage", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
RNS.log("Could not reconstruct path table entry from storage for "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG)
|
RNS.log(f"Could not reconstruct path table entry from storage for {RNS.prettyhexrep(destination_hash)}", RNS.LOG_DEBUG)
|
||||||
if announce_packet == None:
|
if announce_packet == None:
|
||||||
RNS.log("The announce packet could not be loaded from cache", RNS.LOG_DEBUG)
|
RNS.log("The announce packet could not be loaded from cache", RNS.LOG_DEBUG)
|
||||||
if receiving_interface == None:
|
if receiving_interface == None:
|
||||||
@ -236,10 +236,10 @@ class Transport:
|
|||||||
else:
|
else:
|
||||||
specifier = "entries"
|
specifier = "entries"
|
||||||
|
|
||||||
RNS.log("Loaded "+str(len(Transport.destination_table))+" path table "+specifier+" from storage", RNS.LOG_VERBOSE)
|
RNS.log(f"Loaded {len(Transport.destination_table)} path table {specifier} from storage", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not load destination table from storage, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Could not load destination table from storage, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if os.path.isfile(tunnel_table_path) and not Transport.owner.is_connected_to_shared_instance:
|
if os.path.isfile(tunnel_table_path) and not Transport.owner.is_connected_to_shared_instance:
|
||||||
serialised_tunnels = []
|
serialised_tunnels = []
|
||||||
@ -284,21 +284,21 @@ class Transport:
|
|||||||
else:
|
else:
|
||||||
specifier = "entries"
|
specifier = "entries"
|
||||||
|
|
||||||
RNS.log("Loaded "+str(len(Transport.tunnels))+" tunnel table "+specifier+" from storage", RNS.LOG_VERBOSE)
|
RNS.log(f"Loaded {len(Transport.tunnels)} tunnel table {specifier} from storage", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not load tunnel table from storage, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Could not load tunnel table from storage, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if RNS.Reticulum.probe_destination_enabled():
|
if RNS.Reticulum.probe_destination_enabled():
|
||||||
Transport.probe_destination = RNS.Destination(Transport.identity, RNS.Destination.IN, RNS.Destination.SINGLE, Transport.APP_NAME, "probe")
|
Transport.probe_destination = RNS.Destination(Transport.identity, RNS.Destination.IN, RNS.Destination.SINGLE, Transport.APP_NAME, "probe")
|
||||||
Transport.probe_destination.accepts_links(False)
|
Transport.probe_destination.accepts_links(False)
|
||||||
Transport.probe_destination.set_proof_strategy(RNS.Destination.PROVE_ALL)
|
Transport.probe_destination.set_proof_strategy(RNS.Destination.PROVE_ALL)
|
||||||
Transport.probe_destination.announce()
|
Transport.probe_destination.announce()
|
||||||
RNS.log("Transport Instance will respond to probe requests on "+str(Transport.probe_destination), RNS.LOG_NOTICE)
|
RNS.log(f"Transport Instance will respond to probe requests on {Transport.probe_destination}", RNS.LOG_NOTICE)
|
||||||
else:
|
else:
|
||||||
Transport.probe_destination = None
|
Transport.probe_destination = None
|
||||||
|
|
||||||
RNS.log("Transport instance "+str(Transport.identity)+" started", RNS.LOG_VERBOSE)
|
RNS.log(f"Transport instance {Transport.identity} started", RNS.LOG_VERBOSE)
|
||||||
Transport.start_time = time.time()
|
Transport.start_time = time.time()
|
||||||
|
|
||||||
# Sort interfaces according to bitrate
|
# Sort interfaces according to bitrate
|
||||||
@ -354,7 +354,7 @@ class Transport:
|
|||||||
last_path_request = Transport.path_requests[link.destination.hash]
|
last_path_request = Transport.path_requests[link.destination.hash]
|
||||||
|
|
||||||
if time.time() - last_path_request > Transport.PATH_REQUEST_MI:
|
if time.time() - last_path_request > Transport.PATH_REQUEST_MI:
|
||||||
RNS.log("Trying to rediscover path for "+RNS.prettyhexrep(link.destination.hash)+" since an attempted link was never established", RNS.LOG_DEBUG)
|
RNS.log(f"Trying to rediscover path for {RNS.prettyhexrep(link.destination.hash)} since an attempted link was never established", RNS.LOG_DEBUG)
|
||||||
if not link.destination.hash in path_requests:
|
if not link.destination.hash in path_requests:
|
||||||
blocked_if = None
|
blocked_if = None
|
||||||
path_requests[link.destination.hash] = blocked_if
|
path_requests[link.destination.hash] = blocked_if
|
||||||
@ -388,7 +388,7 @@ class Transport:
|
|||||||
for destination_hash in Transport.announce_table:
|
for destination_hash in Transport.announce_table:
|
||||||
announce_entry = Transport.announce_table[destination_hash]
|
announce_entry = Transport.announce_table[destination_hash]
|
||||||
if announce_entry[2] > Transport.PATHFINDER_R:
|
if announce_entry[2] > Transport.PATHFINDER_R:
|
||||||
RNS.log("Completed announce processing for "+RNS.prettyhexrep(destination_hash)+", retry limit reached", RNS.LOG_EXTREME)
|
RNS.log(f"Completed announce processing for {RNS.prettyhexrep(destination_hash)}, retry limit reached", RNS.LOG_EXTREME)
|
||||||
completed_announces.append(destination_hash)
|
completed_announces.append(destination_hash)
|
||||||
else:
|
else:
|
||||||
if time.time() > announce_entry[1]:
|
if time.time() > announce_entry[1]:
|
||||||
@ -420,9 +420,9 @@ class Transport:
|
|||||||
|
|
||||||
new_packet.hops = announce_entry[4]
|
new_packet.hops = announce_entry[4]
|
||||||
if block_rebroadcasts:
|
if block_rebroadcasts:
|
||||||
RNS.log("Rebroadcasting announce as path response for "+RNS.prettyhexrep(announce_destination.hash)+" with hop count "+str(new_packet.hops), RNS.LOG_DEBUG)
|
RNS.log(f"Rebroadcasting announce as path response for {RNS.prettyhexrep(announce_destination.hash)} with hop count {new_packet.hops}", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
RNS.log("Rebroadcasting announce for "+RNS.prettyhexrep(announce_destination.hash)+" with hop count "+str(new_packet.hops), RNS.LOG_DEBUG)
|
RNS.log(f"Rebroadcasting announce for {RNS.prettyhexrep(announce_destination.hash)} with hop count {new_packet.hops}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
outgoing.append(new_packet)
|
outgoing.append(new_packet)
|
||||||
|
|
||||||
@ -490,14 +490,14 @@ class Transport:
|
|||||||
# If the path has been invalidated between the time of
|
# If the path has been invalidated between the time of
|
||||||
# making the link request and now, try to rediscover it
|
# making the link request and now, try to rediscover it
|
||||||
if not Transport.has_path(link_entry[6]):
|
if not Transport.has_path(link_entry[6]):
|
||||||
RNS.log("Trying to rediscover path for "+RNS.prettyhexrep(link_entry[6])+" since an attempted link was never established, and path is now missing", RNS.LOG_DEBUG)
|
RNS.log(f"Trying to rediscover path for {RNS.prettyhexrep(link_entry[6])} since an attempted link was never established, and path is now missing", RNS.LOG_DEBUG)
|
||||||
path_request_conditions =True
|
path_request_conditions =True
|
||||||
|
|
||||||
# If this link request was originated from a local client
|
# If this link request was originated from a local client
|
||||||
# attempt to rediscover a path to the destination, if this
|
# attempt to rediscover a path to the destination, if this
|
||||||
# has not already happened recently.
|
# has not already happened recently.
|
||||||
elif not path_request_throttle and lr_taken_hops == 0:
|
elif not path_request_throttle and lr_taken_hops == 0:
|
||||||
RNS.log("Trying to rediscover path for "+RNS.prettyhexrep(link_entry[6])+" since an attempted local client link was never established", RNS.LOG_DEBUG)
|
RNS.log(f"Trying to rediscover path for {RNS.prettyhexrep(link_entry[6])} since an attempted local client link was never established", RNS.LOG_DEBUG)
|
||||||
path_request_conditions = True
|
path_request_conditions = True
|
||||||
|
|
||||||
# If the link destination was previously only 1 hop
|
# If the link destination was previously only 1 hop
|
||||||
@ -506,7 +506,7 @@ class Transport:
|
|||||||
# In that case, try to discover a new path, and mark
|
# In that case, try to discover a new path, and mark
|
||||||
# the old one as unresponsive.
|
# the old one as unresponsive.
|
||||||
elif not path_request_throttle and Transport.hops_to(link_entry[6]) == 1:
|
elif not path_request_throttle and Transport.hops_to(link_entry[6]) == 1:
|
||||||
RNS.log("Trying to rediscover path for "+RNS.prettyhexrep(link_entry[6])+" since an attempted link was never established, and destination was previously local to an interface on this instance", RNS.LOG_DEBUG)
|
RNS.log(f"Trying to rediscover path for {RNS.prettyhexrep(link_entry[6])} since an attempted link was never established, and destination was previously local to an interface on this instance", RNS.LOG_DEBUG)
|
||||||
path_request_conditions = True
|
path_request_conditions = True
|
||||||
blocked_if = link_entry[4]
|
blocked_if = link_entry[4]
|
||||||
|
|
||||||
@ -528,7 +528,7 @@ class Transport:
|
|||||||
# changed. In that case, we try to discover a new path,
|
# changed. In that case, we try to discover a new path,
|
||||||
# and mark the old one as potentially unresponsive.
|
# and mark the old one as potentially unresponsive.
|
||||||
elif not path_request_throttle and lr_taken_hops == 1:
|
elif not path_request_throttle and lr_taken_hops == 1:
|
||||||
RNS.log("Trying to rediscover path for "+RNS.prettyhexrep(link_entry[6])+" since an attempted link was never established, and link initiator is local to an interface on this instance", RNS.LOG_DEBUG)
|
RNS.log(f"Trying to rediscover path for {RNS.prettyhexrep(link_entry[6])} since an attempted link was never established, and link initiator is local to an interface on this instance", RNS.LOG_DEBUG)
|
||||||
path_request_conditions = True
|
path_request_conditions = True
|
||||||
blocked_if = link_entry[4]
|
blocked_if = link_entry[4]
|
||||||
|
|
||||||
@ -561,10 +561,10 @@ class Transport:
|
|||||||
|
|
||||||
if time.time() > destination_expiry:
|
if time.time() > destination_expiry:
|
||||||
stale_paths.append(destination_hash)
|
stale_paths.append(destination_hash)
|
||||||
RNS.log("Path to "+RNS.prettyhexrep(destination_hash)+" timed out and was removed", RNS.LOG_DEBUG)
|
RNS.log(f"Path to {RNS.prettyhexrep(destination_hash)} timed out and was removed", RNS.LOG_DEBUG)
|
||||||
elif not attached_interface in Transport.interfaces:
|
elif not attached_interface in Transport.interfaces:
|
||||||
stale_paths.append(destination_hash)
|
stale_paths.append(destination_hash)
|
||||||
RNS.log("Path to "+RNS.prettyhexrep(destination_hash)+" was removed since the attached interface no longer exists", RNS.LOG_DEBUG)
|
RNS.log(f"Path to {RNS.prettyhexrep(destination_hash)} was removed since the attached interface no longer exists", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
# Cull the pending discovery path requests table
|
# Cull the pending discovery path requests table
|
||||||
stale_discovery_path_requests = []
|
stale_discovery_path_requests = []
|
||||||
@ -573,7 +573,7 @@ class Transport:
|
|||||||
|
|
||||||
if time.time() > entry["timeout"]:
|
if time.time() > entry["timeout"]:
|
||||||
stale_discovery_path_requests.append(destination_hash)
|
stale_discovery_path_requests.append(destination_hash)
|
||||||
RNS.log("Waiting path request for "+RNS.prettyhexrep(destination_hash)+" timed out and was removed", RNS.LOG_DEBUG)
|
RNS.log(f"Waiting path request for {RNS.prettyhexrep(destination_hash)} timed out and was removed", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
# Cull the tunnel table
|
# Cull the tunnel table
|
||||||
stale_tunnels = []
|
stale_tunnels = []
|
||||||
@ -584,7 +584,7 @@ class Transport:
|
|||||||
expires = tunnel_entry[3]
|
expires = tunnel_entry[3]
|
||||||
if time.time() > expires:
|
if time.time() > expires:
|
||||||
stale_tunnels.append(tunnel_id)
|
stale_tunnels.append(tunnel_id)
|
||||||
RNS.log("Tunnel "+RNS.prettyhexrep(tunnel_id)+" timed out and was removed", RNS.LOG_EXTREME)
|
RNS.log(f"Tunnel {RNS.prettyhexrep(tunnel_id)} timed out and was removed", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
stale_tunnel_paths = []
|
stale_tunnel_paths = []
|
||||||
tunnel_paths = tunnel_entry[2]
|
tunnel_paths = tunnel_entry[2]
|
||||||
@ -593,7 +593,7 @@ class Transport:
|
|||||||
|
|
||||||
if time.time() > tunnel_path_entry[0] + Transport.DESTINATION_TIMEOUT:
|
if time.time() > tunnel_path_entry[0] + Transport.DESTINATION_TIMEOUT:
|
||||||
stale_tunnel_paths.append(tunnel_path)
|
stale_tunnel_paths.append(tunnel_path)
|
||||||
RNS.log("Tunnel path to "+RNS.prettyhexrep(tunnel_path)+" timed out and was removed", RNS.LOG_EXTREME)
|
RNS.log(f"Tunnel path to {RNS.prettyhexrep(tunnel_path)} timed out and was removed", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
for tunnel_path in stale_tunnel_paths:
|
for tunnel_path in stale_tunnel_paths:
|
||||||
tunnel_paths.pop(tunnel_path)
|
tunnel_paths.pop(tunnel_path)
|
||||||
@ -602,9 +602,9 @@ class Transport:
|
|||||||
|
|
||||||
if ti > 0:
|
if ti > 0:
|
||||||
if ti == 1:
|
if ti == 1:
|
||||||
RNS.log("Removed "+str(ti)+" tunnel path", RNS.LOG_EXTREME)
|
RNS.log(f"Removed {ti} tunnel path", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
RNS.log("Removed "+str(ti)+" tunnel paths", RNS.LOG_EXTREME)
|
RNS.log(f"Removed {ti} tunnel paths", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for truncated_packet_hash in stale_reverse_entries:
|
for truncated_packet_hash in stale_reverse_entries:
|
||||||
@ -613,9 +613,9 @@ class Transport:
|
|||||||
|
|
||||||
if i > 0:
|
if i > 0:
|
||||||
if i == 1:
|
if i == 1:
|
||||||
RNS.log("Released "+str(i)+" reverse table entry", RNS.LOG_EXTREME)
|
RNS.log(f"Released {i} reverse table entry", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
RNS.log("Released "+str(i)+" reverse table entries", RNS.LOG_EXTREME)
|
RNS.log(f"Released {i} reverse table entries", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for link_id in stale_links:
|
for link_id in stale_links:
|
||||||
@ -624,9 +624,9 @@ class Transport:
|
|||||||
|
|
||||||
if i > 0:
|
if i > 0:
|
||||||
if i == 1:
|
if i == 1:
|
||||||
RNS.log("Released "+str(i)+" link", RNS.LOG_EXTREME)
|
RNS.log(f"Released {i} link", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
RNS.log("Released "+str(i)+" links", RNS.LOG_EXTREME)
|
RNS.log(f"Released {i} links", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for destination_hash in stale_paths:
|
for destination_hash in stale_paths:
|
||||||
@ -635,9 +635,9 @@ class Transport:
|
|||||||
|
|
||||||
if i > 0:
|
if i > 0:
|
||||||
if i == 1:
|
if i == 1:
|
||||||
RNS.log("Removed "+str(i)+" path", RNS.LOG_EXTREME)
|
RNS.log(f"Removed {i} path", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
RNS.log("Removed "+str(i)+" paths", RNS.LOG_EXTREME)
|
RNS.log(f"Removed {i} paths", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for destination_hash in stale_discovery_path_requests:
|
for destination_hash in stale_discovery_path_requests:
|
||||||
@ -646,9 +646,9 @@ class Transport:
|
|||||||
|
|
||||||
if i > 0:
|
if i > 0:
|
||||||
if i == 1:
|
if i == 1:
|
||||||
RNS.log("Removed "+str(i)+" waiting path request", RNS.LOG_EXTREME)
|
RNS.log(f"Removed {i} waiting path request", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
RNS.log("Removed "+str(i)+" waiting path requests", RNS.LOG_EXTREME)
|
RNS.log(f"Removed {i} waiting path requests", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for tunnel_id in stale_tunnels:
|
for tunnel_id in stale_tunnels:
|
||||||
@ -657,9 +657,9 @@ class Transport:
|
|||||||
|
|
||||||
if i > 0:
|
if i > 0:
|
||||||
if i == 1:
|
if i == 1:
|
||||||
RNS.log("Removed "+str(i)+" tunnel", RNS.LOG_EXTREME)
|
RNS.log(f"Removed {i} tunnel", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
RNS.log("Removed "+str(i)+" tunnels", RNS.LOG_EXTREME)
|
RNS.log(f"Removed {i} tunnels", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for destination_hash in stale_path_states:
|
for destination_hash in stale_path_states:
|
||||||
@ -668,9 +668,9 @@ class Transport:
|
|||||||
|
|
||||||
if i > 0:
|
if i > 0:
|
||||||
if i == 1:
|
if i == 1:
|
||||||
RNS.log("Removed "+str(i)+" path state entry", RNS.LOG_EXTREME)
|
RNS.log(f"Removed {i} path state entry", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
RNS.log("Removed "+str(i)+" path state entries", RNS.LOG_EXTREME)
|
RNS.log(f"Removed {i} path state entries", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
Transport.tables_last_culled = time.time()
|
Transport.tables_last_culled = time.time()
|
||||||
|
|
||||||
@ -686,7 +686,7 @@ class Transport:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An exception occurred while running Transport jobs.", RNS.LOG_ERROR)
|
RNS.log("An exception occurred while running Transport jobs.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
Transport.jobs_running = False
|
Transport.jobs_running = False
|
||||||
|
|
||||||
@ -749,7 +749,7 @@ class Transport:
|
|||||||
interface.processOutgoing(raw)
|
interface.processOutgoing(raw)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while transmitting on "+str(interface)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while transmitting on {interface}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def outbound(packet):
|
def outbound(packet):
|
||||||
@ -857,7 +857,7 @@ class Transport:
|
|||||||
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
||||||
if packet.attached_interface == None:
|
if packet.attached_interface == None:
|
||||||
if interface.mode == RNS.Interfaces.Interface.Interface.MODE_ACCESS_POINT:
|
if interface.mode == RNS.Interfaces.Interface.Interface.MODE_ACCESS_POINT:
|
||||||
RNS.log("Blocking announce broadcast on "+str(interface)+" due to AP mode", RNS.LOG_EXTREME)
|
RNS.log(f"Blocking announce broadcast on {interface} due to AP mode", RNS.LOG_EXTREME)
|
||||||
should_transmit = False
|
should_transmit = False
|
||||||
|
|
||||||
elif interface.mode == RNS.Interfaces.Interface.Interface.MODE_ROAMING:
|
elif interface.mode == RNS.Interfaces.Interface.Interface.MODE_ROAMING:
|
||||||
@ -870,15 +870,15 @@ class Transport:
|
|||||||
if from_interface == None or not hasattr(from_interface, "mode"):
|
if from_interface == None or not hasattr(from_interface, "mode"):
|
||||||
should_transmit = False
|
should_transmit = False
|
||||||
if from_interface == None:
|
if from_interface == None:
|
||||||
RNS.log("Blocking announce broadcast on "+str(interface)+" since next hop interface doesn't exist", RNS.LOG_EXTREME)
|
RNS.log(f"Blocking announce broadcast on {interface} since next hop interface doesn't exist", RNS.LOG_EXTREME)
|
||||||
elif not hasattr(from_interface, "mode"):
|
elif not hasattr(from_interface, "mode"):
|
||||||
RNS.log("Blocking announce broadcast on "+str(interface)+" since next hop interface has no mode configured", RNS.LOG_EXTREME)
|
RNS.log(f"Blocking announce broadcast on {interface} since next hop interface has no mode configured", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
if from_interface.mode == RNS.Interfaces.Interface.Interface.MODE_ROAMING:
|
if from_interface.mode == RNS.Interfaces.Interface.Interface.MODE_ROAMING:
|
||||||
RNS.log("Blocking announce broadcast on "+str(interface)+" due to roaming-mode next-hop interface", RNS.LOG_EXTREME)
|
RNS.log(f"Blocking announce broadcast on {interface} due to roaming-mode next-hop interface", RNS.LOG_EXTREME)
|
||||||
should_transmit = False
|
should_transmit = False
|
||||||
elif from_interface.mode == RNS.Interfaces.Interface.Interface.MODE_BOUNDARY:
|
elif from_interface.mode == RNS.Interfaces.Interface.Interface.MODE_BOUNDARY:
|
||||||
RNS.log("Blocking announce broadcast on "+str(interface)+" due to boundary-mode next-hop interface", RNS.LOG_EXTREME)
|
RNS.log(f"Blocking announce broadcast on {interface} due to boundary-mode next-hop interface", RNS.LOG_EXTREME)
|
||||||
should_transmit = False
|
should_transmit = False
|
||||||
|
|
||||||
elif interface.mode == RNS.Interfaces.Interface.Interface.MODE_BOUNDARY:
|
elif interface.mode == RNS.Interfaces.Interface.Interface.MODE_BOUNDARY:
|
||||||
@ -891,12 +891,12 @@ class Transport:
|
|||||||
if from_interface == None or not hasattr(from_interface, "mode"):
|
if from_interface == None or not hasattr(from_interface, "mode"):
|
||||||
should_transmit = False
|
should_transmit = False
|
||||||
if from_interface == None:
|
if from_interface == None:
|
||||||
RNS.log("Blocking announce broadcast on "+str(interface)+" since next hop interface doesn't exist", RNS.LOG_EXTREME)
|
RNS.log(f"Blocking announce broadcast on {interface} since next hop interface doesn't exist", RNS.LOG_EXTREME)
|
||||||
elif not hasattr(from_interface, "mode"):
|
elif not hasattr(from_interface, "mode"):
|
||||||
RNS.log("Blocking announce broadcast on "+str(interface)+" since next hop interface has no mode configured", RNS.LOG_EXTREME)
|
RNS.log(f"Blocking announce broadcast on {interface} since next hop interface has no mode configured", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
if from_interface.mode == RNS.Interfaces.Interface.Interface.MODE_ROAMING:
|
if from_interface.mode == RNS.Interfaces.Interface.Interface.MODE_ROAMING:
|
||||||
RNS.log("Blocking announce broadcast on "+str(interface)+" due to roaming-mode next-hop interface", RNS.LOG_EXTREME)
|
RNS.log(f"Blocking announce broadcast on {interface} due to roaming-mode next-hop interface", RNS.LOG_EXTREME)
|
||||||
should_transmit = False
|
should_transmit = False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -959,23 +959,23 @@ class Transport:
|
|||||||
timer.start()
|
timer.start()
|
||||||
|
|
||||||
if wait_time < 1:
|
if wait_time < 1:
|
||||||
wait_time_str = str(round(wait_time*1000,2))+"ms"
|
wait_time_str = f"{round(wait_time * 1000, 2)}ms"
|
||||||
else:
|
else:
|
||||||
wait_time_str = str(round(wait_time*1,2))+"s"
|
wait_time_str = f"{round(wait_time * 1, 2)}s"
|
||||||
|
|
||||||
ql_str = str(len(interface.announce_queue))
|
ql_str = str(len(interface.announce_queue))
|
||||||
RNS.log("Added announce to queue (height "+ql_str+") on "+str(interface)+" for processing in "+wait_time_str, RNS.LOG_EXTREME)
|
RNS.log(f"Added announce to queue (height {ql_str}) on {interface} for processing in {wait_time_str}", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
wait_time = max(interface.announce_allowed_at - time.time(), 0)
|
wait_time = max(interface.announce_allowed_at - time.time(), 0)
|
||||||
|
|
||||||
if wait_time < 1:
|
if wait_time < 1:
|
||||||
wait_time_str = str(round(wait_time*1000,2))+"ms"
|
wait_time_str = f"{round(wait_time * 1000, 2)}ms"
|
||||||
else:
|
else:
|
||||||
wait_time_str = str(round(wait_time*1,2))+"s"
|
wait_time_str = f"{round(wait_time * 1, 2)}s"
|
||||||
|
|
||||||
ql_str = str(len(interface.announce_queue))
|
ql_str = str(len(interface.announce_queue))
|
||||||
RNS.log("Added announce to queue (height "+ql_str+") on "+str(interface)+" for processing in "+wait_time_str, RNS.LOG_EXTREME)
|
RNS.log(f"Added announce to queue (height {ql_str}) on {interface} for processing in {wait_time_str}", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
@ -1013,7 +1013,7 @@ class Transport:
|
|||||||
# Filter packets intended for other transport instances
|
# Filter packets intended for other transport instances
|
||||||
if packet.transport_id != None and packet.packet_type != RNS.Packet.ANNOUNCE:
|
if packet.transport_id != None and packet.packet_type != RNS.Packet.ANNOUNCE:
|
||||||
if packet.transport_id != Transport.identity.hash:
|
if packet.transport_id != Transport.identity.hash:
|
||||||
RNS.log("Ignored packet "+RNS.prettyhexrep(packet.packet_hash)+" in transport for other transport instance", RNS.LOG_EXTREME)
|
RNS.log(f"Ignored packet {RNS.prettyhexrep(packet.packet_hash)} in transport for other transport instance", RNS.LOG_EXTREME)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if packet.context == RNS.Packet.KEEPALIVE:
|
if packet.context == RNS.Packet.KEEPALIVE:
|
||||||
@ -1032,7 +1032,7 @@ class Transport:
|
|||||||
if packet.destination_type == RNS.Destination.PLAIN:
|
if packet.destination_type == RNS.Destination.PLAIN:
|
||||||
if packet.packet_type != RNS.Packet.ANNOUNCE:
|
if packet.packet_type != RNS.Packet.ANNOUNCE:
|
||||||
if packet.hops > 1:
|
if packet.hops > 1:
|
||||||
RNS.log("Dropped PLAIN packet "+RNS.prettyhexrep(packet.hash)+" with "+str(packet.hops)+" hops", RNS.LOG_DEBUG)
|
RNS.log(f"Dropped PLAIN packet {RNS.prettyhexrep(packet.hash)} with {packet.hops} hops", RNS.LOG_DEBUG)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
@ -1043,7 +1043,7 @@ class Transport:
|
|||||||
if packet.destination_type == RNS.Destination.GROUP:
|
if packet.destination_type == RNS.Destination.GROUP:
|
||||||
if packet.packet_type != RNS.Packet.ANNOUNCE:
|
if packet.packet_type != RNS.Packet.ANNOUNCE:
|
||||||
if packet.hops > 1:
|
if packet.hops > 1:
|
||||||
RNS.log("Dropped GROUP packet "+RNS.prettyhexrep(packet.hash)+" with "+str(packet.hops)+" hops", RNS.LOG_DEBUG)
|
RNS.log(f"Dropped GROUP packet {RNS.prettyhexrep(packet.hash)} with {packet.hops} hops", RNS.LOG_DEBUG)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
@ -1061,7 +1061,7 @@ class Transport:
|
|||||||
RNS.log("Dropped invalid announce packet", RNS.LOG_DEBUG)
|
RNS.log("Dropped invalid announce packet", RNS.LOG_DEBUG)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
RNS.log("Filtered packet with hash "+RNS.prettyhexrep(packet.packet_hash), RNS.LOG_EXTREME)
|
RNS.log(f"Filtered packet with hash {RNS.prettyhexrep(packet.packet_hash)}", RNS.LOG_EXTREME)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -1316,7 +1316,7 @@ class Transport:
|
|||||||
# TODO: There should probably be some kind of REJECT
|
# TODO: There should probably be some kind of REJECT
|
||||||
# mechanism here, to signal to the source that their
|
# mechanism here, to signal to the source that their
|
||||||
# expected path failed.
|
# expected path failed.
|
||||||
RNS.log("Got packet in transport, but no known path to final destination "+RNS.prettyhexrep(packet.destination_hash)+". Dropping packet.", RNS.LOG_EXTREME)
|
RNS.log(f"Got packet in transport, but no known path to final destination {RNS.prettyhexrep(packet.destination_hash)}. Dropping packet.", RNS.LOG_EXTREME)
|
||||||
|
|
||||||
# Link transport handling. Directs packets according
|
# Link transport handling. Directs packets according
|
||||||
# to entries in the link tables
|
# to entries in the link tables
|
||||||
@ -1391,17 +1391,17 @@ class Transport:
|
|||||||
announce_entry = Transport.announce_table[packet.destination_hash]
|
announce_entry = Transport.announce_table[packet.destination_hash]
|
||||||
|
|
||||||
if packet.hops-1 == announce_entry[4]:
|
if packet.hops-1 == announce_entry[4]:
|
||||||
RNS.log("Heard a local rebroadcast of announce for "+RNS.prettyhexrep(packet.destination_hash), RNS.LOG_DEBUG)
|
RNS.log(f"Heard a local rebroadcast of announce for {RNS.prettyhexrep(packet.destination_hash)}", RNS.LOG_DEBUG)
|
||||||
announce_entry[6] += 1
|
announce_entry[6] += 1
|
||||||
if announce_entry[6] >= Transport.LOCAL_REBROADCASTS_MAX:
|
if announce_entry[6] >= Transport.LOCAL_REBROADCASTS_MAX:
|
||||||
RNS.log("Max local rebroadcasts of announce for "+RNS.prettyhexrep(packet.destination_hash)+" reached, dropping announce from our table", RNS.LOG_DEBUG)
|
RNS.log(f"Max local rebroadcasts of announce for {RNS.prettyhexrep(packet.destination_hash)} reached, dropping announce from our table", RNS.LOG_DEBUG)
|
||||||
if packet.destination_hash in Transport.announce_table:
|
if packet.destination_hash in Transport.announce_table:
|
||||||
Transport.announce_table.pop(packet.destination_hash)
|
Transport.announce_table.pop(packet.destination_hash)
|
||||||
|
|
||||||
if packet.hops-1 == announce_entry[4]+1 and announce_entry[2] > 0:
|
if packet.hops-1 == announce_entry[4]+1 and announce_entry[2] > 0:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now < announce_entry[1]:
|
if now < announce_entry[1]:
|
||||||
RNS.log("Rebroadcasted announce for "+RNS.prettyhexrep(packet.destination_hash)+" has been passed on to another node, no further tries needed", RNS.LOG_DEBUG)
|
RNS.log(f"Rebroadcasted announce for {RNS.prettyhexrep(packet.destination_hash)} has been passed on to another node, no further tries needed", RNS.LOG_DEBUG)
|
||||||
Transport.announce_table.pop(packet.destination_hash)
|
Transport.announce_table.pop(packet.destination_hash)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -1458,7 +1458,7 @@ class Transport:
|
|||||||
if not random_blob in random_blobs:
|
if not random_blob in random_blobs:
|
||||||
# TODO: Check that this ^ approach actually
|
# TODO: Check that this ^ approach actually
|
||||||
# works under all circumstances
|
# works under all circumstances
|
||||||
RNS.log("Replacing destination table entry for "+str(RNS.prettyhexrep(packet.destination_hash))+" with new announce due to expired path", RNS.LOG_DEBUG)
|
RNS.log(f"Replacing destination table entry for {RNS.prettyhexrep(packet.destination_hash)} with new announce due to expired path", RNS.LOG_DEBUG)
|
||||||
Transport.mark_path_unknown_state(packet.destination_hash)
|
Transport.mark_path_unknown_state(packet.destination_hash)
|
||||||
should_add = True
|
should_add = True
|
||||||
else:
|
else:
|
||||||
@ -1469,7 +1469,7 @@ class Transport:
|
|||||||
# this announce before, update the path table.
|
# this announce before, update the path table.
|
||||||
if (announce_emitted > path_announce_emitted):
|
if (announce_emitted > path_announce_emitted):
|
||||||
if not random_blob in random_blobs:
|
if not random_blob in random_blobs:
|
||||||
RNS.log("Replacing destination table entry for "+str(RNS.prettyhexrep(packet.destination_hash))+" with new announce, since it was more recently emitted", RNS.LOG_DEBUG)
|
RNS.log(f"Replacing destination table entry for {RNS.prettyhexrep(packet.destination_hash)} with new announce, since it was more recently emitted", RNS.LOG_DEBUG)
|
||||||
Transport.mark_path_unknown_state(packet.destination_hash)
|
Transport.mark_path_unknown_state(packet.destination_hash)
|
||||||
should_add = True
|
should_add = True
|
||||||
else:
|
else:
|
||||||
@ -1481,7 +1481,7 @@ class Transport:
|
|||||||
# allow updating the path table to this one.
|
# allow updating the path table to this one.
|
||||||
elif announce_emitted == path_announce_emitted:
|
elif announce_emitted == path_announce_emitted:
|
||||||
if Transport.path_is_unresponsive(packet.destination_hash):
|
if Transport.path_is_unresponsive(packet.destination_hash):
|
||||||
RNS.log("Replacing destination table entry for "+str(RNS.prettyhexrep(packet.destination_hash))+" with new announce, since previously tried path was unresponsive", RNS.LOG_DEBUG)
|
RNS.log(f"Replacing destination table entry for {RNS.prettyhexrep(packet.destination_hash)} with new announce, since previously tried path was unresponsive", RNS.LOG_DEBUG)
|
||||||
should_add = True
|
should_add = True
|
||||||
else:
|
else:
|
||||||
should_add = False
|
should_add = False
|
||||||
@ -1551,7 +1551,7 @@ class Transport:
|
|||||||
# Insert announce into announce table for retransmission
|
# Insert announce into announce table for retransmission
|
||||||
|
|
||||||
if rate_blocked:
|
if rate_blocked:
|
||||||
RNS.log("Blocking rebroadcast of announce from "+RNS.prettyhexrep(packet.destination_hash)+" due to excessive announce rate", RNS.LOG_DEBUG)
|
RNS.log(f"Blocking rebroadcast of announce from {RNS.prettyhexrep(packet.destination_hash)} due to excessive announce rate", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if Transport.from_local_client(packet):
|
if Transport.from_local_client(packet):
|
||||||
@ -1648,9 +1648,9 @@ class Transport:
|
|||||||
pr_entry = Transport.discovery_path_requests[packet.destination_hash]
|
pr_entry = Transport.discovery_path_requests[packet.destination_hash]
|
||||||
attached_interface = pr_entry["requesting_interface"]
|
attached_interface = pr_entry["requesting_interface"]
|
||||||
|
|
||||||
interface_str = " on "+str(attached_interface)
|
interface_str = f" on {attached_interface}"
|
||||||
|
|
||||||
RNS.log("Got matching announce, answering waiting discovery path request for "+RNS.prettyhexrep(packet.destination_hash)+interface_str, RNS.LOG_DEBUG)
|
RNS.log(f"Got matching announce, answering waiting discovery path request for {RNS.prettyhexrep(packet.destination_hash)}{interface_str}", RNS.LOG_DEBUG)
|
||||||
announce_identity = RNS.Identity.recall(packet.destination_hash)
|
announce_identity = RNS.Identity.recall(packet.destination_hash)
|
||||||
announce_destination = RNS.Destination(announce_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, "unknown", "unknown");
|
announce_destination = RNS.Destination(announce_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, "unknown", "unknown");
|
||||||
announce_destination.hash = packet.destination_hash
|
announce_destination.hash = packet.destination_hash
|
||||||
@ -1675,7 +1675,7 @@ class Transport:
|
|||||||
|
|
||||||
destination_table_entry = [now, received_from, announce_hops, expires, random_blobs, packet.receiving_interface, packet]
|
destination_table_entry = [now, received_from, announce_hops, expires, random_blobs, packet.receiving_interface, packet]
|
||||||
Transport.destination_table[packet.destination_hash] = destination_table_entry
|
Transport.destination_table[packet.destination_hash] = destination_table_entry
|
||||||
RNS.log("Destination "+RNS.prettyhexrep(packet.destination_hash)+" is now "+str(announce_hops)+" hops away via "+RNS.prettyhexrep(received_from)+" on "+str(packet.receiving_interface), RNS.LOG_DEBUG)
|
RNS.log(f"Destination {RNS.prettyhexrep(packet.destination_hash)} is now {announce_hops} hops away via {RNS.prettyhexrep(received_from)} on {packet.receiving_interface}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
# If the receiving interface is a tunnel, we add the
|
# If the receiving interface is a tunnel, we add the
|
||||||
# announce to the tunnels table
|
# announce to the tunnels table
|
||||||
@ -1685,7 +1685,7 @@ class Transport:
|
|||||||
paths[packet.destination_hash] = destination_table_entry
|
paths[packet.destination_hash] = destination_table_entry
|
||||||
expires = time.time() + Transport.DESTINATION_TIMEOUT
|
expires = time.time() + Transport.DESTINATION_TIMEOUT
|
||||||
tunnel_entry[3] = expires
|
tunnel_entry[3] = expires
|
||||||
RNS.log("Path to "+RNS.prettyhexrep(packet.destination_hash)+" associated with tunnel "+RNS.prettyhexrep(packet.receiving_interface.tunnel_id), RNS.LOG_DEBUG)
|
RNS.log(f"Path to {RNS.prettyhexrep(packet.destination_hash)} associated with tunnel {RNS.prettyhexrep(packet.receiving_interface.tunnel_id)}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
# Call externally registered callbacks from apps
|
# Call externally registered callbacks from apps
|
||||||
# wanting to know when an announce arrives
|
# wanting to know when an announce arrives
|
||||||
@ -1720,7 +1720,7 @@ class Transport:
|
|||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while processing external announce callback.", RNS.LOG_ERROR)
|
RNS.log("Error while processing external announce callback.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.trace_exception(e)
|
RNS.trace_exception(e)
|
||||||
|
|
||||||
# Handling for link requests to local destinations
|
# Handling for link requests to local destinations
|
||||||
@ -1764,7 +1764,7 @@ class Transport:
|
|||||||
if destination.callbacks.proof_requested(packet):
|
if destination.callbacks.proof_requested(packet):
|
||||||
packet.prove()
|
packet.prove()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing proof request callback. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while executing proof request callback. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
# Handling for proofs and link-request proofs
|
# Handling for proofs and link-request proofs
|
||||||
elif packet.packet_type == RNS.Packet.PROOF:
|
elif packet.packet_type == RNS.Packet.PROOF:
|
||||||
@ -1785,7 +1785,7 @@ class Transport:
|
|||||||
signature = packet.data[:RNS.Identity.SIGLENGTH//8]
|
signature = packet.data[:RNS.Identity.SIGLENGTH//8]
|
||||||
|
|
||||||
if peer_identity.validate(signature, signed_data):
|
if peer_identity.validate(signature, signed_data):
|
||||||
RNS.log("Link request proof validated for transport via "+str(link_entry[4]), RNS.LOG_EXTREME)
|
RNS.log(f"Link request proof validated for transport via {link_entry[4]}", RNS.LOG_EXTREME)
|
||||||
new_raw = packet.raw[0:1]
|
new_raw = packet.raw[0:1]
|
||||||
new_raw += struct.pack("!B", packet.hops)
|
new_raw += struct.pack("!B", packet.hops)
|
||||||
new_raw += packet.raw[2:]
|
new_raw += packet.raw[2:]
|
||||||
@ -1793,10 +1793,10 @@ class Transport:
|
|||||||
Transport.transmit(link_entry[4], new_raw)
|
Transport.transmit(link_entry[4], new_raw)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Invalid link request proof in transport for link "+RNS.prettyhexrep(packet.destination_hash)+", dropping proof.", RNS.LOG_DEBUG)
|
RNS.log(f"Invalid link request proof in transport for link {RNS.prettyhexrep(packet.destination_hash)}, dropping proof.", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while transporting link request proof. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while transporting link request proof. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Link request proof received on wrong interface, not transporting it.", RNS.LOG_DEBUG)
|
RNS.log("Link request proof received on wrong interface, not transporting it.", RNS.LOG_DEBUG)
|
||||||
@ -1845,7 +1845,7 @@ class Transport:
|
|||||||
if (RNS.Reticulum.transport_enabled() or from_local_client or proof_for_local_client) and packet.destination_hash in Transport.reverse_table:
|
if (RNS.Reticulum.transport_enabled() or from_local_client or proof_for_local_client) and packet.destination_hash in Transport.reverse_table:
|
||||||
reverse_entry = Transport.reverse_table.pop(packet.destination_hash)
|
reverse_entry = Transport.reverse_table.pop(packet.destination_hash)
|
||||||
if packet.receiving_interface == reverse_entry[1]:
|
if packet.receiving_interface == reverse_entry[1]:
|
||||||
RNS.log("Proof received on correct interface, transporting it via "+str(reverse_entry[0]), RNS.LOG_EXTREME)
|
RNS.log(f"Proof received on correct interface, transporting it via {reverse_entry[0]}", RNS.LOG_EXTREME)
|
||||||
new_raw = packet.raw[0:1]
|
new_raw = packet.raw[0:1]
|
||||||
new_raw += struct.pack("!B", packet.hops)
|
new_raw += struct.pack("!B", packet.hops)
|
||||||
new_raw += packet.raw[2:]
|
new_raw += packet.raw[2:]
|
||||||
@ -1913,19 +1913,19 @@ class Transport:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error occurred while validating tunnel establishment packet.", RNS.LOG_DEBUG)
|
RNS.log("An error occurred while validating tunnel establishment packet.", RNS.LOG_DEBUG)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_tunnel(tunnel_id, interface):
|
def handle_tunnel(tunnel_id, interface):
|
||||||
expires = time.time() + Transport.DESTINATION_TIMEOUT
|
expires = time.time() + Transport.DESTINATION_TIMEOUT
|
||||||
if not tunnel_id in Transport.tunnels:
|
if not tunnel_id in Transport.tunnels:
|
||||||
RNS.log("Tunnel endpoint "+RNS.prettyhexrep(tunnel_id)+" established.", RNS.LOG_DEBUG)
|
RNS.log(f"Tunnel endpoint {RNS.prettyhexrep(tunnel_id)} established.", RNS.LOG_DEBUG)
|
||||||
paths = {}
|
paths = {}
|
||||||
tunnel_entry = [tunnel_id, interface, paths, expires]
|
tunnel_entry = [tunnel_id, interface, paths, expires]
|
||||||
interface.tunnel_id = tunnel_id
|
interface.tunnel_id = tunnel_id
|
||||||
Transport.tunnels[tunnel_id] = tunnel_entry
|
Transport.tunnels[tunnel_id] = tunnel_entry
|
||||||
else:
|
else:
|
||||||
RNS.log("Tunnel endpoint "+RNS.prettyhexrep(tunnel_id)+" reappeared. Restoring paths...", RNS.LOG_DEBUG)
|
RNS.log(f"Tunnel endpoint {RNS.prettyhexrep(tunnel_id)} reappeared. Restoring paths...", RNS.LOG_DEBUG)
|
||||||
tunnel_entry = Transport.tunnels[tunnel_id]
|
tunnel_entry = Transport.tunnels[tunnel_id]
|
||||||
tunnel_entry[1] = interface
|
tunnel_entry[1] = interface
|
||||||
tunnel_entry[3] = expires
|
tunnel_entry[3] = expires
|
||||||
@ -1950,21 +1950,21 @@ class Transport:
|
|||||||
if announce_hops <= old_hops or time.time() > old_expires:
|
if announce_hops <= old_hops or time.time() > old_expires:
|
||||||
should_add = True
|
should_add = True
|
||||||
else:
|
else:
|
||||||
RNS.log("Did not restore path to "+RNS.prettyhexrep(packet.destination_hash)+" because a newer path with fewer hops exist", RNS.LOG_DEBUG)
|
RNS.log(f"Did not restore path to {RNS.prettyhexrep(packet.destination_hash)} because a newer path with fewer hops exist", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
if time.time() < expires:
|
if time.time() < expires:
|
||||||
should_add = True
|
should_add = True
|
||||||
else:
|
else:
|
||||||
RNS.log("Did not restore path to "+RNS.prettyhexrep(packet.destination_hash)+" because it has expired", RNS.LOG_DEBUG)
|
RNS.log(f"Did not restore path to {RNS.prettyhexrep(packet.destination_hash)} because it has expired", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
if should_add:
|
if should_add:
|
||||||
Transport.destination_table[destination_hash] = new_entry
|
Transport.destination_table[destination_hash] = new_entry
|
||||||
RNS.log("Restored path to "+RNS.prettyhexrep(packet.destination_hash)+" is now "+str(announce_hops)+" hops away via "+RNS.prettyhexrep(received_from)+" on "+str(receiving_interface), RNS.LOG_DEBUG)
|
RNS.log(f"Restored path to {RNS.prettyhexrep(packet.destination_hash)} is now {announce_hops} hops away via {RNS.prettyhexrep(received_from)} on {receiving_interface}", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
deprecated_paths.append(destination_hash)
|
deprecated_paths.append(destination_hash)
|
||||||
|
|
||||||
for deprecated_path in deprecated_paths:
|
for deprecated_path in deprecated_paths:
|
||||||
RNS.log("Removing path to "+RNS.prettyhexrep(deprecated_path)+" from tunnel "+RNS.prettyhexrep(tunnel_id), RNS.LOG_DEBUG)
|
RNS.log(f"Removing path to {RNS.prettyhexrep(deprecated_path)} from tunnel {RNS.prettyhexrep(tunnel_id)}", RNS.LOG_DEBUG)
|
||||||
paths.pop(deprecated_path)
|
paths.pop(deprecated_path)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -1988,7 +1988,7 @@ class Transport:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def register_link(link):
|
def register_link(link):
|
||||||
RNS.log("Registering link "+str(link), RNS.LOG_EXTREME)
|
RNS.log(f"Registering link {link}", RNS.LOG_EXTREME)
|
||||||
if link.initiator:
|
if link.initiator:
|
||||||
Transport.pending_links.append(link)
|
Transport.pending_links.append(link)
|
||||||
else:
|
else:
|
||||||
@ -1996,10 +1996,10 @@ class Transport:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def activate_link(link):
|
def activate_link(link):
|
||||||
RNS.log("Activating link "+str(link), RNS.LOG_EXTREME)
|
RNS.log(f"Activating link {link}", RNS.LOG_EXTREME)
|
||||||
if link in Transport.pending_links:
|
if link in Transport.pending_links:
|
||||||
if link.status != RNS.Link.ACTIVE:
|
if link.status != RNS.Link.ACTIVE:
|
||||||
raise IOError("Invalid link state for link activation: "+str(link.status))
|
raise OSError(f"Invalid link state for link activation: {link.status}")
|
||||||
Transport.pending_links.remove(link)
|
Transport.pending_links.remove(link)
|
||||||
Transport.active_links.append(link)
|
Transport.active_links.append(link)
|
||||||
link.status = RNS.Link.ACTIVE
|
link.status = RNS.Link.ACTIVE
|
||||||
@ -2061,18 +2061,18 @@ class Transport:
|
|||||||
if packet.receiving_interface != None:
|
if packet.receiving_interface != None:
|
||||||
interface_reference = str(packet.receiving_interface)
|
interface_reference = str(packet.receiving_interface)
|
||||||
|
|
||||||
file = open(RNS.Reticulum.cachepath+"/"+packet_hash, "wb")
|
file = open(f"{RNS.Reticulum.cachepath}/{packet_hash}", "wb")
|
||||||
file.write(umsgpack.packb([packet.raw, interface_reference]))
|
file.write(umsgpack.packb([packet.raw, interface_reference]))
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error writing packet to cache. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error writing packet to cache. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_cached_packet(packet_hash):
|
def get_cached_packet(packet_hash):
|
||||||
try:
|
try:
|
||||||
packet_hash = RNS.hexrep(packet_hash, delimit=False)
|
packet_hash = RNS.hexrep(packet_hash, delimit=False)
|
||||||
path = RNS.Reticulum.cachepath+"/"+packet_hash
|
path = f"{RNS.Reticulum.cachepath}/{packet_hash}"
|
||||||
|
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
file = open(path, "rb")
|
file = open(path, "rb")
|
||||||
@ -2091,7 +2091,7 @@ class Transport:
|
|||||||
return None
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Exception occurred while getting cached packet.", RNS.LOG_ERROR)
|
RNS.log("Exception occurred while getting cached packet.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cache_request_packet(packet):
|
def cache_request_packet(packet):
|
||||||
@ -2281,12 +2281,12 @@ class Transport:
|
|||||||
|
|
||||||
queued_announces = True if len(on_interface.announce_queue) > 0 else False
|
queued_announces = True if len(on_interface.announce_queue) > 0 else False
|
||||||
if queued_announces:
|
if queued_announces:
|
||||||
RNS.log("Blocking recursive path request on "+str(on_interface)+" due to queued announces", RNS.LOG_EXTREME)
|
RNS.log(f"Blocking recursive path request on {on_interface} due to queued announces", RNS.LOG_EXTREME)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now < on_interface.announce_allowed_at:
|
if now < on_interface.announce_allowed_at:
|
||||||
RNS.log("Blocking recursive path request on "+str(on_interface)+" due to active announce cap", RNS.LOG_EXTREME)
|
RNS.log(f"Blocking recursive path request on {on_interface} due to active announce cap", RNS.LOG_EXTREME)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
tx_time = ((len(path_request_data)+RNS.Reticulum.HEADER_MINSIZE)*8) / on_interface.bitrate
|
tx_time = ((len(path_request_data)+RNS.Reticulum.HEADER_MINSIZE)*8) / on_interface.bitrate
|
||||||
@ -2310,8 +2310,8 @@ 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 "+str(remote_identity), RNS.LOG_ERROR)
|
RNS.log(f"An error occurred while processing remote status request from {remote_identity}", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -2346,8 +2346,8 @@ 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 "+str(remote_identity), RNS.LOG_ERROR)
|
RNS.log(f"An error occurred while processing remote status request from {remote_identity}", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -2393,13 +2393,13 @@ class Transport:
|
|||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Ignoring duplicate path request for "+RNS.prettyhexrep(destination_hash)+" with tag "+RNS.prettyhexrep(unique_tag), RNS.LOG_DEBUG)
|
RNS.log(f"Ignoring duplicate path request for {RNS.prettyhexrep(destination_hash)} with tag {RNS.prettyhexrep(unique_tag)}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Ignoring tagless path request for "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG)
|
RNS.log(f"Ignoring tagless path request for {RNS.prettyhexrep(destination_hash)}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while handling path request. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while handling path request. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def path_request(destination_hash, is_from_local_client, attached_interface, requestor_transport_id=None, tag=None):
|
def path_request(destination_hash, is_from_local_client, attached_interface, requestor_transport_id=None, tag=None):
|
||||||
@ -2409,11 +2409,11 @@ class Transport:
|
|||||||
if RNS.Reticulum.transport_enabled() and attached_interface.mode in RNS.Interfaces.Interface.Interface.DISCOVER_PATHS_FOR:
|
if RNS.Reticulum.transport_enabled() and attached_interface.mode in RNS.Interfaces.Interface.Interface.DISCOVER_PATHS_FOR:
|
||||||
should_search_for_unknown = True
|
should_search_for_unknown = True
|
||||||
|
|
||||||
interface_str = " on "+str(attached_interface)
|
interface_str = f" on {attached_interface}"
|
||||||
else:
|
else:
|
||||||
interface_str = ""
|
interface_str = ""
|
||||||
|
|
||||||
RNS.log("Path request for "+RNS.prettyhexrep(destination_hash)+interface_str, RNS.LOG_DEBUG)
|
RNS.log(f"Path request for {RNS.prettyhexrep(destination_hash)}{interface_str}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
destination_exists_on_local_client = False
|
destination_exists_on_local_client = False
|
||||||
if len(Transport.local_client_interfaces) > 0:
|
if len(Transport.local_client_interfaces) > 0:
|
||||||
@ -2427,7 +2427,7 @@ class Transport:
|
|||||||
local_destination = next((d for d in Transport.destinations if d.hash == destination_hash), None)
|
local_destination = next((d for d in Transport.destinations if d.hash == destination_hash), None)
|
||||||
if local_destination != None:
|
if local_destination != None:
|
||||||
local_destination.announce(path_response=True, tag=tag, attached_interface=attached_interface)
|
local_destination.announce(path_response=True, tag=tag, attached_interface=attached_interface)
|
||||||
RNS.log("Answering path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", destination is local to this system", RNS.LOG_DEBUG)
|
RNS.log(f"Answering path request for {RNS.prettyhexrep(destination_hash)}{interface_str}, destination is local to this system", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
elif (RNS.Reticulum.transport_enabled() or is_from_local_client) and (destination_hash in Transport.destination_table):
|
elif (RNS.Reticulum.transport_enabled() or is_from_local_client) and (destination_hash in Transport.destination_table):
|
||||||
packet = Transport.destination_table[destination_hash][6]
|
packet = Transport.destination_table[destination_hash][6]
|
||||||
@ -2445,9 +2445,9 @@ class Transport:
|
|||||||
# inefficient. There is probably a better way. Doing
|
# inefficient. There is probably a better way. Doing
|
||||||
# path invalidation here would decrease the network
|
# path invalidation here would decrease the network
|
||||||
# convergence time. Maybe just drop it?
|
# convergence time. Maybe just drop it?
|
||||||
RNS.log("Not answering path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", since next hop is the requestor", RNS.LOG_DEBUG)
|
RNS.log(f"Not answering path request for {RNS.prettyhexrep(destination_hash)}{interface_str}, since next hop is the requestor", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
RNS.log("Answering path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", path is known", RNS.LOG_DEBUG)
|
RNS.log(f"Answering path request for {RNS.prettyhexrep(destination_hash)}{interface_str}, path is known", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
now = time.time()
|
now = time.time()
|
||||||
retries = Transport.PATHFINDER_R
|
retries = Transport.PATHFINDER_R
|
||||||
@ -2459,7 +2459,7 @@ class Transport:
|
|||||||
retransmit_timeout = now
|
retransmit_timeout = now
|
||||||
else:
|
else:
|
||||||
if Transport.is_local_client_interface(Transport.next_hop_interface(destination_hash)):
|
if Transport.is_local_client_interface(Transport.next_hop_interface(destination_hash)):
|
||||||
RNS.log("Path request destination "+RNS.prettyhexrep(destination_hash)+" is on a local client interface, rebroadcasting immediately", RNS.LOG_EXTREME)
|
RNS.log(f"Path request destination {RNS.prettyhexrep(destination_hash)} is on a local client interface, rebroadcasting immediately", RNS.LOG_EXTREME)
|
||||||
retransmit_timeout = now
|
retransmit_timeout = now
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -2486,7 +2486,7 @@ class Transport:
|
|||||||
elif is_from_local_client:
|
elif is_from_local_client:
|
||||||
# Forward path request on all interfaces
|
# Forward path request on all interfaces
|
||||||
# except the local client
|
# except the local client
|
||||||
RNS.log("Forwarding path request from local client for "+RNS.prettyhexrep(destination_hash)+interface_str+" to all other interfaces", RNS.LOG_DEBUG)
|
RNS.log(f"Forwarding path request from local client for {RNS.prettyhexrep(destination_hash)}{interface_str} to all other interfaces", RNS.LOG_DEBUG)
|
||||||
request_tag = RNS.Identity.get_random_hash()
|
request_tag = RNS.Identity.get_random_hash()
|
||||||
for interface in Transport.interfaces:
|
for interface in Transport.interfaces:
|
||||||
if not interface == attached_interface:
|
if not interface == attached_interface:
|
||||||
@ -2494,11 +2494,11 @@ class Transport:
|
|||||||
|
|
||||||
elif should_search_for_unknown:
|
elif should_search_for_unknown:
|
||||||
if destination_hash in Transport.discovery_path_requests:
|
if destination_hash in Transport.discovery_path_requests:
|
||||||
RNS.log("There is already a waiting path request for "+RNS.prettyhexrep(destination_hash)+" on behalf of path request"+interface_str, RNS.LOG_DEBUG)
|
RNS.log(f"There is already a waiting path request for {RNS.prettyhexrep(destination_hash)} on behalf of path request{interface_str}", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
# Forward path request on all interfaces
|
# Forward path request on all interfaces
|
||||||
# except the requestor interface
|
# except the requestor interface
|
||||||
RNS.log("Attempting to discover unknown path to "+RNS.prettyhexrep(destination_hash)+" on behalf of path request"+interface_str, RNS.LOG_DEBUG)
|
RNS.log(f"Attempting to discover unknown path to {RNS.prettyhexrep(destination_hash)} on behalf of path request{interface_str}", RNS.LOG_DEBUG)
|
||||||
pr_entry = { "destination_hash": destination_hash, "timeout": time.time()+Transport.PATH_REQUEST_TIMEOUT, "requesting_interface": attached_interface }
|
pr_entry = { "destination_hash": destination_hash, "timeout": time.time()+Transport.PATH_REQUEST_TIMEOUT, "requesting_interface": attached_interface }
|
||||||
Transport.discovery_path_requests[destination_hash] = pr_entry
|
Transport.discovery_path_requests[destination_hash] = pr_entry
|
||||||
|
|
||||||
@ -2511,12 +2511,12 @@ class Transport:
|
|||||||
elif not is_from_local_client and len(Transport.local_client_interfaces) > 0:
|
elif not is_from_local_client and len(Transport.local_client_interfaces) > 0:
|
||||||
# Forward the path request on all local
|
# Forward the path request on all local
|
||||||
# client interfaces
|
# client interfaces
|
||||||
RNS.log("Forwarding path request for "+RNS.prettyhexrep(destination_hash)+interface_str+" to local clients", RNS.LOG_DEBUG)
|
RNS.log(f"Forwarding path request for {RNS.prettyhexrep(destination_hash)}{interface_str} to local clients", RNS.LOG_DEBUG)
|
||||||
for interface in Transport.local_client_interfaces:
|
for interface in Transport.local_client_interfaces:
|
||||||
Transport.request_path(destination_hash, on_interface=interface)
|
Transport.request_path(destination_hash, on_interface=interface)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Ignoring path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", no path known", RNS.LOG_DEBUG)
|
RNS.log(f"Ignoring path request for {RNS.prettyhexrep(destination_hash)}{interface_str}, no path known", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_local_client(packet):
|
def from_local_client(packet):
|
||||||
@ -2568,7 +2568,7 @@ class Transport:
|
|||||||
try:
|
try:
|
||||||
interface.detach()
|
interface.detach()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error occurred while detaching "+str(interface)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"An error occurred while detaching {interface}. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def shared_connection_disappeared():
|
def shared_connection_disappeared():
|
||||||
@ -2604,10 +2604,10 @@ class Transport:
|
|||||||
if na == 1:
|
if na == 1:
|
||||||
na_str = "1 announce"
|
na_str = "1 announce"
|
||||||
else:
|
else:
|
||||||
na_str = str(na)+" announces"
|
na_str = f"{na} announces"
|
||||||
|
|
||||||
interface.announce_queue = []
|
interface.announce_queue = []
|
||||||
RNS.log("Dropped "+na_str+" on "+str(interface), RNS.LOG_VERBOSE)
|
RNS.log(f"Dropped {na_str} on {interface}", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -2640,20 +2640,20 @@ class Transport:
|
|||||||
else:
|
else:
|
||||||
RNS.log("Saving packet hashlist to storage...", RNS.LOG_DEBUG)
|
RNS.log("Saving packet hashlist to storage...", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
packet_hashlist_path = RNS.Reticulum.storagepath+"/packet_hashlist"
|
packet_hashlist_path = f"{RNS.Reticulum.storagepath}/packet_hashlist"
|
||||||
file = open(packet_hashlist_path, "wb")
|
file = open(packet_hashlist_path, "wb")
|
||||||
file.write(umsgpack.packb(Transport.packet_hashlist))
|
file.write(umsgpack.packb(Transport.packet_hashlist))
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
save_time = time.time() - save_start
|
save_time = time.time() - save_start
|
||||||
if save_time < 1:
|
if save_time < 1:
|
||||||
time_str = str(round(save_time*1000,2))+"ms"
|
time_str = f"{round(save_time * 1000, 2)}ms"
|
||||||
else:
|
else:
|
||||||
time_str = str(round(save_time,2))+"s"
|
time_str = f"{round(save_time, 2)}s"
|
||||||
RNS.log("Saved packet hashlist in "+time_str, RNS.LOG_DEBUG)
|
RNS.log(f"Saved packet hashlist in {time_str}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not save packet hashlist to storage, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Could not save packet hashlist to storage, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
Transport.saving_packet_hashlist = False
|
Transport.saving_packet_hashlist = False
|
||||||
|
|
||||||
@ -2710,20 +2710,20 @@ class Transport:
|
|||||||
|
|
||||||
Transport.cache(de[6], force_cache=True)
|
Transport.cache(de[6], force_cache=True)
|
||||||
|
|
||||||
destination_table_path = RNS.Reticulum.storagepath+"/destination_table"
|
destination_table_path = f"{RNS.Reticulum.storagepath}/destination_table"
|
||||||
file = open(destination_table_path, "wb")
|
file = open(destination_table_path, "wb")
|
||||||
file.write(umsgpack.packb(serialised_destinations))
|
file.write(umsgpack.packb(serialised_destinations))
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
save_time = time.time() - save_start
|
save_time = time.time() - save_start
|
||||||
if save_time < 1:
|
if save_time < 1:
|
||||||
time_str = str(round(save_time*1000,2))+"ms"
|
time_str = f"{round(save_time * 1000, 2)}ms"
|
||||||
else:
|
else:
|
||||||
time_str = str(round(save_time,2))+"s"
|
time_str = f"{round(save_time, 2)}s"
|
||||||
RNS.log("Saved "+str(len(serialised_destinations))+" path table entries in "+time_str, RNS.LOG_DEBUG)
|
RNS.log(f"Saved {len(serialised_destinations)} path table entries in {time_str}", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not save path table to storage, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Could not save path table to storage, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
Transport.saving_path_table = False
|
Transport.saving_path_table = False
|
||||||
|
|
||||||
@ -2788,19 +2788,19 @@ class Transport:
|
|||||||
serialised_tunnel = [tunnel_id, interface_hash, serialised_paths, expires]
|
serialised_tunnel = [tunnel_id, interface_hash, serialised_paths, expires]
|
||||||
serialised_tunnels.append(serialised_tunnel)
|
serialised_tunnels.append(serialised_tunnel)
|
||||||
|
|
||||||
tunnels_path = RNS.Reticulum.storagepath+"/tunnels"
|
tunnels_path = f"{RNS.Reticulum.storagepath}/tunnels"
|
||||||
file = open(tunnels_path, "wb")
|
file = open(tunnels_path, "wb")
|
||||||
file.write(umsgpack.packb(serialised_tunnels))
|
file.write(umsgpack.packb(serialised_tunnels))
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
save_time = time.time() - save_start
|
save_time = time.time() - save_start
|
||||||
if save_time < 1:
|
if save_time < 1:
|
||||||
time_str = str(round(save_time*1000,2))+"ms"
|
time_str = f"{round(save_time * 1000, 2)}ms"
|
||||||
else:
|
else:
|
||||||
time_str = str(round(save_time,2))+"s"
|
time_str = f"{round(save_time, 2)}s"
|
||||||
RNS.log("Saved "+str(len(serialised_tunnels))+" tunnel table entries in "+time_str, RNS.LOG_DEBUG)
|
RNS.log(f"Saved {len(serialised_tunnels)} tunnel table entries in {time_str}", RNS.LOG_DEBUG)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not save tunnel table to storage, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Could not save tunnel table to storage, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
Transport.saving_tunnel_table = False
|
Transport.saving_tunnel_table = False
|
||||||
|
|
||||||
|
@ -23,5 +23,5 @@
|
|||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
|
|
||||||
modules = glob.glob(os.path.dirname(__file__)+"/*.py")
|
modules = glob.glob(f"{os.path.dirname(__file__)}/*.py")
|
||||||
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
||||||
|
@ -54,9 +54,9 @@ def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identi
|
|||||||
|
|
||||||
if jail != None:
|
if jail != None:
|
||||||
fetch_jail = os.path.abspath(os.path.expanduser(jail))
|
fetch_jail = os.path.abspath(os.path.expanduser(jail))
|
||||||
RNS.log("Restricting fetch requests to paths under \""+fetch_jail+"\"", RNS.LOG_VERBOSE)
|
RNS.log(f"Restricting fetch requests to paths under \"{fetch_jail}\"", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
identity_path = RNS.Reticulum.identitypath+"/"+APP_NAME
|
identity_path = f"{RNS.Reticulum.identitypath}/{APP_NAME}"
|
||||||
if os.path.isfile(identity_path):
|
if os.path.isfile(identity_path):
|
||||||
identity = RNS.Identity.from_file(identity_path)
|
identity = RNS.Identity.from_file(identity_path)
|
||||||
|
|
||||||
@ -68,8 +68,8 @@ def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identi
|
|||||||
destination = RNS.Destination(identity, RNS.Destination.IN, RNS.Destination.SINGLE, APP_NAME, "receive")
|
destination = RNS.Destination(identity, RNS.Destination.IN, RNS.Destination.SINGLE, APP_NAME, "receive")
|
||||||
|
|
||||||
if display_identity:
|
if display_identity:
|
||||||
print("Identity : "+str(identity))
|
print(f"Identity : {identity}")
|
||||||
print("Listening on : "+RNS.prettyhexrep(destination.hash))
|
print(f"Listening on : {RNS.prettyhexrep(destination.hash)}")
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
if disable_auth:
|
if disable_auth:
|
||||||
@ -79,14 +79,14 @@ def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identi
|
|||||||
try:
|
try:
|
||||||
allowed_file_name = "allowed_identities"
|
allowed_file_name = "allowed_identities"
|
||||||
allowed_file = None
|
allowed_file = None
|
||||||
if os.path.isfile(os.path.expanduser("/etc/rncp/"+allowed_file_name)):
|
if os.path.isfile(os.path.expanduser(f"/etc/rncp/{allowed_file_name}")):
|
||||||
allowed_file = os.path.expanduser("/etc/rncp/"+allowed_file_name)
|
allowed_file = os.path.expanduser(f"/etc/rncp/{allowed_file_name}")
|
||||||
elif os.path.isfile(os.path.expanduser("~/.config/rncp/"+allowed_file_name)):
|
elif os.path.isfile(os.path.expanduser(f"~/.config/rncp/{allowed_file_name}")):
|
||||||
allowed_file = os.path.expanduser("~/.config/rncp/"+allowed_file_name)
|
allowed_file = os.path.expanduser(f"~/.config/rncp/{allowed_file_name}")
|
||||||
elif os.path.isfile(os.path.expanduser("~/.rncp/"+allowed_file_name)):
|
elif os.path.isfile(os.path.expanduser(f"~/.rncp/{allowed_file_name}")):
|
||||||
allowed_file = os.path.expanduser("~/.rncp/"+allowed_file_name)
|
allowed_file = os.path.expanduser(f"~/.rncp/{allowed_file_name}")
|
||||||
if allowed_file != None:
|
if allowed_file != None:
|
||||||
af = open(allowed_file, "r")
|
af = open(allowed_file)
|
||||||
al = af.read().replace("\r", "").split("\n")
|
al = af.read().replace("\r", "").split("\n")
|
||||||
ali = []
|
ali = []
|
||||||
for a in al:
|
for a in al:
|
||||||
@ -103,16 +103,16 @@ def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identi
|
|||||||
else:
|
else:
|
||||||
ms = "ies"
|
ms = "ies"
|
||||||
|
|
||||||
RNS.log("Loaded "+str(len(ali))+" allowed identit"+ms+" from "+str(allowed_file), RNS.LOG_VERBOSE)
|
RNS.log(f"Loaded {len(ali)} allowed identit{ms} from {allowed_file}", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while parsing allowed_identities file. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"Error while parsing allowed_identities file. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if allowed != None:
|
if allowed != None:
|
||||||
for a in allowed:
|
for a in allowed:
|
||||||
try:
|
try:
|
||||||
if len(a) != dest_len:
|
if len(a) != dest_len:
|
||||||
raise ValueError("Allowed destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Allowed destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(a)
|
destination_hash = bytes.fromhex(a)
|
||||||
allowed_identity_hashes.append(destination_hash)
|
allowed_identity_hashes.append(destination_hash)
|
||||||
@ -141,11 +141,11 @@ def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identi
|
|||||||
target_link = link
|
target_link = link
|
||||||
|
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
RNS.log("Client-requested file not found: "+str(file_path), RNS.LOG_VERBOSE)
|
RNS.log(f"Client-requested file not found: {file_path}", RNS.LOG_VERBOSE)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
if target_link != None:
|
if target_link != None:
|
||||||
RNS.log("Sending file "+str(file_path)+" to client", RNS.LOG_VERBOSE)
|
RNS.log(f"Sending file {file_path} to client", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
temp_file = TemporaryFile()
|
temp_file = TemporaryFile()
|
||||||
real_file = open(file_path, "rb")
|
real_file = open(file_path, "rb")
|
||||||
@ -169,7 +169,7 @@ def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identi
|
|||||||
|
|
||||||
destination.set_link_established_callback(client_link_established)
|
destination.set_link_established_callback(client_link_established)
|
||||||
destination.register_request_handler("fetch_file", response_generator=fetch_request, allow=RNS.Destination.ALLOW_LIST, allowed_list=allowed_identity_hashes)
|
destination.register_request_handler("fetch_file", response_generator=fetch_request, allow=RNS.Destination.ALLOW_LIST, allowed_list=allowed_identity_hashes)
|
||||||
print("rncp listening on "+RNS.prettyhexrep(destination.hash))
|
print(f"rncp listening on {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
if announce >= 0:
|
if announce >= 0:
|
||||||
def job():
|
def job():
|
||||||
@ -220,15 +220,15 @@ def receive_resource_callback(resource):
|
|||||||
|
|
||||||
def receive_resource_started(resource):
|
def receive_resource_started(resource):
|
||||||
if resource.link.get_remote_identity():
|
if resource.link.get_remote_identity():
|
||||||
id_str = " from "+RNS.prettyhexrep(resource.link.get_remote_identity().hash)
|
id_str = f" from {RNS.prettyhexrep(resource.link.get_remote_identity().hash)}"
|
||||||
else:
|
else:
|
||||||
id_str = ""
|
id_str = ""
|
||||||
|
|
||||||
print("Starting resource transfer "+RNS.prettyhexrep(resource.hash)+id_str)
|
print(f"Starting resource transfer {RNS.prettyhexrep(resource.hash)}{id_str}")
|
||||||
|
|
||||||
def receive_resource_concluded(resource):
|
def receive_resource_concluded(resource):
|
||||||
if resource.status == RNS.Resource.COMPLETE:
|
if resource.status == RNS.Resource.COMPLETE:
|
||||||
print(str(resource)+" completed")
|
print(f"{resource} completed")
|
||||||
|
|
||||||
if resource.total_size > 4:
|
if resource.total_size > 4:
|
||||||
filename_len = int.from_bytes(resource.data.read(2), "big")
|
filename_len = int.from_bytes(resource.data.read(2), "big")
|
||||||
@ -238,7 +238,7 @@ def receive_resource_concluded(resource):
|
|||||||
saved_filename = filename
|
saved_filename = filename
|
||||||
while os.path.isfile(saved_filename):
|
while os.path.isfile(saved_filename):
|
||||||
counter += 1
|
counter += 1
|
||||||
saved_filename = filename+"."+str(counter)
|
saved_filename = f"{filename}.{counter}"
|
||||||
|
|
||||||
file = open(saved_filename, "wb")
|
file = open(saved_filename, "wb")
|
||||||
file.write(resource.data.read())
|
file.write(resource.data.read())
|
||||||
@ -285,7 +285,7 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
try:
|
try:
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||||
if len(destination) != dest_len:
|
if len(destination) != dest_len:
|
||||||
raise ValueError("Allowed destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Allowed destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(destination)
|
destination_hash = bytes.fromhex(destination)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -296,11 +296,11 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
|
|
||||||
reticulum = RNS.Reticulum(configdir=configdir, loglevel=targetloglevel)
|
reticulum = RNS.Reticulum(configdir=configdir, loglevel=targetloglevel)
|
||||||
|
|
||||||
identity_path = RNS.Reticulum.identitypath+"/"+APP_NAME
|
identity_path = f"{RNS.Reticulum.identitypath}/{APP_NAME}"
|
||||||
if os.path.isfile(identity_path):
|
if os.path.isfile(identity_path):
|
||||||
identity = RNS.Identity.from_file(identity_path)
|
identity = RNS.Identity.from_file(identity_path)
|
||||||
if identity == None:
|
if identity == None:
|
||||||
RNS.log("Could not load identity for rncp. The identity file at \""+str(identity_path)+"\" may be corrupt or unreadable.", RNS.LOG_ERROR)
|
RNS.log(f"Could not load identity for rncp. The identity file at \"{identity_path}\" may be corrupt or unreadable.", RNS.LOG_ERROR)
|
||||||
exit(2)
|
exit(2)
|
||||||
else:
|
else:
|
||||||
identity = None
|
identity = None
|
||||||
@ -313,9 +313,9 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
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)
|
||||||
if silent:
|
if silent:
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested")
|
print(f"Path to {RNS.prettyhexrep(destination_hash)} requested")
|
||||||
else:
|
else:
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested ", end=" ")
|
print(f"Path to {RNS.prettyhexrep(destination_hash)} requested ", end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
@ -324,7 +324,7 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
while not RNS.Transport.has_path(destination_hash) and time.time() < estab_timeout:
|
while not RNS.Transport.has_path(destination_hash) and time.time() < estab_timeout:
|
||||||
if not silent:
|
if not silent:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
@ -336,9 +336,9 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print("Establishing link with "+RNS.prettyhexrep(destination_hash))
|
print(f"Establishing link with {RNS.prettyhexrep(destination_hash)}")
|
||||||
else:
|
else:
|
||||||
print("\r \rEstablishing link with "+RNS.prettyhexrep(destination_hash)+" ", end=" ")
|
print(f'\r \rEstablishing link with {RNS.prettyhexrep(destination_hash)} ', end=" ")
|
||||||
|
|
||||||
listener_identity = RNS.Identity.recall(destination_hash)
|
listener_identity = RNS.Identity.recall(destination_hash)
|
||||||
listener_destination = RNS.Destination(
|
listener_destination = RNS.Destination(
|
||||||
@ -353,15 +353,15 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
while link.status != RNS.Link.ACTIVE and time.time() < estab_timeout:
|
while link.status != RNS.Link.ACTIVE and time.time() < estab_timeout:
|
||||||
if not silent:
|
if not silent:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
if not RNS.Transport.has_path(destination_hash):
|
if not RNS.Transport.has_path(destination_hash):
|
||||||
if silent:
|
if silent:
|
||||||
print("Could not establish link with "+RNS.prettyhexrep(destination_hash))
|
print(f"Could not establish link with {RNS.prettyhexrep(destination_hash)}")
|
||||||
else:
|
else:
|
||||||
print("\r \rCould not establish link with "+RNS.prettyhexrep(destination_hash))
|
print(f'\r \rCould not establish link with {RNS.prettyhexrep(destination_hash)}')
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
@ -411,7 +411,7 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
saved_filename = filename
|
saved_filename = filename
|
||||||
while os.path.isfile(saved_filename):
|
while os.path.isfile(saved_filename):
|
||||||
counter += 1
|
counter += 1
|
||||||
saved_filename = filename+"."+str(counter)
|
saved_filename = f"{filename}.{counter}"
|
||||||
|
|
||||||
file = open(saved_filename, "wb")
|
file = open(saved_filename, "wb")
|
||||||
file.write(resource.data.read())
|
file.write(resource.data.read())
|
||||||
@ -437,19 +437,19 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
while not request_resolved:
|
while not request_resolved:
|
||||||
if not silent:
|
if not silent:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
if request_status == "fetch_not_allowed":
|
if request_status == "fetch_not_allowed":
|
||||||
if not silent: print("\r \r", end="")
|
if not silent: print("\r \r", end="")
|
||||||
print("Fetch request failed, fetching the file "+str(file)+" was not allowed by the remote")
|
print(f"Fetch request failed, fetching the file {file} was not allowed by the remote")
|
||||||
link.teardown()
|
link.teardown()
|
||||||
time.sleep(0.15)
|
time.sleep(0.15)
|
||||||
exit(0)
|
exit(0)
|
||||||
elif request_status == "not_found":
|
elif request_status == "not_found":
|
||||||
if not silent: print("\r \r", end="")
|
if not silent: print("\r \r", end="")
|
||||||
print("Fetch request failed, the file "+str(file)+" was not found on the remote")
|
print(f"Fetch request failed, the file {file} was not found on the remote")
|
||||||
link.teardown()
|
link.teardown()
|
||||||
time.sleep(0.15)
|
time.sleep(0.15)
|
||||||
exit(0)
|
exit(0)
|
||||||
@ -474,13 +474,13 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
if current_resource:
|
if current_resource:
|
||||||
prg = current_resource.get_progress()
|
prg = current_resource.get_progress()
|
||||||
percent = round(prg * 100.0, 1)
|
percent = round(prg * 100.0, 1)
|
||||||
stat_str = str(percent)+"% - " + size_str(int(prg*current_resource.total_size)) + " of " + size_str(current_resource.total_size) + " - " +size_str(speed, "b")+"ps"
|
stat_str = f"{percent}% - {size_str(int(prg * current_resource.total_size))} of {size_str(current_resource.total_size)} - {size_str(speed, 'b')}ps"
|
||||||
if prg != 1.0:
|
if prg != 1.0:
|
||||||
print("\r \rTransferring file "+syms[i]+" "+stat_str, end=" ")
|
print(f'\r \rTransferring file {syms[i]} {stat_str}', end=" ")
|
||||||
else:
|
else:
|
||||||
print("\r \rTransfer complete "+stat_str, end=" ")
|
print(f'\r \rTransfer complete {stat_str}', end=" ")
|
||||||
else:
|
else:
|
||||||
print("\r \rWaiting for transfer to start "+syms[i]+" ", end=" ")
|
print(f'\r \rWaiting for transfer to start {syms[i]} ', end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
@ -492,10 +492,10 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print(str(file)+" fetched from "+RNS.prettyhexrep(destination_hash))
|
print(f"{file} fetched from {RNS.prettyhexrep(destination_hash)}")
|
||||||
else:
|
else:
|
||||||
#print("\r \r"+str(file)+" fetched from "+RNS.prettyhexrep(destination_hash))
|
#print("\r \r"+str(file)+" fetched from "+RNS.prettyhexrep(destination_hash))
|
||||||
print("\n"+str(file)+" fetched from "+RNS.prettyhexrep(destination_hash))
|
print(f"\n{file} fetched from {RNS.prettyhexrep(destination_hash)}")
|
||||||
link.teardown()
|
link.teardown()
|
||||||
time.sleep(0.15)
|
time.sleep(0.15)
|
||||||
exit(0)
|
exit(0)
|
||||||
@ -512,7 +512,7 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
try:
|
try:
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||||
if len(destination) != dest_len:
|
if len(destination) != dest_len:
|
||||||
raise ValueError("Allowed destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Allowed destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(destination)
|
destination_hash = bytes.fromhex(destination)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -547,11 +547,11 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
|
|
||||||
reticulum = RNS.Reticulum(configdir=configdir, loglevel=targetloglevel)
|
reticulum = RNS.Reticulum(configdir=configdir, loglevel=targetloglevel)
|
||||||
|
|
||||||
identity_path = RNS.Reticulum.identitypath+"/"+APP_NAME
|
identity_path = f"{RNS.Reticulum.identitypath}/{APP_NAME}"
|
||||||
if os.path.isfile(identity_path):
|
if os.path.isfile(identity_path):
|
||||||
identity = RNS.Identity.from_file(identity_path)
|
identity = RNS.Identity.from_file(identity_path)
|
||||||
if identity == None:
|
if identity == None:
|
||||||
RNS.log("Could not load identity for rncp. The identity file at \""+str(identity_path)+"\" may be corrupt or unreadable.", RNS.LOG_ERROR)
|
RNS.log(f"Could not load identity for rncp. The identity file at \"{identity_path}\" may be corrupt or unreadable.", RNS.LOG_ERROR)
|
||||||
exit(2)
|
exit(2)
|
||||||
else:
|
else:
|
||||||
identity = None
|
identity = None
|
||||||
@ -564,9 +564,9 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
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)
|
||||||
if silent:
|
if silent:
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested")
|
print(f"Path to {RNS.prettyhexrep(destination_hash)} requested")
|
||||||
else:
|
else:
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested ", end=" ")
|
print(f"Path to {RNS.prettyhexrep(destination_hash)} requested ", end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
@ -575,7 +575,7 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
while not RNS.Transport.has_path(destination_hash) and time.time() < estab_timeout:
|
while not RNS.Transport.has_path(destination_hash) and time.time() < estab_timeout:
|
||||||
if not silent:
|
if not silent:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
@ -587,9 +587,9 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print("Establishing link with "+RNS.prettyhexrep(destination_hash))
|
print(f"Establishing link with {RNS.prettyhexrep(destination_hash)}")
|
||||||
else:
|
else:
|
||||||
print("\r \rEstablishing link with "+RNS.prettyhexrep(destination_hash)+" ", end=" ")
|
print(f'\r \rEstablishing link with {RNS.prettyhexrep(destination_hash)} ', end=" ")
|
||||||
|
|
||||||
receiver_identity = RNS.Identity.recall(destination_hash)
|
receiver_identity = RNS.Identity.recall(destination_hash)
|
||||||
receiver_destination = RNS.Destination(
|
receiver_destination = RNS.Destination(
|
||||||
@ -604,21 +604,21 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
while link.status != RNS.Link.ACTIVE and time.time() < estab_timeout:
|
while link.status != RNS.Link.ACTIVE and time.time() < estab_timeout:
|
||||||
if not silent:
|
if not silent:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
if time.time() > estab_timeout:
|
if time.time() > estab_timeout:
|
||||||
if silent:
|
if silent:
|
||||||
print("Link establishment with "+RNS.prettyhexrep(destination_hash)+" timed out")
|
print(f"Link establishment with {RNS.prettyhexrep(destination_hash)} timed out")
|
||||||
else:
|
else:
|
||||||
print("\r \rLink establishment with "+RNS.prettyhexrep(destination_hash)+" timed out")
|
print(f'\r \rLink establishment with {RNS.prettyhexrep(destination_hash)} timed out')
|
||||||
exit(1)
|
exit(1)
|
||||||
elif not RNS.Transport.has_path(destination_hash):
|
elif not RNS.Transport.has_path(destination_hash):
|
||||||
if silent:
|
if silent:
|
||||||
print("No path found to "+RNS.prettyhexrep(destination_hash))
|
print(f"No path found to {RNS.prettyhexrep(destination_hash)}")
|
||||||
else:
|
else:
|
||||||
print("\r \rNo path found to "+RNS.prettyhexrep(destination_hash))
|
print(f'\r \rNo path found to {RNS.prettyhexrep(destination_hash)}')
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
@ -633,16 +633,16 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
while resource.status < RNS.Resource.TRANSFERRING:
|
while resource.status < RNS.Resource.TRANSFERRING:
|
||||||
if not silent:
|
if not silent:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
|
|
||||||
if resource.status > RNS.Resource.COMPLETE:
|
if resource.status > RNS.Resource.COMPLETE:
|
||||||
if silent:
|
if silent:
|
||||||
print("File was not accepted by "+RNS.prettyhexrep(destination_hash))
|
print(f"File was not accepted by {RNS.prettyhexrep(destination_hash)}")
|
||||||
else:
|
else:
|
||||||
print("\r \rFile was not accepted by "+RNS.prettyhexrep(destination_hash))
|
print(f'\r \rFile was not accepted by {RNS.prettyhexrep(destination_hash)}')
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
@ -654,11 +654,11 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
prg = current_resource.get_progress()
|
prg = current_resource.get_progress()
|
||||||
percent = round(prg * 100.0, 1)
|
percent = round(prg * 100.0, 1)
|
||||||
stat_str = str(percent)+"% - " + size_str(int(prg*current_resource.total_size)) + " of " + size_str(current_resource.total_size) + " - " +size_str(speed, "b")+"ps"
|
stat_str = f"{percent}% - {size_str(int(prg * current_resource.total_size))} of {size_str(current_resource.total_size)} - {size_str(speed, 'b')}ps"
|
||||||
if not done:
|
if not done:
|
||||||
print("\r \rTransferring file "+syms[i]+" "+stat_str, end=" ")
|
print(f'\r \rTransferring file {syms[i]} {stat_str}', end=" ")
|
||||||
else:
|
else:
|
||||||
print("\r \rTransfer complete "+stat_str, end=" ")
|
print(f'\r \rTransfer complete {stat_str}', end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
return i
|
return i
|
||||||
@ -678,10 +678,10 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print(str(file_path)+" copied to "+RNS.prettyhexrep(destination_hash))
|
print(f"{file_path} copied to {RNS.prettyhexrep(destination_hash)}")
|
||||||
else:
|
else:
|
||||||
# print("\r \r"+str(file_path)+" copied to "+RNS.prettyhexrep(destination_hash))
|
# print("\r \r"+str(file_path)+" copied to "+RNS.prettyhexrep(destination_hash))
|
||||||
print("\n"+str(file_path)+" copied to "+RNS.prettyhexrep(destination_hash))
|
print(f"\n{file_path} copied to {RNS.prettyhexrep(destination_hash)}")
|
||||||
link.teardown()
|
link.teardown()
|
||||||
time.sleep(0.25)
|
time.sleep(0.25)
|
||||||
real_file.close()
|
real_file.close()
|
||||||
@ -707,7 +707,7 @@ def main():
|
|||||||
parser.add_argument('-p', '--print-identity', action='store_true', default=False, help="print identity and destination info and exit")
|
parser.add_argument('-p', '--print-identity', action='store_true', default=False, help="print identity and destination info and exit")
|
||||||
parser.add_argument("-w", action="store", metavar="seconds", type=float, help="sender timeout before giving up", default=RNS.Transport.PATH_REQUEST_TIMEOUT)
|
parser.add_argument("-w", action="store", metavar="seconds", type=float, help="sender timeout before giving up", default=RNS.Transport.PATH_REQUEST_TIMEOUT)
|
||||||
# parser.add_argument("--limit", action="store", metavar="files", type=float, help="maximum number of files to accept", default=None)
|
# parser.add_argument("--limit", action="store", metavar="files", type=float, help="maximum number of files to accept", default=None)
|
||||||
parser.add_argument("--version", action="version", version="rncp {version}".format(version=__version__))
|
parser.add_argument("--version", action="version", version=f"rncp {__version__}")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@ -777,12 +777,12 @@ def size_str(num, suffix='B'):
|
|||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1000.0:
|
if abs(num) < 1000.0:
|
||||||
if unit == "":
|
if unit == "":
|
||||||
return "%.0f %s%s" % (num, unit, suffix)
|
return f"{num:.0f} {unit}{suffix}"
|
||||||
else:
|
else:
|
||||||
return "%.2f %s%s" % (num, unit, suffix)
|
return f"{num:.2f} {unit}{suffix}"
|
||||||
num /= 1000.0
|
num /= 1000.0
|
||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return f"{num:.2f}{last_unit}{suffix}"
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -43,14 +43,14 @@ def spin(until=None, msg=None, timeout=None):
|
|||||||
if timeout != None:
|
if timeout != None:
|
||||||
timeout = time.time()+timeout
|
timeout = time.time()+timeout
|
||||||
|
|
||||||
print(msg+" ", end=" ")
|
print(f"{msg} ", end=" ")
|
||||||
while (timeout == None or time.time()<timeout) and not until():
|
while (timeout == None or time.time()<timeout) and not until():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
print("\r"+" "*len(msg)+" \r", end="")
|
print(f"\r{' ' * len(msg)} \r", end="")
|
||||||
|
|
||||||
if timeout != None and time.time() > timeout:
|
if timeout != None and time.time() > timeout:
|
||||||
return False
|
return False
|
||||||
@ -92,7 +92,7 @@ def main():
|
|||||||
parser.add_argument("-b", "--base64", action="store_true", default=False, help="Use base64-encoded input and output")
|
parser.add_argument("-b", "--base64", action="store_true", default=False, help="Use base64-encoded input and output")
|
||||||
parser.add_argument("-B", "--base32", action="store_true", default=False, help="Use base32-encoded input and output")
|
parser.add_argument("-B", "--base32", action="store_true", default=False, help="Use base32-encoded input and output")
|
||||||
|
|
||||||
parser.add_argument("--version", action="version", version="rnid {version}".format(version=__version__))
|
parser.add_argument("--version", action="version", version=f"rnid {__version__}")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@ -124,30 +124,30 @@ def main():
|
|||||||
else:
|
else:
|
||||||
identity_bytes = bytes.fromhex(args.import_str)
|
identity_bytes = bytes.fromhex(args.import_str)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Invalid identity data specified for import: "+str(e))
|
print(f"Invalid identity data specified for import: {e}")
|
||||||
exit(41)
|
exit(41)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
identity = RNS.Identity.from_bytes(identity_bytes)
|
identity = RNS.Identity.from_bytes(identity_bytes)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Could not create Reticulum identity from specified data: "+str(e))
|
print(f"Could not create Reticulum identity from specified data: {e}")
|
||||||
exit(42)
|
exit(42)
|
||||||
|
|
||||||
RNS.log("Identity imported")
|
RNS.log("Identity imported")
|
||||||
if args.base64:
|
if args.base64:
|
||||||
RNS.log("Public Key : "+base64.urlsafe_b64encode(identity.get_public_key()).decode("utf-8"))
|
RNS.log(f"Public Key : {base64.urlsafe_b64encode(identity.get_public_key()).decode('utf-8')}")
|
||||||
elif args.base32:
|
elif args.base32:
|
||||||
RNS.log("Public Key : "+base64.b32encode(identity.get_public_key()).decode("utf-8"))
|
RNS.log(f"Public Key : {base64.b32encode(identity.get_public_key()).decode('utf-8')}")
|
||||||
else:
|
else:
|
||||||
RNS.log("Public Key : "+RNS.hexrep(identity.get_public_key(), delimit=False))
|
RNS.log(f"Public Key : {RNS.hexrep(identity.get_public_key(), delimit=False)}")
|
||||||
if identity.prv:
|
if identity.prv:
|
||||||
if args.print_private:
|
if args.print_private:
|
||||||
if args.base64:
|
if args.base64:
|
||||||
RNS.log("Private Key : "+base64.urlsafe_b64encode(identity.get_private_key()).decode("utf-8"))
|
RNS.log(f"Private Key : {base64.urlsafe_b64encode(identity.get_private_key()).decode('utf-8')}")
|
||||||
elif args.base32:
|
elif args.base32:
|
||||||
RNS.log("Private Key : "+base64.b32encode(identity.get_private_key()).decode("utf-8"))
|
RNS.log(f"Private Key : {base64.b32encode(identity.get_private_key()).decode('utf-8')}")
|
||||||
else:
|
else:
|
||||||
RNS.log("Private Key : "+RNS.hexrep(identity.get_private_key(), delimit=False))
|
RNS.log(f"Private Key : {RNS.hexrep(identity.get_private_key(), delimit=False)}")
|
||||||
else:
|
else:
|
||||||
RNS.log("Private Key : Hidden")
|
RNS.log("Private Key : Hidden")
|
||||||
|
|
||||||
@ -156,13 +156,13 @@ def main():
|
|||||||
wp = os.path.expanduser(args.write)
|
wp = os.path.expanduser(args.write)
|
||||||
if not os.path.isfile(wp) or args.force:
|
if not os.path.isfile(wp) or args.force:
|
||||||
identity.to_file(wp)
|
identity.to_file(wp)
|
||||||
RNS.log("Wrote imported identity to "+str(args.write))
|
RNS.log(f"Wrote imported identity to {args.write}")
|
||||||
else:
|
else:
|
||||||
print("File "+str(wp)+" already exists, not overwriting")
|
print(f"File {wp} already exists, not overwriting")
|
||||||
exit(43)
|
exit(43)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Error while writing imported identity to file: "+str(e))
|
print(f"Error while writing imported identity to file: {e}")
|
||||||
exit(44)
|
exit(44)
|
||||||
|
|
||||||
exit(0)
|
exit(0)
|
||||||
@ -189,16 +189,16 @@ def main():
|
|||||||
if args.generate:
|
if args.generate:
|
||||||
identity = RNS.Identity()
|
identity = RNS.Identity()
|
||||||
if not args.force and os.path.isfile(args.generate):
|
if not args.force and os.path.isfile(args.generate):
|
||||||
RNS.log("Identity file "+str(args.generate)+" already exists. Not overwriting.", RNS.LOG_ERROR)
|
RNS.log(f"Identity file {args.generate} already exists. Not overwriting.", RNS.LOG_ERROR)
|
||||||
exit(3)
|
exit(3)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
identity.to_file(args.generate)
|
identity.to_file(args.generate)
|
||||||
RNS.log("New identity written to "+str(args.generate))
|
RNS.log(f"New identity written to {args.generate}")
|
||||||
exit(0)
|
exit(0)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error ocurred while saving the generated Identity.", RNS.LOG_ERROR)
|
RNS.log("An error ocurred while saving the generated Identity.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
exit(4)
|
exit(4)
|
||||||
|
|
||||||
identity = None
|
identity = None
|
||||||
@ -210,24 +210,24 @@ def main():
|
|||||||
|
|
||||||
if identity == None:
|
if identity == None:
|
||||||
if not args.request:
|
if not args.request:
|
||||||
RNS.log("Could not recall Identity for "+RNS.prettyhexrep(destination_hash)+".", RNS.LOG_ERROR)
|
RNS.log(f"Could not recall Identity for {RNS.prettyhexrep(destination_hash)}.", RNS.LOG_ERROR)
|
||||||
RNS.log("You can query the network for unknown Identities with the -R option.", RNS.LOG_ERROR)
|
RNS.log("You can query the network for unknown Identities with the -R option.", RNS.LOG_ERROR)
|
||||||
exit(5)
|
exit(5)
|
||||||
else:
|
else:
|
||||||
RNS.Transport.request_path(destination_hash)
|
RNS.Transport.request_path(destination_hash)
|
||||||
def spincheck():
|
def spincheck():
|
||||||
return RNS.Identity.recall(destination_hash) != None
|
return RNS.Identity.recall(destination_hash) != None
|
||||||
spin(spincheck, "Requesting unknown Identity for "+RNS.prettyhexrep(destination_hash), args.t)
|
spin(spincheck, f"Requesting unknown Identity for {RNS.prettyhexrep(destination_hash)}", args.t)
|
||||||
|
|
||||||
if not spincheck():
|
if not spincheck():
|
||||||
RNS.log("Identity request timed out", RNS.LOG_ERROR)
|
RNS.log("Identity request timed out", RNS.LOG_ERROR)
|
||||||
exit(6)
|
exit(6)
|
||||||
else:
|
else:
|
||||||
identity = RNS.Identity.recall(destination_hash)
|
identity = RNS.Identity.recall(destination_hash)
|
||||||
RNS.log("Received Identity "+str(identity)+" for destination "+RNS.prettyhexrep(destination_hash)+" from the network")
|
RNS.log(f"Received Identity {identity} for destination {RNS.prettyhexrep(destination_hash)} from the network")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Recalled Identity "+str(identity)+" for destination "+RNS.prettyhexrep(destination_hash))
|
RNS.log(f"Recalled Identity {identity} for destination {RNS.prettyhexrep(destination_hash)}")
|
||||||
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -243,7 +243,7 @@ def main():
|
|||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
identity = RNS.Identity.from_file(identity_str)
|
identity = RNS.Identity.from_file(identity_str)
|
||||||
RNS.log("Loaded Identity "+str(identity)+" from "+str(identity_str))
|
RNS.log(f"Loaded Identity {identity} from {identity_str}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not decode Identity from specified file")
|
RNS.log("Could not decode Identity from specified file")
|
||||||
@ -261,15 +261,15 @@ def main():
|
|||||||
aspects = aspects[1:]
|
aspects = aspects[1:]
|
||||||
if identity.pub != None:
|
if identity.pub != None:
|
||||||
destination = RNS.Destination(identity, RNS.Destination.OUT, RNS.Destination.SINGLE, app_name, *aspects)
|
destination = RNS.Destination(identity, RNS.Destination.OUT, RNS.Destination.SINGLE, app_name, *aspects)
|
||||||
RNS.log("The "+str(args.hash)+" destination for this Identity is "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"The {args.hash} destination for this Identity is {RNS.prettyhexrep(destination.hash)}")
|
||||||
RNS.log("The full destination specifier is "+str(destination))
|
RNS.log(f"The full destination specifier is {destination}")
|
||||||
time.sleep(0.25)
|
time.sleep(0.25)
|
||||||
exit(0)
|
exit(0)
|
||||||
else:
|
else:
|
||||||
raise KeyError("No public key known")
|
raise KeyError("No public key known")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error ocurred while attempting to send the announce.", RNS.LOG_ERROR)
|
RNS.log("An error ocurred while attempting to send the announce.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
@ -284,39 +284,39 @@ def main():
|
|||||||
aspects = aspects[1:]
|
aspects = aspects[1:]
|
||||||
if identity.prv != None:
|
if identity.prv != None:
|
||||||
destination = RNS.Destination(identity, RNS.Destination.IN, RNS.Destination.SINGLE, app_name, *aspects)
|
destination = RNS.Destination(identity, RNS.Destination.IN, RNS.Destination.SINGLE, app_name, *aspects)
|
||||||
RNS.log("Created destination "+str(destination))
|
RNS.log(f"Created destination {destination}")
|
||||||
RNS.log("Announcing destination "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"Announcing destination {RNS.prettyhexrep(destination.hash)}")
|
||||||
destination.announce()
|
destination.announce()
|
||||||
time.sleep(0.25)
|
time.sleep(0.25)
|
||||||
exit(0)
|
exit(0)
|
||||||
else:
|
else:
|
||||||
destination = RNS.Destination(identity, RNS.Destination.OUT, RNS.Destination.SINGLE, app_name, *aspects)
|
destination = RNS.Destination(identity, RNS.Destination.OUT, RNS.Destination.SINGLE, app_name, *aspects)
|
||||||
RNS.log("The "+str(args.announce)+" destination for this Identity is "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"The {args.announce} destination for this Identity is {RNS.prettyhexrep(destination.hash)}")
|
||||||
RNS.log("The full destination specifier is "+str(destination))
|
RNS.log(f"The full destination specifier is {destination}")
|
||||||
RNS.log("Cannot announce this destination, since the private key is not held")
|
RNS.log("Cannot announce this destination, since the private key is not held")
|
||||||
time.sleep(0.25)
|
time.sleep(0.25)
|
||||||
exit(33)
|
exit(33)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error ocurred while attempting to send the announce.", RNS.LOG_ERROR)
|
RNS.log("An error ocurred while attempting to send the announce.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
if args.print_identity:
|
if args.print_identity:
|
||||||
if args.base64:
|
if args.base64:
|
||||||
RNS.log("Public Key : "+base64.urlsafe_b64encode(identity.get_public_key()).decode("utf-8"))
|
RNS.log(f"Public Key : {base64.urlsafe_b64encode(identity.get_public_key()).decode('utf-8')}")
|
||||||
elif args.base32:
|
elif args.base32:
|
||||||
RNS.log("Public Key : "+base64.b32encode(identity.get_public_key()).decode("utf-8"))
|
RNS.log(f"Public Key : {base64.b32encode(identity.get_public_key()).decode('utf-8')}")
|
||||||
else:
|
else:
|
||||||
RNS.log("Public Key : "+RNS.hexrep(identity.get_public_key(), delimit=False))
|
RNS.log(f"Public Key : {RNS.hexrep(identity.get_public_key(), delimit=False)}")
|
||||||
if identity.prv:
|
if identity.prv:
|
||||||
if args.print_private:
|
if args.print_private:
|
||||||
if args.base64:
|
if args.base64:
|
||||||
RNS.log("Private Key : "+base64.urlsafe_b64encode(identity.get_private_key()).decode("utf-8"))
|
RNS.log(f"Private Key : {base64.urlsafe_b64encode(identity.get_private_key()).decode('utf-8')}")
|
||||||
elif args.base32:
|
elif args.base32:
|
||||||
RNS.log("Private Key : "+base64.b32encode(identity.get_private_key()).decode("utf-8"))
|
RNS.log(f"Private Key : {base64.b32encode(identity.get_private_key()).decode('utf-8')}")
|
||||||
else:
|
else:
|
||||||
RNS.log("Private Key : "+RNS.hexrep(identity.get_private_key(), delimit=False))
|
RNS.log(f"Private Key : {RNS.hexrep(identity.get_private_key(), delimit=False)}")
|
||||||
else:
|
else:
|
||||||
RNS.log("Private Key : Hidden")
|
RNS.log("Private Key : Hidden")
|
||||||
exit(0)
|
exit(0)
|
||||||
@ -324,11 +324,11 @@ def main():
|
|||||||
if args.export:
|
if args.export:
|
||||||
if identity.prv:
|
if identity.prv:
|
||||||
if args.base64:
|
if args.base64:
|
||||||
RNS.log("Exported Identity : "+base64.urlsafe_b64encode(identity.get_private_key()).decode("utf-8"))
|
RNS.log(f"Exported Identity : {base64.urlsafe_b64encode(identity.get_private_key()).decode('utf-8')}")
|
||||||
elif args.base32:
|
elif args.base32:
|
||||||
RNS.log("Exported Identity : "+base64.b32encode(identity.get_private_key()).decode("utf-8"))
|
RNS.log(f"Exported Identity : {base64.b32encode(identity.get_private_key()).decode('utf-8')}")
|
||||||
else:
|
else:
|
||||||
RNS.log("Exported Identity : "+RNS.hexrep(identity.get_private_key(), delimit=False))
|
RNS.log(f"Exported Identity : {RNS.hexrep(identity.get_private_key(), delimit=False)}")
|
||||||
else:
|
else:
|
||||||
RNS.log("Identity doesn't hold a private key, cannot export")
|
RNS.log("Identity doesn't hold a private key, cannot export")
|
||||||
exit(50)
|
exit(50)
|
||||||
@ -336,28 +336,28 @@ def main():
|
|||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
if args.validate:
|
if args.validate:
|
||||||
if not args.read and args.validate.lower().endswith("."+SIG_EXT):
|
if not args.read and args.validate.lower().endswith(f".{SIG_EXT}"):
|
||||||
args.read = str(args.validate).replace("."+SIG_EXT, "")
|
args.read = str(args.validate).replace(f".{SIG_EXT}", "")
|
||||||
|
|
||||||
if not os.path.isfile(args.validate):
|
if not os.path.isfile(args.validate):
|
||||||
RNS.log("Signature file "+str(args.read)+" not found", RNS.LOG_ERROR)
|
RNS.log(f"Signature file {args.read} not found", RNS.LOG_ERROR)
|
||||||
exit(10)
|
exit(10)
|
||||||
|
|
||||||
if not os.path.isfile(args.read):
|
if not os.path.isfile(args.read):
|
||||||
RNS.log("Input file "+str(args.read)+" not found", RNS.LOG_ERROR)
|
RNS.log(f"Input file {args.read} not found", RNS.LOG_ERROR)
|
||||||
exit(11)
|
exit(11)
|
||||||
|
|
||||||
data_input = None
|
data_input = None
|
||||||
if args.read:
|
if args.read:
|
||||||
if not os.path.isfile(args.read):
|
if not os.path.isfile(args.read):
|
||||||
RNS.log("Input file "+str(args.read)+" not found", RNS.LOG_ERROR)
|
RNS.log(f"Input file {args.read} not found", RNS.LOG_ERROR)
|
||||||
exit(12)
|
exit(12)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
data_input = open(args.read, "rb")
|
data_input = open(args.read, "rb")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not open input file for reading", RNS.LOG_ERROR)
|
RNS.log("Could not open input file for reading", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
exit(13)
|
exit(13)
|
||||||
|
|
||||||
# TODO: Actually expand this to a good solution
|
# TODO: Actually expand this to a good solution
|
||||||
@ -368,28 +368,28 @@ def main():
|
|||||||
|
|
||||||
data_output = None
|
data_output = None
|
||||||
if args.encrypt and not args.write and not args.stdout and args.read:
|
if args.encrypt and not args.write and not args.stdout and args.read:
|
||||||
args.write = str(args.read)+"."+ENCRYPT_EXT
|
args.write = f"{args.read}.{ENCRYPT_EXT}"
|
||||||
|
|
||||||
if args.decrypt and not args.write and not args.stdout and args.read and args.read.lower().endswith("."+ENCRYPT_EXT):
|
if args.decrypt and not args.write and not args.stdout and args.read and args.read.lower().endswith(f".{ENCRYPT_EXT}"):
|
||||||
args.write = str(args.read).replace("."+ENCRYPT_EXT, "")
|
args.write = str(args.read).replace(f".{ENCRYPT_EXT}", "")
|
||||||
|
|
||||||
if args.sign and identity.prv == None:
|
if args.sign and identity.prv == None:
|
||||||
RNS.log("Specified Identity does not hold a private key. Cannot sign.", RNS.LOG_ERROR)
|
RNS.log("Specified Identity does not hold a private key. Cannot sign.", RNS.LOG_ERROR)
|
||||||
exit(14)
|
exit(14)
|
||||||
|
|
||||||
if args.sign and not args.write and not args.stdout and args.read:
|
if args.sign and not args.write and not args.stdout and args.read:
|
||||||
args.write = str(args.read)+"."+SIG_EXT
|
args.write = f"{args.read}.{SIG_EXT}"
|
||||||
|
|
||||||
if args.write:
|
if args.write:
|
||||||
if not args.force and os.path.isfile(args.write):
|
if not args.force and os.path.isfile(args.write):
|
||||||
RNS.log("Output file "+str(args.write)+" already exists. Not overwriting.", RNS.LOG_ERROR)
|
RNS.log(f"Output file {args.write} already exists. Not overwriting.", RNS.LOG_ERROR)
|
||||||
exit(15)
|
exit(15)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
data_output = open(args.write, "wb")
|
data_output = open(args.write, "wb")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not open output file for writing", RNS.LOG_ERROR)
|
RNS.log("Could not open output file for writing", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
exit(15)
|
exit(15)
|
||||||
|
|
||||||
# TODO: Actually expand this to a good solution
|
# TODO: Actually expand this to a good solution
|
||||||
@ -414,7 +414,7 @@ def main():
|
|||||||
exit(18)
|
exit(18)
|
||||||
|
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
RNS.log("Signing "+str(args.read))
|
RNS.log(f"Signing {args.read}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data_output.write(identity.sign(data_input.read()))
|
data_output.write(identity.sign(data_input.read()))
|
||||||
@ -423,13 +423,13 @@ def main():
|
|||||||
|
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
if args.read:
|
if args.read:
|
||||||
RNS.log("File "+str(args.read)+" signed with "+str(identity)+" to "+str(args.write))
|
RNS.log(f"File {args.read} signed with {identity} to {args.write}")
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
RNS.log("An error ocurred while encrypting data.", RNS.LOG_ERROR)
|
RNS.log("An error ocurred while encrypting data.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
try:
|
try:
|
||||||
data_output.close()
|
data_output.close()
|
||||||
except:
|
except:
|
||||||
@ -453,8 +453,8 @@ def main():
|
|||||||
try:
|
try:
|
||||||
sig_input = open(args.validate, "rb")
|
sig_input = open(args.validate, "rb")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error ocurred while opening "+str(args.validate)+".", RNS.LOG_ERROR)
|
RNS.log(f"An error ocurred while opening {args.validate}.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
exit(21)
|
exit(21)
|
||||||
|
|
||||||
|
|
||||||
@ -464,17 +464,17 @@ def main():
|
|||||||
|
|
||||||
if not validated:
|
if not validated:
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
RNS.log("Signature "+str(args.validate)+" for file "+str(args.read)+" is invalid", RNS.LOG_ERROR)
|
RNS.log(f"Signature {args.validate} for file {args.read} is invalid", RNS.LOG_ERROR)
|
||||||
exit(22)
|
exit(22)
|
||||||
else:
|
else:
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
RNS.log("Signature "+str(args.validate)+" for file "+str(args.read)+" made by Identity "+str(identity)+" is valid")
|
RNS.log(f"Signature {args.validate} for file {args.read} made by Identity {identity} is valid")
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
RNS.log("An error ocurred while validating signature.", RNS.LOG_ERROR)
|
RNS.log("An error ocurred while validating signature.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
try:
|
try:
|
||||||
data_output.close()
|
data_output.close()
|
||||||
except:
|
except:
|
||||||
@ -497,7 +497,7 @@ def main():
|
|||||||
exit(25)
|
exit(25)
|
||||||
|
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
RNS.log("Encrypting "+str(args.read))
|
RNS.log(f"Encrypting {args.read}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
more_data = True
|
more_data = True
|
||||||
@ -511,13 +511,13 @@ def main():
|
|||||||
data_input.close()
|
data_input.close()
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
if args.read:
|
if args.read:
|
||||||
RNS.log("File "+str(args.read)+" encrypted for "+str(identity)+" to "+str(args.write))
|
RNS.log(f"File {args.read} encrypted for {identity} to {args.write}")
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
RNS.log("An error ocurred while encrypting data.", RNS.LOG_ERROR)
|
RNS.log("An error ocurred while encrypting data.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
try:
|
try:
|
||||||
data_output.close()
|
data_output.close()
|
||||||
except:
|
except:
|
||||||
@ -544,7 +544,7 @@ def main():
|
|||||||
exit(29)
|
exit(29)
|
||||||
|
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
RNS.log("Decrypting "+str(args.read)+"...")
|
RNS.log(f"Decrypting {args.read}...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
more_data = True
|
more_data = True
|
||||||
@ -564,13 +564,13 @@ def main():
|
|||||||
data_input.close()
|
data_input.close()
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
if args.read:
|
if args.read:
|
||||||
RNS.log("File "+str(args.read)+" decrypted with "+str(identity)+" to "+str(args.write))
|
RNS.log(f"File {args.read} decrypted with {identity} to {args.write}")
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if not args.stdout:
|
if not args.stdout:
|
||||||
RNS.log("An error ocurred while decrypting data.", RNS.LOG_ERROR)
|
RNS.log("An error ocurred while decrypting data.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log(f"The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
try:
|
try:
|
||||||
data_output.close()
|
data_output.close()
|
||||||
except:
|
except:
|
||||||
|
@ -48,7 +48,7 @@ def main():
|
|||||||
parser.add_argument('-v', '--verbose', action='count', default=0)
|
parser.add_argument('-v', '--verbose', action='count', default=0)
|
||||||
parser.add_argument('-q', '--quiet', action='count', default=0)
|
parser.add_argument('-q', '--quiet', action='count', default=0)
|
||||||
parser.add_argument("--exampleconfig", action='store_true', default=False, help="print verbose configuration example to stdout and exit")
|
parser.add_argument("--exampleconfig", action='store_true', default=False, help="print verbose configuration example to stdout and exit")
|
||||||
parser.add_argument("--version", action="version", version="ir {version}".format(version=__version__))
|
parser.add_argument("--version", action="version", version=f"ir {__version__}")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
@ -35,7 +35,7 @@ def connect_remote(destination_hash, auth_identity, timeout, no_output = False):
|
|||||||
global remote_link, reticulum
|
global remote_link, reticulum
|
||||||
if not RNS.Transport.has_path(destination_hash):
|
if not RNS.Transport.has_path(destination_hash):
|
||||||
if not no_output:
|
if not no_output:
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested", end=" ")
|
print(f"Path to {RNS.prettyhexrep(destination_hash)} requested", end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
RNS.Transport.request_path(destination_hash)
|
RNS.Transport.request_path(destination_hash)
|
||||||
pr_time = time.time()
|
pr_time = time.time()
|
||||||
@ -88,7 +88,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
try:
|
try:
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||||
if len(remote) != dest_len:
|
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))
|
raise ValueError(f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
identity_hash = bytes.fromhex(remote)
|
identity_hash = bytes.fromhex(remote)
|
||||||
remote_hash = RNS.Destination.hash_from_name_and_identity("rnstransport.remote.management", identity_hash)
|
remote_hash = RNS.Destination.hash_from_name_and_identity("rnstransport.remote.management", identity_hash)
|
||||||
@ -97,7 +97,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
|
|
||||||
identity = RNS.Identity.from_file(os.path.expanduser(management_identity))
|
identity = RNS.Identity.from_file(os.path.expanduser(management_identity))
|
||||||
if identity == None:
|
if identity == None:
|
||||||
raise ValueError("Could not load management identity from "+str(management_identity))
|
raise ValueError(f"Could not load management identity from {management_identity}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
connect_remote(remote_hash, identity, remote_timeout, no_output)
|
connect_remote(remote_hash, identity, remote_timeout, no_output)
|
||||||
@ -118,7 +118,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
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:
|
||||||
raise ValueError("Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -166,7 +166,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
m_str = " "
|
m_str = " "
|
||||||
else:
|
else:
|
||||||
m_str = "s"
|
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"]))
|
print(f"{RNS.prettyhexrep(path['hash'])} is {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:
|
if destination_hash != None and displayed == 0:
|
||||||
print("No path known")
|
print("No path known")
|
||||||
@ -178,7 +178,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
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:
|
||||||
raise ValueError("Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -242,21 +242,21 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
else:
|
else:
|
||||||
s_str = "s"
|
s_str = "s"
|
||||||
|
|
||||||
rv_str = ", "+str(entry["rate_violations"])+" active rate violation"+s_str
|
rv_str = f", {entry['rate_violations']} active rate violation{s_str}"
|
||||||
else:
|
else:
|
||||||
rv_str = ""
|
rv_str = ""
|
||||||
|
|
||||||
if entry["blocked_until"] > time.time():
|
if entry["blocked_until"] > time.time():
|
||||||
bli = time.time()-(int(entry["blocked_until"])-time.time())
|
bli = time.time()-(int(entry["blocked_until"])-time.time())
|
||||||
bl_str = ", new announces allowed in "+pretty_date(int(bli))
|
bl_str = f", new announces allowed in {pretty_date(int(bli))}"
|
||||||
else:
|
else:
|
||||||
bl_str = ""
|
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)
|
print(f"{RNS.prettyhexrep(entry['hash'])} last heard {last_str} ago, {hour_rate} announces/hour in the last {span_str}{rv_str}{bl_str}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Error while processing entry for "+RNS.prettyhexrep(entry["hash"]))
|
print(f"Error while processing entry for {RNS.prettyhexrep(entry['hash'])}")
|
||||||
print(str(e))
|
print(str(e))
|
||||||
|
|
||||||
if destination_hash != None and displayed == 0:
|
if destination_hash != None and displayed == 0:
|
||||||
@ -283,7 +283,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
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:
|
||||||
raise ValueError("Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -293,9 +293,9 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if reticulum.drop_path(destination_hash):
|
if reticulum.drop_path(destination_hash):
|
||||||
print("Dropped path to "+RNS.prettyhexrep(destination_hash))
|
print(f"Dropped path to {RNS.prettyhexrep(destination_hash)}")
|
||||||
else:
|
else:
|
||||||
print("Unable to drop path to "+RNS.prettyhexrep(destination_hash)+". Does it exist?")
|
print(f"Unable to drop path to {RNS.prettyhexrep(destination_hash)}. Does it exist?")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
elif drop_via:
|
elif drop_via:
|
||||||
@ -308,7 +308,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
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:
|
||||||
raise ValueError("Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -318,9 +318,9 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if reticulum.drop_all_via(destination_hash):
|
if reticulum.drop_all_via(destination_hash):
|
||||||
print("Dropped all paths via "+RNS.prettyhexrep(destination_hash))
|
print(f"Dropped all paths via {RNS.prettyhexrep(destination_hash)}")
|
||||||
else:
|
else:
|
||||||
print("Unable to drop paths via "+RNS.prettyhexrep(destination_hash)+". Does the transport instance exist?")
|
print(f"Unable to drop paths via {RNS.prettyhexrep(destination_hash)}. Does the transport instance exist?")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -333,7 +333,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
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:
|
||||||
raise ValueError("Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -344,7 +344,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, 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(f"Path to {RNS.prettyhexrep(destination_hash)} requested ", end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
@ -352,7 +352,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
limit = time.time()+timeout
|
limit = time.time()+timeout
|
||||||
while not RNS.Transport.has_path(destination_hash) and time.time()<limit:
|
while not RNS.Transport.has_path(destination_hash) and time.time()<limit:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
@ -371,7 +371,7 @@ def program_setup(configdir, table, rates, drop, destination_hexhash, verbosity,
|
|||||||
else:
|
else:
|
||||||
ms = ""
|
ms = ""
|
||||||
|
|
||||||
print("\rPath found, destination "+RNS.prettyhexrep(destination_hash)+" is "+str(hops)+" hop"+ms+" away via "+next_hop+" on "+next_hop_interface)
|
print(f'\rPath found, destination {RNS.prettyhexrep(destination_hash)} is {hops} hop{ms} away via {next_hop} on {next_hop_interface}')
|
||||||
else:
|
else:
|
||||||
print("\r \rPath not found")
|
print("\r \rPath not found")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -392,7 +392,7 @@ def main():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--version",
|
"--version",
|
||||||
action="version",
|
action="version",
|
||||||
version="rnpath {version}".format(version=__version__)
|
version=f"rnpath {__version__}"
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
@ -547,26 +547,26 @@ def pretty_date(time=False):
|
|||||||
return ''
|
return ''
|
||||||
if day_diff == 0:
|
if day_diff == 0:
|
||||||
if second_diff < 10:
|
if second_diff < 10:
|
||||||
return str(second_diff) + " seconds"
|
return f"{second_diff} seconds"
|
||||||
if second_diff < 60:
|
if second_diff < 60:
|
||||||
return str(second_diff) + " seconds"
|
return f"{second_diff} seconds"
|
||||||
if second_diff < 120:
|
if second_diff < 120:
|
||||||
return "1 minute"
|
return "1 minute"
|
||||||
if second_diff < 3600:
|
if second_diff < 3600:
|
||||||
return str(int(second_diff / 60)) + " minutes"
|
return f"{int(second_diff / 60)} minutes"
|
||||||
if second_diff < 7200:
|
if second_diff < 7200:
|
||||||
return "an hour"
|
return "an hour"
|
||||||
if second_diff < 86400:
|
if second_diff < 86400:
|
||||||
return str(int(second_diff / 3600)) + " hours"
|
return f"{int(second_diff / 3600)} hours"
|
||||||
if day_diff == 1:
|
if day_diff == 1:
|
||||||
return "1 day"
|
return "1 day"
|
||||||
if day_diff < 7:
|
if day_diff < 7:
|
||||||
return str(day_diff) + " days"
|
return f"{day_diff} days"
|
||||||
if day_diff < 31:
|
if day_diff < 31:
|
||||||
return str(int(day_diff / 7)) + " weeks"
|
return f"{int(day_diff / 7)} weeks"
|
||||||
if day_diff < 365:
|
if day_diff < 365:
|
||||||
return str(int(day_diff / 30)) + " months"
|
return f"{int(day_diff / 30)} months"
|
||||||
return str(int(day_diff / 365)) + " years"
|
return f"{int(day_diff / 365)} years"
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
@ -49,7 +49,7 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
|||||||
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:
|
||||||
raise ValueError("Destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(destination_hexhash)
|
destination_hash = bytes.fromhex(destination_hexhash)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -70,7 +70,7 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
|||||||
|
|
||||||
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(f"Path to {RNS.prettyhexrep(destination_hash)} requested ", end=" ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
_timeout = time.time() + (timeout or DEFAULT_TIMEOUT+reticulum.get_first_hop_timeout(destination_hash))
|
_timeout = time.time() + (timeout or DEFAULT_TIMEOUT+reticulum.get_first_hop_timeout(destination_hash))
|
||||||
@ -78,7 +78,7 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
|||||||
syms = "⢄⢂⢁⡁⡈⡐⡠"
|
syms = "⢄⢂⢁⡁⡈⡐⡠"
|
||||||
while not RNS.Transport.has_path(destination_hash) and not time.time() > _timeout:
|
while not RNS.Transport.has_path(destination_hash) and not time.time() > _timeout:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
|||||||
probe = RNS.Packet(request_destination, os.urandom(size))
|
probe = RNS.Packet(request_destination, os.urandom(size))
|
||||||
probe.pack()
|
probe.pack()
|
||||||
except OSError:
|
except OSError:
|
||||||
print("Error: Probe packet size of "+str(len(probe.raw))+" bytes exceed MTU of "+str(RNS.Reticulum.MTU)+" bytes")
|
print(f"Error: Probe packet size of {len(probe.raw)} bytes exceed MTU of {RNS.Reticulum.MTU} bytes")
|
||||||
exit(3)
|
exit(3)
|
||||||
|
|
||||||
receipt = probe.send()
|
receipt = probe.send()
|
||||||
@ -115,19 +115,19 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
|||||||
|
|
||||||
if more_output:
|
if more_output:
|
||||||
nhd = reticulum.get_next_hop(destination_hash)
|
nhd = reticulum.get_next_hop(destination_hash)
|
||||||
via_str = " via "+RNS.prettyhexrep(nhd) if nhd != None else ""
|
via_str = f" via {RNS.prettyhexrep(nhd)}" if nhd != None else ""
|
||||||
if_str = " on "+str(reticulum.get_next_hop_if_name(destination_hash)) if reticulum.get_next_hop_if_name(destination_hash) != "None" else ""
|
if_str = f" on {reticulum.get_next_hop_if_name(destination_hash)}" if reticulum.get_next_hop_if_name(destination_hash) != "None" else ""
|
||||||
more = via_str+if_str
|
more = via_str+if_str
|
||||||
else:
|
else:
|
||||||
more = ""
|
more = ""
|
||||||
|
|
||||||
print("\rSent probe "+str(sent)+" ("+str(size)+" bytes) to "+RNS.prettyhexrep(destination_hash)+more+" ", end=" ")
|
print(f'\rSent probe {sent} ({size} bytes) to {RNS.prettyhexrep(destination_hash)}{more} ', end=" ")
|
||||||
|
|
||||||
_timeout = time.time() + (timeout or DEFAULT_TIMEOUT+reticulum.get_first_hop_timeout(destination_hash))
|
_timeout = time.time() + (timeout or DEFAULT_TIMEOUT+reticulum.get_first_hop_timeout(destination_hash))
|
||||||
i = 0
|
i = 0
|
||||||
while receipt.status == RNS.PacketReceipt.SENT and not time.time() > _timeout:
|
while receipt.status == RNS.PacketReceipt.SENT and not time.time() > _timeout:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
@ -149,10 +149,10 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
|||||||
rtt = receipt.get_rtt()
|
rtt = receipt.get_rtt()
|
||||||
if (rtt >= 1):
|
if (rtt >= 1):
|
||||||
rtt = round(rtt, 3)
|
rtt = round(rtt, 3)
|
||||||
rttstring = str(rtt)+" seconds"
|
rttstring = f"{rtt} seconds"
|
||||||
else:
|
else:
|
||||||
rtt = round(rtt*1000, 3)
|
rtt = round(rtt*1000, 3)
|
||||||
rttstring = str(rtt)+" milliseconds"
|
rttstring = f"{rtt} milliseconds"
|
||||||
|
|
||||||
reception_stats = ""
|
reception_stats = ""
|
||||||
if reticulum.is_connected_to_shared_instance:
|
if reticulum.is_connected_to_shared_instance:
|
||||||
@ -161,28 +161,24 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
|||||||
reception_q = reticulum.get_packet_q(receipt.proof_packet.packet_hash)
|
reception_q = reticulum.get_packet_q(receipt.proof_packet.packet_hash)
|
||||||
|
|
||||||
if reception_rssi != None:
|
if reception_rssi != None:
|
||||||
reception_stats += " [RSSI "+str(reception_rssi)+" dBm]"
|
reception_stats += f" [RSSI {reception_rssi} dBm]"
|
||||||
|
|
||||||
if reception_snr != None:
|
if reception_snr != None:
|
||||||
reception_stats += " [SNR "+str(reception_snr)+" dB]"
|
reception_stats += f" [SNR {reception_snr} dB]"
|
||||||
|
|
||||||
if reception_q != None:
|
if reception_q != None:
|
||||||
reception_stats += " [Link Quality "+str(reception_q)+"%]"
|
reception_stats += f" [Link Quality {reception_q}%]"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if receipt.proof_packet != None:
|
if receipt.proof_packet != None:
|
||||||
if receipt.proof_packet.rssi != None:
|
if receipt.proof_packet.rssi != None:
|
||||||
reception_stats += " [RSSI "+str(receipt.proof_packet.rssi)+" dBm]"
|
reception_stats += f" [RSSI {receipt.proof_packet.rssi} dBm]"
|
||||||
|
|
||||||
if receipt.proof_packet.snr != None:
|
if receipt.proof_packet.snr != None:
|
||||||
reception_stats += " [SNR "+str(receipt.proof_packet.snr)+" dB]"
|
reception_stats += f" [SNR {receipt.proof_packet.snr} dB]"
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"Valid reply from "+
|
f"Valid reply from {RNS.prettyhexrep(receipt.destination.hash)}\nRound-trip time is {rttstring} over {hops} hop{ms}{reception_stats}\n"
|
||||||
RNS.prettyhexrep(receipt.destination.hash)+
|
|
||||||
"\nRound-trip time is "+rttstring+
|
|
||||||
" over "+str(hops)+" hop"+ms+
|
|
||||||
reception_stats+"\n"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -207,7 +203,7 @@ def main():
|
|||||||
parser.add_argument("-n", "--probes", action="store", default=1, help="number of probes to send", type=int)
|
parser.add_argument("-n", "--probes", action="store", default=1, help="number of probes to send", type=int)
|
||||||
parser.add_argument("-t", "--timeout", metavar="seconds", action="store", default=None, help="timeout before giving up", type=float)
|
parser.add_argument("-t", "--timeout", metavar="seconds", action="store", default=None, help="timeout before giving up", type=float)
|
||||||
parser.add_argument("-w", "--wait", metavar="seconds", action="store", default=0, help="time between each probe", type=float)
|
parser.add_argument("-w", "--wait", metavar="seconds", action="store", default=0, help="time between each probe", type=float)
|
||||||
parser.add_argument("--version", action="version", version="rnprobe {version}".format(version=__version__))
|
parser.add_argument("--version", action="version", version=f"rnprobe {__version__}")
|
||||||
parser.add_argument("full_name", nargs="?", default=None, help="full destination name in dotted notation", type=str)
|
parser.add_argument("full_name", nargs="?", default=None, help="full destination name in dotted notation", type=str)
|
||||||
parser.add_argument("destination_hash", nargs="?", default=None, help="hexadecimal hash of the destination", type=str)
|
parser.add_argument("destination_hash", nargs="?", default=None, help="hexadecimal hash of the destination", type=str)
|
||||||
|
|
||||||
|
@ -40,9 +40,9 @@ def program_setup(configdir, verbosity = 0, quietness = 0, service = False):
|
|||||||
|
|
||||||
reticulum = RNS.Reticulum(configdir=configdir, verbosity=targetverbosity, logdest=targetlogdest)
|
reticulum = RNS.Reticulum(configdir=configdir, verbosity=targetverbosity, logdest=targetlogdest)
|
||||||
if reticulum.is_connected_to_shared_instance:
|
if reticulum.is_connected_to_shared_instance:
|
||||||
RNS.log("Started rnsd version {version} connected to another shared local instance, this is probably NOT what you want!".format(version=__version__), RNS.LOG_WARNING)
|
RNS.log(f"Started rnsd version {__version__} connected to another shared local instance, this is probably NOT what you want!", RNS.LOG_WARNING)
|
||||||
else:
|
else:
|
||||||
RNS.log("Started rnsd version {version}".format(version=__version__), RNS.LOG_NOTICE)
|
RNS.log(f"Started rnsd version {__version__}", RNS.LOG_NOTICE)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
@ -55,7 +55,7 @@ def main():
|
|||||||
parser.add_argument('-q', '--quiet', action='count', default=0)
|
parser.add_argument('-q', '--quiet', action='count', default=0)
|
||||||
parser.add_argument('-s', '--service', action='store_true', default=False, help="rnsd is running as a service and should log to file")
|
parser.add_argument('-s', '--service', action='store_true', default=False, help="rnsd is running as a service and should log to file")
|
||||||
parser.add_argument("--exampleconfig", action='store_true', default=False, help="print verbose configuration example to stdout and exit")
|
parser.add_argument("--exampleconfig", action='store_true', default=False, help="print verbose configuration example to stdout and exit")
|
||||||
parser.add_argument("--version", action="version", version="rnsd {version}".format(version=__version__))
|
parser.add_argument("--version", action="version", version=f"rnsd {__version__}")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
@ -42,12 +42,12 @@ def size_str(num, suffix='B'):
|
|||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1000.0:
|
if abs(num) < 1000.0:
|
||||||
if unit == "":
|
if unit == "":
|
||||||
return "%.0f %s%s" % (num, unit, suffix)
|
return f"{num:.0f} {unit}{suffix}"
|
||||||
else:
|
else:
|
||||||
return "%.2f %s%s" % (num, unit, suffix)
|
return f"{num:.2f} {unit}{suffix}"
|
||||||
num /= 1000.0
|
num /= 1000.0
|
||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return f"{num:.2f}{last_unit}{suffix}"
|
||||||
|
|
||||||
request_result = None
|
request_result = None
|
||||||
request_concluded = False
|
request_concluded = False
|
||||||
@ -144,7 +144,7 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
|
|||||||
try:
|
try:
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||||
if len(remote) != dest_len:
|
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))
|
raise ValueError(f"Destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
identity_hash = bytes.fromhex(remote)
|
identity_hash = bytes.fromhex(remote)
|
||||||
destination_hash = RNS.Destination.hash_from_name_and_identity("rnstransport.remote.management", identity_hash)
|
destination_hash = RNS.Destination.hash_from_name_and_identity("rnstransport.remote.management", identity_hash)
|
||||||
@ -281,13 +281,13 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
|
|||||||
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(f" Status : {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(f" 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"])))
|
||||||
@ -295,7 +295,7 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
|
|||||||
if "battery_percent" in ifstat and ifstat["battery_percent"] != None:
|
if "battery_percent" in ifstat and ifstat["battery_percent"] != None:
|
||||||
try:
|
try:
|
||||||
bpi = int(ifstat["battery_percent"])
|
bpi = int(ifstat["battery_percent"])
|
||||||
print(" Battery : {bp}%".format(bp=bpi))
|
print(f" Battery : {bpi}%")
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -488,10 +488,10 @@ def speed_str(num, suffix='bps'):
|
|||||||
|
|
||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1000.0:
|
if abs(num) < 1000.0:
|
||||||
return "%3.2f %s%s" % (num, unit, suffix)
|
return f"{num:3.2f} {unit}{suffix}"
|
||||||
num /= 1000.0
|
num /= 1000.0
|
||||||
|
|
||||||
return "%.2f %s%s" % (num, last_unit, suffix)
|
return f"{num:.2f} {last_unit}{suffix}"
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -42,7 +42,7 @@ allowed_identity_hashes = []
|
|||||||
def prepare_identity(identity_path):
|
def prepare_identity(identity_path):
|
||||||
global identity
|
global identity
|
||||||
if identity_path == None:
|
if identity_path == None:
|
||||||
identity_path = RNS.Reticulum.identitypath+"/"+APP_NAME
|
identity_path = f"{RNS.Reticulum.identitypath}/{APP_NAME}"
|
||||||
|
|
||||||
if os.path.isfile(identity_path):
|
if os.path.isfile(identity_path):
|
||||||
identity = RNS.Identity.from_file(identity_path)
|
identity = RNS.Identity.from_file(identity_path)
|
||||||
@ -62,8 +62,8 @@ def listen(configdir, identitypath = None, verbosity = 0, quietness = 0, allowed
|
|||||||
destination = RNS.Destination(identity, RNS.Destination.IN, RNS.Destination.SINGLE, APP_NAME, "execute")
|
destination = RNS.Destination(identity, RNS.Destination.IN, RNS.Destination.SINGLE, APP_NAME, "execute")
|
||||||
|
|
||||||
if print_identity:
|
if print_identity:
|
||||||
print("Identity : "+str(identity))
|
print(f"Identity : {identity}")
|
||||||
print("Listening on : "+RNS.prettyhexrep(destination.hash))
|
print(f"Listening on : {RNS.prettyhexrep(destination.hash)}")
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
if disable_auth:
|
if disable_auth:
|
||||||
@ -74,7 +74,7 @@ def listen(configdir, identitypath = None, verbosity = 0, quietness = 0, allowed
|
|||||||
try:
|
try:
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||||
if len(a) != dest_len:
|
if len(a) != dest_len:
|
||||||
raise ValueError("Allowed destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Allowed destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(a)
|
destination_hash = bytes.fromhex(a)
|
||||||
allowed_identity_hashes.append(destination_hash)
|
allowed_identity_hashes.append(destination_hash)
|
||||||
@ -103,7 +103,7 @@ def listen(configdir, identitypath = None, verbosity = 0, quietness = 0, allowed
|
|||||||
allow = RNS.Destination.ALLOW_ALL,
|
allow = RNS.Destination.ALLOW_ALL,
|
||||||
)
|
)
|
||||||
|
|
||||||
RNS.log("rnx listening for commands on "+RNS.prettyhexrep(destination.hash))
|
RNS.log(f"rnx listening for commands on {RNS.prettyhexrep(destination.hash)}")
|
||||||
|
|
||||||
if not disable_announce:
|
if not disable_announce:
|
||||||
destination.announce()
|
destination.announce()
|
||||||
@ -114,16 +114,16 @@ def listen(configdir, identitypath = None, verbosity = 0, quietness = 0, allowed
|
|||||||
def command_link_established(link):
|
def command_link_established(link):
|
||||||
link.set_remote_identified_callback(initiator_identified)
|
link.set_remote_identified_callback(initiator_identified)
|
||||||
link.set_link_closed_callback(command_link_closed)
|
link.set_link_closed_callback(command_link_closed)
|
||||||
RNS.log("Command link "+str(link)+" established")
|
RNS.log(f"Command link {link} established")
|
||||||
|
|
||||||
def command_link_closed(link):
|
def command_link_closed(link):
|
||||||
RNS.log("Command link "+str(link)+" closed")
|
RNS.log(f"Command link {link} closed")
|
||||||
|
|
||||||
def initiator_identified(link, identity):
|
def initiator_identified(link, identity):
|
||||||
global allow_all
|
global allow_all
|
||||||
RNS.log("Initiator of link "+str(link)+" identified as "+RNS.prettyhexrep(identity.hash))
|
RNS.log(f"Initiator of link {link} identified as {RNS.prettyhexrep(identity.hash)}")
|
||||||
if not allow_all and not identity.hash in allowed_identity_hashes:
|
if not allow_all and not identity.hash in allowed_identity_hashes:
|
||||||
RNS.log("Identity "+RNS.prettyhexrep(identity.hash)+" not allowed, tearing down link")
|
RNS.log(f"Identity {RNS.prettyhexrep(identity.hash)} not allowed, tearing down link")
|
||||||
link.teardown()
|
link.teardown()
|
||||||
|
|
||||||
def execute_received_command(path, data, request_id, remote_identity, requested_at):
|
def execute_received_command(path, data, request_id, remote_identity, requested_at):
|
||||||
@ -134,9 +134,9 @@ def execute_received_command(path, data, request_id, remote_identity, requested_
|
|||||||
stdin = data[4] # Data passed to stdin
|
stdin = data[4] # Data passed to stdin
|
||||||
|
|
||||||
if remote_identity != None:
|
if remote_identity != None:
|
||||||
RNS.log("Executing command ["+command+"] for "+RNS.prettyhexrep(remote_identity.hash))
|
RNS.log(f"Executing command [{command}] for {RNS.prettyhexrep(remote_identity.hash)}")
|
||||||
else:
|
else:
|
||||||
RNS.log("Executing command ["+command+"] for unknown requestor")
|
RNS.log(f"Executing command [{command}] for unknown requestor")
|
||||||
|
|
||||||
result = [
|
result = [
|
||||||
False, # 0: Command was executed
|
False, # 0: Command was executed
|
||||||
@ -178,7 +178,7 @@ def execute_received_command(path, data, request_id, remote_identity, requested_
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
if timeout != None and time.time() > result[6]+timeout:
|
if timeout != None and time.time() > result[6]+timeout:
|
||||||
RNS.log("Command ["+command+"] timed out and is being killed...")
|
RNS.log(f"Command [{command}] timed out and is being killed...")
|
||||||
process.terminate()
|
process.terminate()
|
||||||
process.wait()
|
process.wait()
|
||||||
if process.poll() != None:
|
if process.poll() != None:
|
||||||
@ -219,9 +219,9 @@ def execute_received_command(path, data, request_id, remote_identity, requested_
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
if remote_identity != None:
|
if remote_identity != None:
|
||||||
RNS.log("Delivering result of command ["+str(command)+"] to "+RNS.prettyhexrep(remote_identity.hash))
|
RNS.log(f"Delivering result of command [{command}] to {RNS.prettyhexrep(remote_identity.hash)}")
|
||||||
else:
|
else:
|
||||||
RNS.log("Delivering result of command ["+str(command)+"] to unknown requestor")
|
RNS.log(f"Delivering result of command [{command}] to unknown requestor")
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -231,14 +231,14 @@ def spin(until=None, msg=None, timeout=None):
|
|||||||
if timeout != None:
|
if timeout != None:
|
||||||
timeout = time.time()+timeout
|
timeout = time.time()+timeout
|
||||||
|
|
||||||
print(msg+" ", end=" ")
|
print(f"{msg} ", end=" ")
|
||||||
while (timeout == None or time.time()<timeout) and not until():
|
while (timeout == None or time.time()<timeout) and not until():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print(("\b\b"+syms[i]+" "), end="")
|
print(f'\x08\x08{syms[i]} ', end="")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
print("\r"+" "*len(msg)+" \r", end="")
|
print(f"\r{' ' * len(msg)} \r", end="")
|
||||||
|
|
||||||
if timeout != None and time.time() > timeout:
|
if timeout != None and time.time() > timeout:
|
||||||
return False
|
return False
|
||||||
@ -259,8 +259,8 @@ def spin_stat(until=None, timeout=None):
|
|||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
prg = current_progress
|
prg = current_progress
|
||||||
percent = round(prg * 100.0, 1)
|
percent = round(prg * 100.0, 1)
|
||||||
stat_str = str(percent)+"% - " + size_str(int(prg*response_transfer_size)) + " of " + size_str(response_transfer_size) + " - " +size_str(speed, "b")+"ps"
|
stat_str = f"{percent}% - {size_str(int(prg * response_transfer_size))} of {size_str(response_transfer_size)} - {size_str(speed, 'b')}ps"
|
||||||
print("\r \rReceiving result "+syms[i]+" "+stat_str, end=" ")
|
print(f'\r \rReceiving result {syms[i]} {stat_str}', end=" ")
|
||||||
|
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
@ -303,7 +303,7 @@ def execute(configdir, identitypath = None, verbosity = 0, quietness = 0, detail
|
|||||||
try:
|
try:
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||||
if len(destination) != dest_len:
|
if len(destination) != dest_len:
|
||||||
raise ValueError("Allowed destination length is invalid, must be {hex} hexadecimal characters ({byte} bytes).".format(hex=dest_len, byte=dest_len//2))
|
raise ValueError(f"Allowed destination length is invalid, must be {dest_len} hexadecimal characters ({dest_len // 2} bytes).")
|
||||||
try:
|
try:
|
||||||
destination_hash = bytes.fromhex(destination)
|
destination_hash = bytes.fromhex(destination)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -321,7 +321,7 @@ def execute(configdir, identitypath = None, verbosity = 0, quietness = 0, detail
|
|||||||
|
|
||||||
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)
|
||||||
if not spin(until=lambda: RNS.Transport.has_path(destination_hash), msg="Path to "+RNS.prettyhexrep(destination_hash)+" requested", timeout=timeout):
|
if not spin(until=lambda: RNS.Transport.has_path(destination_hash), msg=f"Path to {RNS.prettyhexrep(destination_hash)} requested", timeout=timeout):
|
||||||
print("Path not found")
|
print("Path not found")
|
||||||
exit(242)
|
exit(242)
|
||||||
|
|
||||||
@ -339,8 +339,8 @@ def execute(configdir, identitypath = None, verbosity = 0, quietness = 0, detail
|
|||||||
link = RNS.Link(listener_destination)
|
link = RNS.Link(listener_destination)
|
||||||
link.did_identify = False
|
link.did_identify = False
|
||||||
|
|
||||||
if not spin(until=lambda: link.status == RNS.Link.ACTIVE, msg="Establishing link with "+RNS.prettyhexrep(destination_hash), timeout=timeout):
|
if not spin(until=lambda: link.status == RNS.Link.ACTIVE, msg=f"Establishing link with {RNS.prettyhexrep(destination_hash)}", timeout=timeout):
|
||||||
print("Could not establish link with "+RNS.prettyhexrep(destination_hash))
|
print(f"Could not establish link with {RNS.prettyhexrep(destination_hash)}")
|
||||||
exit(243)
|
exit(243)
|
||||||
|
|
||||||
if not noid and not link.did_identify:
|
if not noid and not link.did_identify:
|
||||||
@ -443,7 +443,7 @@ def execute(configdir, identitypath = None, verbosity = 0, quietness = 0, detail
|
|||||||
print("\n--- End of remote output, rnx done ---")
|
print("\n--- End of remote output, rnx done ---")
|
||||||
if started != None and concluded != None:
|
if started != None and concluded != None:
|
||||||
cmd_duration = round(concluded - started, 3)
|
cmd_duration = round(concluded - started, 3)
|
||||||
print("Remote command execution took "+str(cmd_duration)+" seconds")
|
print(f"Remote command execution took {cmd_duration} seconds")
|
||||||
|
|
||||||
total_size = request_receipt.response_size
|
total_size = request_receipt.response_size
|
||||||
if request_receipt.request_size != None:
|
if request_receipt.request_size != None:
|
||||||
@ -453,27 +453,27 @@ def execute(configdir, identitypath = None, verbosity = 0, quietness = 0, detail
|
|||||||
if transfer_duration == 1:
|
if transfer_duration == 1:
|
||||||
tdstr = " in 1 second"
|
tdstr = " in 1 second"
|
||||||
elif transfer_duration < 10:
|
elif transfer_duration < 10:
|
||||||
tdstr = " in "+str(transfer_duration)+" seconds"
|
tdstr = f" in {transfer_duration} seconds"
|
||||||
else:
|
else:
|
||||||
tdstr = " in "+pretty_time(transfer_duration)
|
tdstr = f" in {pretty_time(transfer_duration)}"
|
||||||
|
|
||||||
spdstr = ", effective rate "+size_str(total_size/transfer_duration, "b")+"ps"
|
spdstr = f", effective rate {size_str(total_size / transfer_duration, 'b')}ps"
|
||||||
|
|
||||||
print("Transferred "+size_str(total_size)+tdstr+spdstr)
|
print(f"Transferred {size_str(total_size)}{tdstr}{spdstr}")
|
||||||
|
|
||||||
if outlen != None and stdout != None:
|
if outlen != None and stdout != None:
|
||||||
if len(stdout) < outlen:
|
if len(stdout) < outlen:
|
||||||
tstr = ", "+str(len(stdout))+" bytes displayed"
|
tstr = f", {len(stdout)} bytes displayed"
|
||||||
else:
|
else:
|
||||||
tstr = ""
|
tstr = ""
|
||||||
print("Remote wrote "+str(outlen)+" bytes to stdout"+tstr)
|
print(f"Remote wrote {outlen} bytes to stdout{tstr}")
|
||||||
|
|
||||||
if errlen != None and stderr != None:
|
if errlen != None and stderr != None:
|
||||||
if len(stderr) < errlen:
|
if len(stderr) < errlen:
|
||||||
tstr = ", "+str(len(stderr))+" bytes displayed"
|
tstr = f", {len(stderr)} bytes displayed"
|
||||||
else:
|
else:
|
||||||
tstr = ""
|
tstr = ""
|
||||||
print("Remote wrote "+str(errlen)+" bytes to stderr"+tstr)
|
print(f"Remote wrote {errlen} bytes to stderr{tstr}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if stdout != None and len(stdout) > 0:
|
if stdout != None and len(stdout) > 0:
|
||||||
@ -487,9 +487,9 @@ def execute(configdir, identitypath = None, verbosity = 0, quietness = 0, detail
|
|||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
print("\nOutput truncated before being returned:")
|
print("\nOutput truncated before being returned:")
|
||||||
if len(stdout) != 0 and len(stdout) < outlen:
|
if len(stdout) != 0 and len(stdout) < outlen:
|
||||||
print(" stdout truncated to "+str(len(stdout))+" bytes")
|
print(f" stdout truncated to {len(stdout)} bytes")
|
||||||
if len(stderr) != 0 and len(stderr) < errlen:
|
if len(stderr) != 0 and len(stderr) < errlen:
|
||||||
print(" stderr truncated to "+str(len(stderr))+" bytes")
|
print(f" stderr truncated to {len(stderr)} bytes")
|
||||||
else:
|
else:
|
||||||
print("Remote could not execute command")
|
print("Remote could not execute command")
|
||||||
if interactive:
|
if interactive:
|
||||||
@ -547,7 +547,7 @@ def main():
|
|||||||
parser.add_argument("--stdin", action='store', default=None, help="pass input to stdin", type=str)
|
parser.add_argument("--stdin", action='store', default=None, help="pass input to stdin", type=str)
|
||||||
parser.add_argument("--stdout", action='store', default=None, help="max size in bytes of returned stdout", type=int)
|
parser.add_argument("--stdout", action='store', default=None, help="max size in bytes of returned stdout", type=int)
|
||||||
parser.add_argument("--stderr", action='store', default=None, help="max size in bytes of returned stderr", type=int)
|
parser.add_argument("--stderr", action='store', default=None, help="max size in bytes of returned stderr", type=int)
|
||||||
parser.add_argument("--version", action="version", version="rnx {version}".format(version=__version__))
|
parser.add_argument("--version", action="version", version=f"rnx {__version__}")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@ -593,7 +593,7 @@ def main():
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
cstr = str(code) if code and code != 0 else ""
|
cstr = str(code) if code and code != 0 else ""
|
||||||
prompt = cstr+"> "
|
prompt = f"{cstr}> "
|
||||||
print(prompt,end="")
|
print(prompt,end="")
|
||||||
|
|
||||||
# cmdbuf = b""
|
# cmdbuf = b""
|
||||||
@ -661,12 +661,12 @@ def size_str(num, suffix='B'):
|
|||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1000.0:
|
if abs(num) < 1000.0:
|
||||||
if unit == "":
|
if unit == "":
|
||||||
return "%.0f %s%s" % (num, unit, suffix)
|
return f"{num:.0f} {unit}{suffix}"
|
||||||
else:
|
else:
|
||||||
return "%.2f %s%s" % (num, unit, suffix)
|
return f"{num:.2f} {unit}{suffix}"
|
||||||
num /= 1000.0
|
num /= 1000.0
|
||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return f"{num:.2f}{last_unit}{suffix}"
|
||||||
|
|
||||||
def pretty_time(time, verbose=False):
|
def pretty_time(time, verbose=False):
|
||||||
days = int(time // (24 * 3600))
|
days = int(time // (24 * 3600))
|
||||||
@ -684,16 +684,16 @@ def pretty_time(time, verbose=False):
|
|||||||
|
|
||||||
components = []
|
components = []
|
||||||
if days > 0:
|
if days > 0:
|
||||||
components.append(str(days)+" day"+sd if verbose else str(days)+"d")
|
components.append(f"{days} day{sd}" if verbose else f"{days}d")
|
||||||
|
|
||||||
if hours > 0:
|
if hours > 0:
|
||||||
components.append(str(hours)+" hour"+sh if verbose else str(hours)+"h")
|
components.append(f"{hours} hour{sh}" if verbose else f"{hours}h")
|
||||||
|
|
||||||
if minutes > 0:
|
if minutes > 0:
|
||||||
components.append(str(minutes)+" minute"+sm if verbose else str(minutes)+"m")
|
components.append(f"{minutes} minute{sm}" if verbose else f"{minutes}m")
|
||||||
|
|
||||||
if seconds > 0:
|
if seconds > 0:
|
||||||
components.append(str(seconds)+" second"+ss if verbose else str(seconds)+"s")
|
components.append(f"{seconds} second{ss}" if verbose else f"{seconds}s")
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
tstr = ""
|
tstr = ""
|
||||||
|
@ -147,7 +147,7 @@ def rand():
|
|||||||
def trace_exception(e):
|
def trace_exception(e):
|
||||||
import traceback
|
import traceback
|
||||||
exception_info = "".join(traceback.TracebackException.from_exception(e).format())
|
exception_info = "".join(traceback.TracebackException.from_exception(e).format())
|
||||||
log(f"An unhandled {str(type(e))} exception occurred: {str(e)}", LOG_ERROR)
|
log(f"An unhandled {type(e)} exception occurred: {e}", LOG_ERROR)
|
||||||
log(exception_info, LOG_ERROR)
|
log(exception_info, LOG_ERROR)
|
||||||
|
|
||||||
def hexrep(data, delimit=True):
|
def hexrep(data, delimit=True):
|
||||||
@ -159,12 +159,12 @@ def hexrep(data, delimit=True):
|
|||||||
delimiter = ":"
|
delimiter = ":"
|
||||||
if not delimit:
|
if not delimit:
|
||||||
delimiter = ""
|
delimiter = ""
|
||||||
hexrep = delimiter.join("{:02x}".format(c) for c in data)
|
hexrep = delimiter.join(f"{c:02x}" for c in data)
|
||||||
return hexrep
|
return hexrep
|
||||||
|
|
||||||
def prettyhexrep(data):
|
def prettyhexrep(data):
|
||||||
delimiter = ""
|
delimiter = ""
|
||||||
hexrep = "<"+delimiter.join("{:02x}".format(c) for c in data)+">"
|
hexrep = "<"+delimiter.join(f"{c:02x}" for c in data)+">"
|
||||||
return hexrep
|
return hexrep
|
||||||
|
|
||||||
def prettyspeed(num, suffix="b"):
|
def prettyspeed(num, suffix="b"):
|
||||||
@ -182,12 +182,12 @@ def prettysize(num, suffix='B'):
|
|||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1000.0:
|
if abs(num) < 1000.0:
|
||||||
if unit == "":
|
if unit == "":
|
||||||
return "%.0f %s%s" % (num, unit, suffix)
|
return f"{num:.0f} {unit}{suffix}"
|
||||||
else:
|
else:
|
||||||
return "%.2f %s%s" % (num, unit, suffix)
|
return f"{num:.2f} {unit}{suffix}"
|
||||||
num /= 1000.0
|
num /= 1000.0
|
||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return f"{num:.2f}{last_unit}{suffix}"
|
||||||
|
|
||||||
def prettyfrequency(hz, suffix="Hz"):
|
def prettyfrequency(hz, suffix="Hz"):
|
||||||
num = hz*1e6
|
num = hz*1e6
|
||||||
@ -196,10 +196,10 @@ def prettyfrequency(hz, suffix="Hz"):
|
|||||||
|
|
||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1000.0:
|
if abs(num) < 1000.0:
|
||||||
return "%.2f %s%s" % (num, unit, suffix)
|
return f"{num:.2f} {unit}{suffix}"
|
||||||
num /= 1000.0
|
num /= 1000.0
|
||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return f"{num:.2f}{last_unit}{suffix}"
|
||||||
|
|
||||||
def prettydistance(m, suffix="m"):
|
def prettydistance(m, suffix="m"):
|
||||||
num = m*1e6
|
num = m*1e6
|
||||||
@ -212,10 +212,10 @@ def prettydistance(m, suffix="m"):
|
|||||||
if unit == "c": divisor = 100
|
if unit == "c": divisor = 100
|
||||||
|
|
||||||
if abs(num) < divisor:
|
if abs(num) < divisor:
|
||||||
return "%.2f %s%s" % (num, unit, suffix)
|
return f"{num:.2f} {unit}{suffix}"
|
||||||
num /= divisor
|
num /= divisor
|
||||||
|
|
||||||
return "%.2f %s%s" % (num, last_unit, suffix)
|
return f"{num:.2f} {last_unit}{suffix}"
|
||||||
|
|
||||||
def prettytime(time, verbose=False, compact=False):
|
def prettytime(time, verbose=False, compact=False):
|
||||||
days = int(time // (24 * 3600))
|
days = int(time // (24 * 3600))
|
||||||
|
2
RNS/vendor/__init__.py
vendored
2
RNS/vendor/__init__.py
vendored
@ -1,5 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
|
|
||||||
modules = glob.glob(os.path.dirname(__file__)+"/*.py")
|
modules = glob.glob(f"{os.path.dirname(__file__)}/*.py")
|
||||||
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
||||||
|
120
RNS/vendor/configobj.py
vendored
120
RNS/vendor/configobj.py
vendored
@ -129,7 +129,7 @@ def getObj(s):
|
|||||||
global compiler
|
global compiler
|
||||||
if compiler is None:
|
if compiler is None:
|
||||||
import compiler
|
import compiler
|
||||||
s = "a=" + s
|
s = f"a={s}"
|
||||||
p = compiler.parse(s)
|
p = compiler.parse(s)
|
||||||
return p.getChildren()[1].getChildren()[0].getChildren()[1]
|
return p.getChildren()[1].getChildren()[0].getChildren()[1]
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ class UnknownType(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Builder(object):
|
class Builder:
|
||||||
|
|
||||||
def build(self, o):
|
def build(self, o):
|
||||||
if m is None:
|
if m is None:
|
||||||
@ -261,7 +261,7 @@ class InterpolationLoopError(InterpolationError):
|
|||||||
def __init__(self, option):
|
def __init__(self, option):
|
||||||
InterpolationError.__init__(
|
InterpolationError.__init__(
|
||||||
self,
|
self,
|
||||||
'interpolation loop detected in value "%s".' % option)
|
f'interpolation loop detected in value "{option}".')
|
||||||
|
|
||||||
|
|
||||||
class RepeatSectionError(ConfigObjError):
|
class RepeatSectionError(ConfigObjError):
|
||||||
@ -274,7 +274,7 @@ class RepeatSectionError(ConfigObjError):
|
|||||||
class MissingInterpolationOption(InterpolationError):
|
class MissingInterpolationOption(InterpolationError):
|
||||||
"""A value specified for interpolation was missing."""
|
"""A value specified for interpolation was missing."""
|
||||||
def __init__(self, option):
|
def __init__(self, option):
|
||||||
msg = 'missing option "%s" in interpolation.' % option
|
msg = f'missing option "{option}" in interpolation.'
|
||||||
InterpolationError.__init__(self, msg)
|
InterpolationError.__init__(self, msg)
|
||||||
|
|
||||||
|
|
||||||
@ -283,7 +283,7 @@ class UnreprError(ConfigObjError):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class InterpolationEngine(object):
|
class InterpolationEngine:
|
||||||
"""
|
"""
|
||||||
A helper class to help perform string interpolation.
|
A helper class to help perform string interpolation.
|
||||||
|
|
||||||
@ -336,7 +336,7 @@ class InterpolationEngine(object):
|
|||||||
replacement = recursive_interpolate(k, v, s, backtrail)
|
replacement = recursive_interpolate(k, v, s, backtrail)
|
||||||
# Replace the matched string with its final value
|
# Replace the matched string with its final value
|
||||||
start, end = match.span()
|
start, end = match.span()
|
||||||
value = ''.join((value[:start], replacement, value[end:]))
|
value = f"{value[:start]}{replacement}{value[end:]}"
|
||||||
new_search_start = start + len(replacement)
|
new_search_start = start + len(replacement)
|
||||||
# Pick up the next interpolation key, if any, for next time
|
# Pick up the next interpolation key, if any, for next time
|
||||||
# through the while loop
|
# through the while loop
|
||||||
@ -553,11 +553,11 @@ class Section(dict):
|
|||||||
"""Fetch the item and do string interpolation."""
|
"""Fetch the item and do string interpolation."""
|
||||||
val = dict.__getitem__(self, key)
|
val = dict.__getitem__(self, key)
|
||||||
if self.main.interpolation:
|
if self.main.interpolation:
|
||||||
if isinstance(val, six.string_types):
|
if isinstance(val, str):
|
||||||
return self._interpolate(key, val)
|
return self._interpolate(key, val)
|
||||||
if isinstance(val, list):
|
if isinstance(val, list):
|
||||||
def _check(entry):
|
def _check(entry):
|
||||||
if isinstance(entry, six.string_types):
|
if isinstance(entry, str):
|
||||||
return self._interpolate(key, entry)
|
return self._interpolate(key, entry)
|
||||||
return entry
|
return entry
|
||||||
new = [_check(entry) for entry in val]
|
new = [_check(entry) for entry in val]
|
||||||
@ -580,8 +580,8 @@ class Section(dict):
|
|||||||
``unrepr`` must be set when setting a value to a dictionary, without
|
``unrepr`` must be set when setting a value to a dictionary, without
|
||||||
creating a new sub-section.
|
creating a new sub-section.
|
||||||
"""
|
"""
|
||||||
if not isinstance(key, six.string_types):
|
if not isinstance(key, str):
|
||||||
raise ValueError('The key "%s" is not a string.' % key)
|
raise ValueError(f'The key "{key}" is not a string.')
|
||||||
|
|
||||||
# add the comment
|
# add the comment
|
||||||
if key not in self.comments:
|
if key not in self.comments:
|
||||||
@ -614,14 +614,14 @@ class Section(dict):
|
|||||||
if key not in self:
|
if key not in self:
|
||||||
self.scalars.append(key)
|
self.scalars.append(key)
|
||||||
if not self.main.stringify:
|
if not self.main.stringify:
|
||||||
if isinstance(value, six.string_types):
|
if isinstance(value, str):
|
||||||
pass
|
pass
|
||||||
elif isinstance(value, (list, tuple)):
|
elif isinstance(value, (list, tuple)):
|
||||||
for entry in value:
|
for entry in value:
|
||||||
if not isinstance(entry, six.string_types):
|
if not isinstance(entry, str):
|
||||||
raise TypeError('Value is not a string "%s".' % entry)
|
raise TypeError(f'Value is not a string "{entry}".')
|
||||||
else:
|
else:
|
||||||
raise TypeError('Value is not a string "%s".' % value)
|
raise TypeError(f'Value is not a string "{value}".')
|
||||||
dict.__setitem__(self, key, value)
|
dict.__setitem__(self, key, value)
|
||||||
|
|
||||||
|
|
||||||
@ -728,7 +728,7 @@ class Section(dict):
|
|||||||
|
|
||||||
def iterkeys(self):
|
def iterkeys(self):
|
||||||
"""D.iterkeys() -> an iterator over the keys of D"""
|
"""D.iterkeys() -> an iterator over the keys of D"""
|
||||||
return iter((self.scalars + self.sections))
|
return iter(self.scalars + self.sections)
|
||||||
|
|
||||||
__iter__ = iterkeys
|
__iter__ = iterkeys
|
||||||
|
|
||||||
@ -745,7 +745,7 @@ class Section(dict):
|
|||||||
return self[key]
|
return self[key]
|
||||||
except MissingInterpolationOption:
|
except MissingInterpolationOption:
|
||||||
return dict.__getitem__(self, key)
|
return dict.__getitem__(self, key)
|
||||||
return '{%s}' % ', '.join([('%s: %s' % (repr(key), repr(_getval(key))))
|
return '{%s}' % ', '.join([f'{key!r}: {_getval(key)!r}'
|
||||||
for key in (self.scalars + self.sections)])
|
for key in (self.scalars + self.sections)])
|
||||||
|
|
||||||
__str__ = __repr__
|
__str__ = __repr__
|
||||||
@ -823,7 +823,7 @@ class Section(dict):
|
|||||||
elif oldkey in self.sections:
|
elif oldkey in self.sections:
|
||||||
the_list = self.sections
|
the_list = self.sections
|
||||||
else:
|
else:
|
||||||
raise KeyError('Key "%s" not found.' % oldkey)
|
raise KeyError(f'Key "{oldkey}" not found.')
|
||||||
pos = the_list.index(oldkey)
|
pos = the_list.index(oldkey)
|
||||||
#
|
#
|
||||||
val = self[oldkey]
|
val = self[oldkey]
|
||||||
@ -959,13 +959,13 @@ class Section(dict):
|
|||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
if not isinstance(val, six.string_types):
|
if not isinstance(val, str):
|
||||||
# TODO: Why do we raise a KeyError here?
|
# TODO: Why do we raise a KeyError here?
|
||||||
raise KeyError()
|
raise KeyError()
|
||||||
else:
|
else:
|
||||||
return self.main._bools[val.lower()]
|
return self.main._bools[val.lower()]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ValueError('Value "%s" is neither True nor False' % val)
|
raise ValueError(f'Value "{val}" is neither True nor False')
|
||||||
|
|
||||||
|
|
||||||
def as_int(self, key):
|
def as_int(self, key):
|
||||||
@ -1210,7 +1210,7 @@ class ConfigObj(Section):
|
|||||||
# TODO: check the values too.
|
# TODO: check the values too.
|
||||||
for entry in options:
|
for entry in options:
|
||||||
if entry not in OPTION_DEFAULTS:
|
if entry not in OPTION_DEFAULTS:
|
||||||
raise TypeError('Unrecognised option "%s".' % entry)
|
raise TypeError(f'Unrecognised option "{entry}".')
|
||||||
for entry, value in list(OPTION_DEFAULTS.items()):
|
for entry, value in list(OPTION_DEFAULTS.items()):
|
||||||
if entry not in options:
|
if entry not in options:
|
||||||
options[entry] = value
|
options[entry] = value
|
||||||
@ -1230,14 +1230,14 @@ class ConfigObj(Section):
|
|||||||
|
|
||||||
|
|
||||||
def _load(self, infile, configspec):
|
def _load(self, infile, configspec):
|
||||||
if isinstance(infile, six.string_types):
|
if isinstance(infile, str):
|
||||||
self.filename = infile
|
self.filename = infile
|
||||||
if os.path.isfile(infile):
|
if os.path.isfile(infile):
|
||||||
with open(infile, 'rb') as h:
|
with open(infile, 'rb') as h:
|
||||||
content = h.readlines() or []
|
content = h.readlines() or []
|
||||||
elif self.file_error:
|
elif self.file_error:
|
||||||
# raise an error if the file doesn't exist
|
# raise an error if the file doesn't exist
|
||||||
raise IOError('Config file not found: "%s".' % self.filename)
|
raise OSError(f'Config file not found: "{self.filename}".')
|
||||||
else:
|
else:
|
||||||
# file doesn't already exist
|
# file doesn't already exist
|
||||||
if self.create_empty:
|
if self.create_empty:
|
||||||
@ -1298,15 +1298,15 @@ class ConfigObj(Section):
|
|||||||
break
|
break
|
||||||
break
|
break
|
||||||
|
|
||||||
assert all(isinstance(line, six.string_types) for line in content), repr(content)
|
assert all(isinstance(line, str) for line in content), repr(content)
|
||||||
content = [line.rstrip('\r\n') for line in content]
|
content = [line.rstrip('\r\n') for line in content]
|
||||||
|
|
||||||
self._parse(content)
|
self._parse(content)
|
||||||
# if we had any errors, now is the time to raise them
|
# if we had any errors, now is the time to raise them
|
||||||
if self._errors:
|
if self._errors:
|
||||||
info = "at line %s." % self._errors[0].line_number
|
info = f"at line {self._errors[0].line_number}."
|
||||||
if len(self._errors) > 1:
|
if len(self._errors) > 1:
|
||||||
msg = "Parsing failed with several errors.\nFirst error %s" % info
|
msg = f"Parsing failed with several errors.\nFirst error {info}"
|
||||||
error = ConfigObjError(msg)
|
error = ConfigObjError(msg)
|
||||||
else:
|
else:
|
||||||
error = self._errors[0]
|
error = self._errors[0]
|
||||||
@ -1363,9 +1363,7 @@ class ConfigObj(Section):
|
|||||||
return self[key]
|
return self[key]
|
||||||
except MissingInterpolationOption:
|
except MissingInterpolationOption:
|
||||||
return dict.__getitem__(self, key)
|
return dict.__getitem__(self, key)
|
||||||
return ('ConfigObj({%s})' %
|
return ('ConfigObj({%s})' % ', '.join([f'{key!r}: {_getval(key)!r}' for key in (self.scalars + self.sections)]))
|
||||||
', '.join([('%s: %s' % (repr(key), repr(_getval(key))))
|
|
||||||
for key in (self.scalars + self.sections)]))
|
|
||||||
|
|
||||||
|
|
||||||
def _handle_bom(self, infile):
|
def _handle_bom(self, infile):
|
||||||
@ -1403,7 +1401,7 @@ class ConfigObj(Section):
|
|||||||
else:
|
else:
|
||||||
line = infile
|
line = infile
|
||||||
|
|
||||||
if isinstance(line, six.text_type):
|
if isinstance(line, str):
|
||||||
# it's already decoded and there's no need to do anything
|
# it's already decoded and there's no need to do anything
|
||||||
# else, just use the _decode utility method to handle
|
# else, just use the _decode utility method to handle
|
||||||
# listifying appropriately
|
# listifying appropriately
|
||||||
@ -1448,7 +1446,7 @@ class ConfigObj(Section):
|
|||||||
|
|
||||||
# No encoding specified - so we need to check for UTF8/UTF16
|
# No encoding specified - so we need to check for UTF8/UTF16
|
||||||
for BOM, (encoding, final_encoding) in list(BOMS.items()):
|
for BOM, (encoding, final_encoding) in list(BOMS.items()):
|
||||||
if not isinstance(line, six.binary_type) or not line.startswith(BOM):
|
if not isinstance(line, bytes) or not line.startswith(BOM):
|
||||||
# didn't specify a BOM, or it's not a bytestring
|
# didn't specify a BOM, or it's not a bytestring
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
@ -1464,9 +1462,9 @@ class ConfigObj(Section):
|
|||||||
else:
|
else:
|
||||||
infile = newline
|
infile = newline
|
||||||
# UTF-8
|
# UTF-8
|
||||||
if isinstance(infile, six.text_type):
|
if isinstance(infile, str):
|
||||||
return infile.splitlines(True)
|
return infile.splitlines(True)
|
||||||
elif isinstance(infile, six.binary_type):
|
elif isinstance(infile, bytes):
|
||||||
return infile.decode('utf-8').splitlines(True)
|
return infile.decode('utf-8').splitlines(True)
|
||||||
else:
|
else:
|
||||||
return self._decode(infile, 'utf-8')
|
return self._decode(infile, 'utf-8')
|
||||||
@ -1479,7 +1477,7 @@ class ConfigObj(Section):
|
|||||||
# returning a bytestring is fine
|
# returning a bytestring is fine
|
||||||
return self._decode(infile, None)
|
return self._decode(infile, None)
|
||||||
# No BOM discovered and no encoding specified, default to UTF-8
|
# No BOM discovered and no encoding specified, default to UTF-8
|
||||||
if isinstance(infile, six.binary_type):
|
if isinstance(infile, bytes):
|
||||||
return infile.decode('utf-8').splitlines(True)
|
return infile.decode('utf-8').splitlines(True)
|
||||||
else:
|
else:
|
||||||
return self._decode(infile, 'utf-8')
|
return self._decode(infile, 'utf-8')
|
||||||
@ -1487,7 +1485,7 @@ class ConfigObj(Section):
|
|||||||
|
|
||||||
def _a_to_u(self, aString):
|
def _a_to_u(self, aString):
|
||||||
"""Decode ASCII strings to unicode if a self.encoding is specified."""
|
"""Decode ASCII strings to unicode if a self.encoding is specified."""
|
||||||
if isinstance(aString, six.binary_type) and self.encoding:
|
if isinstance(aString, bytes) and self.encoding:
|
||||||
return aString.decode(self.encoding)
|
return aString.decode(self.encoding)
|
||||||
else:
|
else:
|
||||||
return aString
|
return aString
|
||||||
@ -1499,9 +1497,9 @@ class ConfigObj(Section):
|
|||||||
|
|
||||||
if is a string, it also needs converting to a list.
|
if is a string, it also needs converting to a list.
|
||||||
"""
|
"""
|
||||||
if isinstance(infile, six.string_types):
|
if isinstance(infile, str):
|
||||||
return infile.splitlines(True)
|
return infile.splitlines(True)
|
||||||
if isinstance(infile, six.binary_type):
|
if isinstance(infile, bytes):
|
||||||
# NOTE: Could raise a ``UnicodeDecodeError``
|
# NOTE: Could raise a ``UnicodeDecodeError``
|
||||||
if encoding:
|
if encoding:
|
||||||
return infile.decode(encoding).splitlines(True)
|
return infile.decode(encoding).splitlines(True)
|
||||||
@ -1510,7 +1508,7 @@ class ConfigObj(Section):
|
|||||||
|
|
||||||
if encoding:
|
if encoding:
|
||||||
for i, line in enumerate(infile):
|
for i, line in enumerate(infile):
|
||||||
if isinstance(line, six.binary_type):
|
if isinstance(line, bytes):
|
||||||
# NOTE: The isinstance test here handles mixed lists of unicode/string
|
# NOTE: The isinstance test here handles mixed lists of unicode/string
|
||||||
# NOTE: But the decode will break on any non-string values
|
# NOTE: But the decode will break on any non-string values
|
||||||
# NOTE: Or could raise a ``UnicodeDecodeError``
|
# NOTE: Or could raise a ``UnicodeDecodeError``
|
||||||
@ -1520,7 +1518,7 @@ class ConfigObj(Section):
|
|||||||
|
|
||||||
def _decode_element(self, line):
|
def _decode_element(self, line):
|
||||||
"""Decode element to unicode if necessary."""
|
"""Decode element to unicode if necessary."""
|
||||||
if isinstance(line, six.binary_type) and self.default_encoding:
|
if isinstance(line, bytes) and self.default_encoding:
|
||||||
return line.decode(self.default_encoding)
|
return line.decode(self.default_encoding)
|
||||||
else:
|
else:
|
||||||
return line
|
return line
|
||||||
@ -1532,7 +1530,7 @@ class ConfigObj(Section):
|
|||||||
Used by ``stringify`` within validate, to turn non-string values
|
Used by ``stringify`` within validate, to turn non-string values
|
||||||
into strings.
|
into strings.
|
||||||
"""
|
"""
|
||||||
if not isinstance(value, six.string_types):
|
if not isinstance(value, str):
|
||||||
# intentially 'str' because it's just whatever the "normal"
|
# intentially 'str' because it's just whatever the "normal"
|
||||||
# string type is for the python version we're dealing with
|
# string type is for the python version we're dealing with
|
||||||
return str(value)
|
return str(value)
|
||||||
@ -1627,7 +1625,7 @@ class ConfigObj(Section):
|
|||||||
mat = self._keyword.match(line)
|
mat = self._keyword.match(line)
|
||||||
if mat is None:
|
if mat is None:
|
||||||
self._handle_error(
|
self._handle_error(
|
||||||
'Invalid line ({0!r}) (matched as neither section nor keyword)'.format(line),
|
f'Invalid line ({line!r}) (matched as neither section nor keyword)',
|
||||||
ParseError, infile, cur_index)
|
ParseError, infile, cur_index)
|
||||||
else:
|
else:
|
||||||
# is a keyword value
|
# is a keyword value
|
||||||
@ -1735,7 +1733,7 @@ class ConfigObj(Section):
|
|||||||
"""
|
"""
|
||||||
line = infile[cur_index]
|
line = infile[cur_index]
|
||||||
cur_index += 1
|
cur_index += 1
|
||||||
message = '{0} at line {1}.'.format(text, cur_index)
|
message = f'{text} at line {cur_index}.'
|
||||||
error = ErrorClass(message, cur_index, line)
|
error = ErrorClass(message, cur_index, line)
|
||||||
if self.raise_errors:
|
if self.raise_errors:
|
||||||
# raise the error - parsing stops here
|
# raise the error - parsing stops here
|
||||||
@ -1783,16 +1781,16 @@ class ConfigObj(Section):
|
|||||||
if not value:
|
if not value:
|
||||||
return ','
|
return ','
|
||||||
elif len(value) == 1:
|
elif len(value) == 1:
|
||||||
return self._quote(value[0], multiline=False) + ','
|
return f"{self._quote(value[0], multiline=False)},"
|
||||||
return ', '.join([self._quote(val, multiline=False)
|
return ', '.join([self._quote(val, multiline=False)
|
||||||
for val in value])
|
for val in value])
|
||||||
if not isinstance(value, six.string_types):
|
if not isinstance(value, str):
|
||||||
if self.stringify:
|
if self.stringify:
|
||||||
# intentially 'str' because it's just whatever the "normal"
|
# intentially 'str' because it's just whatever the "normal"
|
||||||
# string type is for the python version we're dealing with
|
# string type is for the python version we're dealing with
|
||||||
value = str(value)
|
value = str(value)
|
||||||
else:
|
else:
|
||||||
raise TypeError('Value "%s" is not a string.' % value)
|
raise TypeError(f'Value "{value}" is not a string.')
|
||||||
|
|
||||||
if not value:
|
if not value:
|
||||||
return '""'
|
return '""'
|
||||||
@ -1809,7 +1807,7 @@ class ConfigObj(Section):
|
|||||||
# for normal values either single or double quotes will do
|
# for normal values either single or double quotes will do
|
||||||
elif '\n' in value:
|
elif '\n' in value:
|
||||||
# will only happen if multiline is off - e.g. '\n' in key
|
# will only happen if multiline is off - e.g. '\n' in key
|
||||||
raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
|
raise ConfigObjError(f'Value "{value}" cannot be safely quoted.')
|
||||||
elif ((value[0] not in wspace_plus) and
|
elif ((value[0] not in wspace_plus) and
|
||||||
(value[-1] not in wspace_plus) and
|
(value[-1] not in wspace_plus) and
|
||||||
(',' not in value)):
|
(',' not in value)):
|
||||||
@ -1828,7 +1826,7 @@ class ConfigObj(Section):
|
|||||||
|
|
||||||
def _get_single_quote(self, value):
|
def _get_single_quote(self, value):
|
||||||
if ("'" in value) and ('"' in value):
|
if ("'" in value) and ('"' in value):
|
||||||
raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
|
raise ConfigObjError(f'Value "{value}" cannot be safely quoted.')
|
||||||
elif '"' in value:
|
elif '"' in value:
|
||||||
quot = squot
|
quot = squot
|
||||||
else:
|
else:
|
||||||
@ -1838,7 +1836,7 @@ class ConfigObj(Section):
|
|||||||
|
|
||||||
def _get_triple_quote(self, value):
|
def _get_triple_quote(self, value):
|
||||||
if (value.find('"""') != -1) and (value.find("'''") != -1):
|
if (value.find('"""') != -1) and (value.find("'''") != -1):
|
||||||
raise ConfigObjError('Value "%s" cannot be safely quoted.' % value)
|
raise ConfigObjError(f'Value "{value}" cannot be safely quoted.')
|
||||||
if value.find('"""') == -1:
|
if value.find('"""') == -1:
|
||||||
quot = tdquot
|
quot = tdquot
|
||||||
else:
|
else:
|
||||||
@ -1943,9 +1941,9 @@ class ConfigObj(Section):
|
|||||||
except ConfigObjError as e:
|
except ConfigObjError as e:
|
||||||
# FIXME: Should these errors have a reference
|
# FIXME: Should these errors have a reference
|
||||||
# to the already parsed ConfigObj ?
|
# to the already parsed ConfigObj ?
|
||||||
raise ConfigspecError('Parsing configspec failed: %s' % e)
|
raise ConfigspecError(f'Parsing configspec failed: {e}')
|
||||||
except IOError as e:
|
except OSError as e:
|
||||||
raise IOError('Reading configspec failed: %s' % e)
|
raise OSError(f'Reading configspec failed: {e}')
|
||||||
|
|
||||||
self.configspec = configspec
|
self.configspec = configspec
|
||||||
|
|
||||||
@ -1986,20 +1984,12 @@ class ConfigObj(Section):
|
|||||||
val = self._decode_element(self._quote(this_entry))
|
val = self._decode_element(self._quote(this_entry))
|
||||||
else:
|
else:
|
||||||
val = repr(this_entry)
|
val = repr(this_entry)
|
||||||
return '%s%s%s%s%s' % (indent_string,
|
return f"{indent_string}{self._decode_element(self._quote(entry, multiline=False))}{self._a_to_u(' = ')}{val}{self._decode_element(comment)}"
|
||||||
self._decode_element(self._quote(entry, multiline=False)),
|
|
||||||
self._a_to_u(' = '),
|
|
||||||
val,
|
|
||||||
self._decode_element(comment))
|
|
||||||
|
|
||||||
|
|
||||||
def _write_marker(self, indent_string, depth, entry, comment):
|
def _write_marker(self, indent_string, depth, entry, comment):
|
||||||
"""Write a section marker line"""
|
"""Write a section marker line"""
|
||||||
return '%s%s%s%s%s' % (indent_string,
|
return f"{indent_string}{self._a_to_u('[' * depth)}{self._quote(self._decode_element(entry), multiline=False)}{self._a_to_u(']' * depth)}{self._decode_element(comment)}"
|
||||||
self._a_to_u('[' * depth),
|
|
||||||
self._quote(self._decode_element(entry), multiline=False),
|
|
||||||
self._a_to_u(']' * depth),
|
|
||||||
self._decode_element(comment))
|
|
||||||
|
|
||||||
|
|
||||||
def _handle_comment(self, comment):
|
def _handle_comment(self, comment):
|
||||||
@ -2111,7 +2101,7 @@ class ConfigObj(Section):
|
|||||||
if not output.endswith(newline):
|
if not output.endswith(newline):
|
||||||
output += newline
|
output += newline
|
||||||
|
|
||||||
if isinstance(output, six.binary_type):
|
if isinstance(output, bytes):
|
||||||
output_bytes = output
|
output_bytes = output
|
||||||
else:
|
else:
|
||||||
output_bytes = output.encode(self.encoding or
|
output_bytes = output.encode(self.encoding or
|
||||||
@ -2284,7 +2274,7 @@ class ConfigObj(Section):
|
|||||||
out[entry] = False
|
out[entry] = False
|
||||||
else:
|
else:
|
||||||
ret_false = False
|
ret_false = False
|
||||||
msg = 'Value %r was provided as a section' % entry
|
msg = f'Value {entry!r} was provided as a section'
|
||||||
out[entry] = validator.baseErrorClass(msg)
|
out[entry] = validator.baseErrorClass(msg)
|
||||||
for entry in incorrect_sections:
|
for entry in incorrect_sections:
|
||||||
ret_true = False
|
ret_true = False
|
||||||
@ -2292,7 +2282,7 @@ class ConfigObj(Section):
|
|||||||
out[entry] = False
|
out[entry] = False
|
||||||
else:
|
else:
|
||||||
ret_false = False
|
ret_false = False
|
||||||
msg = 'Section %r was provided as a single value' % entry
|
msg = f'Section {entry!r} was provided as a single value'
|
||||||
out[entry] = validator.baseErrorClass(msg)
|
out[entry] = validator.baseErrorClass(msg)
|
||||||
|
|
||||||
# Missing sections will have been created as empty ones when the
|
# Missing sections will have been created as empty ones when the
|
||||||
@ -2353,7 +2343,7 @@ class ConfigObj(Section):
|
|||||||
This method raises a ``ReloadError`` if the ConfigObj doesn't have
|
This method raises a ``ReloadError`` if the ConfigObj doesn't have
|
||||||
a filename attribute pointing to a file.
|
a filename attribute pointing to a file.
|
||||||
"""
|
"""
|
||||||
if not isinstance(self.filename, six.string_types):
|
if not isinstance(self.filename, str):
|
||||||
raise ReloadError()
|
raise ReloadError()
|
||||||
|
|
||||||
filename = self.filename
|
filename = self.filename
|
||||||
@ -2372,7 +2362,7 @@ class ConfigObj(Section):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SimpleVal(object):
|
class SimpleVal:
|
||||||
"""
|
"""
|
||||||
A simple validator.
|
A simple validator.
|
||||||
Can be used to check that all members expected are present.
|
Can be used to check that all members expected are present.
|
||||||
|
12
RNS/vendor/i2plib/aiosam.py
vendored
12
RNS/vendor/i2plib/aiosam.py
vendored
@ -11,7 +11,7 @@ def parse_reply(data):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
msg = sam.Message(data.decode().strip())
|
msg = sam.Message(data.decode().strip())
|
||||||
logger.debug("SAM reply: "+str(msg))
|
logger.debug(f"SAM reply: {msg}")
|
||||||
except:
|
except:
|
||||||
raise ConnectionAbortedError("Invalid SAM response")
|
raise ConnectionAbortedError("Invalid SAM response")
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ async def create_session(session_name, sam_address=sam.DEFAULT_ADDRESS,
|
|||||||
:param options: (optional) A dict object with i2cp options
|
:param options: (optional) A dict object with i2cp options
|
||||||
:return: A (reader, writer) pair
|
:return: A (reader, writer) pair
|
||||||
"""
|
"""
|
||||||
logger.debug("Creating session {}".format(session_name))
|
logger.debug(f"Creating session {session_name}")
|
||||||
if destination:
|
if destination:
|
||||||
if type(destination) == sam.Destination:
|
if type(destination) == sam.Destination:
|
||||||
destination = destination
|
destination = destination
|
||||||
@ -101,7 +101,7 @@ async def create_session(session_name, sam_address=sam.DEFAULT_ADDRESS,
|
|||||||
else:
|
else:
|
||||||
dest_string = sam.TRANSIENT_DESTINATION
|
dest_string = sam.TRANSIENT_DESTINATION
|
||||||
|
|
||||||
options = " ".join(["{}={}".format(k, v) for k, v in options.items()])
|
options = " ".join([f"{k}={v}" for k, v in options.items()])
|
||||||
|
|
||||||
reader, writer = await get_sam_socket(sam_address, loop)
|
reader, writer = await get_sam_socket(sam_address, loop)
|
||||||
writer.write(sam.session_create(
|
writer.write(sam.session_create(
|
||||||
@ -113,7 +113,7 @@ async def create_session(session_name, sam_address=sam.DEFAULT_ADDRESS,
|
|||||||
destination = sam.Destination(
|
destination = sam.Destination(
|
||||||
reply["DESTINATION"], has_private_key=True)
|
reply["DESTINATION"], has_private_key=True)
|
||||||
logger.debug(destination.base32)
|
logger.debug(destination.base32)
|
||||||
logger.debug("Session created {}".format(session_name))
|
logger.debug(f"Session created {session_name}")
|
||||||
return (reader, writer)
|
return (reader, writer)
|
||||||
else:
|
else:
|
||||||
writer.close()
|
writer.close()
|
||||||
@ -129,7 +129,7 @@ async def stream_connect(session_name, destination,
|
|||||||
:param loop: (optional) Event loop instance
|
:param loop: (optional) Event loop instance
|
||||||
:return: A (reader, writer) pair
|
:return: A (reader, writer) pair
|
||||||
"""
|
"""
|
||||||
logger.debug("Connecting stream {}".format(session_name))
|
logger.debug(f"Connecting stream {session_name}")
|
||||||
if isinstance(destination, str) and not destination.endswith(".i2p"):
|
if isinstance(destination, str) and not destination.endswith(".i2p"):
|
||||||
destination = sam.Destination(destination)
|
destination = sam.Destination(destination)
|
||||||
elif isinstance(destination, str):
|
elif isinstance(destination, str):
|
||||||
@ -140,7 +140,7 @@ async def stream_connect(session_name, destination,
|
|||||||
silent="false"))
|
silent="false"))
|
||||||
reply = parse_reply(await reader.readline())
|
reply = parse_reply(await reader.readline())
|
||||||
if reply.ok:
|
if reply.ok:
|
||||||
logger.debug("Stream connected {}".format(session_name))
|
logger.debug(f"Stream connected {session_name}")
|
||||||
return (reader, writer)
|
return (reader, writer)
|
||||||
else:
|
else:
|
||||||
writer.close()
|
writer.close()
|
||||||
|
28
RNS/vendor/i2plib/sam.py
vendored
28
RNS/vendor/i2plib/sam.py
vendored
@ -23,7 +23,7 @@ TRANSIENT_DESTINATION = "TRANSIENT"
|
|||||||
VALID_BASE32_ADDRESS = re.compile(r"^([a-zA-Z0-9]{52}).b32.i2p$")
|
VALID_BASE32_ADDRESS = re.compile(r"^([a-zA-Z0-9]{52}).b32.i2p$")
|
||||||
VALID_BASE64_ADDRESS = re.compile(r"^([a-zA-Z0-9-~=]{516,528})$")
|
VALID_BASE64_ADDRESS = re.compile(r"^([a-zA-Z0-9-~=]{516,528})$")
|
||||||
|
|
||||||
class Message(object):
|
class Message:
|
||||||
"""Parse SAM message to an object"""
|
"""Parse SAM message to an object"""
|
||||||
def __init__(self, s):
|
def __init__(self, s):
|
||||||
self.opts = {}
|
self.opts = {}
|
||||||
@ -51,34 +51,30 @@ class Message(object):
|
|||||||
# SAM request messages
|
# SAM request messages
|
||||||
|
|
||||||
def hello(min_version, max_version):
|
def hello(min_version, max_version):
|
||||||
return "HELLO VERSION MIN={} MAX={}\n".format(min_version,
|
return f"HELLO VERSION MIN={min_version} MAX={max_version}\n".encode()
|
||||||
max_version).encode()
|
|
||||||
|
|
||||||
def session_create(style, session_id, destination, options=""):
|
def session_create(style, session_id, destination, options=""):
|
||||||
return "SESSION CREATE STYLE={} ID={} DESTINATION={} {}\n".format(
|
return f"SESSION CREATE STYLE={style} ID={session_id} DESTINATION={destination} {options}\n".encode()
|
||||||
style, session_id, destination, options).encode()
|
|
||||||
|
|
||||||
|
|
||||||
def stream_connect(session_id, destination, silent="false"):
|
def stream_connect(session_id, destination, silent="false"):
|
||||||
return "STREAM CONNECT ID={} DESTINATION={} SILENT={}\n".format(
|
return f"STREAM CONNECT ID={session_id} DESTINATION={destination} SILENT={silent}\n".encode()
|
||||||
session_id, destination, silent).encode()
|
|
||||||
|
|
||||||
def stream_accept(session_id, silent="false"):
|
def stream_accept(session_id, silent="false"):
|
||||||
return "STREAM ACCEPT ID={} SILENT={}\n".format(session_id, silent).encode()
|
return f"STREAM ACCEPT ID={session_id} SILENT={silent}\n".encode()
|
||||||
|
|
||||||
def stream_forward(session_id, port, options=""):
|
def stream_forward(session_id, port, options=""):
|
||||||
return "STREAM FORWARD ID={} PORT={} {}\n".format(
|
return f"STREAM FORWARD ID={session_id} PORT={port} {options}\n".encode()
|
||||||
session_id, port, options).encode()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def naming_lookup(name):
|
def naming_lookup(name):
|
||||||
return "NAMING LOOKUP NAME={}\n".format(name).encode()
|
return f"NAMING LOOKUP NAME={name}\n".encode()
|
||||||
|
|
||||||
def dest_generate(signature_type):
|
def dest_generate(signature_type):
|
||||||
return "DEST GENERATE SIGNATURE_TYPE={}\n".format(signature_type).encode()
|
return f"DEST GENERATE SIGNATURE_TYPE={signature_type}\n".encode()
|
||||||
|
|
||||||
class Destination(object):
|
class Destination:
|
||||||
"""I2P destination
|
"""I2P destination
|
||||||
|
|
||||||
https://geti2p.net/spec/common-structures#destination
|
https://geti2p.net/spec/common-structures#destination
|
||||||
@ -101,7 +97,7 @@ class Destination(object):
|
|||||||
|
|
||||||
def __init__(self, data=None, path=None, has_private_key=False):
|
def __init__(self, data=None, path=None, has_private_key=False):
|
||||||
#: Binary destination
|
#: Binary destination
|
||||||
self.data = bytes()
|
self.data = b''
|
||||||
#: Base64 encoded destination
|
#: Base64 encoded destination
|
||||||
self.base64 = ""
|
self.base64 = ""
|
||||||
#: :class:`RNS.vendor.i2plib.PrivateKey` instance or None
|
#: :class:`RNS.vendor.i2plib.PrivateKey` instance or None
|
||||||
@ -123,7 +119,7 @@ class Destination(object):
|
|||||||
self.base64 = data if type(data) == str else i2p_b64encode(data)
|
self.base64 = data if type(data) == str else i2p_b64encode(data)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Destination: {}>".format(self.base32)
|
return f"<Destination: {self.base32}>"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def base32(self):
|
def base32(self):
|
||||||
@ -131,7 +127,7 @@ class Destination(object):
|
|||||||
desthash = sha256(self.data).digest()
|
desthash = sha256(self.data).digest()
|
||||||
return b32encode(desthash).decode()[:52].lower()
|
return b32encode(desthash).decode()[:52].lower()
|
||||||
|
|
||||||
class PrivateKey(object):
|
class PrivateKey:
|
||||||
"""I2P private key
|
"""I2P private key
|
||||||
|
|
||||||
https://geti2p.net/spec/common-structures#keysandcert
|
https://geti2p.net/spec/common-structures#keysandcert
|
||||||
|
7
RNS/vendor/i2plib/tunnel.py
vendored
7
RNS/vendor/i2plib/tunnel.py
vendored
@ -18,7 +18,7 @@ async def proxy_data(reader, writer):
|
|||||||
break
|
break
|
||||||
writer.write(data)
|
writer.write(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug('proxy_data_task exception {}'.format(e))
|
logger.debug(f'proxy_data_task exception {e}')
|
||||||
finally:
|
finally:
|
||||||
try:
|
try:
|
||||||
writer.close()
|
writer.close()
|
||||||
@ -26,7 +26,7 @@ async def proxy_data(reader, writer):
|
|||||||
pass
|
pass
|
||||||
logger.debug('close connection')
|
logger.debug('close connection')
|
||||||
|
|
||||||
class I2PTunnel(object):
|
class I2PTunnel:
|
||||||
"""Base I2P Tunnel object, not to be used directly
|
"""Base I2P Tunnel object, not to be used directly
|
||||||
|
|
||||||
:param local_address: A local address to use for a tunnel.
|
:param local_address: A local address to use for a tunnel.
|
||||||
@ -141,8 +141,7 @@ class ServerTunnel(I2PTunnel):
|
|||||||
# data and dest may come in one chunk
|
# data and dest may come in one chunk
|
||||||
dest, data = incoming.split(b"\n", 1)
|
dest, data = incoming.split(b"\n", 1)
|
||||||
remote_destination = sam.Destination(dest.decode())
|
remote_destination = sam.Destination(dest.decode())
|
||||||
logger.debug("{} client connected: {}.b32.i2p".format(
|
logger.debug(f"{self.session_name} client connected: {remote_destination.base32}.b32.i2p")
|
||||||
self.session_name, remote_destination.base32))
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.status["exception"] = e
|
self.status["exception"] = e
|
||||||
|
2
RNS/vendor/i2plib/utils.py
vendored
2
RNS/vendor/i2plib/utils.py
vendored
@ -38,5 +38,5 @@ def generate_session_id(length=6):
|
|||||||
"""Generate random session id"""
|
"""Generate random session id"""
|
||||||
rand = random.SystemRandom()
|
rand = random.SystemRandom()
|
||||||
sid = [rand.choice(string.ascii_letters) for _ in range(length)]
|
sid = [rand.choice(string.ascii_letters) for _ in range(length)]
|
||||||
return "reticulum-" + "".join(sid)
|
return f"reticulum-{''.join(sid)}"
|
||||||
|
|
||||||
|
2
RNS/vendor/ifaddr/__init__.py
vendored
2
RNS/vendor/ifaddr/__init__.py
vendored
@ -28,6 +28,6 @@ if os.name == "nt":
|
|||||||
elif os.name == "posix":
|
elif os.name == "posix":
|
||||||
from RNS.vendor.ifaddr._posix import get_adapters
|
from RNS.vendor.ifaddr._posix import get_adapters
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Unsupported Operating System: %s" % os.name)
|
raise RuntimeError(f"Unsupported Operating System: {os.name}")
|
||||||
|
|
||||||
__all__ = ['Adapter', 'IP', 'get_adapters']
|
__all__ = ['Adapter', 'IP', 'get_adapters']
|
||||||
|
2
RNS/vendor/ifaddr/_posix.py
vendored
2
RNS/vendor/ifaddr/_posix.py
vendored
@ -79,7 +79,7 @@ def get_adapters(include_unconfigured: bool = False) -> Iterable[shared.Adapter]
|
|||||||
prefixlen = shared.ipv6_prefixlength(ipaddress.IPv6Address(netmaskStr))
|
prefixlen = shared.ipv6_prefixlength(ipaddress.IPv6Address(netmaskStr))
|
||||||
else:
|
else:
|
||||||
assert netmask is not None, f'sockaddr_to_ip({addr[0].ifa_netmask}) returned None'
|
assert netmask is not None, f'sockaddr_to_ip({addr[0].ifa_netmask}) returned None'
|
||||||
netmaskStr = str('0.0.0.0/' + netmask)
|
netmaskStr = str(f"0.0.0.0/{netmask}")
|
||||||
prefixlen = ipaddress.IPv4Network(netmaskStr).prefixlen
|
prefixlen = ipaddress.IPv4Network(netmaskStr).prefixlen
|
||||||
ip = shared.IP(ip_addr, prefixlen, name)
|
ip = shared.IP(ip_addr, prefixlen, name)
|
||||||
add_ip(name, ip)
|
add_ip(name, ip)
|
||||||
|
12
RNS/vendor/ifaddr/_shared.py
vendored
12
RNS/vendor/ifaddr/_shared.py
vendored
@ -26,7 +26,7 @@ import platform
|
|||||||
|
|
||||||
from typing import List, Optional, Tuple, Union
|
from typing import List, Optional, Tuple, Union
|
||||||
|
|
||||||
class Adapter(object):
|
class Adapter:
|
||||||
"""
|
"""
|
||||||
Represents a network interface device controller (NIC), such as a
|
Represents a network interface device controller (NIC), such as a
|
||||||
network card. An adapter can have multiple IPs.
|
network card. An adapter can have multiple IPs.
|
||||||
@ -58,9 +58,7 @@ class Adapter(object):
|
|||||||
self.index = index
|
self.index = index
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "Adapter(name={name}, nice_name={nice_name}, ips={ips}, index={index})".format(
|
return f"Adapter(name={self.name!r}, nice_name={self.nice_name!r}, ips={self.ips!r}, index={self.index!r})"
|
||||||
name=repr(self.name), nice_name=repr(self.nice_name), ips=repr(self.ips), index=repr(self.index)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Type of an IPv4 address (a string in "xxx.xxx.xxx.xxx" format)
|
# Type of an IPv4 address (a string in "xxx.xxx.xxx.xxx" format)
|
||||||
@ -70,7 +68,7 @@ _IPv4Address = str
|
|||||||
_IPv6Address = Tuple[str, int, int]
|
_IPv6Address = Tuple[str, int, int]
|
||||||
|
|
||||||
|
|
||||||
class IP(object):
|
class IP:
|
||||||
"""
|
"""
|
||||||
Represents an IP address of an adapter.
|
Represents an IP address of an adapter.
|
||||||
"""
|
"""
|
||||||
@ -112,9 +110,7 @@ class IP(object):
|
|||||||
return isinstance(self.ip, tuple)
|
return isinstance(self.ip, tuple)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "IP(ip={ip}, network_prefix={network_prefix}, nice_name={nice_name})".format(
|
return f"IP(ip={self.ip!r}, network_prefix={self.network_prefix!r}, nice_name={self.nice_name!r})"
|
||||||
ip=repr(self.ip), network_prefix=repr(self.network_prefix), nice_name=repr(self.nice_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if platform.system() == "Darwin" or "BSD" in platform.system():
|
if platform.system() == "Darwin" or "BSD" in platform.system():
|
||||||
|
2
RNS/vendor/ifaddr/niwrapper.py
vendored
2
RNS/vendor/ifaddr/niwrapper.py
vendored
@ -40,7 +40,7 @@ def ifaddresses(ifname) -> dict:
|
|||||||
for ip in a.ips:
|
for ip in a.ips:
|
||||||
t = {}
|
t = {}
|
||||||
if ip.is_IPv4:
|
if ip.is_IPv4:
|
||||||
net = ipaddress.ip_network(str(ip.ip)+"/"+str(ip.network_prefix), strict=False)
|
net = ipaddress.ip_network(f"{ip.ip}/{ip.network_prefix}", strict=False)
|
||||||
t["addr"] = ip.ip
|
t["addr"] = ip.ip
|
||||||
t["prefix"] = ip.network_prefix
|
t["prefix"] = ip.network_prefix
|
||||||
t["broadcast"] = str(net.broadcast_address)
|
t["broadcast"] = str(net.broadcast_address)
|
||||||
|
55
RNS/vendor/six.py
vendored
55
RNS/vendor/six.py
vendored
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
"""Utilities for writing code that runs on Python 2 and 3"""
|
"""Utilities for writing code that runs on Python 2 and 3"""
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import itertools
|
import itertools
|
||||||
@ -57,7 +56,7 @@ else:
|
|||||||
MAXSIZE = int((1 << 31) - 1)
|
MAXSIZE = int((1 << 31) - 1)
|
||||||
else:
|
else:
|
||||||
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
|
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
|
||||||
class X(object):
|
class X:
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return 1 << 31
|
return 1 << 31
|
||||||
@ -88,7 +87,7 @@ def _import_module(name):
|
|||||||
return sys.modules[name]
|
return sys.modules[name]
|
||||||
|
|
||||||
|
|
||||||
class _LazyDescr(object):
|
class _LazyDescr:
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -108,7 +107,7 @@ class _LazyDescr(object):
|
|||||||
class MovedModule(_LazyDescr):
|
class MovedModule(_LazyDescr):
|
||||||
|
|
||||||
def __init__(self, name, old, new=None):
|
def __init__(self, name, old, new=None):
|
||||||
super(MovedModule, self).__init__(name)
|
super().__init__(name)
|
||||||
if PY3:
|
if PY3:
|
||||||
if new is None:
|
if new is None:
|
||||||
new = name
|
new = name
|
||||||
@ -129,7 +128,7 @@ class MovedModule(_LazyDescr):
|
|||||||
class _LazyModule(types.ModuleType):
|
class _LazyModule(types.ModuleType):
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
super(_LazyModule, self).__init__(name)
|
super().__init__(name)
|
||||||
self.__doc__ = self.__class__.__doc__
|
self.__doc__ = self.__class__.__doc__
|
||||||
|
|
||||||
def __dir__(self):
|
def __dir__(self):
|
||||||
@ -144,7 +143,7 @@ class _LazyModule(types.ModuleType):
|
|||||||
class MovedAttribute(_LazyDescr):
|
class MovedAttribute(_LazyDescr):
|
||||||
|
|
||||||
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
|
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
|
||||||
super(MovedAttribute, self).__init__(name)
|
super().__init__(name)
|
||||||
if PY3:
|
if PY3:
|
||||||
if new_mod is None:
|
if new_mod is None:
|
||||||
new_mod = name
|
new_mod = name
|
||||||
@ -166,7 +165,7 @@ class MovedAttribute(_LazyDescr):
|
|||||||
return getattr(module, self.attr)
|
return getattr(module, self.attr)
|
||||||
|
|
||||||
|
|
||||||
class _SixMetaPathImporter(object):
|
class _SixMetaPathImporter:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
A meta path importer to import six.moves and its submodules.
|
A meta path importer to import six.moves and its submodules.
|
||||||
@ -181,10 +180,10 @@ class _SixMetaPathImporter(object):
|
|||||||
|
|
||||||
def _add_module(self, mod, *fullnames):
|
def _add_module(self, mod, *fullnames):
|
||||||
for fullname in fullnames:
|
for fullname in fullnames:
|
||||||
self.known_modules[self.name + "." + fullname] = mod
|
self.known_modules[f"{self.name}.{fullname}"] = mod
|
||||||
|
|
||||||
def _get_module(self, fullname):
|
def _get_module(self, fullname):
|
||||||
return self.known_modules[self.name + "." + fullname]
|
return self.known_modules[f"{self.name}.{fullname}"]
|
||||||
|
|
||||||
def find_module(self, fullname, path=None):
|
def find_module(self, fullname, path=None):
|
||||||
if fullname in self.known_modules:
|
if fullname in self.known_modules:
|
||||||
@ -200,7 +199,7 @@ class _SixMetaPathImporter(object):
|
|||||||
try:
|
try:
|
||||||
return self.known_modules[fullname]
|
return self.known_modules[fullname]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ImportError("This loader does not know module " + fullname)
|
raise ImportError(f"This loader does not know module {fullname}")
|
||||||
|
|
||||||
def load_module(self, fullname):
|
def load_module(self, fullname):
|
||||||
try:
|
try:
|
||||||
@ -312,9 +311,9 @@ _moved_attributes = [
|
|||||||
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
|
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
|
||||||
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
|
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
|
||||||
"tkinter.simpledialog"),
|
"tkinter.simpledialog"),
|
||||||
MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
|
MovedModule("urllib_parse", f"{__name__}.moves.urllib_parse", "urllib.parse"),
|
||||||
MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
|
MovedModule("urllib_error", f"{__name__}.moves.urllib_error", "urllib.error"),
|
||||||
MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
|
MovedModule("urllib", f"{__name__}.moves.urllib", f"{__name__}.moves.urllib"),
|
||||||
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
|
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
|
||||||
MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
|
MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
|
||||||
MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
|
MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
|
||||||
@ -328,12 +327,12 @@ if sys.platform == "win32":
|
|||||||
for attr in _moved_attributes:
|
for attr in _moved_attributes:
|
||||||
setattr(_MovedItems, attr.name, attr)
|
setattr(_MovedItems, attr.name, attr)
|
||||||
if isinstance(attr, MovedModule):
|
if isinstance(attr, MovedModule):
|
||||||
_importer._add_module(attr, "moves." + attr.name)
|
_importer._add_module(attr, f"moves.{attr.name}")
|
||||||
del attr
|
del attr
|
||||||
|
|
||||||
_MovedItems._moved_attributes = _moved_attributes
|
_MovedItems._moved_attributes = _moved_attributes
|
||||||
|
|
||||||
moves = _MovedItems(__name__ + ".moves")
|
moves = _MovedItems(f"{__name__}.moves")
|
||||||
_importer._add_module(moves, "moves")
|
_importer._add_module(moves, "moves")
|
||||||
|
|
||||||
|
|
||||||
@ -375,7 +374,7 @@ del attr
|
|||||||
|
|
||||||
Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
|
Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
|
||||||
|
|
||||||
_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
|
_importer._add_module(Module_six_moves_urllib_parse(f"{__name__}.moves.urllib_parse"),
|
||||||
"moves.urllib_parse", "moves.urllib.parse")
|
"moves.urllib_parse", "moves.urllib.parse")
|
||||||
|
|
||||||
|
|
||||||
@ -395,7 +394,7 @@ del attr
|
|||||||
|
|
||||||
Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
|
Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
|
||||||
|
|
||||||
_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
|
_importer._add_module(Module_six_moves_urllib_error(f"{__name__}.moves.urllib.error"),
|
||||||
"moves.urllib_error", "moves.urllib.error")
|
"moves.urllib_error", "moves.urllib.error")
|
||||||
|
|
||||||
|
|
||||||
@ -447,7 +446,7 @@ del attr
|
|||||||
|
|
||||||
Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
|
Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
|
||||||
|
|
||||||
_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
|
_importer._add_module(Module_six_moves_urllib_request(f"{__name__}.moves.urllib.request"),
|
||||||
"moves.urllib_request", "moves.urllib.request")
|
"moves.urllib_request", "moves.urllib.request")
|
||||||
|
|
||||||
|
|
||||||
@ -468,7 +467,7 @@ del attr
|
|||||||
|
|
||||||
Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
|
Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
|
||||||
|
|
||||||
_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
|
_importer._add_module(Module_six_moves_urllib_response(f"{__name__}.moves.urllib.response"),
|
||||||
"moves.urllib_response", "moves.urllib.response")
|
"moves.urllib_response", "moves.urllib.response")
|
||||||
|
|
||||||
|
|
||||||
@ -486,7 +485,7 @@ del attr
|
|||||||
|
|
||||||
Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
|
Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
|
||||||
|
|
||||||
_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
|
_importer._add_module(Module_six_moves_urllib_robotparser(f"{__name__}.moves.urllib.robotparser"),
|
||||||
"moves.urllib_robotparser", "moves.urllib.robotparser")
|
"moves.urllib_robotparser", "moves.urllib.robotparser")
|
||||||
|
|
||||||
|
|
||||||
@ -503,7 +502,7 @@ class Module_six_moves_urllib(types.ModuleType):
|
|||||||
def __dir__(self):
|
def __dir__(self):
|
||||||
return ['parse', 'error', 'request', 'response', 'robotparser']
|
return ['parse', 'error', 'request', 'response', 'robotparser']
|
||||||
|
|
||||||
_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
|
_importer._add_module(Module_six_moves_urllib(f"{__name__}.moves.urllib"),
|
||||||
"moves.urllib")
|
"moves.urllib")
|
||||||
|
|
||||||
|
|
||||||
@ -520,7 +519,7 @@ def remove_move(name):
|
|||||||
try:
|
try:
|
||||||
del moves.__dict__[name]
|
del moves.__dict__[name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise AttributeError("no such move, %r" % (name,))
|
raise AttributeError(f"no such move, {name!r}")
|
||||||
|
|
||||||
|
|
||||||
if PY3:
|
if PY3:
|
||||||
@ -576,7 +575,7 @@ else:
|
|||||||
def create_unbound_method(func, cls):
|
def create_unbound_method(func, cls):
|
||||||
return types.MethodType(func, None, cls)
|
return types.MethodType(func, None, cls)
|
||||||
|
|
||||||
class Iterator(object):
|
class Iterator:
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
return type(self).__next__(self)
|
return type(self).__next__(self)
|
||||||
@ -910,7 +909,7 @@ def ensure_binary(s, encoding='utf-8', errors='strict'):
|
|||||||
return s
|
return s
|
||||||
if isinstance(s, text_type):
|
if isinstance(s, text_type):
|
||||||
return s.encode(encoding, errors)
|
return s.encode(encoding, errors)
|
||||||
raise TypeError("not expecting type '%s'" % type(s))
|
raise TypeError(f"not expecting type '{type(s)}'")
|
||||||
|
|
||||||
|
|
||||||
def ensure_str(s, encoding='utf-8', errors='strict'):
|
def ensure_str(s, encoding='utf-8', errors='strict'):
|
||||||
@ -932,7 +931,7 @@ def ensure_str(s, encoding='utf-8', errors='strict'):
|
|||||||
elif PY3 and isinstance(s, binary_type):
|
elif PY3 and isinstance(s, binary_type):
|
||||||
return s.decode(encoding, errors)
|
return s.decode(encoding, errors)
|
||||||
elif not isinstance(s, (text_type, binary_type)):
|
elif not isinstance(s, (text_type, binary_type)):
|
||||||
raise TypeError("not expecting type '%s'" % type(s))
|
raise TypeError(f"not expecting type '{type(s)}'")
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
@ -952,7 +951,7 @@ def ensure_text(s, encoding='utf-8', errors='strict'):
|
|||||||
elif isinstance(s, text_type):
|
elif isinstance(s, text_type):
|
||||||
return s
|
return s
|
||||||
else:
|
else:
|
||||||
raise TypeError("not expecting type '%s'" % type(s))
|
raise TypeError(f"not expecting type '{type(s)}'")
|
||||||
|
|
||||||
|
|
||||||
def python_2_unicode_compatible(klass):
|
def python_2_unicode_compatible(klass):
|
||||||
@ -965,9 +964,7 @@ def python_2_unicode_compatible(klass):
|
|||||||
"""
|
"""
|
||||||
if PY2:
|
if PY2:
|
||||||
if '__str__' not in klass.__dict__:
|
if '__str__' not in klass.__dict__:
|
||||||
raise ValueError("@python_2_unicode_compatible cannot be applied "
|
raise ValueError(f"@python_2_unicode_compatible cannot be applied to {klass.__name__} because it doesn't define __str__().")
|
||||||
"to %s because it doesn't define __str__()." %
|
|
||||||
klass.__name__)
|
|
||||||
klass.__unicode__ = klass.__str__
|
klass.__unicode__ = klass.__str__
|
||||||
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
|
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
|
||||||
return klass
|
return klass
|
||||||
|
70
RNS/vendor/umsgpack.py
vendored
70
RNS/vendor/umsgpack.py
vendored
@ -52,7 +52,7 @@ import io
|
|||||||
if sys.version_info[0:2] >= (3, 3):
|
if sys.version_info[0:2] >= (3, 3):
|
||||||
from collections.abc import Hashable
|
from collections.abc import Hashable
|
||||||
else:
|
else:
|
||||||
from collections import Hashable
|
from collections.abc import Hashable
|
||||||
|
|
||||||
__version__ = "2.7.1"
|
__version__ = "2.7.1"
|
||||||
"Module version string"
|
"Module version string"
|
||||||
@ -66,7 +66,7 @@ version = (2, 7, 1)
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Extension type for application-defined types and data
|
# Extension type for application-defined types and data
|
||||||
class Ext(object):
|
class Ext:
|
||||||
"""
|
"""
|
||||||
The Ext class facilitates creating a serializable extension object to store
|
The Ext class facilitates creating a serializable extension object to store
|
||||||
an application-defined type and data byte array.
|
an application-defined type and data byte array.
|
||||||
@ -100,7 +100,7 @@ class Ext(object):
|
|||||||
if not isinstance(type, int):
|
if not isinstance(type, int):
|
||||||
raise TypeError("ext type is not type integer")
|
raise TypeError("ext type is not type integer")
|
||||||
elif not (-2**7 <= type <= 2**7 - 1):
|
elif not (-2**7 <= type <= 2**7 - 1):
|
||||||
raise ValueError("ext type value {:d} is out of range (-128 to 127)".format(type))
|
raise ValueError(f"ext type value {type} is out of range (-128 to 127)")
|
||||||
# Check data is type bytes or str
|
# Check data is type bytes or str
|
||||||
elif sys.version_info[0] == 3 and not isinstance(data, bytes):
|
elif sys.version_info[0] == 3 and not isinstance(data, bytes):
|
||||||
raise TypeError("ext data is not type \'bytes\'")
|
raise TypeError("ext data is not type \'bytes\'")
|
||||||
@ -127,8 +127,8 @@ class Ext(object):
|
|||||||
"""
|
"""
|
||||||
String representation of this Ext object.
|
String representation of this Ext object.
|
||||||
"""
|
"""
|
||||||
s = "Ext Object (Type: {:d}, Data: ".format(self.type)
|
s = f"Ext Object (Type: {self.type}, Data: "
|
||||||
s += " ".join(["0x{:02}".format(ord(self.data[i:i + 1]))
|
s += " ".join([f"0x{ord(self.data[i:i + 1]):02}"
|
||||||
for i in xrange(min(len(self.data), 8))])
|
for i in xrange(min(len(self.data), 8))])
|
||||||
if len(self.data) > 8:
|
if len(self.data) > 8:
|
||||||
s += " ..."
|
s += " ..."
|
||||||
@ -177,11 +177,11 @@ def ext_serializable(ext_type):
|
|||||||
if not isinstance(ext_type, int):
|
if not isinstance(ext_type, int):
|
||||||
raise TypeError("Ext type is not type integer")
|
raise TypeError("Ext type is not type integer")
|
||||||
elif not (-2**7 <= ext_type <= 2**7 - 1):
|
elif not (-2**7 <= ext_type <= 2**7 - 1):
|
||||||
raise ValueError("Ext type value {:d} is out of range of -128 to 127".format(ext_type))
|
raise ValueError(f"Ext type value {ext_type} is out of range of -128 to 127")
|
||||||
elif ext_type in _ext_type_to_class:
|
elif ext_type in _ext_type_to_class:
|
||||||
raise ValueError("Ext type {:d} already registered with class {:s}".format(ext_type, repr(_ext_type_to_class[ext_type])))
|
raise ValueError(f"Ext type {ext_type} already registered with class {_ext_type_to_class[ext_type]!r}")
|
||||||
elif cls in _ext_class_to_type:
|
elif cls in _ext_class_to_type:
|
||||||
raise ValueError("Class {:s} already registered with Ext type {:d}".format(repr(cls), ext_type))
|
raise ValueError(f"Class {cls!r} already registered with Ext type {ext_type}")
|
||||||
|
|
||||||
_ext_type_to_class[ext_type] = cls
|
_ext_type_to_class[ext_type] = cls
|
||||||
_ext_class_to_type[cls] = ext_type
|
_ext_class_to_type[cls] = ext_type
|
||||||
@ -495,7 +495,7 @@ def _pack2(obj, fp, **options):
|
|||||||
try:
|
try:
|
||||||
_pack_ext(Ext(_ext_class_to_type[obj.__class__], obj.packb()), fp, options)
|
_pack_ext(Ext(_ext_class_to_type[obj.__class__], obj.packb()), fp, options)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise NotImplementedError("Ext serializable class {:s} is missing implementation of packb()".format(repr(obj.__class__)))
|
raise NotImplementedError(f"Ext serializable class {obj.__class__!r} is missing implementation of packb()")
|
||||||
elif isinstance(obj, bool):
|
elif isinstance(obj, bool):
|
||||||
_pack_boolean(obj, fp, options)
|
_pack_boolean(obj, fp, options)
|
||||||
elif isinstance(obj, (int, long)):
|
elif isinstance(obj, (int, long)):
|
||||||
@ -525,7 +525,7 @@ def _pack2(obj, fp, **options):
|
|||||||
_pack_ext(ext_handlers[t](obj), fp, options)
|
_pack_ext(ext_handlers[t](obj), fp, options)
|
||||||
else:
|
else:
|
||||||
raise UnsupportedTypeException(
|
raise UnsupportedTypeException(
|
||||||
"unsupported type: {:s}".format(str(type(obj))))
|
f"unsupported type: {type(obj)}")
|
||||||
elif _ext_class_to_type:
|
elif _ext_class_to_type:
|
||||||
# Linear search for superclass
|
# Linear search for superclass
|
||||||
t = next((t for t in _ext_class_to_type if isinstance(obj, t)), None)
|
t = next((t for t in _ext_class_to_type if isinstance(obj, t)), None)
|
||||||
@ -533,11 +533,11 @@ def _pack2(obj, fp, **options):
|
|||||||
try:
|
try:
|
||||||
_pack_ext(Ext(_ext_class_to_type[t], obj.packb()), fp, options)
|
_pack_ext(Ext(_ext_class_to_type[t], obj.packb()), fp, options)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise NotImplementedError("Ext serializable class {:s} is missing implementation of packb()".format(repr(t)))
|
raise NotImplementedError(f"Ext serializable class {t!r} is missing implementation of packb()")
|
||||||
else:
|
else:
|
||||||
raise UnsupportedTypeException("unsupported type: {:s}".format(str(type(obj))))
|
raise UnsupportedTypeException(f"unsupported type: {type(obj)}")
|
||||||
else:
|
else:
|
||||||
raise UnsupportedTypeException("unsupported type: {:s}".format(str(type(obj))))
|
raise UnsupportedTypeException(f"unsupported type: {type(obj)}")
|
||||||
|
|
||||||
|
|
||||||
# Pack for Python 3, with unicode 'str' type, 'bytes' type, and no 'long' type
|
# Pack for Python 3, with unicode 'str' type, 'bytes' type, and no 'long' type
|
||||||
@ -582,7 +582,7 @@ def _pack3(obj, fp, **options):
|
|||||||
try:
|
try:
|
||||||
_pack_ext(Ext(_ext_class_to_type[obj.__class__], obj.packb()), fp, options)
|
_pack_ext(Ext(_ext_class_to_type[obj.__class__], obj.packb()), fp, options)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise NotImplementedError("Ext serializable class {:s} is missing implementation of packb()".format(repr(obj.__class__)))
|
raise NotImplementedError(f"Ext serializable class {obj.__class__!r} is missing implementation of packb()")
|
||||||
elif isinstance(obj, bool):
|
elif isinstance(obj, bool):
|
||||||
_pack_boolean(obj, fp, options)
|
_pack_boolean(obj, fp, options)
|
||||||
elif isinstance(obj, int):
|
elif isinstance(obj, int):
|
||||||
@ -612,7 +612,7 @@ def _pack3(obj, fp, **options):
|
|||||||
_pack_ext(ext_handlers[t](obj), fp, options)
|
_pack_ext(ext_handlers[t](obj), fp, options)
|
||||||
else:
|
else:
|
||||||
raise UnsupportedTypeException(
|
raise UnsupportedTypeException(
|
||||||
"unsupported type: {:s}".format(str(type(obj))))
|
f"unsupported type: {type(obj)}")
|
||||||
elif _ext_class_to_type:
|
elif _ext_class_to_type:
|
||||||
# Linear search for superclass
|
# Linear search for superclass
|
||||||
t = next((t for t in _ext_class_to_type if isinstance(obj, t)), None)
|
t = next((t for t in _ext_class_to_type if isinstance(obj, t)), None)
|
||||||
@ -620,12 +620,12 @@ def _pack3(obj, fp, **options):
|
|||||||
try:
|
try:
|
||||||
_pack_ext(Ext(_ext_class_to_type[t], obj.packb()), fp, options)
|
_pack_ext(Ext(_ext_class_to_type[t], obj.packb()), fp, options)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise NotImplementedError("Ext serializable class {:s} is missing implementation of packb()".format(repr(t)))
|
raise NotImplementedError(f"Ext serializable class {t!r} is missing implementation of packb()")
|
||||||
else:
|
else:
|
||||||
raise UnsupportedTypeException("unsupported type: {:s}".format(str(type(obj))))
|
raise UnsupportedTypeException(f"unsupported type: {type(obj)}")
|
||||||
else:
|
else:
|
||||||
raise UnsupportedTypeException(
|
raise UnsupportedTypeException(
|
||||||
"unsupported type: {:s}".format(str(type(obj))))
|
f"unsupported type: {type(obj)}")
|
||||||
|
|
||||||
|
|
||||||
def _packb2(obj, **options):
|
def _packb2(obj, **options):
|
||||||
@ -737,21 +737,21 @@ def _unpack_integer(code, fp, options):
|
|||||||
return struct.unpack(">I", _read_except(fp, 4))[0]
|
return struct.unpack(">I", _read_except(fp, 4))[0]
|
||||||
elif code == b'\xcf':
|
elif code == b'\xcf':
|
||||||
return struct.unpack(">Q", _read_except(fp, 8))[0]
|
return struct.unpack(">Q", _read_except(fp, 8))[0]
|
||||||
raise Exception("logic error, not int: 0x{:02x}".format(ord(code)))
|
raise Exception(f"logic error, not int: 0x{ord(code):02x}")
|
||||||
|
|
||||||
|
|
||||||
def _unpack_reserved(code, fp, options):
|
def _unpack_reserved(code, fp, options):
|
||||||
if code == b'\xc1':
|
if code == b'\xc1':
|
||||||
raise ReservedCodeException(
|
raise ReservedCodeException(
|
||||||
"encountered reserved code: 0x{:02x}".format(ord(code)))
|
f"encountered reserved code: 0x{ord(code):02x}")
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"logic error, not reserved code: 0x{:02x}".format(ord(code)))
|
f"logic error, not reserved code: 0x{ord(code):02x}")
|
||||||
|
|
||||||
|
|
||||||
def _unpack_nil(code, fp, options):
|
def _unpack_nil(code, fp, options):
|
||||||
if code == b'\xc0':
|
if code == b'\xc0':
|
||||||
return None
|
return None
|
||||||
raise Exception("logic error, not nil: 0x{:02x}".format(ord(code)))
|
raise Exception(f"logic error, not nil: 0x{ord(code):02x}")
|
||||||
|
|
||||||
|
|
||||||
def _unpack_boolean(code, fp, options):
|
def _unpack_boolean(code, fp, options):
|
||||||
@ -759,7 +759,7 @@ def _unpack_boolean(code, fp, options):
|
|||||||
return False
|
return False
|
||||||
elif code == b'\xc3':
|
elif code == b'\xc3':
|
||||||
return True
|
return True
|
||||||
raise Exception("logic error, not boolean: 0x{:02x}".format(ord(code)))
|
raise Exception(f"logic error, not boolean: 0x{ord(code):02x}")
|
||||||
|
|
||||||
|
|
||||||
def _unpack_float(code, fp, options):
|
def _unpack_float(code, fp, options):
|
||||||
@ -767,7 +767,7 @@ def _unpack_float(code, fp, options):
|
|||||||
return struct.unpack(">f", _read_except(fp, 4))[0]
|
return struct.unpack(">f", _read_except(fp, 4))[0]
|
||||||
elif code == b'\xcb':
|
elif code == b'\xcb':
|
||||||
return struct.unpack(">d", _read_except(fp, 8))[0]
|
return struct.unpack(">d", _read_except(fp, 8))[0]
|
||||||
raise Exception("logic error, not float: 0x{:02x}".format(ord(code)))
|
raise Exception(f"logic error, not float: 0x{ord(code):02x}")
|
||||||
|
|
||||||
|
|
||||||
def _unpack_string(code, fp, options):
|
def _unpack_string(code, fp, options):
|
||||||
@ -780,7 +780,7 @@ def _unpack_string(code, fp, options):
|
|||||||
elif code == b'\xdb':
|
elif code == b'\xdb':
|
||||||
length = struct.unpack(">I", _read_except(fp, 4))[0]
|
length = struct.unpack(">I", _read_except(fp, 4))[0]
|
||||||
else:
|
else:
|
||||||
raise Exception("logic error, not string: 0x{:02x}".format(ord(code)))
|
raise Exception(f"logic error, not string: 0x{ord(code):02x}")
|
||||||
|
|
||||||
# Always return raw bytes in compatibility mode
|
# Always return raw bytes in compatibility mode
|
||||||
global compatibility
|
global compatibility
|
||||||
@ -804,7 +804,7 @@ def _unpack_binary(code, fp, options):
|
|||||||
elif code == b'\xc6':
|
elif code == b'\xc6':
|
||||||
length = struct.unpack(">I", _read_except(fp, 4))[0]
|
length = struct.unpack(">I", _read_except(fp, 4))[0]
|
||||||
else:
|
else:
|
||||||
raise Exception("logic error, not binary: 0x{:02x}".format(ord(code)))
|
raise Exception(f"logic error, not binary: 0x{ord(code):02x}")
|
||||||
|
|
||||||
return _read_except(fp, length)
|
return _read_except(fp, length)
|
||||||
|
|
||||||
@ -827,7 +827,7 @@ def _unpack_ext(code, fp, options):
|
|||||||
elif code == b'\xc9':
|
elif code == b'\xc9':
|
||||||
length = struct.unpack(">I", _read_except(fp, 4))[0]
|
length = struct.unpack(">I", _read_except(fp, 4))[0]
|
||||||
else:
|
else:
|
||||||
raise Exception("logic error, not ext: 0x{:02x}".format(ord(code)))
|
raise Exception(f"logic error, not ext: 0x{ord(code):02x}")
|
||||||
|
|
||||||
ext_type = struct.unpack("b", _read_except(fp, 1))[0]
|
ext_type = struct.unpack("b", _read_except(fp, 1))[0]
|
||||||
ext_data = _read_except(fp, length)
|
ext_data = _read_except(fp, length)
|
||||||
@ -842,7 +842,7 @@ def _unpack_ext(code, fp, options):
|
|||||||
try:
|
try:
|
||||||
return _ext_type_to_class[ext_type].unpackb(ext_data)
|
return _ext_type_to_class[ext_type].unpackb(ext_data)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise NotImplementedError("Ext serializable class {:s} is missing implementation of unpackb()".format(repr(_ext_type_to_class[ext_type])))
|
raise NotImplementedError(f"Ext serializable class {_ext_type_to_class[ext_type]!r} is missing implementation of unpackb()")
|
||||||
|
|
||||||
# Timestamp extension
|
# Timestamp extension
|
||||||
if ext_type == -1:
|
if ext_type == -1:
|
||||||
@ -868,7 +868,7 @@ def _unpack_ext_timestamp(ext_data, options):
|
|||||||
microseconds = struct.unpack(">I", ext_data[0:4])[0] // 1000
|
microseconds = struct.unpack(">I", ext_data[0:4])[0] // 1000
|
||||||
else:
|
else:
|
||||||
raise UnsupportedTimestampException(
|
raise UnsupportedTimestampException(
|
||||||
"unsupported timestamp with data length {:d}".format(len(ext_data)))
|
f"unsupported timestamp with data length {len(ext_data)}")
|
||||||
|
|
||||||
return _epoch + datetime.timedelta(seconds=seconds,
|
return _epoch + datetime.timedelta(seconds=seconds,
|
||||||
microseconds=microseconds)
|
microseconds=microseconds)
|
||||||
@ -882,10 +882,10 @@ def _unpack_array(code, fp, options):
|
|||||||
elif code == b'\xdd':
|
elif code == b'\xdd':
|
||||||
length = struct.unpack(">I", _read_except(fp, 4))[0]
|
length = struct.unpack(">I", _read_except(fp, 4))[0]
|
||||||
else:
|
else:
|
||||||
raise Exception("logic error, not array: 0x{:02x}".format(ord(code)))
|
raise Exception(f"logic error, not array: 0x{ord(code):02x}")
|
||||||
|
|
||||||
if options.get('use_tuple'):
|
if options.get('use_tuple'):
|
||||||
return tuple((_unpack(fp, options) for i in xrange(length)))
|
return tuple(_unpack(fp, options) for i in xrange(length))
|
||||||
|
|
||||||
return [_unpack(fp, options) for i in xrange(length)]
|
return [_unpack(fp, options) for i in xrange(length)]
|
||||||
|
|
||||||
@ -904,7 +904,7 @@ def _unpack_map(code, fp, options):
|
|||||||
elif code == b'\xdf':
|
elif code == b'\xdf':
|
||||||
length = struct.unpack(">I", _read_except(fp, 4))[0]
|
length = struct.unpack(">I", _read_except(fp, 4))[0]
|
||||||
else:
|
else:
|
||||||
raise Exception("logic error, not map: 0x{:02x}".format(ord(code)))
|
raise Exception(f"logic error, not map: 0x{ord(code):02x}")
|
||||||
|
|
||||||
d = {} if not options.get('use_ordered_dict') else collections.OrderedDict()
|
d = {} if not options.get('use_ordered_dict') else collections.OrderedDict()
|
||||||
for _ in xrange(length):
|
for _ in xrange(length):
|
||||||
@ -916,10 +916,10 @@ def _unpack_map(code, fp, options):
|
|||||||
k = _deep_list_to_tuple(k)
|
k = _deep_list_to_tuple(k)
|
||||||
elif not isinstance(k, Hashable):
|
elif not isinstance(k, Hashable):
|
||||||
raise UnhashableKeyException(
|
raise UnhashableKeyException(
|
||||||
"encountered unhashable key: \"{:s}\" ({:s})".format(str(k), str(type(k))))
|
f"encountered unhashable key: \"{k}\" ({type(k)})")
|
||||||
elif k in d:
|
elif k in d:
|
||||||
raise DuplicateKeyException(
|
raise DuplicateKeyException(
|
||||||
"encountered duplicate key: \"{:s}\" ({:s})".format(str(k), str(type(k))))
|
f"encountered duplicate key: \"{k}\" ({type(k)})")
|
||||||
|
|
||||||
# Unpack value
|
# Unpack value
|
||||||
v = _unpack(fp, options)
|
v = _unpack(fp, options)
|
||||||
@ -928,7 +928,7 @@ def _unpack_map(code, fp, options):
|
|||||||
d[k] = v
|
d[k] = v
|
||||||
except TypeError:
|
except TypeError:
|
||||||
raise UnhashableKeyException(
|
raise UnhashableKeyException(
|
||||||
"encountered unhashable key: \"{:s}\"".format(str(k)))
|
f"encountered unhashable key: \"{k}\"")
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,12 +13,12 @@ project = 'Reticulum Network Stack'
|
|||||||
copyright = '2023, Mark Qvist'
|
copyright = '2023, Mark Qvist'
|
||||||
author = 'Mark Qvist'
|
author = 'Mark Qvist'
|
||||||
|
|
||||||
exec(open("../../RNS/_version.py", "r").read())
|
exec(open("../../RNS/_version.py").read())
|
||||||
version = __version__
|
version = __version__
|
||||||
|
|
||||||
# The full version, including alpha/beta/rc tags
|
# The full version, including alpha/beta/rc tags
|
||||||
import RNS
|
import RNS
|
||||||
release = RNS._version.__version__+" beta"
|
release = f"{RNS._version.__version__} beta"
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
extensions = [
|
extensions = [
|
||||||
|
6
setup.py
6
setup.py
@ -9,14 +9,14 @@ if '--pure' in sys.argv:
|
|||||||
sys.argv.remove('--pure')
|
sys.argv.remove('--pure')
|
||||||
print("Building pure-python wheel")
|
print("Building pure-python wheel")
|
||||||
|
|
||||||
exec(open("RNS/_version.py", "r").read())
|
exec(open("RNS/_version.py").read())
|
||||||
with open("README.md", "r") as fh:
|
with open("README.md") as fh:
|
||||||
long_description = fh.read()
|
long_description = fh.read()
|
||||||
|
|
||||||
if pure_python:
|
if pure_python:
|
||||||
pkg_name = "rnspure"
|
pkg_name = "rnspure"
|
||||||
requirements = []
|
requirements = []
|
||||||
long_description = long_description.replace("</p>", "</p>"+pure_notice)
|
long_description = long_description.replace("</p>", f"</p>{pure_notice}")
|
||||||
else:
|
else:
|
||||||
pkg_name = "rns"
|
pkg_name = "rns"
|
||||||
requirements = ['cryptography>=3.4.7', 'pyserial>=3.5']
|
requirements = ['cryptography>=3.4.7', 'pyserial>=3.5']
|
||||||
|
@ -145,7 +145,7 @@ class SystemMessage(MessageBase):
|
|||||||
MSGTYPE = 0xf000
|
MSGTYPE = 0xf000
|
||||||
|
|
||||||
def pack(self) -> bytes:
|
def pack(self) -> bytes:
|
||||||
return bytes()
|
return b''
|
||||||
|
|
||||||
def unpack(self, raw):
|
def unpack(self, raw):
|
||||||
pass
|
pass
|
||||||
@ -160,7 +160,7 @@ class ProtocolHarness(contextlib.AbstractContextManager):
|
|||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
self.channel._shutdown()
|
self.channel._shutdown()
|
||||||
|
|
||||||
def __exit__(self, __exc_type: typing.Type[BaseException], __exc_value: BaseException,
|
def __exit__(self, __exc_type: type[BaseException], __exc_value: BaseException,
|
||||||
__traceback: types.TracebackType) -> bool:
|
__traceback: types.TracebackType) -> bool:
|
||||||
# self._log.debug(f"__exit__({__exc_type}, {__exc_value}, {__traceback})")
|
# self._log.debug(f"__exit__({__exc_type}, {__exc_value}, {__traceback})")
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
@ -431,7 +431,7 @@ class TestChannel(unittest.TestCase):
|
|||||||
self.assertEqual(len(data), count)
|
self.assertEqual(len(data), count)
|
||||||
|
|
||||||
read_finished = False
|
read_finished = False
|
||||||
result = bytes()
|
result = b''
|
||||||
|
|
||||||
def read_thread():
|
def read_thread():
|
||||||
nonlocal read_finished, result
|
nonlocal read_finished, result
|
||||||
|
@ -11,22 +11,22 @@ class TestSHA256(unittest.TestCase):
|
|||||||
|
|
||||||
def test_empty(self):
|
def test_empty(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.f(''.encode("utf-8")),
|
self.f(b''),
|
||||||
bytes.fromhex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"))
|
bytes.fromhex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"))
|
||||||
|
|
||||||
def test_less_than_block_length(self):
|
def test_less_than_block_length(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.f('abc'.encode("utf-8")),
|
self.f(b'abc'),
|
||||||
bytes.fromhex("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"))
|
bytes.fromhex("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"))
|
||||||
|
|
||||||
def test_block_length(self):
|
def test_block_length(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.f('a'.encode("utf-8")*64),
|
self.f(b'a'*64),
|
||||||
bytes.fromhex("ffe054fe7ae0cb6dc65c3af9b61d5209f439851db43d0ba5997337df154668eb"))
|
bytes.fromhex("ffe054fe7ae0cb6dc65c3af9b61d5209f439851db43d0ba5997337df154668eb"))
|
||||||
|
|
||||||
def test_several_blocks(self):
|
def test_several_blocks(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.f('a'.encode("utf-8")*1000000),
|
self.f(b'a'*1000000),
|
||||||
bytes.fromhex("cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"))
|
bytes.fromhex("cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"))
|
||||||
|
|
||||||
def test_random_blocks(self):
|
def test_random_blocks(self):
|
||||||
@ -49,10 +49,10 @@ class TestSHA256(unittest.TestCase):
|
|||||||
if (i%1000 == 0):
|
if (i%1000 == 0):
|
||||||
gbytes = round(b/1000000000,3)
|
gbytes = round(b/1000000000,3)
|
||||||
mbps = round((b*8/1000000)/(time.time()-start), 2)
|
mbps = round((b*8/1000000)/(time.time()-start), 2)
|
||||||
print(str(i)+" rounds OK, total data: "+str(gbytes)+"GB, "+str(mbps)+"mbps")
|
print(f"{i} rounds OK, total data: {gbytes}GB, {mbps}mbps")
|
||||||
|
|
||||||
if not ok:
|
if not ok:
|
||||||
print("Failed at round "+str(i))
|
print(f"Failed at round {i}")
|
||||||
else:
|
else:
|
||||||
print("SHA-256 test OK")
|
print("SHA-256 test OK")
|
||||||
|
|
||||||
@ -65,25 +65,25 @@ class TestSHA512(unittest.TestCase):
|
|||||||
|
|
||||||
def test_empty(self):
|
def test_empty(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.f(''.encode("utf-8")),
|
self.f(b''),
|
||||||
bytes.fromhex(
|
bytes.fromhex(
|
||||||
'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce'+
|
'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce'+
|
||||||
'47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e'))
|
'47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e'))
|
||||||
|
|
||||||
def test_less_than_block_length(self):
|
def test_less_than_block_length(self):
|
||||||
self.assertEqual(self.f('abc'.encode("utf-8")),
|
self.assertEqual(self.f(b'abc'),
|
||||||
bytes.fromhex(
|
bytes.fromhex(
|
||||||
'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a'+
|
'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a'+
|
||||||
'2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f'))
|
'2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f'))
|
||||||
|
|
||||||
def test_block_length(self):
|
def test_block_length(self):
|
||||||
self.assertEqual(self.f('a'.encode("utf-8")*128),
|
self.assertEqual(self.f(b'a'*128),
|
||||||
bytes.fromhex(
|
bytes.fromhex(
|
||||||
'b73d1929aa615934e61a871596b3f3b33359f42b8175602e89f7e06e5f658a24'+
|
'b73d1929aa615934e61a871596b3f3b33359f42b8175602e89f7e06e5f658a24'+
|
||||||
'3667807ed300314b95cacdd579f3e33abdfbe351909519a846d465c59582f321'))
|
'3667807ed300314b95cacdd579f3e33abdfbe351909519a846d465c59582f321'))
|
||||||
|
|
||||||
def test_several_blocks(self):
|
def test_several_blocks(self):
|
||||||
self.assertEqual(self.f('a'.encode("utf-8")*1000000),
|
self.assertEqual(self.f(b'a'*1000000),
|
||||||
bytes.fromhex(
|
bytes.fromhex(
|
||||||
'e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb'+
|
'e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb'+
|
||||||
'de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b'))
|
'de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b'))
|
||||||
@ -108,10 +108,10 @@ class TestSHA512(unittest.TestCase):
|
|||||||
if (i%1000 == 0):
|
if (i%1000 == 0):
|
||||||
gbytes = round(b/1000000000,3)
|
gbytes = round(b/1000000000,3)
|
||||||
mbps = round((b*8/1000000)/(time.time()-start), 2)
|
mbps = round((b*8/1000000)/(time.time()-start), 2)
|
||||||
print(str(i)+" rounds OK, total data: "+str(gbytes)+"GB, "+str(mbps)+"mbps")
|
print(f"{i} rounds OK, total data: {gbytes}GB, {mbps}mbps")
|
||||||
|
|
||||||
if not ok:
|
if not ok:
|
||||||
print("Failed at round "+str(i))
|
print(f"Failed at round {i}")
|
||||||
else:
|
else:
|
||||||
print("SHA-512 test OK")
|
print("SHA-512 test OK")
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@ class TestIdentity(unittest.TestCase):
|
|||||||
tmdev = tmax - tmin
|
tmdev = tmax - tmin
|
||||||
mpct = (tmax/tmed)*100
|
mpct = (tmax/tmed)*100
|
||||||
print("Random messages:")
|
print("Random messages:")
|
||||||
print(" Signature timing min/avg/med/max/mdev: "+str(round(tmin, 3))+"/"+str(round(tmean, 3))+"/"+str(round(tmed, 3))+"/"+str(round(tmax, 3))+"/"+str(round(tmdev, 3)))
|
print(f" Signature timing min/avg/med/max/mdev: {round(tmin, 3)}/{round(tmean, 3)}/{round(tmed, 3)}/{round(tmax, 3)}/{round(tmdev, 3)}")
|
||||||
print(" Max deviation from median: "+str(round(mpct, 1))+"%")
|
print(f" Max deviation from median: {round(mpct, 1)}%")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
id1 = RNS.Identity()
|
id1 = RNS.Identity()
|
||||||
@ -85,8 +85,8 @@ class TestIdentity(unittest.TestCase):
|
|||||||
tmdev = tmax - tmin
|
tmdev = tmax - tmin
|
||||||
mpct = (tmax/tmed)*100
|
mpct = (tmax/tmed)*100
|
||||||
print("All 0xff messages:")
|
print("All 0xff messages:")
|
||||||
print(" Signature timing min/avg/med/max/mdev: "+str(round(tmin, 3))+"/"+str(round(tmean, 3))+"/"+str(round(tmed, 3))+"/"+str(round(tmax, 3))+"/"+str(round(tmdev, 3)))
|
print(f" Signature timing min/avg/med/max/mdev: {round(tmin, 3)}/{round(tmean, 3)}/{round(tmed, 3)}/{round(tmax, 3)}/{round(tmdev, 3)}")
|
||||||
print(" Max deviation from median: "+str(round(mpct, 1))+"%")
|
print(f" Max deviation from median: {round(mpct, 1)}%")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
id1 = RNS.Identity()
|
id1 = RNS.Identity()
|
||||||
@ -108,8 +108,8 @@ class TestIdentity(unittest.TestCase):
|
|||||||
tmdev = tmax - tmin
|
tmdev = tmax - tmin
|
||||||
mpct = (tmax/tmed)*100
|
mpct = (tmax/tmed)*100
|
||||||
print("All 0x00 messages:")
|
print("All 0x00 messages:")
|
||||||
print(" Signature timing min/avg/med/max/mdev: "+str(round(tmin, 3))+"/"+str(round(tmean, 3))+"/"+str(round(tmed, 3))+"/"+str(round(tmax, 3))+"/"+str(round(tmdev, 3)))
|
print(f" Signature timing min/avg/med/max/mdev: {round(tmin, 3)}/{round(tmean, 3)}/{round(tmed, 3)}/{round(tmax, 3)}/{round(tmdev, 3)}")
|
||||||
print(" Max deviation from median: "+str(round(mpct, 1))+"%")
|
print(f" Max deviation from median: {round(mpct, 1)}%")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
b = 0
|
b = 0
|
||||||
@ -127,7 +127,7 @@ class TestIdentity(unittest.TestCase):
|
|||||||
self.assertEqual(True, id2.validate(signature, msg))
|
self.assertEqual(True, id2.validate(signature, msg))
|
||||||
t += time.time() - start
|
t += time.time() - start
|
||||||
|
|
||||||
print("Sign/validate chunks < MTU: "+self.size_str(b/t, "b")+"ps")
|
print(f"Sign/validate chunks < MTU: {self.size_str(b / t, 'b')}ps")
|
||||||
|
|
||||||
for i in range(1, 500):
|
for i in range(1, 500):
|
||||||
mlen = 16*1024
|
mlen = 16*1024
|
||||||
@ -142,7 +142,7 @@ class TestIdentity(unittest.TestCase):
|
|||||||
self.assertEqual(True, id2.validate(signature, msg))
|
self.assertEqual(True, id2.validate(signature, msg))
|
||||||
t += time.time() - start
|
t += time.time() - start
|
||||||
|
|
||||||
print("Sign/validate 16KB chunks: "+self.size_str(b/t, "b")+"ps")
|
print(f"Sign/validate 16KB chunks: {self.size_str(b / t, 'b')}ps")
|
||||||
|
|
||||||
|
|
||||||
def test_2_encrypt(self):
|
def test_2_encrypt(self):
|
||||||
@ -176,8 +176,8 @@ class TestIdentity(unittest.TestCase):
|
|||||||
self.assertEqual(msg, decrypted)
|
self.assertEqual(msg, decrypted)
|
||||||
d_t += time.time() - d_start
|
d_t += time.time() - d_start
|
||||||
|
|
||||||
print("Encrypt chunks < MTU: "+self.size_str(b/e_t, "b")+"ps")
|
print(f"Encrypt chunks < MTU: {self.size_str(b / e_t, 'b')}ps")
|
||||||
print("Decrypt chunks < MTU: "+self.size_str(b/d_t, "b")+"ps")
|
print(f"Decrypt chunks < MTU: {self.size_str(b / d_t, 'b')}ps")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
# Test encrypt and decrypt of large chunks
|
# Test encrypt and decrypt of large chunks
|
||||||
@ -203,8 +203,8 @@ class TestIdentity(unittest.TestCase):
|
|||||||
self.assertEqual(msg, id1.decrypt(token))
|
self.assertEqual(msg, id1.decrypt(token))
|
||||||
d_t += time.time() - d_start
|
d_t += time.time() - d_start
|
||||||
|
|
||||||
print("Encrypt "+self.size_str(mlen)+" chunks: "+self.size_str(b/e_t, "b")+"ps")
|
print(f"Encrypt {self.size_str(mlen)} chunks: {self.size_str(b / e_t, 'b')}ps")
|
||||||
print("Decrypt "+self.size_str(mlen)+" chunks: "+self.size_str(b/d_t, "b")+"ps")
|
print(f"Decrypt {self.size_str(mlen)} chunks: {self.size_str(b / d_t, 'b')}ps")
|
||||||
|
|
||||||
def size_str(self, num, suffix='B'):
|
def size_str(self, num, suffix='B'):
|
||||||
units = ['','K','M','G','T','P','E','Z']
|
units = ['','K','M','G','T','P','E','Z']
|
||||||
@ -218,12 +218,12 @@ class TestIdentity(unittest.TestCase):
|
|||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1000.0:
|
if abs(num) < 1000.0:
|
||||||
if unit == "":
|
if unit == "":
|
||||||
return "%.0f %s%s" % (num, unit, suffix)
|
return f"{num:.0f} {unit}{suffix}"
|
||||||
else:
|
else:
|
||||||
return "%.2f %s%s" % (num, unit, suffix)
|
return f"{num:.2f} {unit}{suffix}"
|
||||||
num /= 1000.0
|
num /= 1000.0
|
||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return f"{num:.2f}{last_unit}{suffix}"
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(verbosity=2)
|
unittest.main(verbosity=2)
|
||||||
|
@ -28,7 +28,7 @@ BUFFER_TEST_TARGET = 32000
|
|||||||
|
|
||||||
def targets_job(caller):
|
def targets_job(caller):
|
||||||
cmd = "python -c \"from tests.link import targets; targets()\""
|
cmd = "python -c \"from tests.link import targets; targets()\""
|
||||||
print("Opening subprocess for "+str(cmd)+"...", RNS.LOG_VERBOSE)
|
print(f"Opening subprocess for {cmd}...", RNS.LOG_VERBOSE)
|
||||||
ppath = os.getcwd()
|
ppath = os.getcwd()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -144,7 +144,7 @@ class TestLink(unittest.TestCase):
|
|||||||
|
|
||||||
packet_size = RNS.Link.MDU
|
packet_size = RNS.Link.MDU
|
||||||
pstart = time.time()
|
pstart = time.time()
|
||||||
print("Sending "+str(num_packets)+" link packets of "+str(packet_size)+" bytes...")
|
print(f"Sending {num_packets} link packets of {packet_size} bytes...")
|
||||||
for i in range(0, num_packets):
|
for i in range(0, num_packets):
|
||||||
time.sleep(0.003)
|
time.sleep(0.003)
|
||||||
b += packet_size
|
b += packet_size
|
||||||
@ -154,7 +154,7 @@ class TestLink(unittest.TestCase):
|
|||||||
receipts.append(p.send())
|
receipts.append(p.send())
|
||||||
pr_t += time.time() - start
|
pr_t += time.time() - start
|
||||||
|
|
||||||
print("Sent "+self.size_str(b)+", "+self.size_str(b/pr_t, "b")+"ps")
|
print(f"Sent {self.size_str(b)}, {self.size_str(b / pr_t, 'b')}ps")
|
||||||
print("Checking receipts...", end=" ")
|
print("Checking receipts...", end=" ")
|
||||||
|
|
||||||
all_ok = False
|
all_ok = False
|
||||||
@ -175,11 +175,11 @@ class TestLink(unittest.TestCase):
|
|||||||
|
|
||||||
if n_failed > 0:
|
if n_failed > 0:
|
||||||
ns = "s" if n_failed != 1 else ""
|
ns = "s" if n_failed != 1 else ""
|
||||||
print("Failed to receive proof for "+str(n_failed)+" packet"+ns)
|
print(f"Failed to receive proof for {n_failed} packet{ns}")
|
||||||
|
|
||||||
self.assertEqual(all_ok, True)
|
self.assertEqual(all_ok, True)
|
||||||
print("OK!")
|
print("OK!")
|
||||||
print("Single packet and proof round-trip throughput is "+self.size_str(b/pduration, "b")+"ps")
|
print(f"Single packet and proof round-trip throughput is {self.size_str(b / pduration, 'b')}ps")
|
||||||
|
|
||||||
l1.teardown()
|
l1.teardown()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
@ -209,7 +209,7 @@ class TestLink(unittest.TestCase):
|
|||||||
resource_timeout = 120
|
resource_timeout = 120
|
||||||
resource_size = 128
|
resource_size = 128
|
||||||
data = os.urandom(resource_size)
|
data = os.urandom(resource_size)
|
||||||
print("Sending "+self.size_str(resource_size)+" resource...")
|
print(f"Sending {self.size_str(resource_size)} resource...")
|
||||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ class TestLink(unittest.TestCase):
|
|||||||
|
|
||||||
t = time.time() - start
|
t = time.time() - start
|
||||||
self.assertEqual(resource.status, RNS.Resource.COMPLETE)
|
self.assertEqual(resource.status, RNS.Resource.COMPLETE)
|
||||||
print("Resource completed at "+self.size_str(resource_size/t, "b")+"ps")
|
print(f"Resource completed at {self.size_str(resource_size / t, 'b')}ps")
|
||||||
|
|
||||||
l1.teardown()
|
l1.teardown()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
@ -249,7 +249,7 @@ class TestLink(unittest.TestCase):
|
|||||||
resource_timeout = 120
|
resource_timeout = 120
|
||||||
resource_size = 256*1000
|
resource_size = 256*1000
|
||||||
data = os.urandom(resource_size)
|
data = os.urandom(resource_size)
|
||||||
print("Sending "+self.size_str(resource_size)+" resource...")
|
print(f"Sending {self.size_str(resource_size)} resource...")
|
||||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
@ -259,7 +259,7 @@ class TestLink(unittest.TestCase):
|
|||||||
|
|
||||||
t = time.time() - start
|
t = time.time() - start
|
||||||
self.assertEqual(resource.status, RNS.Resource.COMPLETE)
|
self.assertEqual(resource.status, RNS.Resource.COMPLETE)
|
||||||
print("Resource completed at "+self.size_str(resource_size/t, "b")+"ps")
|
print(f"Resource completed at {self.size_str(resource_size / t, 'b')}ps")
|
||||||
|
|
||||||
l1.teardown()
|
l1.teardown()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
@ -288,7 +288,7 @@ class TestLink(unittest.TestCase):
|
|||||||
resource_timeout = 120
|
resource_timeout = 120
|
||||||
resource_size = 1000*1000
|
resource_size = 1000*1000
|
||||||
data = os.urandom(resource_size)
|
data = os.urandom(resource_size)
|
||||||
print("Sending "+self.size_str(resource_size)+" resource...")
|
print(f"Sending {self.size_str(resource_size)} resource...")
|
||||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
@ -298,7 +298,7 @@ class TestLink(unittest.TestCase):
|
|||||||
|
|
||||||
t = time.time() - start
|
t = time.time() - start
|
||||||
self.assertEqual(resource.status, RNS.Resource.COMPLETE)
|
self.assertEqual(resource.status, RNS.Resource.COMPLETE)
|
||||||
print("Resource completed at "+self.size_str(resource_size/t, "b")+"ps")
|
print(f"Resource completed at {self.size_str(resource_size / t, 'b')}ps")
|
||||||
|
|
||||||
l1.teardown()
|
l1.teardown()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
@ -332,7 +332,7 @@ class TestLink(unittest.TestCase):
|
|||||||
resource_timeout = 120
|
resource_timeout = 120
|
||||||
resource_size = 5*1000*1000
|
resource_size = 5*1000*1000
|
||||||
data = os.urandom(resource_size)
|
data = os.urandom(resource_size)
|
||||||
print("Sending "+self.size_str(resource_size)+" resource...")
|
print(f"Sending {self.size_str(resource_size)} resource...")
|
||||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
@ -342,7 +342,7 @@ class TestLink(unittest.TestCase):
|
|||||||
|
|
||||||
t = time.time() - start
|
t = time.time() - start
|
||||||
self.assertEqual(resource.status, RNS.Resource.COMPLETE)
|
self.assertEqual(resource.status, RNS.Resource.COMPLETE)
|
||||||
print("Resource completed at "+self.size_str(resource_size/t, "b")+"ps")
|
print(f"Resource completed at {self.size_str(resource_size / t, 'b')}ps")
|
||||||
|
|
||||||
l1.teardown()
|
l1.teardown()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
@ -379,7 +379,7 @@ class TestLink(unittest.TestCase):
|
|||||||
resource_timeout = 120
|
resource_timeout = 120
|
||||||
resource_size = 50*1000*1000
|
resource_size = 50*1000*1000
|
||||||
data = os.urandom(resource_size)
|
data = os.urandom(resource_size)
|
||||||
print("Sending "+self.size_str(resource_size)+" resource...")
|
print(f"Sending {self.size_str(resource_size)} resource...")
|
||||||
resource = RNS.Resource(data, l1, timeout=resource_timeout, callback=self.lr_callback)
|
resource = RNS.Resource(data, l1, timeout=resource_timeout, callback=self.lr_callback)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
@ -389,7 +389,7 @@ class TestLink(unittest.TestCase):
|
|||||||
|
|
||||||
t = time.time() - start
|
t = time.time() - start
|
||||||
self.assertEqual(TestLink.large_resource_status, RNS.Resource.COMPLETE)
|
self.assertEqual(TestLink.large_resource_status, RNS.Resource.COMPLETE)
|
||||||
print("Resource completed at "+self.size_str(resource_size/t, "b")+"ps")
|
print(f"Resource completed at {self.size_str(resource_size / t, 'b')}ps")
|
||||||
|
|
||||||
l1.teardown()
|
l1.teardown()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
@ -478,7 +478,7 @@ class TestLink(unittest.TestCase):
|
|||||||
channel = l1.get_channel()
|
channel = l1.get_channel()
|
||||||
buffer = RNS.Buffer.create_bidirectional_buffer(0, 0, channel, handle_data)
|
buffer = RNS.Buffer.create_bidirectional_buffer(0, 0, channel, handle_data)
|
||||||
|
|
||||||
buffer.write("Hi there".encode("utf-8"))
|
buffer.write(b"Hi there")
|
||||||
buffer.flush()
|
buffer.flush()
|
||||||
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
@ -508,7 +508,7 @@ class TestLink(unittest.TestCase):
|
|||||||
if local_bitrate is not None:
|
if local_bitrate is not None:
|
||||||
local_interface.bitrate = local_bitrate
|
local_interface.bitrate = local_bitrate
|
||||||
local_interface._force_bitrate = True
|
local_interface._force_bitrate = True
|
||||||
print("Forcing local bitrate of " + str(local_bitrate) + " bps (" + str(round(local_bitrate/8, 0)) + " B/s)")
|
print(f"Forcing local bitrate of {local_bitrate} bps ({round(local_bitrate / 8, 0)} B/s)")
|
||||||
|
|
||||||
# TODO: Load this from public bytes only
|
# TODO: Load this from public bytes only
|
||||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||||
@ -525,7 +525,7 @@ class TestLink(unittest.TestCase):
|
|||||||
# delay a reasonable time for link to come up at current bitrate
|
# delay a reasonable time for link to come up at current bitrate
|
||||||
link_sleep = max(RNS.Link.MDU * 3 / local_interface.bitrate * 8, 2)
|
link_sleep = max(RNS.Link.MDU * 3 / local_interface.bitrate * 8, 2)
|
||||||
timeout_at = time.time() + link_sleep
|
timeout_at = time.time() + link_sleep
|
||||||
print("Waiting " + str(round(link_sleep, 1)) + " sec for link to come up")
|
print(f"Waiting {round(link_sleep, 1)} sec for link to come up")
|
||||||
while l1.status != RNS.Link.ACTIVE and time.time() < timeout_at:
|
while l1.status != RNS.Link.ACTIVE and time.time() < timeout_at:
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
@ -564,14 +564,14 @@ class TestLink(unittest.TestCase):
|
|||||||
expected_rx_message = b""
|
expected_rx_message = b""
|
||||||
for i in range(0, len(message)):
|
for i in range(0, len(message)):
|
||||||
if i > 0 and (i % StreamDataMessage.MAX_DATA_LEN) == 0:
|
if i > 0 and (i % StreamDataMessage.MAX_DATA_LEN) == 0:
|
||||||
expected_rx_message += " back at you".encode("utf-8")
|
expected_rx_message += b" back at you"
|
||||||
expected_rx_message += bytes([message[i]])
|
expected_rx_message += bytes([message[i]])
|
||||||
expected_rx_message += " back at you".encode("utf-8")
|
expected_rx_message += b" back at you"
|
||||||
|
|
||||||
# since the segments will be received at max length for a
|
# since the segments will be received at max length for a
|
||||||
# StreamDataMessage, the appended text will end up in a
|
# StreamDataMessage, the appended text will end up in a
|
||||||
# separate packet.
|
# separate packet.
|
||||||
print("Sending " + str(len(message)) + " bytes, receiving " + str(len(expected_rx_message)) + " bytes, ")
|
print(f"Sending {len(message)} bytes, receiving {len(expected_rx_message)} bytes, ")
|
||||||
|
|
||||||
buffer.write(message)
|
buffer.write(message)
|
||||||
buffer.flush()
|
buffer.flush()
|
||||||
@ -621,12 +621,12 @@ class TestLink(unittest.TestCase):
|
|||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1000.0:
|
if abs(num) < 1000.0:
|
||||||
if unit == "":
|
if unit == "":
|
||||||
return "%.0f %s%s" % (num, unit, suffix)
|
return f"{num:.0f} {unit}{suffix}"
|
||||||
else:
|
else:
|
||||||
return "%.2f %s%s" % (num, unit, suffix)
|
return f"{num:.2f} {unit}{suffix}"
|
||||||
num /= 1000.0
|
num /= 1000.0
|
||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return f"{num:.2f}{last_unit}{suffix}"
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(verbosity=1)
|
unittest.main(verbosity=1)
|
||||||
@ -650,16 +650,16 @@ def targets(yp=False):
|
|||||||
threads = yappi.get_thread_stats()
|
threads = yappi.get_thread_stats()
|
||||||
for thread in threads:
|
for thread in threads:
|
||||||
print(
|
print(
|
||||||
"Function stats for (%s) (%d)" % (thread.name, thread.id)
|
f"Function stats for ({thread.name}) ({int(thread.id)})"
|
||||||
) # it is the Thread.__class__.__name__
|
) # it is the Thread.__class__.__name__
|
||||||
yappi.get_func_stats(ctx_id=thread.id).save("receiver_thread_"+str(thread.id)+".data", type="pstat")
|
yappi.get_func_stats(ctx_id=thread.id).save(f"receiver_thread_{thread.id}.data", type="pstat")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Error: "+str(e))
|
print(f"Error: {e}")
|
||||||
|
|
||||||
|
|
||||||
if hasattr(resource.link.attached_interface, "rxptime"):
|
if hasattr(resource.link.attached_interface, "rxptime"):
|
||||||
rx_pr = (resource.link.attached_interface.rxb*8)/resource.link.attached_interface.rxptime
|
rx_pr = (resource.link.attached_interface.rxb*8)/resource.link.attached_interface.rxptime
|
||||||
print("Average RX proccessing rate: "+size_str(rx_pr, "b")+"ps")
|
print(f"Average RX proccessing rate: {size_str(rx_pr, 'b')}ps")
|
||||||
|
|
||||||
def link_established(link):
|
def link_established(link):
|
||||||
print("Link established")
|
print("Link established")
|
||||||
@ -670,7 +670,7 @@ def targets(yp=False):
|
|||||||
|
|
||||||
def handle_message(message):
|
def handle_message(message):
|
||||||
if isinstance(message, MessageTest):
|
if isinstance(message, MessageTest):
|
||||||
message.data = message.data + " back"
|
message.data = f"{message.data} back"
|
||||||
channel.send(message)
|
channel.send(message)
|
||||||
|
|
||||||
channel.register_message_type(MessageTest)
|
channel.register_message_type(MessageTest)
|
||||||
@ -685,17 +685,17 @@ def targets(yp=False):
|
|||||||
buffer_read_len += len(data)
|
buffer_read_len += len(data)
|
||||||
response_data.append(data)
|
response_data.append(data)
|
||||||
|
|
||||||
if data == "Hi there".encode("utf-8"):
|
if data == b"Hi there":
|
||||||
RNS.log("Sending response")
|
RNS.log("Sending response")
|
||||||
for data in response_data:
|
for data in response_data:
|
||||||
buffer.write(data + " back at you".encode("utf-8"))
|
buffer.write(data + b" back at you")
|
||||||
buffer.flush()
|
buffer.flush()
|
||||||
buffer_read_len = 0
|
buffer_read_len = 0
|
||||||
|
|
||||||
if buffer_read_len == BUFFER_TEST_TARGET:
|
if buffer_read_len == BUFFER_TEST_TARGET:
|
||||||
RNS.log("Sending response")
|
RNS.log("Sending response")
|
||||||
for data in response_data:
|
for data in response_data:
|
||||||
buffer.write(data + " back at you".encode("utf-8"))
|
buffer.write(data + b" back at you")
|
||||||
buffer.flush()
|
buffer.flush()
|
||||||
buffer_read_len = 0
|
buffer_read_len = 0
|
||||||
|
|
||||||
@ -745,7 +745,7 @@ def resource_profiling():
|
|||||||
resource_timeout = 120
|
resource_timeout = 120
|
||||||
resource_size = 5*1000*1000
|
resource_size = 5*1000*1000
|
||||||
data = os.urandom(resource_size)
|
data = os.urandom(resource_size)
|
||||||
print("Sending "+size_str(resource_size)+" resource...")
|
print(f"Sending {size_str(resource_size)} resource...")
|
||||||
|
|
||||||
import yappi
|
import yappi
|
||||||
yappi.start()
|
yappi.start()
|
||||||
@ -759,22 +759,22 @@ def resource_profiling():
|
|||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
t = time.time() - start
|
t = time.time() - start
|
||||||
print("Resource completed at "+size_str(resource_size/t, "b")+"ps")
|
print(f"Resource completed at {size_str(resource_size / t, 'b')}ps")
|
||||||
|
|
||||||
yappi.get_func_stats().save("sender_main_calls.data", type="pstat")
|
yappi.get_func_stats().save("sender_main_calls.data", type="pstat")
|
||||||
threads = yappi.get_thread_stats()
|
threads = yappi.get_thread_stats()
|
||||||
for thread in threads:
|
for thread in threads:
|
||||||
print(
|
print(
|
||||||
"Function stats for (%s) (%d)" % (thread.name, thread.id)
|
f"Function stats for ({thread.name}) ({int(thread.id)})"
|
||||||
) # it is the Thread.__class__.__name__
|
) # it is the Thread.__class__.__name__
|
||||||
yappi.get_func_stats(ctx_id=thread.id).save("sender_thread_"+str(thread.id)+".data", type="pstat")
|
yappi.get_func_stats(ctx_id=thread.id).save(f"sender_thread_{thread.id}.data", type="pstat")
|
||||||
|
|
||||||
# t_pstats = yappi.convert2pstats(tstats)
|
# t_pstats = yappi.convert2pstats(tstats)
|
||||||
# t_pstats.save("resource_tstat.data", type="pstat")
|
# t_pstats.save("resource_tstat.data", type="pstat")
|
||||||
|
|
||||||
if hasattr(resource.link.attached_interface, "rxptime"):
|
if hasattr(resource.link.attached_interface, "rxptime"):
|
||||||
rx_pr = (resource.link.attached_interface.rxb*8)/resource.link.attached_interface.rxptime
|
rx_pr = (resource.link.attached_interface.rxb*8)/resource.link.attached_interface.rxptime
|
||||||
print("Average RX proccessing rate: "+size_str(rx_pr, "b")+"ps")
|
print(f"Average RX proccessing rate: {size_str(rx_pr, 'b')}ps")
|
||||||
|
|
||||||
l1.teardown()
|
l1.teardown()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
@ -791,9 +791,9 @@ def size_str(num, suffix='B'):
|
|||||||
for unit in units:
|
for unit in units:
|
||||||
if abs(num) < 1000.0:
|
if abs(num) < 1000.0:
|
||||||
if unit == "":
|
if unit == "":
|
||||||
return "%.0f %s%s" % (num, unit, suffix)
|
return f"{num:.0f} {unit}{suffix}"
|
||||||
else:
|
else:
|
||||||
return "%.2f %s%s" % (num, unit, suffix)
|
return f"{num:.2f} {unit}{suffix}"
|
||||||
num /= 1000.0
|
num /= 1000.0
|
||||||
|
|
||||||
return "%.2f%s%s" % (num, last_unit, suffix)
|
return f"{num:.2f}{last_unit}{suffix}"
|
Loading…
Reference in New Issue
Block a user