Compare commits

...

17 Commits

Author SHA1 Message Date
Mark Qvist 0c96508cca Updated default config. 2021-08-29 13:48:12 +02:00
Mark Qvist 1fd59f1a02 Fixed resource sequencing fail handling. 2021-08-29 13:46:31 +02:00
Mark Qvist 0a0d0af821 Updated docs. 2021-08-29 13:13:51 +02:00
Mark Qvist b694cbdc91 Improved announce handling for local clients. 2021-08-29 12:43:54 +02:00
Mark Qvist 71c3333e10 Improved announce handling for local clients. 2021-08-29 12:28:30 +02:00
Mark Qvist 972fcdee22 Fixed identity saving. 2021-08-29 01:24:21 +02:00
Mark Qvist 17dbfe6401 Updated speed test example. 2021-08-29 00:13:50 +02:00
Mark Qvist 781cb4712d Fixed request packet receipts timing out in spite of delivery. 2021-08-28 23:53:51 +02:00
Mark Qvist cdb08325cc Fixed timeout calculation condition. 2021-08-28 20:34:41 +02:00
Mark Qvist 62d954d7bf Fixed timeout calculation condition. 2021-08-28 20:21:50 +02:00
Mark Qvist 4bbf1ae57d Updated docs 2021-08-28 20:10:00 +02:00
Mark Qvist 2678aeb6a1 Improved timeout calculation and handling. 2021-08-28 20:01:01 +02:00
Mark Qvist 6d441dac02 Better resource advertisement timeout. 2021-08-28 14:41:25 +02:00
Mark Qvist 66b2be87f4 Added speedtest example. 2021-08-27 22:59:34 +02:00
Mark Qvist 2e7126ef39 Cleaned up log statements 2021-08-27 22:51:16 +02:00
Mark Qvist c0f909850b Updated docs. 2021-08-27 19:54:57 +02:00
Mark Qvist a199e4c929 Improved link and resource callbacks and resource handling. 2021-08-27 19:52:48 +02:00
25 changed files with 673 additions and 170 deletions
+337
View File
@@ -0,0 +1,337 @@
##########################################################
# This RNS example demonstrates a simple speedtest #
# program to measure link throughput. #
##########################################################
import os
import sys
import time
import argparse
import RNS
# Let's define an app name. We'll use this for all
# destinations we create.
APP_NAME = "example_utilities"
##########################################################
#### Server Part #########################################
##########################################################
latest_client_link = None
first_packet_at = None
last_packet_at = None
received_data = 0
rc = 0
data_cap = 2*1024*1024
printed = False
# This initialisation is executed when the users chooses
# to run as a server
def server(configpath):
# We must first initialise Reticulum
reticulum = RNS.Reticulum(configpath)
# Randomly create a new identity for our link example
server_identity = RNS.Identity()
# We create a destination that clients can connect to. We
# want clients to create links to this destination, so we
# need to create a "single" destination type.
server_destination = RNS.Destination(
server_identity,
RNS.Destination.IN,
RNS.Destination.SINGLE,
APP_NAME,
"speedtest"
)
# We configure a function that will get called every time
# a new client creates a link to this destination.
server_destination.set_link_established_callback(client_connected)
# Everything's ready!
# Let's Wait for client requests or user input
server_loop(server_destination)
def server_loop(destination):
# Let the user know that everything is ready
RNS.log(
"Speedtest "+
RNS.prettyhexrep(destination.hash)+
" running, waiting for a connection."
)
RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)")
# We enter a loop that runs until the users exits.
# If the user hits enter, we will announce our server
# destination on the network, which will let clients
# know how to create messages directed towards it.
while True:
entered = input()
destination.announce()
RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash))
# When a client establishes a link to our server
# destination, this function will be called with
# a reference to the link.
def client_connected(link):
global latest_client_link, first_packet_at, rc
RNS.log("Client connected")
first_packet_at = time.time()
rc = 0
link.set_link_closed_callback(client_disconnected)
link.set_packet_callback(server_packet_received)
latest_client_link = link
def client_disconnected(link):
RNS.log("Client disconnected")
# A convenience function for printing a human-
# readable file size
def size_str(num, suffix='B'):
units = ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']
last_unit = 'Yi'
if suffix == 'b':
num *= 8
units = ['','K','M','G','T','P','E','Z']
last_unit = 'Y'
for unit in units:
if abs(num) < 1024.0:
return "%3.2f %s%s" % (num, unit, suffix)
num /= 1024.0
return "%.2f %s%s" % (num, last_unit, suffix)
def server_packet_received(message, packet):
global latest_client_link, first_packet_at, last_packet_at, received_data, rc, data_cap
received_data += len(packet.data)
rc += 1
if rc >= 50:
RNS.log(size_str(received_data))
rc = 0
if received_data > data_cap:
rcv_d = received_data
received_data = 0
rc = 0
last_packet_at = time.time()
# Print statistics
download_time = last_packet_at-first_packet_at
hours, rem = divmod(download_time, 3600)
minutes, seconds = divmod(rem, 60)
timestring = "{:0>2}:{:0>2}:{:05.2f}".format(int(hours),int(minutes),seconds)
print("")
print("")
print("--- Statistics -----")
print("\tTime taken : "+timestring)
print("\tData transferred : "+size_str(rcv_d))
print("\tTransfer rate : "+size_str(rcv_d/download_time, suffix='b')+"/s")
print("")
sys.stdout.flush()
latest_client_link.teardown()
time.sleep(0.2)
rc = 0
received_data = 0
# latest_client_link.teardown()
# os._exit(0)
##########################################################
#### Client Part #########################################
##########################################################
# A reference to the server link
server_link = None
# This initialisation is executed when the users chooses
# to run as a client
def client(destination_hexhash, configpath):
# We need a binary representation of the destination
# hash that was entered on the command line
try:
if len(destination_hexhash) != 20:
raise ValueError("Destination length is invalid, must be 20 hexadecimal characters (10 bytes)")
destination_hash = bytes.fromhex(destination_hexhash)
except:
RNS.log("Invalid destination entered. Check your input!\n")
exit()
# We must first initialise Reticulum
reticulum = RNS.Reticulum(configpath)
# Check if we know a path to the destination
if not RNS.Transport.has_path(destination_hash):
RNS.log("Destination is not yet known. Requesting path and waiting for announce to arrive...")
RNS.Transport.request_path(destination_hash)
while not RNS.Transport.has_path(destination_hash):
time.sleep(0.1)
# Recall the server identity
server_identity = RNS.Identity.recall(destination_hash)
# Inform the user that we'll begin connecting
RNS.log("Establishing link with server...")
# When the server identity is known, we set
# up a destination
server_destination = RNS.Destination(
server_identity,
RNS.Destination.OUT,
RNS.Destination.SINGLE,
APP_NAME,
"speedtest"
)
# And create a link
link = RNS.Link(server_destination)
# We'll also set up functions to inform the
# user when the link is established or closed
link.set_link_established_callback(link_established)
link.set_link_closed_callback(link_closed)
# Everything is set up, so let's enter a loop
# for the user to interact with the example
client_loop()
def client_loop():
global server_link
# Wait for the link to become active
while not server_link:
time.sleep(0.1)
should_quit = False
while not should_quit:
try:
text = input()
# Check if we should quit the example
if text == "quit" or text == "q" or text == "exit":
should_quit = True
server_link.teardown()
except Exception as e:
raise e
# This function is called when a link
# has been established with the server
def link_established(link):
# We store a reference to the link
# instance for later use
global server_link, data_cap, printed
server_link = link
data_sent = 0
# Inform the user that the server is
# connected
RNS.log("Link established with server,sending...")
rd = os.urandom(RNS.Link.MDU)
started = time.time()
while link.status == RNS.Link.ACTIVE and data_sent < data_cap*1.25:
RNS.Packet(server_link, rd, create_receipt=False).send()
data_sent += len(rd)
if data_sent > data_cap and not printed:
printed = True
ended = time.time()
# Print statistics
download_time = ended-started
hours, rem = divmod(download_time, 3600)
minutes, seconds = divmod(rem, 60)
timestring = "{:0>2}:{:0>2}:{:05.2f}".format(int(hours),int(minutes),seconds)
print("")
print("")
print("--- Statistics -----")
print("\tTime taken : "+timestring)
print("\tData transferred : "+size_str(data_sent))
print("\tTransfer rate : "+size_str(data_sent/download_time, suffix='b')+"/s")
print("")
sys.stdout.flush()
time.sleep(0.1)
# When a link is closed, we'll inform the
# user, and exit the program
def link_closed(link):
if link.teardown_reason == RNS.Link.TIMEOUT:
RNS.log("The link timed out, exiting now")
elif link.teardown_reason == RNS.Link.DESTINATION_CLOSED:
RNS.log("The link was closed by the server, exiting now")
else:
RNS.log("Link closed, exiting now")
RNS.Reticulum.exit_handler()
time.sleep(1.5)
os._exit(0)
def client_packet_received(message, packet):
pass
##########################################################
#### Program Startup #####################################
##########################################################
# This part of the program runs at startup,
# and parses input of from the user, and then
# starts up the desired program mode.
if __name__ == "__main__":
try:
parser = argparse.ArgumentParser(description="Speedtest example")
parser.add_argument(
"-s",
"--server",
action="store_true",
help="wait for incoming requests from clients"
)
parser.add_argument(
"--config",
action="store",
default=None,
help="path to alternative Reticulum config directory",
type=str
)
parser.add_argument(
"destination",
nargs="?",
default=None,
help="hexadecimal hash of the server destination",
type=str
)
args = parser.parse_args()
if args.config:
configarg = args.config
else:
configarg = None
if args.server:
server(configarg)
else:
if (args.destination == None):
print("")
parser.print_help()
print("")
else:
client(args.destination, configarg)
except KeyboardInterrupt:
print("")
exit()
+1 -1
View File
@@ -22,7 +22,7 @@ class Destination:
encrypted communication with it. encrypted communication with it.
:param identity: An instance of :ref:`RNS.Identity<api-identity>`. Can hold only public keys for an outgoing destination, or holding private keys for an ingoing. :param identity: An instance of :ref:`RNS.Identity<api-identity>`. Can hold only public keys for an outgoing destination, or holding private keys for an ingoing.
:param direction: ``RNS.Destination.IN`` or ``RNS.Destination.OUT`` :param direction: ``RNS.Destination.IN`` or ``RNS.Destination.OUT``.
:param type: ``RNS.Destination.SINGLE``, ``RNS.Destination.GROUP`` or ``RNS.Destination.PLAIN``. :param type: ``RNS.Destination.SINGLE``, ``RNS.Destination.GROUP`` or ``RNS.Destination.PLAIN``.
:param app_name: A string specifying the app name. :param app_name: A string specifying the app name.
:param \*aspects: Any non-zero number of string arguments. :param \*aspects: Any non-zero number of string arguments.
+18 -24
View File
@@ -64,16 +64,13 @@ class Identity:
:param destination_hash: Destination hash as *bytes*. :param destination_hash: Destination hash as *bytes*.
:returns: An :ref:`RNS.Identity<api-identity>` instance that can be used to create an outgoing :ref:`RNS.Destination<api-destination>`, or *None* if the destination is unknown. :returns: An :ref:`RNS.Identity<api-identity>` instance that can be used to create an outgoing :ref:`RNS.Destination<api-destination>`, or *None* if the destination is unknown.
""" """
RNS.log("Searching for "+RNS.prettyhexrep(destination_hash)+"...", RNS.LOG_EXTREME)
if destination_hash in Identity.known_destinations: if destination_hash in Identity.known_destinations:
identity_data = Identity.known_destinations[destination_hash] identity_data = Identity.known_destinations[destination_hash]
identity = Identity(create_keys=False) identity = Identity(create_keys=False)
identity.load_public_key(identity_data[2]) identity.load_public_key(identity_data[2])
identity.app_data = identity_data[3] identity.app_data = identity_data[3]
RNS.log("Found "+RNS.prettyhexrep(destination_hash)+" in known destinations", RNS.LOG_EXTREME)
return identity return identity
else: else:
RNS.log("Could not find "+RNS.prettyhexrep(destination_hash)+" in known destinations", RNS.LOG_EXTREME)
return None return None
@staticmethod @staticmethod
@@ -84,13 +81,10 @@ class Identity:
:param destination_hash: Destination hash as *bytes*. :param destination_hash: Destination hash as *bytes*.
:returns: *Bytes* containing app_data, or *None* if the destination is unknown. :returns: *Bytes* containing app_data, or *None* if the destination is unknown.
""" """
RNS.log("Searching for app_data for "+RNS.prettyhexrep(destination_hash)+"...", RNS.LOG_EXTREME)
if destination_hash in Identity.known_destinations: if destination_hash in Identity.known_destinations:
app_data = Identity.known_destinations[destination_hash][3] app_data = Identity.known_destinations[destination_hash][3]
RNS.log("Found "+RNS.prettyhexrep(destination_hash)+" app_data in known destinations", RNS.LOG_EXTREME)
return app_data return app_data
else: else:
RNS.log("Could not find "+RNS.prettyhexrep(destination_hash)+" app_data in known destinations", RNS.LOG_EXTREME)
return None return None
@staticmethod @staticmethod
@@ -197,6 +191,24 @@ class Identity:
else: else:
return None return None
def to_file(self, path):
"""
Saves the identity to a file. This will write the private key to disk,
and anyone with access to this file will be able to decrypt all
communication for the identity. Be very careful with this method.
:param path: The full path specifying where to save the identity.
:returns: True if the file was saved, otherwise False.
"""
try:
with open(path, "wb") as key_file:
key_file.write(self.get_private_key())
return True
return False
except Exception as e:
RNS.log("Error while saving identity to "+str(path), RNS.LOG_ERROR)
RNS.log("The contained exception was: "+str(e))
@staticmethod @staticmethod
def from_bytes(prv_bytes): def from_bytes(prv_bytes):
""" """
@@ -331,24 +343,6 @@ class Identity:
self.hash = Identity.truncated_hash(self.get_public_key()) self.hash = Identity.truncated_hash(self.get_public_key())
self.hexhash = self.hash.hex() self.hexhash = self.hash.hex()
def to_file(self, path):
"""
Saves the identity to a file. This will write the private key to disk,
and anyone with access to this file will be able to decrypt all
communication for the identity. Be very careful with this method.
:param path: The full path specifying where to save the identity.
:returns: True if the file was saved, otherwise False.
"""
try:
with open(path, "wb") as key_file:
key_file.write(self.get_public_key())
return True
return False
except Exception as e:
RNS.log("Error while saving identity to "+str(path), RNS.LOG_ERROR)
RNS.log("The contained exception was: "+str(e))
def load(self, path): def load(self, path):
try: try:
with open(path, "rb") as key_file: with open(path, "rb") as key_file:
-1
View File
@@ -224,7 +224,6 @@ class AX25KISSInterface(Interface):
kiss_frame = bytes([KISS.FEND])+bytes([0x00])+data+bytes([KISS.FEND]) kiss_frame = bytes([KISS.FEND])+bytes([0x00])+data+bytes([KISS.FEND])
if (self.txdelay > 0): if (self.txdelay > 0):
RNS.log(str(self.name)+" delaying TX for "+str(self.txdelay)+" seconds", RNS.LOG_EXTREME)
sleep(self.txdelay) sleep(self.txdelay)
written = self.serial.write(kiss_frame) written = self.serial.write(kiss_frame)
+106 -28
View File
@@ -30,6 +30,8 @@ class Link:
This class. This class.
:param destination: A :ref:`RNS.Destination<api-destination>` instance which to establish a link to. :param destination: A :ref:`RNS.Destination<api-destination>` instance which to establish a link to.
:param established_callback: A function or method with the signature *callback(link)* to be called when the link has been established.
:param closed_callback: A function or method with the signature *callback(link)* to be called when the link is closed.
:param owner: Internal use by :ref:`RNS.Transport<api-Transport>`, ignore this argument. :param owner: Internal use by :ref:`RNS.Transport<api-Transport>`, ignore this argument.
:param peer_pub_bytes: Internal use, ignore this argument. :param peer_pub_bytes: Internal use, ignore this argument.
:param peer_sig_pub_bytes: Internal use, ignore this argument. :param peer_sig_pub_bytes: Internal use, ignore this argument.
@@ -44,14 +46,15 @@ class Link:
MDU = math.floor((RNS.Reticulum.MDU-RNS.Identity.AES_HMAC_OVERHEAD)/RNS.Identity.AES128_BLOCKSIZE)*RNS.Identity.AES128_BLOCKSIZE - 1 MDU = math.floor((RNS.Reticulum.MDU-RNS.Identity.AES_HMAC_OVERHEAD)/RNS.Identity.AES128_BLOCKSIZE)*RNS.Identity.AES128_BLOCKSIZE - 1
# TODO: This should not be hardcoded, # This value is set at a reasonable
# but calculated from something like # level for a 1 Kb/s channel.
# first-hop RTT latency and distance ESTABLISHMENT_TIMEOUT_PER_HOP = 3
DEFAULT_TIMEOUT = 15.0
""" """
Default timeout for link establishment in seconds. Default timeout for link establishment in seconds per hop to destination.
""" """
TIMEOUT_FACTOR = 3
TRAFFIC_TIMEOUT_FACTOR = 20
KEEPALIVE_TIMEOUT_FACTOR = 4
STALE_GRACE = 2 STALE_GRACE = 2
KEEPALIVE = 360 KEEPALIVE = 360
""" """
@@ -80,6 +83,7 @@ class Link:
link = Link(owner = owner, peer_pub_bytes=data[:Link.ECPUBSIZE//2], peer_sig_pub_bytes=data[Link.ECPUBSIZE//2:Link.ECPUBSIZE]) link = Link(owner = owner, peer_pub_bytes=data[:Link.ECPUBSIZE//2], peer_sig_pub_bytes=data[Link.ECPUBSIZE//2:Link.ECPUBSIZE])
link.set_link_id(packet) link.set_link_id(packet)
link.destination = packet.destination link.destination = packet.destination
link.establishment_timeout = Link.ESTABLISHMENT_TIMEOUT_PER_HOP * max(1, packet.hops)
RNS.log("Validating link request "+RNS.prettyhexrep(link.link_id), RNS.LOG_VERBOSE) RNS.log("Validating link request "+RNS.prettyhexrep(link.link_id), RNS.LOG_VERBOSE)
link.handshake() link.handshake()
link.attached_interface = packet.receiving_interface link.attached_interface = packet.receiving_interface
@@ -102,7 +106,7 @@ class Link:
return None return None
def __init__(self, destination=None, owner=None, peer_pub_bytes = None, peer_sig_pub_bytes = None): def __init__(self, destination=None, established_callback = None, closed_callback = None, owner=None, peer_pub_bytes = None, peer_sig_pub_bytes = None):
if destination != None and destination.type != RNS.Destination.SINGLE: if destination != None and destination.type != RNS.Destination.SINGLE:
raise TypeError("Links can only be established to the \"single\" destination type") raise TypeError("Links can only be established to the \"single\" destination type")
self.rtt = None self.rtt = None
@@ -117,9 +121,8 @@ class Link:
self.rx = 0 self.rx = 0
self.txbytes = 0 self.txbytes = 0
self.rxbytes = 0 self.rxbytes = 0
self.default_timeout = Link.DEFAULT_TIMEOUT self.traffic_timeout_factor = Link.TRAFFIC_TIMEOUT_FACTOR
self.proof_timeout = self.default_timeout self.keepalive_timeout_factor = Link.KEEPALIVE_TIMEOUT_FACTOR
self.timeout_factor = Link.TIMEOUT_FACTOR
self.keepalive = Link.KEEPALIVE self.keepalive = Link.KEEPALIVE
self.watchdog_lock = False self.watchdog_lock = False
self.status = Link.PENDING self.status = Link.PENDING
@@ -135,6 +138,7 @@ class Link:
self.sig_prv = self.owner.identity.sig_prv self.sig_prv = self.owner.identity.sig_prv
else: else:
self.initiator = True self.initiator = True
self.establishment_timeout = Link.ESTABLISHMENT_TIMEOUT_PER_HOP * max(1, RNS.Transport.hops_to(destination.hash))
self.prv = X25519PrivateKey.generate() self.prv = X25519PrivateKey.generate()
self.sig_prv = Ed25519PrivateKey.generate() self.sig_prv = Ed25519PrivateKey.generate()
@@ -158,6 +162,12 @@ class Link:
else: else:
self.load_peer(peer_pub_bytes, peer_sig_pub_bytes) self.load_peer(peer_pub_bytes, peer_sig_pub_bytes)
if established_callback != None:
self.set_link_established_callback(established_callback)
if closed_callback != None:
self.set_link_closed_callback(closed_callback)
if (self.initiator): if (self.initiator):
peer_pub_bytes = self.destination.identity.get_public_key()[:Link.ECPUBSIZE//2] peer_pub_bytes = self.destination.identity.get_public_key()[:Link.ECPUBSIZE//2]
peer_sig_pub_bytes = self.destination.identity.get_public_key()[Link.ECPUBSIZE//2:Link.ECPUBSIZE] peer_sig_pub_bytes = self.destination.identity.get_public_key()[Link.ECPUBSIZE//2:Link.ECPUBSIZE]
@@ -234,7 +244,6 @@ class Link:
RNS.log("Link "+str(self)+" established with "+str(self.destination)+", RTT is "+str(self.rtt), RNS.LOG_VERBOSE) RNS.log("Link "+str(self)+" established with "+str(self.destination)+", RTT is "+str(self.rtt), RNS.LOG_VERBOSE)
rtt_data = umsgpack.packb(self.rtt) rtt_data = umsgpack.packb(self.rtt)
rtt_packet = RNS.Packet(self, rtt_data, context=RNS.Packet.LRRTT) rtt_packet = RNS.Packet(self, rtt_data, context=RNS.Packet.LRRTT)
RNS.log("Sending RTT packet", RNS.LOG_EXTREME);
rtt_packet.send() rtt_packet.send()
self.had_outbound() self.had_outbound()
@@ -266,38 +275,50 @@ class Link:
self.had_outbound() self.had_outbound()
def request(self, path, data = None, response_callback = None, failed_callback = None): def request(self, path, data = None, response_callback = None, failed_callback = None, progress_callback = None, timeout = None):
""" """
Sends a request to the remote peer. Sends a request to the remote peer.
:param path: The request path. :param path: The request path.
:param response_callback: A function or method with the signature *response_callback(request_receipt)* to be called when a response is received. See the :ref:`Request Example<example-request>` for more info. :param response_callback: An optional function or method with the signature *response_callback(request_receipt)* to be called when a response is received. See the :ref:`Request Example<example-request>` for more info.
:param failed_callback: A function or method with the signature *failed_callback(request_receipt)* to be called when a request fails. See the :ref:`Request Example<example-request>` for more info. :param failed_callback: An optional function or method with the signature *failed_callback(request_receipt)* to be called when a request fails. See the :ref:`Request Example<example-request>` for more info.
:param progress_callback: An optional function or method with the signature *progress_callback(request_receipt)* to be called when progress is made receiving the response. Progress can be accessed as a float between 0.0 and 1.0 by the *request_receipt.progress* property.
:param timeout: An optional timeout in seconds for the request. If *None* is supplied it will be calculated based on link RTT.
""" """
request_path_hash = RNS.Identity.truncated_hash(path.encode("utf-8")) request_path_hash = RNS.Identity.truncated_hash(path.encode("utf-8"))
unpacked_request = [time.time(), request_path_hash, data] unpacked_request = [time.time(), request_path_hash, data]
packed_request = umsgpack.packb(unpacked_request) packed_request = umsgpack.packb(unpacked_request)
if timeout == None:
timeout = self.rtt * self.traffic_timeout_factor
if len(packed_request) <= Link.MDU: if len(packed_request) <= Link.MDU:
request_packet = RNS.Packet(self, packed_request, RNS.Packet.DATA, context = RNS.Packet.REQUEST) request_packet = RNS.Packet(self, packed_request, RNS.Packet.DATA, context = RNS.Packet.REQUEST)
packet_receipt = request_packet.send()
packet_receipt.set_timeout(timeout)
return RequestReceipt( return RequestReceipt(
self, self,
packet_receipt = request_packet.send(), packet_receipt = packet_receipt,
response_callback = response_callback, response_callback = response_callback,
failed_callback = failed_callback failed_callback = failed_callback,
progress_callback = progress_callback,
timeout = timeout
) )
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("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) request_resource = RNS.Resource(packed_request, self, request_id = request_id, is_response = False, timeout = timeout)
return RequestReceipt( return RequestReceipt(
self, self,
resource = request_resource, resource = request_resource,
response_callback = response_callback, response_callback = response_callback,
failed_callback = failed_callback failed_callback = failed_callback,
progress_callback = progress_callback,
timeout = timeout
) )
@@ -411,9 +432,9 @@ class Link:
# Link was initiated, but no response # Link was initiated, but no response
# from destination yet # from destination yet
if self.status == Link.PENDING: if self.status == Link.PENDING:
next_check = self.request_time + self.proof_timeout next_check = self.request_time + self.establishment_timeout
sleep_time = next_check - time.time() sleep_time = next_check - time.time()
if time.time() >= self.request_time + self.proof_timeout: if time.time() >= self.request_time + self.establishment_timeout:
RNS.log("Link establishment timed out", RNS.LOG_VERBOSE) RNS.log("Link establishment timed out", RNS.LOG_VERBOSE)
self.status = Link.CLOSED self.status = Link.CLOSED
self.teardown_reason = Link.TIMEOUT self.teardown_reason = Link.TIMEOUT
@@ -421,9 +442,9 @@ class Link:
sleep_time = 0.001 sleep_time = 0.001
elif self.status == Link.HANDSHAKE: elif self.status == Link.HANDSHAKE:
next_check = self.request_time + self.proof_timeout next_check = self.request_time + self.establishment_timeout
sleep_time = next_check - time.time() sleep_time = next_check - time.time()
if time.time() >= self.request_time + self.proof_timeout: if time.time() >= self.request_time + self.establishment_timeout:
RNS.log("Timeout waiting for RTT packet from link initiator", RNS.LOG_DEBUG) RNS.log("Timeout waiting for RTT packet from link initiator", RNS.LOG_DEBUG)
self.status = Link.CLOSED self.status = Link.CLOSED
self.teardown_reason = Link.TIMEOUT self.teardown_reason = Link.TIMEOUT
@@ -432,7 +453,7 @@ class Link:
elif self.status == Link.ACTIVE: elif self.status == Link.ACTIVE:
if time.time() >= self.last_inbound + self.keepalive: if time.time() >= self.last_inbound + self.keepalive:
sleep_time = self.rtt * self.timeout_factor + Link.STALE_GRACE sleep_time = self.rtt * self.keepalive_timeout_factor + Link.STALE_GRACE
self.status = Link.STALE self.status = Link.STALE
if self.initiator: if self.initiator:
self.send_keepalive() self.send_keepalive()
@@ -606,7 +627,13 @@ class Link:
if RNS.ResourceAdvertisement.is_request(packet): if RNS.ResourceAdvertisement.is_request(packet):
RNS.Resource.accept(packet, callback=self.request_resource_concluded) RNS.Resource.accept(packet, callback=self.request_resource_concluded)
elif RNS.ResourceAdvertisement.is_response(packet): elif RNS.ResourceAdvertisement.is_response(packet):
RNS.Resource.accept(packet, callback=self.response_resource_concluded) request_id = RNS.ResourceAdvertisement.get_request_id(packet)
for pending_request in self.pending_requests:
if pending_request.request_id == request_id:
RNS.Resource.accept(packet, callback=self.response_resource_concluded, progress_callback=pending_request.response_resource_progress)
pending_request.response_size = RNS.ResourceAdvertisement.get_size(packet)
pending_request.response_transfer_size = RNS.ResourceAdvertisement.get_transfer_size(packet)
pending_request.started_at = time.time()
elif self.resource_strategy == Link.ACCEPT_NONE: elif self.resource_strategy == Link.ACCEPT_NONE:
pass pass
elif self.resource_strategy == Link.ACCEPT_APP: elif self.resource_strategy == Link.ACCEPT_APP:
@@ -676,6 +703,7 @@ class Link:
return ciphertext return ciphertext
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("Encryption on link "+str(self)+" failed. The contained exception was: "+str(e), RNS.LOG_ERROR)
raise e
def decrypt(self, ciphertext): def decrypt(self, ciphertext):
@@ -690,8 +718,8 @@ class Link:
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("Decryption failed on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
RNS.log(traceback.format_exc(), RNS.LOG_ERROR) RNS.log(traceback.format_exc(), RNS.LOG_ERROR)
# TODO: Do we really need to do this? Or can we recover somehow? # TODO: Think long about implications here
self.teardown() # self.teardown()
def sign(self, message): def sign(self, message):
@@ -831,13 +859,15 @@ class RequestReceipt():
DELIVERED = 0x02 DELIVERED = 0x02
READY = 0x03 READY = 0x03
def __init__(self, link, packet_receipt = None, resource = None, response_callback = None, failed_callback = None): def __init__(self, link, packet_receipt = None, resource = None, response_callback = None, failed_callback = None, progress_callback = None, timeout = None):
self.packet_receipt = packet_receipt self.packet_receipt = packet_receipt
self.resource = resource self.resource = resource
self.started_at = None
if self.packet_receipt != None: if self.packet_receipt != None:
self.hash = packet_receipt.truncated_hash self.hash = packet_receipt.truncated_hash
self.packet_receipt.set_timeout_callback(self.request_timed_out) self.packet_receipt.set_timeout_callback(self.request_timed_out)
self.started_at = time.time()
elif self.resource != None: elif self.resource != None:
self.hash = resource.request_id self.hash = resource.request_id
@@ -847,20 +877,36 @@ class RequestReceipt():
self.request_id = self.hash self.request_id = self.hash
self.response = None self.response = None
self.response_transfer_size = None
self.response_size = None
self.status = RequestReceipt.SENT self.status = RequestReceipt.SENT
self.sent_at = time.time() self.sent_at = time.time()
self.timeout = RNS.Packet.TIMEOUT self.progress = 0
self.concluded_at = None self.concluded_at = None
self.response_concluded_at = None
if timeout != None:
self.timeout = timeout
else:
raise ValueError("No timeout specified for request receipt")
self.callbacks = RequestReceiptCallbacks() self.callbacks = RequestReceiptCallbacks()
self.callbacks.response = response_callback self.callbacks.response = response_callback
self.callbacks.failed = failed_callback self.callbacks.failed = failed_callback
self.callbacks.progress = progress_callback
self.link.pending_requests.append(self) self.link.pending_requests.append(self)
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("Request "+RNS.prettyhexrep(self.request_id)+" successfully sent as resource.", RNS.LOG_DEBUG)
self.started_at = time.time()
self.status = RequestReceipt.DELIVERED
self.__resource_response_timeout = time.time()+self.timeout
load_thread = threading.Thread(target=self.__resource_response_timeout_job)
load_thread.setDaemon(True)
load_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("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
@@ -870,6 +916,7 @@ class RequestReceipt():
if self.callbacks.failed != None: if self.callbacks.failed != None:
self.callbacks.failed(self) self.callbacks.failed(self)
def request_timed_out(self, packet_receipt): def request_timed_out(self, packet_receipt):
self.status = RequestReceipt.FAILED self.status = RequestReceipt.FAILED
self.concluded_at = time.time() self.concluded_at = time.time()
@@ -878,8 +925,30 @@ class RequestReceipt():
if self.callbacks.failed != None: if self.callbacks.failed != None:
self.callbacks.failed(self) self.callbacks.failed(self)
def response_resource_progress(self, resource):
self.progress = resource.progress()
self.__resource_response_timeout = time.time()+self.timeout
if self.callbacks.progress != None:
self.callbacks.progress(self)
def __resource_response_timeout_job(self):
while self.status == RequestReceipt.DELIVERED:
if time.time() > self.__resource_response_timeout:
self.request_timed_out(None)
time.sleep(0.1)
def response_received(self, response): def response_received(self, response):
self.progress = 1.0
self.response = response self.response = response
self.status = RequestReceipt.READY
self.response_concluded_at = time.time()
if len(response) <= Link.MDU:
self.response_size = len(response)
self.response_transfer_size = len(response)
if self.packet_receipt != None: if self.packet_receipt != None:
self.packet_receipt.status = RNS.PacketReceipt.DELIVERED self.packet_receipt.status = RNS.PacketReceipt.DELIVERED
@@ -888,11 +957,20 @@ class RequestReceipt():
if self.packet_receipt.callbacks.delivery != None: if self.packet_receipt.callbacks.delivery != None:
self.packet_receipt.callbacks.delivery(self) self.packet_receipt.callbacks.delivery(self)
if self.callbacks.progress != None:
self.callbacks.progress(self)
if self.callbacks.response != None: if self.callbacks.response != None:
self.callbacks.response(self) self.callbacks.response(self)
def response_time(self):
if self.status == RequestReceipt.READY:
return self.response_concluded_at - self.started_at
class RequestReceiptCallbacks: class RequestReceiptCallbacks:
def __init__(self): def __init__(self):
self.response = None self.response = None
self.failed = None self.failed = None
self.progress = None
+10 -7
View File
@@ -80,10 +80,9 @@ class Packet:
The maximum size of the payload data in a single unencrypted packet The maximum size of the payload data in a single unencrypted packet
""" """
# TODO: This should be calculated # This value is set at a reasonable
# more intelligently # level for a 1 Kb/s channel.
# Default packet timeout TIMEOUT_PER_HOP = 5
TIMEOUT = 60
def __init__(self, destination, data, packet_type = DATA, context = NONE, transport_type = RNS.Transport.BROADCAST, header_type = HEADER_1, transport_id = None, attached_interface = None, create_receipt = True): def __init__(self, destination, data, packet_type = DATA, context = NONE, transport_type = RNS.Transport.BROADCAST, header_type = HEADER_1, transport_id = None, attached_interface = None, create_receipt = True):
if destination != None: if destination != None:
@@ -329,13 +328,18 @@ class PacketReceipt:
self.truncated_hash = packet.getTruncatedHash() self.truncated_hash = packet.getTruncatedHash()
self.sent = True self.sent = True
self.sent_at = time.time() self.sent_at = time.time()
self.timeout = Packet.TIMEOUT
self.proved = False self.proved = False
self.status = PacketReceipt.SENT self.status = PacketReceipt.SENT
self.destination = packet.destination self.destination = packet.destination
self.callbacks = PacketReceiptCallbacks() self.callbacks = PacketReceiptCallbacks()
self.concluded_at = None self.concluded_at = None
if packet.destination.type == RNS.Destination.LINK:
self.timeout = packet.destination.rtt * packet.destination.traffic_timeout_factor
else:
self.timeout = Packet.TIMEOUT_PER_HOP * RNS.Transport.hops_to(self.destination.hash)
def get_status(self): def get_status(self):
""" """
:returns: The status of the associated :ref:`RNS.Packet<api-packet>` instance. Can be one of ``RNS.PacketReceipt.SENT``, ``RNS.PacketReceipt.DELIVERED``, ``RNS.PacketReceipt.FAILED`` or ``RNS.PacketReceipt.CULLED``. :returns: The status of the associated :ref:`RNS.Packet<api-packet>` instance. Can be one of ``RNS.PacketReceipt.SENT``, ``RNS.PacketReceipt.DELIVERED``, ``RNS.PacketReceipt.FAILED`` or ``RNS.PacketReceipt.CULLED``.
@@ -436,7 +440,7 @@ class PacketReceipt:
return (self.sent_at+self.timeout < time.time()) return (self.sent_at+self.timeout < time.time())
def check_timeout(self): def check_timeout(self):
if self.is_timed_out(): if self.status == PacketReceipt.SENT and self.is_timed_out():
if self.timeout == -1: if self.timeout == -1:
self.status = PacketReceipt.CULLED self.status = PacketReceipt.CULLED
else: else:
@@ -448,7 +452,6 @@ class PacketReceipt:
thread = threading.Thread(target=self.callbacks.timeout, args=(self,)) thread = threading.Thread(target=self.callbacks.timeout, args=(self,))
thread.setDaemon(True) thread.setDaemon(True)
thread.start() thread.start()
#self.callbacks.timeout(self)
def set_timeout(self, timeout): def set_timeout(self, timeout):
+21 -5
View File
@@ -52,7 +52,6 @@ class Resource:
# TODO: Should be allocated more # TODO: Should be allocated more
# intelligently # intelligently
# TODO: Set higher
MAX_RETRIES = 5 MAX_RETRIES = 5
SENDER_GRACE_TIME = 10 SENDER_GRACE_TIME = 10
RETRY_GRACE_TIME = 0.25 RETRY_GRACE_TIME = 0.25
@@ -136,7 +135,7 @@ class Resource:
# Create a resource for transmission to a remote destination # Create a resource for transmission to a remote destination
# The data passed can be either a bytes-array or a file opened # The data passed can be either a bytes-array or a file opened
# in binary read mode. # in binary read mode.
def __init__(self, data, link, advertise=True, auto_compress=True, callback=None, progress_callback=None, segment_index = 1, original_hash = None, request_id = None, is_response = False): def __init__(self, data, link, advertise=True, auto_compress=True, callback=None, progress_callback=None, timeout = None, segment_index = 1, original_hash = None, request_id = None, is_response = False):
data_size = None data_size = None
resource_data = None resource_data = None
if hasattr(data, "read"): if hasattr(data, "read"):
@@ -183,8 +182,7 @@ class Resource:
self.link = link self.link = link
self.max_retries = Resource.MAX_RETRIES self.max_retries = Resource.MAX_RETRIES
self.retries_left = self.max_retries self.retries_left = self.max_retries
self.default_timeout = self.link.default_timeout self.timeout_factor = self.link.traffic_timeout_factor
self.timeout_factor = self.link.timeout_factor
self.sender_grace_time = Resource.SENDER_GRACE_TIME self.sender_grace_time = Resource.SENDER_GRACE_TIME
self.hmu_retry_ok = False self.hmu_retry_ok = False
self.watchdog_lock = False self.watchdog_lock = False
@@ -196,6 +194,11 @@ class Resource:
self.receiver_min_consecutive_height = 0 self.receiver_min_consecutive_height = 0
if timeout != None:
self.timeout = timeout
else:
self.timeout = self.link.rtt * self.link.traffic_timeout_factor
if data != None: if data != None:
self.initiator = True self.initiator = True
self.callback = callback self.callback = callback
@@ -370,7 +373,7 @@ class Resource:
sleep_time = None sleep_time = None
if self.status == Resource.ADVERTISED: if self.status == Resource.ADVERTISED:
sleep_time = (self.adv_sent+self.default_timeout)-time.time() sleep_time = (self.adv_sent+self.timeout)-time.time()
if sleep_time < 0: if sleep_time < 0:
if self.retries_left <= 0: if self.retries_left <= 0:
RNS.log("Resource transfer timeout after sending advertisement", RNS.LOG_DEBUG) RNS.log("Resource transfer timeout after sending advertisement", RNS.LOG_DEBUG)
@@ -696,6 +699,7 @@ class Resource:
if part_index % ResourceAdvertisement.HASHMAP_MAX_LEN != 0: if part_index % ResourceAdvertisement.HASHMAP_MAX_LEN != 0:
RNS.log("Resource sequencing error, cancelling transfer!", RNS.LOG_ERROR) RNS.log("Resource sequencing error, cancelling transfer!", RNS.LOG_ERROR)
self.cancel() self.cancel()
return
else: else:
segment = part_index // ResourceAdvertisement.HASHMAP_MAX_LEN segment = part_index // ResourceAdvertisement.HASHMAP_MAX_LEN
@@ -804,6 +808,18 @@ class ResourceAdvertisement:
return adv.q return adv.q
@staticmethod
def get_transfer_size(advertisement_packet):
adv = ResourceAdvertisement.unpack(advertisement_packet.plaintext)
return adv.t
@staticmethod
def get_size(advertisement_packet):
adv = ResourceAdvertisement.unpack(advertisement_packet.plaintext)
return adv.d
def __init__(self, resource=None, request_id=None, is_response=False): def __init__(self, resource=None, request_id=None, is_response=False):
if resource != None: if resource != None:
self.t = resource.size # Transfer size self.t = resource.size # Transfer size
+19 -4
View File
@@ -566,14 +566,29 @@ loglevel = 4
type = UDPInterface type = UDPInterface
interface_enabled = True interface_enabled = True
outgoing = True outgoing = True
device = eth0 listen_ip = 0.0.0.0
port = 4242 listen_port = 4242
forward_ip = 255.255.255.255
forward_port = 4242
# The above configuration will allow communication
# within the local broadcast domains of all local
# IP interfaces. This is enabled by default as an
# easy way to get started, but you might want to
# consider altering it to something more specific.
# Instead of specifying listen_ip, listen_port,
# forward_ip and forward_port, you can also bind
# to a specific network device like below.
# device = eth0
# port = 4242
# Assuming the eth0 device has the address # Assuming the eth0 device has the address
# 10.55.0.72/24, the above configuration would # 10.55.0.72/24, the above configuration would
# be equivalent to the following manual setup. # be equivalent to the following manual setup.
# Note that we are both listening and forwarding # Note that we are both listening and forwarding to
# to the network segments broadcast address. # the broadcast address of the network segments.
# listen_ip = 10.55.0.255 # listen_ip = 10.55.0.255
# listen_port = 4242 # listen_port = 4242
+52 -18
View File
@@ -22,7 +22,10 @@ class Transport:
APP_NAME = "rnstransport" APP_NAME = "rnstransport"
PATHFINDER_M = 18 # Max hops PATHFINDER_M = 128 # Max hops
"""
Maximum amount of hops that Reticulum will transport a packet.
"""
PATHFINDER_C = 2.0 # Decay constant PATHFINDER_C = 2.0 # Decay constant
PATHFINDER_R = 1 # Retransmit retries PATHFINDER_R = 1 # Retransmit retries
PATHFINDER_T = 10 # Retry grace period PATHFINDER_T = 10 # Retry grace period
@@ -180,7 +183,7 @@ class Transport:
while len(Transport.receipts) > Transport.MAX_RECEIPTS: while len(Transport.receipts) > Transport.MAX_RECEIPTS:
culled_receipt = Transport.receipts.pop(0) culled_receipt = Transport.receipts.pop(0)
culled_receipt.timeout = -1 culled_receipt.timeout = -1
receipt.check_timeout() culled_receipt.check_timeout()
for receipt in Transport.receipts: for receipt in Transport.receipts:
receipt.check_timeout() receipt.check_timeout()
@@ -246,8 +249,8 @@ class Transport:
# Cull the packet hashlist if it has reached max size # Cull the packet hashlist if it has reached max size
while (len(Transport.packet_hashlist) > Transport.hashlist_maxsize): if len(Transport.packet_hashlist) > Transport.hashlist_maxsize:
Transport.packet_hashlist.pop(0) Transport.packet_hashlist = Transport.packet_hashlist[len(Transport.packet_hashlist)-Transport.hashlist_maxsize:len(Transport.packet_hashlist)-1]
if time.time() > Transport.tables_last_culled + Transport.tables_cull_interval: if time.time() > Transport.tables_last_culled + Transport.tables_cull_interval:
# Cull the reverse table according to timeout # Cull the reverse table according to timeout
@@ -338,8 +341,6 @@ class Transport:
new_raw += packet.raw[1:2] new_raw += packet.raw[1:2]
new_raw += Transport.destination_table[packet.destination_hash][1] new_raw += Transport.destination_table[packet.destination_hash][1]
new_raw += packet.raw[2:] new_raw += packet.raw[2:]
# TODO: Remove at some point
# RNS.log("Packet was inserted into transport via "+RNS.prettyhexrep(Transport.destination_table[packet.destination_hash][1])+" on: "+str(outbound_interface), RNS.LOG_EXTREME)
outbound_interface.processOutgoing(new_raw) outbound_interface.processOutgoing(new_raw)
Transport.destination_table[packet.destination_hash][0] = time.time() Transport.destination_table[packet.destination_hash][0] = time.time()
sent = True sent = True
@@ -359,8 +360,6 @@ class Transport:
new_raw += packet.raw[1:2] new_raw += packet.raw[1:2]
new_raw += Transport.destination_table[packet.destination_hash][1] new_raw += Transport.destination_table[packet.destination_hash][1]
new_raw += packet.raw[2:] new_raw += packet.raw[2:]
# TODO: Remove at some point
# RNS.log("Packet was inserted into transport via "+RNS.prettyhexrep(Transport.destination_table[packet.destination_hash][1])+" on: "+str(outbound_interface), RNS.LOG_EXTREME)
outbound_interface.processOutgoing(new_raw) outbound_interface.processOutgoing(new_raw)
Transport.destination_table[packet.destination_hash][0] = time.time() Transport.destination_table[packet.destination_hash][0] = time.time()
sent = True sent = True
@@ -390,9 +389,6 @@ class Transport:
should_transmit = False should_transmit = False
if should_transmit: if should_transmit:
RNS.log("Transmitting "+str(len(packet.raw))+" bytes on: "+str(interface), RNS.LOG_EXTREME)
RNS.log("Hash is "+RNS.prettyhexrep(packet.packet_hash), RNS.LOG_EXTREME)
if not stored_hash: if not stored_hash:
Transport.packet_hashlist.append(packet.packet_hash) Transport.packet_hashlist.append(packet.packet_hash)
@@ -452,8 +448,7 @@ class Transport:
@staticmethod @staticmethod
def inbound(raw, interface=None): def inbound(raw, interface=None):
while (Transport.jobs_running): while (Transport.jobs_running):
# TODO: Decrease this for performance sleep(0.01)
sleep(0.1)
Transport.jobs_locked = True Transport.jobs_locked = True
@@ -462,8 +457,6 @@ class Transport:
packet.receiving_interface = interface packet.receiving_interface = interface
packet.hops += 1 packet.hops += 1
RNS.log(str(interface)+" received packet with hash "+RNS.prettyhexrep(packet.packet_hash), RNS.LOG_EXTREME)
if len(Transport.local_client_interfaces) > 0: if len(Transport.local_client_interfaces) > 0:
if Transport.is_local_client_interface(interface): if Transport.is_local_client_interface(interface):
@@ -528,11 +521,13 @@ class Transport:
# accordingly if we are. # accordingly if we are.
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("Received packet in transport for "+RNS.prettyhexrep(packet.destination_hash)+" with matching transport ID, transporting it...", RNS.LOG_DEBUG) # TODO: Remove at some point
# RNS.log("Received packet in transport for "+RNS.prettyhexrep(packet.destination_hash)+" with matching transport ID, transporting it...", RNS.LOG_DEBUG)
if packet.destination_hash in Transport.destination_table: if packet.destination_hash in Transport.destination_table:
next_hop = Transport.destination_table[packet.destination_hash][1] next_hop = Transport.destination_table[packet.destination_hash][1]
remaining_hops = Transport.destination_table[packet.destination_hash][2] remaining_hops = Transport.destination_table[packet.destination_hash][2]
RNS.log("Next hop to destination is "+RNS.prettyhexrep(next_hop)+" with "+str(remaining_hops)+" hops remaining, transporting it.", RNS.LOG_DEBUG) # TODO: Remove at some point
# RNS.log("Next hop to destination is "+RNS.prettyhexrep(next_hop)+" with "+str(remaining_hops)+" hops remaining, transporting it.", RNS.LOG_DEBUG)
if remaining_hops > 1: if remaining_hops > 1:
# Just increase hop count and transmit # Just increase hop count and transmit
new_raw = packet.raw[0:1] new_raw = packet.raw[0:1]
@@ -739,6 +734,9 @@ class Transport:
announce_context = RNS.Packet.NONE announce_context = RNS.Packet.NONE
announce_data = packet.data announce_data = packet.data
if Transport.from_local_client(packet) and packet.context == RNS.Packet.PATH_RESPONSE:
for interface in Transport.interfaces:
if packet.receiving_interface != interface:
new_announce = RNS.Packet( new_announce = RNS.Packet(
announce_destination, announce_destination,
announce_data, announce_data,
@@ -747,12 +745,29 @@ class Transport:
header_type = RNS.Packet.HEADER_2, header_type = RNS.Packet.HEADER_2,
transport_type = Transport.TRANSPORT, transport_type = Transport.TRANSPORT,
transport_id = Transport.identity.hash, transport_id = Transport.identity.hash,
attached_interface = attached_interface attached_interface = interface
) )
new_announce.hops = packet.hops new_announce.hops = packet.hops
new_announce.send() new_announce.send()
else:
for local_interface in Transport.local_client_interfaces:
new_announce = RNS.Packet(
announce_destination,
announce_data,
RNS.Packet.ANNOUNCE,
context = announce_context,
header_type = RNS.Packet.HEADER_2,
transport_type = Transport.TRANSPORT,
transport_id = Transport.identity.hash,
attached_interface = local_interface
)
new_announce.hops = packet.hops
new_announce.send()
Transport.destination_table[packet.destination_hash] = [now, received_from, announce_hops, expires, random_blobs, packet.receiving_interface, packet] Transport.destination_table[packet.destination_hash] = [now, received_from, announce_hops, expires, random_blobs, packet.receiving_interface, packet]
RNS.log("Path to "+RNS.prettyhexrep(packet.destination_hash)+" is now "+str(announce_hops)+" hops away via "+RNS.prettyhexrep(received_from)+" on "+str(packet.receiving_interface), RNS.LOG_VERBOSE) RNS.log("Path to "+RNS.prettyhexrep(packet.destination_hash)+" is now "+str(announce_hops)+" hops away via "+RNS.prettyhexrep(received_from)+" on "+str(packet.receiving_interface), RNS.LOG_VERBOSE)
@@ -869,6 +884,9 @@ class Transport:
if receipt.hash == proof_hash: if receipt.hash == proof_hash:
receipt_validated = receipt.validate_proof_packet(packet) receipt_validated = receipt.validate_proof_packet(packet)
else: else:
# TODO: This looks like it should actually
# be rewritten when implicit proofs are added.
# In case of an implicit proof, we have # In case of an implicit proof, we have
# to check every single outstanding receipt # to check every single outstanding receipt
receipt_validated = receipt.validate_proof_packet(packet) receipt_validated = receipt.validate_proof_packet(packet)
@@ -885,8 +903,13 @@ class Transport:
for registered_destination in Transport.destinations: for registered_destination in Transport.destinations:
if destination.hash == registered_destination.hash: if destination.hash == registered_destination.hash:
raise KeyError("Attempt to register an already registered destination.") raise KeyError("Attempt to register an already registered destination.")
Transport.destinations.append(destination) Transport.destinations.append(destination)
if Transport.owner.is_connected_to_shared_instance:
if destination.type == RNS.Destination.SINGLE:
destination.announce(path_response=True)
@staticmethod @staticmethod
def deregister_destination(destination): def deregister_destination(destination):
if destination in Transport.destinations: if destination in Transport.destinations:
@@ -1033,6 +1056,17 @@ class Transport:
else: else:
return False return False
@staticmethod
def hops_to(destination_hash):
"""
:param destination_hash: A destination hash as *bytes*.
:returns: The number of hops to the specified destination, or ``RNS.Transport.PATHFINDER_M`` if the number of hops is unknown.
"""
if destination_hash in Transport.destination_table:
return Transport.destination_table[destination_hash][2]
else:
return Transport.PATHFINDER_M
@staticmethod @staticmethod
def request_path(destination_hash): def request_path(destination_hash):
""" """
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.2.2" __version__ = "0.2.3"
Binary file not shown.
+1 -1
View File
@@ -1,4 +1,4 @@
# Sphinx build info version 1 # Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 966ae7177c1d48c9ee15971994c623b5 config: 75fee65d4971d4f4b61034cb277ccd5b
tags: 645f666f9bcd5a90fca523b33c5a78b7 tags: 645f666f9bcd5a90fca523b33c5a78b7
+1 -1
View File
@@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = { var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '0.2.2 beta', VERSION: '0.2.3 beta',
LANGUAGE: 'None', LANGUAGE: 'None',
COLLAPSE_INDEX: false, COLLAPSE_INDEX: false,
BUILDER: 'html', BUILDER: 'html',
+3 -3
View File
@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Examples &#8212; Reticulum Network Stack 0.2.2 beta documentation</title> <title>Examples &#8212; Reticulum Network Stack 0.2.3 beta documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/classic.css" /> <link rel="stylesheet" type="text/css" href="_static/classic.css" />
@@ -27,7 +27,7 @@
<li class="right" > <li class="right" >
<a href="reference.html" title="API Reference" <a href="reference.html" title="API Reference"
accesskey="P">previous</a> |</li> accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Examples</a></li> <li class="nav-item nav-item-this"><a href="">Examples</a></li>
</ul> </ul>
</div> </div>
@@ -2319,7 +2319,7 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
<li class="right" > <li class="right" >
<a href="reference.html" title="API Reference" <a href="reference.html" title="API Reference"
>previous</a> |</li> >previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Examples</a></li> <li class="nav-item nav-item-this"><a href="">Examples</a></li>
</ul> </ul>
</div> </div>
+12 -8
View File
@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Index &#8212; Reticulum Network Stack 0.2.2 beta documentation</title> <title>Index &#8212; Reticulum Network Stack 0.2.3 beta documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/classic.css" /> <link rel="stylesheet" type="text/css" href="_static/classic.css" />
@@ -23,7 +23,7 @@
<li class="right" style="margin-right: 10px"> <li class="right" style="margin-right: 10px">
<a href="#" title="General Index" <a href="#" title="General Index"
accesskey="I">index</a></li> accesskey="I">index</a></li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Index</a></li> <li class="nav-item nav-item-this"><a href="">Index</a></li>
</ul> </ul>
</div> </div>
@@ -98,12 +98,10 @@
<li><a href="reference.html#RNS.Identity.decrypt">(RNS.Identity method)</a> <li><a href="reference.html#RNS.Identity.decrypt">(RNS.Identity method)</a>
</li> </li>
</ul></li> </ul></li>
<li><a href="reference.html#RNS.Link.DEFAULT_TIMEOUT">DEFAULT_TIMEOUT (RNS.Link attribute)</a> <li><a href="reference.html#RNS.Transport.deregister_announce_handler">deregister_announce_handler() (RNS.Transport static method)</a>
</li> </li>
</ul></td> </ul></td>
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.Transport.deregister_announce_handler">deregister_announce_handler() (RNS.Transport static method)</a>
</li>
<li><a href="reference.html#RNS.Destination.deregister_request_handler">deregister_request_handler() (RNS.Destination method)</a> <li><a href="reference.html#RNS.Destination.deregister_request_handler">deregister_request_handler() (RNS.Destination method)</a>
</li> </li>
<li><a href="reference.html#RNS.Destination">Destination (class in RNS)</a> <li><a href="reference.html#RNS.Destination">Destination (class in RNS)</a>
@@ -125,6 +123,8 @@
</ul></td> </ul></td>
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.Packet.ENCRYPTED_MDU">ENCRYPTED_MDU (RNS.Packet attribute)</a> <li><a href="reference.html#RNS.Packet.ENCRYPTED_MDU">ENCRYPTED_MDU (RNS.Packet attribute)</a>
</li>
<li><a href="reference.html#RNS.Link.ESTABLISHMENT_TIMEOUT_PER_HOP">ESTABLISHMENT_TIMEOUT_PER_HOP (RNS.Link attribute)</a>
</li> </li>
</ul></td> </ul></td>
</tr></table> </tr></table>
@@ -174,11 +174,13 @@
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.Transport.has_path">has_path() (RNS.Transport static method)</a> <li><a href="reference.html#RNS.Transport.has_path">has_path() (RNS.Transport static method)</a>
</li> </li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.Destination.hash">hash() (RNS.Destination static method)</a> <li><a href="reference.html#RNS.Destination.hash">hash() (RNS.Destination static method)</a>
</li> </li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.Destination.hash_from_name_and_identity">hash_from_name_and_identity() (RNS.Destination static method)</a> <li><a href="reference.html#RNS.Destination.hash_from_name_and_identity">hash_from_name_and_identity() (RNS.Destination static method)</a>
</li>
<li><a href="reference.html#RNS.Transport.hops_to">hops_to() (RNS.Transport static method)</a>
</li> </li>
</ul></td> </ul></td>
</tr></table> </tr></table>
@@ -248,6 +250,8 @@
</li> </li>
</ul></td> </ul></td>
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.Transport.PATHFINDER_M">PATHFINDER_M (RNS.Transport attribute)</a>
</li>
<li><a href="reference.html#RNS.Packet.PLAIN_MDU">PLAIN_MDU (RNS.Packet attribute)</a> <li><a href="reference.html#RNS.Packet.PLAIN_MDU">PLAIN_MDU (RNS.Packet attribute)</a>
</li> </li>
<li><a href="reference.html#RNS.Resource.progress">progress() (RNS.Resource method)</a> <li><a href="reference.html#RNS.Resource.progress">progress() (RNS.Resource method)</a>
@@ -387,7 +391,7 @@
<li class="right" style="margin-right: 10px"> <li class="right" style="margin-right: 10px">
<a href="#" title="General Index" <a href="#" title="General Index"
>index</a></li> >index</a></li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Index</a></li> <li class="nav-item nav-item-this"><a href="">Index</a></li>
</ul> </ul>
</div> </div>
+3 -3
View File
@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Getting Started Fast &#8212; Reticulum Network Stack 0.2.2 beta documentation</title> <title>Getting Started Fast &#8212; Reticulum Network Stack 0.2.3 beta documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/classic.css" /> <link rel="stylesheet" type="text/css" href="_static/classic.css" />
@@ -31,7 +31,7 @@
<li class="right" > <li class="right" >
<a href="whatis.html" title="What is Reticulum?" <a href="whatis.html" title="What is Reticulum?"
accesskey="P">previous</a> |</li> accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li> <li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li>
</ul> </ul>
</div> </div>
@@ -166,7 +166,7 @@ dont use pip, but try this recipe:</p>
<li class="right" > <li class="right" >
<a href="whatis.html" title="What is Reticulum?" <a href="whatis.html" title="What is Reticulum?"
>previous</a> |</li> >previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li> <li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li>
</ul> </ul>
</div> </div>
+3 -3
View File
@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Reticulum Network Stack Manual &#8212; Reticulum Network Stack 0.2.2 beta documentation</title> <title>Reticulum Network Stack Manual &#8212; Reticulum Network Stack 0.2.3 beta documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/classic.css" /> <link rel="stylesheet" type="text/css" href="_static/classic.css" />
@@ -27,7 +27,7 @@
<li class="right" > <li class="right" >
<a href="whatis.html" title="What is Reticulum?" <a href="whatis.html" title="What is Reticulum?"
accesskey="N">next</a> |</li> accesskey="N">next</a> |</li>
<li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Manual</a></li> <li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Manual</a></li>
</ul> </ul>
</div> </div>
@@ -167,7 +167,7 @@ the development of Reticulum itself.</p>
<li class="right" > <li class="right" >
<a href="whatis.html" title="What is Reticulum?" <a href="whatis.html" title="What is Reticulum?"
>next</a> |</li> >next</a> |</li>
<li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Manual</a></li> <li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Manual</a></li>
</ul> </ul>
</div> </div>
Binary file not shown.
+52 -29
View File
@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>API Reference &#8212; Reticulum Network Stack 0.2.2 beta documentation</title> <title>API Reference &#8212; Reticulum Network Stack 0.2.3 beta documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/classic.css" /> <link rel="stylesheet" type="text/css" href="_static/classic.css" />
@@ -31,7 +31,7 @@
<li class="right" > <li class="right" >
<a href="understanding.html" title="Understanding Reticulum" <a href="understanding.html" title="Understanding Reticulum"
accesskey="P">previous</a> |</li> accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">API Reference</a></li> <li class="nav-item nav-item-this"><a href="">API Reference</a></li>
</ul> </ul>
</div> </div>
@@ -230,6 +230,22 @@ Can be used to load previously created and saved identities into Reticulum.</p>
</dl> </dl>
</dd></dl> </dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.Identity.to_file">
<span class="sig-name descname"><span class="pre">to_file</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">path</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.to_file" title="Permalink to this definition"></a></dt>
<dd><p>Saves the identity to a file. This will write the private key to disk,
and anyone with access to this file will be able to decrypt all
communication for the identity. Be very careful with this method.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>path</strong> The full path specifying where to save the identity.</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>True if the file was saved, otherwise False.</p>
</dd>
</dl>
</dd></dl>
<dl class="py method"> <dl class="py method">
<dt class="sig sig-object py" id="RNS.Identity.from_bytes"> <dt class="sig sig-object py" id="RNS.Identity.from_bytes">
<em class="property"><span class="pre">static</span> </em><span class="sig-name descname"><span class="pre">from_bytes</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">prv_bytes</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.from_bytes" title="Permalink to this definition"></a></dt> <em class="property"><span class="pre">static</span> </em><span class="sig-name descname"><span class="pre">from_bytes</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">prv_bytes</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.from_bytes" title="Permalink to this definition"></a></dt>
@@ -293,22 +309,6 @@ Can be used to load previously created and saved identities into Reticulum.</p>
</dl> </dl>
</dd></dl> </dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.Identity.to_file">
<span class="sig-name descname"><span class="pre">to_file</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">path</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.to_file" title="Permalink to this definition"></a></dt>
<dd><p>Saves the identity to a file. This will write the private key to disk,
and anyone with access to this file will be able to decrypt all
communication for the identity. Be very careful with this method.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>path</strong> The full path specifying where to save the identity.</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>True if the file was saved, otherwise False.</p>
</dd>
</dl>
</dd></dl>
<dl class="py method"> <dl class="py method">
<dt class="sig sig-object py" id="RNS.Identity.encrypt"> <dt class="sig sig-object py" id="RNS.Identity.encrypt">
<span class="sig-name descname"><span class="pre">encrypt</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">plaintext</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.encrypt" title="Permalink to this definition"></a></dt> <span class="sig-name descname"><span class="pre">encrypt</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">plaintext</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Identity.encrypt" title="Permalink to this definition"></a></dt>
@@ -398,7 +398,7 @@ encrypted communication with it.</p>
<dt class="field-odd">Parameters</dt> <dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple"> <dd class="field-odd"><ul class="simple">
<li><p><strong>identity</strong> An instance of <a class="reference internal" href="#api-identity"><span class="std std-ref">RNS.Identity</span></a>. Can hold only public keys for an outgoing destination, or holding private keys for an ingoing.</p></li> <li><p><strong>identity</strong> An instance of <a class="reference internal" href="#api-identity"><span class="std std-ref">RNS.Identity</span></a>. Can hold only public keys for an outgoing destination, or holding private keys for an ingoing.</p></li>
<li><p><strong>direction</strong> <code class="docutils literal notranslate"><span class="pre">RNS.Destination.IN</span></code> or <code class="docutils literal notranslate"><span class="pre">RNS.Destination.OUT</span></code></p></li> <li><p><strong>direction</strong> <code class="docutils literal notranslate"><span class="pre">RNS.Destination.IN</span></code> or <code class="docutils literal notranslate"><span class="pre">RNS.Destination.OUT</span></code>.</p></li>
<li><p><strong>type</strong> <code class="docutils literal notranslate"><span class="pre">RNS.Destination.SINGLE</span></code>, <code class="docutils literal notranslate"><span class="pre">RNS.Destination.GROUP</span></code> or <code class="docutils literal notranslate"><span class="pre">RNS.Destination.PLAIN</span></code>.</p></li> <li><p><strong>type</strong> <code class="docutils literal notranslate"><span class="pre">RNS.Destination.SINGLE</span></code>, <code class="docutils literal notranslate"><span class="pre">RNS.Destination.GROUP</span></code> or <code class="docutils literal notranslate"><span class="pre">RNS.Destination.PLAIN</span></code>.</p></li>
<li><p><strong>app_name</strong> A string specifying the app name.</p></li> <li><p><strong>app_name</strong> A string specifying the app name.</p></li>
<li><p><strong>*aspects</strong> Any non-zero number of string arguments.</p></li> <li><p><strong>*aspects</strong> Any non-zero number of string arguments.</p></li>
@@ -774,12 +774,14 @@ from a the <em>send()</em> method of a <a class="reference internal" href="#api-
<span id="api-link"></span><h3>Link<a class="headerlink" href="#link" title="Permalink to this headline"></a></h3> <span id="api-link"></span><h3>Link<a class="headerlink" href="#link" title="Permalink to this headline"></a></h3>
<dl class="py class"> <dl class="py class">
<dt class="sig sig-object py" id="RNS.Link"> <dt class="sig sig-object py" id="RNS.Link">
<em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Link</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">destination</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">owner</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">peer_pub_bytes</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">peer_sig_pub_bytes</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link" title="Permalink to this definition"></a></dt> <em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Link</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">destination</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">established_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">closed_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">owner</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">peer_pub_bytes</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">peer_sig_pub_bytes</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link" title="Permalink to this definition"></a></dt>
<dd><p>This class.</p> <dd><p>This class.</p>
<dl class="field-list simple"> <dl class="field-list simple">
<dt class="field-odd">Parameters</dt> <dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple"> <dd class="field-odd"><ul class="simple">
<li><p><strong>destination</strong> A <a class="reference internal" href="#api-destination"><span class="std std-ref">RNS.Destination</span></a> instance which to establish a link to.</p></li> <li><p><strong>destination</strong> A <a class="reference internal" href="#api-destination"><span class="std std-ref">RNS.Destination</span></a> instance which to establish a link to.</p></li>
<li><p><strong>established_callback</strong> A function or method with the signature <em>callback(link)</em> to be called when the link has been established.</p></li>
<li><p><strong>closed_callback</strong> A function or method with the signature <em>callback(link)</em> to be called when the link is closed.</p></li>
<li><p><strong>owner</strong> Internal use by <a class="reference internal" href="#api-transport"><span class="std std-ref">RNS.Transport</span></a>, ignore this argument.</p></li> <li><p><strong>owner</strong> Internal use by <a class="reference internal" href="#api-transport"><span class="std std-ref">RNS.Transport</span></a>, ignore this argument.</p></li>
<li><p><strong>peer_pub_bytes</strong> Internal use, ignore this argument.</p></li> <li><p><strong>peer_pub_bytes</strong> Internal use, ignore this argument.</p></li>
<li><p><strong>peer_sig_pub_bytes</strong> Internal use, ignore this argument.</p></li> <li><p><strong>peer_sig_pub_bytes</strong> Internal use, ignore this argument.</p></li>
@@ -793,9 +795,9 @@ from a the <em>send()</em> method of a <a class="reference internal" href="#api-
</dd></dl> </dd></dl>
<dl class="py attribute"> <dl class="py attribute">
<dt class="sig sig-object py" id="RNS.Link.DEFAULT_TIMEOUT"> <dt class="sig sig-object py" id="RNS.Link.ESTABLISHMENT_TIMEOUT_PER_HOP">
<span class="sig-name descname"><span class="pre">DEFAULT_TIMEOUT</span></span><em class="property"> <span class="pre">=</span> <span class="pre">15.0</span></em><a class="headerlink" href="#RNS.Link.DEFAULT_TIMEOUT" title="Permalink to this definition"></a></dt> <span class="sig-name descname"><span class="pre">ESTABLISHMENT_TIMEOUT_PER_HOP</span></span><em class="property"> <span class="pre">=</span> <span class="pre">3</span></em><a class="headerlink" href="#RNS.Link.ESTABLISHMENT_TIMEOUT_PER_HOP" title="Permalink to this definition"></a></dt>
<dd><p>Default timeout for link establishment in seconds.</p> <dd><p>Default timeout for link establishment in seconds per hop to destination.</p>
</dd></dl> </dd></dl>
<dl class="py attribute"> <dl class="py attribute">
@@ -820,14 +822,16 @@ thus preserved. This method can be used for authentication.</p>
<dl class="py method"> <dl class="py method">
<dt class="sig sig-object py" id="RNS.Link.request"> <dt class="sig sig-object py" id="RNS.Link.request">
<span class="sig-name descname"><span class="pre">request</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">path</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">data</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">response_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">failed_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.request" title="Permalink to this definition"></a></dt> <span class="sig-name descname"><span class="pre">request</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">path</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">data</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">response_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">failed_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">progress_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.request" title="Permalink to this definition"></a></dt>
<dd><p>Sends a request to the remote peer.</p> <dd><p>Sends a request to the remote peer.</p>
<dl class="field-list simple"> <dl class="field-list simple">
<dt class="field-odd">Parameters</dt> <dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple"> <dd class="field-odd"><ul class="simple">
<li><p><strong>path</strong> The request path.</p></li> <li><p><strong>path</strong> The request path.</p></li>
<li><p><strong>response_callback</strong> A function or method with the signature <em>response_callback(request_receipt)</em> to be called when a response is received. See the <a class="reference internal" href="examples.html#example-request"><span class="std std-ref">Request Example</span></a> for more info.</p></li> <li><p><strong>response_callback</strong> An optional function or method with the signature <em>response_callback(request_receipt)</em> to be called when a response is received. See the <a class="reference internal" href="examples.html#example-request"><span class="std std-ref">Request Example</span></a> for more info.</p></li>
<li><p><strong>failed_callback</strong> A function or method with the signature <em>failed_callback(request_receipt)</em> to be called when a request fails. See the <a class="reference internal" href="examples.html#example-request"><span class="std std-ref">Request Example</span></a> for more info.</p></li> <li><p><strong>failed_callback</strong> An optional function or method with the signature <em>failed_callback(request_receipt)</em> to be called when a request fails. See the <a class="reference internal" href="examples.html#example-request"><span class="std std-ref">Request Example</span></a> for more info.</p></li>
<li><p><strong>progress_callback</strong> An optional function or method with the signature <em>progress_callback(request_receipt)</em> to be called when progress is made receiving the response. Progress can be accessed as a float between 0.0 and 1.0 by the <em>request_receipt.progress</em> property.</p></li>
<li><p><strong>timeout</strong> An optional timeout in seconds for the request. If <em>None</em> is supplied it will be calculated based on link RTT.</p></li>
</ul> </ul>
</dd> </dd>
</dl> </dl>
@@ -975,7 +979,7 @@ client application and throw an error message to the user.</p>
<span id="api-resource"></span><h3>Resource<a class="headerlink" href="#resource" title="Permalink to this headline"></a></h3> <span id="api-resource"></span><h3>Resource<a class="headerlink" href="#resource" title="Permalink to this headline"></a></h3>
<dl class="py class"> <dl class="py class">
<dt class="sig sig-object py" id="RNS.Resource"> <dt class="sig sig-object py" id="RNS.Resource">
<em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Resource</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">data</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">link</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">advertise</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">auto_compress</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">progress_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">segment_index</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">original_hash</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">request_id</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">is_response</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Resource" title="Permalink to this definition"></a></dt> <em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Resource</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">data</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">link</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">advertise</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">auto_compress</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">progress_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">segment_index</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">original_hash</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">request_id</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">is_response</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Resource" title="Permalink to this definition"></a></dt>
<dd><p>The Resource class allows transferring arbitrary amounts <dd><p>The Resource class allows transferring arbitrary amounts
of data over a link. It will automatically handle sequencing, of data over a link. It will automatically handle sequencing,
compression, coordination and checksumming.</p> compression, coordination and checksumming.</p>
@@ -1026,7 +1030,13 @@ the resource advertisement it will begin transferring.</p>
<dl class="py class"> <dl class="py class">
<dt class="sig sig-object py" id="RNS.Transport"> <dt class="sig sig-object py" id="RNS.Transport">
<em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Transport</span></span><a class="headerlink" href="#RNS.Transport" title="Permalink to this definition"></a></dt> <em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Transport</span></span><a class="headerlink" href="#RNS.Transport" title="Permalink to this definition"></a></dt>
<dd><dl class="py method"> <dd><dl class="py attribute">
<dt class="sig sig-object py" id="RNS.Transport.PATHFINDER_M">
<span class="sig-name descname"><span class="pre">PATHFINDER_M</span></span><em class="property"> <span class="pre">=</span> <span class="pre">128</span></em><a class="headerlink" href="#RNS.Transport.PATHFINDER_M" title="Permalink to this definition"></a></dt>
<dd><p>Maximum amount of hops that Reticulum will transport a packet.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.Transport.register_announce_handler"> <dt class="sig sig-object py" id="RNS.Transport.register_announce_handler">
<em class="property"><span class="pre">static</span> </em><span class="sig-name descname"><span class="pre">register_announce_handler</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">handler</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Transport.register_announce_handler" title="Permalink to this definition"></a></dt> <em class="property"><span class="pre">static</span> </em><span class="sig-name descname"><span class="pre">register_announce_handler</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">handler</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Transport.register_announce_handler" title="Permalink to this definition"></a></dt>
<dd><p>Registers an announce handler.</p> <dd><p>Registers an announce handler.</p>
@@ -1061,6 +1071,19 @@ the resource advertisement it will begin transferring.</p>
</dl> </dl>
</dd></dl> </dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.Transport.hops_to">
<em class="property"><span class="pre">static</span> </em><span class="sig-name descname"><span class="pre">hops_to</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">destination_hash</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Transport.hops_to" title="Permalink to this definition"></a></dt>
<dd><dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>destination_hash</strong> A destination hash as <em>bytes</em>.</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The number of hops to the specified destination, or <code class="docutils literal notranslate"><span class="pre">RNS.Transport.PATHFINDER_M</span></code> if the number of hops is unknown.</p>
</dd>
</dl>
</dd></dl>
<dl class="py method"> <dl class="py method">
<dt class="sig sig-object py" id="RNS.Transport.request_path"> <dt class="sig sig-object py" id="RNS.Transport.request_path">
<em class="property"><span class="pre">static</span> </em><span class="sig-name descname"><span class="pre">request_path</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">destination_hash</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Transport.request_path" title="Permalink to this definition"></a></dt> <em class="property"><span class="pre">static</span> </em><span class="sig-name descname"><span class="pre">request_path</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">destination_hash</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Transport.request_path" title="Permalink to this definition"></a></dt>
@@ -1144,7 +1167,7 @@ will announce it.</p>
<li class="right" > <li class="right" >
<a href="understanding.html" title="Understanding Reticulum" <a href="understanding.html" title="Understanding Reticulum"
>previous</a> |</li> >previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">API Reference</a></li> <li class="nav-item nav-item-this"><a href="">API Reference</a></li>
</ul> </ul>
</div> </div>
+3 -3
View File
@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Search &#8212; Reticulum Network Stack 0.2.2 beta documentation</title> <title>Search &#8212; Reticulum Network Stack 0.2.3 beta documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/classic.css" /> <link rel="stylesheet" type="text/css" href="_static/classic.css" />
@@ -29,7 +29,7 @@
<li class="right" style="margin-right: 10px"> <li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index" <a href="genindex.html" title="General Index"
accesskey="I">index</a></li> accesskey="I">index</a></li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Search</a></li> <li class="nav-item nav-item-this"><a href="">Search</a></li>
</ul> </ul>
</div> </div>
@@ -85,7 +85,7 @@
<li class="right" style="margin-right: 10px"> <li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index" <a href="genindex.html" title="General Index"
>index</a></li> >index</a></li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Search</a></li> <li class="nav-item nav-item-this"><a href="">Search</a></li>
</ul> </ul>
</div> </div>
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Understanding Reticulum &#8212; Reticulum Network Stack 0.2.2 beta documentation</title> <title>Understanding Reticulum &#8212; Reticulum Network Stack 0.2.3 beta documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/classic.css" /> <link rel="stylesheet" type="text/css" href="_static/classic.css" />
@@ -31,7 +31,7 @@
<li class="right" > <li class="right" >
<a href="gettingstartedfast.html" title="Getting Started Fast" <a href="gettingstartedfast.html" title="Getting Started Fast"
accesskey="P">previous</a> |</li> accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li> <li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li>
</ul> </ul>
</div> </div>
@@ -853,7 +853,7 @@ proof 11
<li class="right" > <li class="right" >
<a href="gettingstartedfast.html" title="Getting Started Fast" <a href="gettingstartedfast.html" title="Getting Started Fast"
>previous</a> |</li> >previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li> <li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li>
</ul> </ul>
</div> </div>
+3 -3
View File
@@ -5,7 +5,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>What is Reticulum? &#8212; Reticulum Network Stack 0.2.2 beta documentation</title> <title>What is Reticulum? &#8212; Reticulum Network Stack 0.2.3 beta documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/classic.css" /> <link rel="stylesheet" type="text/css" href="_static/classic.css" />
@@ -31,7 +31,7 @@
<li class="right" > <li class="right" >
<a href="index.html" title="Reticulum Network Stack Manual" <a href="index.html" title="Reticulum Network Stack Manual"
accesskey="P">previous</a> |</li> accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li> <li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li>
</ul> </ul>
</div> </div>
@@ -182,7 +182,7 @@ network, and vice versa.</p>
<li class="right" > <li class="right" >
<a href="index.html" title="Reticulum Network Stack Manual" <a href="index.html" title="Reticulum Network Stack Manual"
>previous</a> |</li> >previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> &#187;</li> <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.3 beta documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li> <li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li>
</ul> </ul>
</div> </div>
+1 -1
View File
@@ -22,7 +22,7 @@ copyright = '2021, Mark Qvist'
author = 'Mark Qvist' author = 'Mark Qvist'
# The full version, including alpha/beta/rc tags # The full version, including alpha/beta/rc tags
release = '0.2.2 beta' release = '0.2.3 beta'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------
+1 -1
View File
@@ -21,5 +21,5 @@ setuptools.setup(
"Operating System :: OS Independent", "Operating System :: OS Independent",
], ],
install_requires=['cryptography>=3.4.7', 'pyserial', 'netifaces>=0.10.4'], install_requires=['cryptography>=3.4.7', 'pyserial', 'netifaces>=0.10.4'],
python_requires='>=3.5', python_requires='>=3.6',
) )