mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-11-22 13:40:19 +00:00
Compare commits
8 Commits
527f6cc906
...
d63bbcdc0a
Author | SHA1 | Date | |
---|---|---|---|
|
d63bbcdc0a | ||
|
c36c7186de | ||
|
6fec76205c | ||
|
715f4d9fcb | ||
|
8d7857c4e2 | ||
|
c9a2b45368 | ||
|
c57d927660 | ||
|
8d98c8751a |
17
Changelog.md
17
Changelog.md
@ -1,3 +1,20 @@
|
|||||||
|
### 2024-10-10: RNS β 0.8.3
|
||||||
|
|
||||||
|
This release fixes a bug in resource transfer progress calculation, improves RNode error handling, and brings minor improvements to the `rncp` utility.
|
||||||
|
|
||||||
|
**Changes**
|
||||||
|
- Fixed a bug in resource transfer progress calculations
|
||||||
|
- Added physical layer transfer rate output option to `rncp`
|
||||||
|
- Added save directory option to `rncp`
|
||||||
|
- Improved path handling for the fetch-jail option of of `rncp`
|
||||||
|
- Added error detection for modem communication timeouts on connected RNode devices
|
||||||
|
|
||||||
|
**Release Hashes**
|
||||||
|
```
|
||||||
|
54ddab32769081045db5fe45b27492cc012bf2fad64bc65ed37011f3651469fb rns-0.8.3-py3-none-any.whl
|
||||||
|
a04915111d65b05a5f2ef2687ed208813034196c0c5e711cb01e6db72faa23ef rnspure-0.8.3-py3-none-any.whl
|
||||||
|
```
|
||||||
|
|
||||||
### 2024-10-06: RNS β 0.8.2
|
### 2024-10-06: RNS β 0.8.2
|
||||||
|
|
||||||
This release adds several new boards to `rnodeconf`, fixes a range of bugs and improves transport reliability.
|
This release adds several new boards to `rnodeconf`, fixes a range of bugs and improves transport reliability.
|
||||||
|
@ -176,8 +176,8 @@ class LocalClientInterface(Interface):
|
|||||||
self.send_lock = Lock()
|
self.send_lock = Lock()
|
||||||
|
|
||||||
with self.send_lock:
|
with self.send_lock:
|
||||||
|
# RNS.log(f"Simulating latency of {RNS.prettytime(s)} for {len(data)} bytes", RNS.LOG_EXTREME)
|
||||||
s = len(data) / self.bitrate * 8
|
s = len(data) / self.bitrate * 8
|
||||||
RNS.log(f"Simulating latency of {RNS.prettytime(s)} for {len(data)} bytes")
|
|
||||||
time.sleep(s)
|
time.sleep(s)
|
||||||
|
|
||||||
data = bytes([HDLC.FLAG])+HDLC.escape(data)+bytes([HDLC.FLAG])
|
data = bytes([HDLC.FLAG])+HDLC.escape(data)+bytes([HDLC.FLAG])
|
||||||
|
@ -233,7 +233,6 @@ class Resource:
|
|||||||
data_size = os.stat(data.name).st_size
|
data_size = os.stat(data.name).st_size
|
||||||
|
|
||||||
self.total_size = data_size
|
self.total_size = data_size
|
||||||
self.grand_total_parts = math.ceil(data_size/Resource.SDU)
|
|
||||||
|
|
||||||
if data_size <= Resource.MAX_EFFICIENT_SIZE:
|
if data_size <= Resource.MAX_EFFICIENT_SIZE:
|
||||||
self.total_segments = 1
|
self.total_segments = 1
|
||||||
@ -254,7 +253,6 @@ class Resource:
|
|||||||
|
|
||||||
elif isinstance(data, bytes):
|
elif isinstance(data, bytes):
|
||||||
data_size = len(data)
|
data_size = len(data)
|
||||||
self.grand_total_parts = math.ceil(data_size/Resource.SDU)
|
|
||||||
self.total_size = data_size
|
self.total_size = data_size
|
||||||
|
|
||||||
resource_data = data
|
resource_data = data
|
||||||
@ -348,6 +346,7 @@ class Resource:
|
|||||||
self.size = len(self.data)
|
self.size = len(self.data)
|
||||||
self.sent_parts = 0
|
self.sent_parts = 0
|
||||||
hashmap_entries = int(math.ceil(self.size/float(Resource.SDU)))
|
hashmap_entries = int(math.ceil(self.size/float(Resource.SDU)))
|
||||||
|
self.total_parts = hashmap_entries
|
||||||
|
|
||||||
hashmap_ok = False
|
hashmap_ok = False
|
||||||
while not hashmap_ok:
|
while not hashmap_ok:
|
||||||
@ -963,21 +962,68 @@ class Resource:
|
|||||||
"""
|
"""
|
||||||
if self.status == RNS.Resource.COMPLETE and self.segment_index == self.total_segments:
|
if self.status == RNS.Resource.COMPLETE and self.segment_index == self.total_segments:
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
elif self.initiator:
|
elif self.initiator:
|
||||||
self.processed_parts = (self.segment_index-1)*math.ceil(Resource.MAX_EFFICIENT_SIZE/Resource.SDU)
|
if not self.split:
|
||||||
self.processed_parts += self.sent_parts
|
self.processed_parts = self.sent_parts
|
||||||
self.progress_total_parts = float(self.grand_total_parts)
|
|
||||||
else:
|
|
||||||
self.processed_parts = (self.segment_index-1)*math.ceil(Resource.MAX_EFFICIENT_SIZE/Resource.SDU)
|
|
||||||
self.processed_parts += self.received_count
|
|
||||||
if self.split:
|
|
||||||
self.progress_total_parts = float(math.ceil(self.total_size/Resource.SDU))
|
|
||||||
else:
|
|
||||||
self.progress_total_parts = float(self.total_parts)
|
self.progress_total_parts = float(self.total_parts)
|
||||||
|
|
||||||
|
else:
|
||||||
|
is_last_segment = self.segment_index != self.total_segments
|
||||||
|
total_segments = self.total_segments
|
||||||
|
processed_segments = self.segment_index-1
|
||||||
|
|
||||||
|
current_segment_parts = self.total_parts
|
||||||
|
max_parts_per_segment = math.ceil(Resource.MAX_EFFICIENT_SIZE/Resource.SDU)
|
||||||
|
|
||||||
|
previously_processed_parts = processed_segments*max_parts_per_segment
|
||||||
|
|
||||||
|
if current_segment_parts < max_parts_per_segment:
|
||||||
|
current_segment_factor = max_parts_per_segment / current_segment_parts
|
||||||
|
else:
|
||||||
|
current_segment_factor = 1
|
||||||
|
|
||||||
|
self.processed_parts = previously_processed_parts + self.sent_parts*current_segment_factor
|
||||||
|
self.progress_total_parts = self.total_segments*max_parts_per_segment
|
||||||
|
|
||||||
|
else:
|
||||||
|
if not self.split:
|
||||||
|
self.processed_parts = self.received_count
|
||||||
|
self.progress_total_parts = float(self.total_parts)
|
||||||
|
|
||||||
|
else:
|
||||||
|
is_last_segment = self.segment_index != self.total_segments
|
||||||
|
total_segments = self.total_segments
|
||||||
|
processed_segments = self.segment_index-1
|
||||||
|
|
||||||
|
current_segment_parts = self.total_parts
|
||||||
|
max_parts_per_segment = math.ceil(Resource.MAX_EFFICIENT_SIZE/Resource.SDU)
|
||||||
|
|
||||||
|
previously_processed_parts = processed_segments*max_parts_per_segment
|
||||||
|
|
||||||
|
if current_segment_parts < max_parts_per_segment:
|
||||||
|
current_segment_factor = max_parts_per_segment / current_segment_parts
|
||||||
|
else:
|
||||||
|
current_segment_factor = 1
|
||||||
|
|
||||||
|
self.processed_parts = previously_processed_parts + self.received_count*current_segment_factor
|
||||||
|
self.progress_total_parts = self.total_segments*max_parts_per_segment
|
||||||
|
|
||||||
|
|
||||||
progress = min(1.0, self.processed_parts / self.progress_total_parts)
|
progress = min(1.0, self.processed_parts / self.progress_total_parts)
|
||||||
return progress
|
return progress
|
||||||
|
|
||||||
|
def get_segment_progress(self):
|
||||||
|
if self.status == RNS.Resource.COMPLETE and self.segment_index == self.total_segments:
|
||||||
|
return 1.0
|
||||||
|
elif self.initiator:
|
||||||
|
processed_parts = self.sent_parts
|
||||||
|
else:
|
||||||
|
processed_parts = self.received_count
|
||||||
|
|
||||||
|
progress = min(1.0, processed_parts / self.total_parts)
|
||||||
|
return progress
|
||||||
|
|
||||||
def get_transfer_size(self):
|
def get_transfer_size(self):
|
||||||
"""
|
"""
|
||||||
:returns: The number of bytes needed to transfer the resource.
|
:returns: The number of bytes needed to transfer the resource.
|
||||||
|
@ -35,13 +35,18 @@ APP_NAME = "rncp"
|
|||||||
allow_all = False
|
allow_all = False
|
||||||
allow_fetch = False
|
allow_fetch = False
|
||||||
fetch_jail = None
|
fetch_jail = None
|
||||||
|
save_path = None
|
||||||
|
show_phy_rates = False
|
||||||
allowed_identity_hashes = []
|
allowed_identity_hashes = []
|
||||||
|
|
||||||
REQ_FETCH_NOT_ALLOWED = 0xF0
|
REQ_FETCH_NOT_ALLOWED = 0xF0
|
||||||
|
|
||||||
|
es = " "
|
||||||
|
erase_str = "\33[2K\r"
|
||||||
|
|
||||||
def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identity = False,
|
def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identity = False,
|
||||||
limit = None, disable_auth = None, fetch_allowed = False, jail = None, announce = False):
|
limit = None, disable_auth = None, fetch_allowed = False, jail = None, save = None, announce = False):
|
||||||
global allow_all, allow_fetch, allowed_identity_hashes, fetch_jail
|
global allow_all, allow_fetch, allowed_identity_hashes, fetch_jail, save_path
|
||||||
from tempfile import TemporaryFile
|
from tempfile import TemporaryFile
|
||||||
|
|
||||||
allow_fetch = fetch_allowed
|
allow_fetch = fetch_allowed
|
||||||
@ -56,6 +61,20 @@ def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identi
|
|||||||
fetch_jail = os.path.abspath(os.path.expanduser(jail))
|
fetch_jail = os.path.abspath(os.path.expanduser(jail))
|
||||||
RNS.log("Restricting fetch requests to paths under \""+fetch_jail+"\"", RNS.LOG_VERBOSE)
|
RNS.log("Restricting fetch requests to paths under \""+fetch_jail+"\"", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
|
if save != None:
|
||||||
|
sp = os.path.abspath(os.path.expanduser(save))
|
||||||
|
if os.path.isdir(sp):
|
||||||
|
if os.access(sp, os.W_OK):
|
||||||
|
save_path = sp
|
||||||
|
else:
|
||||||
|
RNS.log("Output directory not writable", RNS.LOG_ERROR)
|
||||||
|
exit(4)
|
||||||
|
else:
|
||||||
|
RNS.log("Output directory not found", RNS.LOG_ERROR)
|
||||||
|
exit(3)
|
||||||
|
|
||||||
|
RNS.log("Saving received files in \""+save_path+"\"", RNS.LOG_VERBOSE)
|
||||||
|
|
||||||
identity_path = RNS.Reticulum.identitypath+"/"+APP_NAME
|
identity_path = RNS.Reticulum.identitypath+"/"+APP_NAME
|
||||||
if os.path.isfile(identity_path):
|
if os.path.isfile(identity_path):
|
||||||
identity = RNS.Identity.from_file(identity_path)
|
identity = RNS.Identity.from_file(identity_path)
|
||||||
@ -130,10 +149,15 @@ def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identi
|
|||||||
if not allow_fetch:
|
if not allow_fetch:
|
||||||
return REQ_FETCH_NOT_ALLOWED
|
return REQ_FETCH_NOT_ALLOWED
|
||||||
|
|
||||||
file_path = os.path.abspath(os.path.expanduser(data))
|
|
||||||
if fetch_jail:
|
if fetch_jail:
|
||||||
if not file_path.startswith(jail):
|
if data.startswith(fetch_jail+"/"):
|
||||||
|
data = data.replace(fetch_jail+"/", "")
|
||||||
|
file_path = os.path.abspath(os.path.expanduser(f"{fetch_jail}/{data}"))
|
||||||
|
if not file_path.startswith(fetch_jail+"/"):
|
||||||
|
RNS.log(f"Disallowing fetch request for {file_path} outside of fetch jail {fetch_jail}", RNS.LOG_WARNING)
|
||||||
return REQ_FETCH_NOT_ALLOWED
|
return REQ_FETCH_NOT_ALLOWED
|
||||||
|
else:
|
||||||
|
file_path = os.path.abspath(os.path.expanduser(f"{data}"))
|
||||||
|
|
||||||
target_link = None
|
target_link = None
|
||||||
for link in RNS.Transport.active_links:
|
for link in RNS.Transport.active_links:
|
||||||
@ -168,7 +192,13 @@ def listen(configdir, verbosity = 0, quietness = 0, allowed = [], display_identi
|
|||||||
|
|
||||||
|
|
||||||
destination.set_link_established_callback(client_link_established)
|
destination.set_link_established_callback(client_link_established)
|
||||||
|
if allow_fetch:
|
||||||
|
if allow_all:
|
||||||
|
RNS.log("Allowing unauthenticated fetch requests", RNS.LOG_WARNING)
|
||||||
|
destination.register_request_handler("fetch_file", response_generator=fetch_request, allow=RNS.Destination.ALLOW_ALL)
|
||||||
|
else:
|
||||||
destination.register_request_handler("fetch_file", response_generator=fetch_request, allow=RNS.Destination.ALLOW_LIST, allowed_list=allowed_identity_hashes)
|
destination.register_request_handler("fetch_file", response_generator=fetch_request, allow=RNS.Destination.ALLOW_LIST, allowed_list=allowed_identity_hashes)
|
||||||
|
|
||||||
print("rncp listening on "+RNS.prettyhexrep(destination.hash))
|
print("rncp listening on "+RNS.prettyhexrep(destination.hash))
|
||||||
|
|
||||||
if announce >= 0:
|
if announce >= 0:
|
||||||
@ -227,6 +257,7 @@ def receive_resource_started(resource):
|
|||||||
print("Starting resource transfer "+RNS.prettyhexrep(resource.hash)+id_str)
|
print("Starting resource transfer "+RNS.prettyhexrep(resource.hash)+id_str)
|
||||||
|
|
||||||
def receive_resource_concluded(resource):
|
def receive_resource_concluded(resource):
|
||||||
|
global save_path
|
||||||
if resource.status == RNS.Resource.COMPLETE:
|
if resource.status == RNS.Resource.COMPLETE:
|
||||||
print(str(resource)+" completed")
|
print(str(resource)+" completed")
|
||||||
|
|
||||||
@ -235,12 +266,20 @@ def receive_resource_concluded(resource):
|
|||||||
filename = resource.data.read(filename_len).decode("utf-8")
|
filename = resource.data.read(filename_len).decode("utf-8")
|
||||||
|
|
||||||
counter = 0
|
counter = 0
|
||||||
|
if save_path:
|
||||||
|
saved_filename = os.path.abspath(os.path.expanduser(save_path+"/"+filename))
|
||||||
|
if not saved_filename.startswith(save_path+"/"):
|
||||||
|
RNS.log(f"Invalid save path {saved_filename}, ignoring", RNS.LOG_ERROR)
|
||||||
|
return
|
||||||
|
else:
|
||||||
saved_filename = filename
|
saved_filename = filename
|
||||||
while os.path.isfile(saved_filename):
|
|
||||||
counter += 1
|
|
||||||
saved_filename = filename+"."+str(counter)
|
|
||||||
|
|
||||||
file = open(saved_filename, "wb")
|
full_save_path = saved_filename
|
||||||
|
while os.path.isfile(full_save_path):
|
||||||
|
counter += 1
|
||||||
|
full_save_path = saved_filename+"."+str(counter)
|
||||||
|
|
||||||
|
file = open(full_save_path, "wb")
|
||||||
file.write(resource.data.read())
|
file.write(resource.data.read())
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
@ -254,33 +293,57 @@ resource_done = False
|
|||||||
current_resource = None
|
current_resource = None
|
||||||
stats = []
|
stats = []
|
||||||
speed = 0.0
|
speed = 0.0
|
||||||
|
phy_speed = 0.0
|
||||||
def sender_progress(resource):
|
def sender_progress(resource):
|
||||||
stats_max = 32
|
stats_max = 32
|
||||||
global current_resource, stats, speed, resource_done
|
global current_resource, stats, speed, phy_speed, resource_done
|
||||||
current_resource = resource
|
current_resource = resource
|
||||||
|
|
||||||
now = time.time()
|
now = time.time()
|
||||||
got = current_resource.get_progress()*current_resource.total_size
|
got = current_resource.get_progress()*current_resource.get_data_size()
|
||||||
entry = [now, got]
|
phy_got = current_resource.get_segment_progress()*current_resource.get_transfer_size()
|
||||||
|
|
||||||
|
entry = [now, got, phy_got]
|
||||||
stats.append(entry)
|
stats.append(entry)
|
||||||
|
|
||||||
while len(stats) > stats_max:
|
while len(stats) > stats_max:
|
||||||
stats.pop(0)
|
stats.pop(0)
|
||||||
|
|
||||||
span = now - stats[0][0]
|
span = now - stats[0][0]
|
||||||
if span == 0:
|
if span == 0:
|
||||||
speed = 0
|
speed = 0
|
||||||
|
phy_speed = 0
|
||||||
|
|
||||||
else:
|
else:
|
||||||
diff = got - stats[0][1]
|
diff = got - stats[0][1]
|
||||||
speed = diff/span
|
speed = diff/span
|
||||||
|
|
||||||
|
phy_diff = phy_got - stats[0][2]
|
||||||
|
if phy_diff > 0:
|
||||||
|
phy_speed = phy_diff/span
|
||||||
|
|
||||||
if resource.status < RNS.Resource.COMPLETE:
|
if resource.status < RNS.Resource.COMPLETE:
|
||||||
resource_done = False
|
resource_done = False
|
||||||
else:
|
else:
|
||||||
resource_done = True
|
resource_done = True
|
||||||
|
|
||||||
link = None
|
link = None
|
||||||
def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = None, timeout = RNS.Transport.PATH_REQUEST_TIMEOUT, silent=False):
|
def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = None, timeout = RNS.Transport.PATH_REQUEST_TIMEOUT, silent=False, phy_rates=False, save=None):
|
||||||
global current_resource, resource_done, link, speed
|
global current_resource, resource_done, link, speed, show_phy_rates, save_path
|
||||||
targetloglevel = 3+verbosity-quietness
|
targetloglevel = 3+verbosity-quietness
|
||||||
|
show_phy_rates = phy_rates
|
||||||
|
|
||||||
|
if save:
|
||||||
|
sp = os.path.abspath(os.path.expanduser(save))
|
||||||
|
if os.path.isdir(sp):
|
||||||
|
if os.access(sp, os.W_OK):
|
||||||
|
save_path = sp
|
||||||
|
else:
|
||||||
|
RNS.log("Output directory not writable", RNS.LOG_ERROR)
|
||||||
|
exit(4)
|
||||||
|
else:
|
||||||
|
RNS.log("Output directory not found", RNS.LOG_ERROR)
|
||||||
|
exit(3)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||||
@ -315,7 +378,7 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
if silent:
|
if silent:
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested")
|
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested")
|
||||||
else:
|
else:
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested ", end=" ")
|
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested ", end=es)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
@ -332,13 +395,13 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
if silent:
|
if silent:
|
||||||
print("Path not found")
|
print("Path not found")
|
||||||
else:
|
else:
|
||||||
print("\r \rPath not found")
|
print(f"{erase_str}Path not found")
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print("Establishing link with "+RNS.prettyhexrep(destination_hash))
|
print("Establishing link with "+RNS.prettyhexrep(destination_hash))
|
||||||
else:
|
else:
|
||||||
print("\r \rEstablishing link with "+RNS.prettyhexrep(destination_hash)+" ", end=" ")
|
print(f"{erase_str}Establishing link with "+RNS.prettyhexrep(destination_hash)+" ", end=es)
|
||||||
|
|
||||||
listener_identity = RNS.Identity.recall(destination_hash)
|
listener_identity = RNS.Identity.recall(destination_hash)
|
||||||
listener_destination = RNS.Destination(
|
listener_destination = RNS.Destination(
|
||||||
@ -361,13 +424,13 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
if silent:
|
if silent:
|
||||||
print("Could not establish link with "+RNS.prettyhexrep(destination_hash))
|
print("Could not establish link with "+RNS.prettyhexrep(destination_hash))
|
||||||
else:
|
else:
|
||||||
print("\r \rCould not establish link with "+RNS.prettyhexrep(destination_hash))
|
print(f"{erase_str}Could not establish link with "+RNS.prettyhexrep(destination_hash))
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print("Requesting file from remote...")
|
print("Requesting file from remote...")
|
||||||
else:
|
else:
|
||||||
print("\r \rRequesting file from remote ", end=" ")
|
print(f"{erase_str}Requesting file from remote ", end=es)
|
||||||
|
|
||||||
link.identify(identity)
|
link.identify(identity)
|
||||||
|
|
||||||
@ -402,18 +465,25 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
|
|
||||||
def fetch_resource_concluded(resource):
|
def fetch_resource_concluded(resource):
|
||||||
nonlocal resource_resolved, resource_status
|
nonlocal resource_resolved, resource_status
|
||||||
|
global save_path
|
||||||
if resource.status == RNS.Resource.COMPLETE:
|
if resource.status == RNS.Resource.COMPLETE:
|
||||||
if resource.total_size > 4:
|
if resource.total_size > 4:
|
||||||
filename_len = int.from_bytes(resource.data.read(2), "big")
|
filename_len = int.from_bytes(resource.data.read(2), "big")
|
||||||
filename = resource.data.read(filename_len).decode("utf-8")
|
filename = resource.data.read(filename_len).decode("utf-8")
|
||||||
|
|
||||||
counter = 0
|
counter = 0
|
||||||
saved_filename = filename
|
if save_path:
|
||||||
while os.path.isfile(saved_filename):
|
saved_filename = os.path.abspath(os.path.expanduser(save_path+"/"+filename))
|
||||||
counter += 1
|
|
||||||
saved_filename = filename+"."+str(counter)
|
|
||||||
|
|
||||||
file = open(saved_filename, "wb")
|
else:
|
||||||
|
saved_filename = filename
|
||||||
|
|
||||||
|
full_save_path = saved_filename
|
||||||
|
while os.path.isfile(full_save_path):
|
||||||
|
counter += 1
|
||||||
|
full_save_path = saved_filename+"."+str(counter)
|
||||||
|
|
||||||
|
file = open(full_save_path, "wb")
|
||||||
file.write(resource.data.read())
|
file.write(resource.data.read())
|
||||||
file.close()
|
file.close()
|
||||||
resource_status = "completed"
|
resource_status = "completed"
|
||||||
@ -442,31 +512,31 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
if request_status == "fetch_not_allowed":
|
if request_status == "fetch_not_allowed":
|
||||||
if not silent: print("\r \r", end="")
|
if not silent: print(f"{erase_str}", end="")
|
||||||
print("Fetch request failed, fetching the file "+str(file)+" was not allowed by the remote")
|
print("Fetch request failed, fetching the file "+str(file)+" was not allowed by the remote")
|
||||||
link.teardown()
|
link.teardown()
|
||||||
time.sleep(0.15)
|
time.sleep(0.15)
|
||||||
exit(0)
|
exit(0)
|
||||||
elif request_status == "not_found":
|
elif request_status == "not_found":
|
||||||
if not silent: print("\r \r", end="")
|
if not silent: print(f"{erase_str}", end="")
|
||||||
print("Fetch request failed, the file "+str(file)+" was not found on the remote")
|
print("Fetch request failed, the file "+str(file)+" was not found on the remote")
|
||||||
link.teardown()
|
link.teardown()
|
||||||
time.sleep(0.15)
|
time.sleep(0.15)
|
||||||
exit(0)
|
exit(0)
|
||||||
elif request_status == "remote_error":
|
elif request_status == "remote_error":
|
||||||
if not silent: print("\r \r", end="")
|
if not silent: print(f"{erase_str}", end="")
|
||||||
print("Fetch request failed due to an error on the remote system")
|
print("Fetch request failed due to an error on the remote system")
|
||||||
link.teardown()
|
link.teardown()
|
||||||
time.sleep(0.15)
|
time.sleep(0.15)
|
||||||
exit(0)
|
exit(0)
|
||||||
elif request_status == "unknown":
|
elif request_status == "unknown":
|
||||||
if not silent: print("\r \r", end="")
|
if not silent: print(f"{erase_str}", end="")
|
||||||
print("Fetch request failed due to an unknown error (probably not authorised)")
|
print("Fetch request failed due to an unknown error (probably not authorised)")
|
||||||
link.teardown()
|
link.teardown()
|
||||||
time.sleep(0.15)
|
time.sleep(0.15)
|
||||||
exit(0)
|
exit(0)
|
||||||
elif request_status == "found":
|
elif request_status == "found":
|
||||||
if not silent: print("\r \r", end="")
|
if not silent: print(f"{erase_str}", end="")
|
||||||
|
|
||||||
while not resource_resolved:
|
while not resource_resolved:
|
||||||
if not silent:
|
if not silent:
|
||||||
@ -474,13 +544,21 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
if current_resource:
|
if current_resource:
|
||||||
prg = current_resource.get_progress()
|
prg = current_resource.get_progress()
|
||||||
percent = round(prg * 100.0, 1)
|
percent = round(prg * 100.0, 1)
|
||||||
stat_str = str(percent)+"% - " + size_str(int(prg*current_resource.total_size)) + " of " + size_str(current_resource.total_size) + " - " +size_str(speed, "b")+"ps"
|
if show_phy_rates:
|
||||||
|
pss = size_str(phy_speed, "b")
|
||||||
|
phy_str = f" ({pss}ps at physical layer)"
|
||||||
|
else:
|
||||||
|
phy_str = ""
|
||||||
|
ps = size_str(int(prg*current_resource.total_size))
|
||||||
|
ts = size_str(current_resource.total_size)
|
||||||
|
ss = size_str(speed, "b")
|
||||||
|
stat_str = f"{percent}% - {ps} of {ts} - {ss}ps{phy_str}"
|
||||||
if prg != 1.0:
|
if prg != 1.0:
|
||||||
print("\r \rTransferring file "+syms[i]+" "+stat_str, end=" ")
|
print(f"{erase_str}Transferring file {syms[i]} {stat_str}", end=es)
|
||||||
else:
|
else:
|
||||||
print("\r \rTransfer complete "+stat_str, end=" ")
|
print(f"{erase_str}Transfer complete {stat_str}", end=es)
|
||||||
else:
|
else:
|
||||||
print("\r \rWaiting for transfer to start "+syms[i]+" ", end=" ")
|
print(f"{erase_str}Waiting for transfer to start {syms[i]} ", end=es)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
@ -488,13 +566,12 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
if silent:
|
if silent:
|
||||||
print("The transfer failed")
|
print("The transfer failed")
|
||||||
else:
|
else:
|
||||||
print("\r \rThe transfer failed")
|
print(f"{erase_str}The transfer failed")
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print(str(file)+" fetched from "+RNS.prettyhexrep(destination_hash))
|
print(str(file)+" fetched from "+RNS.prettyhexrep(destination_hash))
|
||||||
else:
|
else:
|
||||||
#print("\r \r"+str(file)+" fetched from "+RNS.prettyhexrep(destination_hash))
|
|
||||||
print("\n"+str(file)+" fetched from "+RNS.prettyhexrep(destination_hash))
|
print("\n"+str(file)+" fetched from "+RNS.prettyhexrep(destination_hash))
|
||||||
link.teardown()
|
link.teardown()
|
||||||
time.sleep(0.15)
|
time.sleep(0.15)
|
||||||
@ -504,10 +581,11 @@ def fetch(configdir, verbosity = 0, quietness = 0, destination = None, file = No
|
|||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
def send(configdir, verbosity = 0, quietness = 0, destination = None, file = None, timeout = RNS.Transport.PATH_REQUEST_TIMEOUT, silent=False):
|
def send(configdir, verbosity = 0, quietness = 0, destination = None, file = None, timeout = RNS.Transport.PATH_REQUEST_TIMEOUT, silent=False, phy_rates=False):
|
||||||
global current_resource, resource_done, link, speed
|
global current_resource, resource_done, link, speed, show_phy_rates
|
||||||
from tempfile import TemporaryFile
|
from tempfile import TemporaryFile
|
||||||
targetloglevel = 3+verbosity-quietness
|
targetloglevel = 3+verbosity-quietness
|
||||||
|
show_phy_rates = phy_rates
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
|
||||||
@ -536,14 +614,14 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
print("Filename exceeds max size, cannot send")
|
print("Filename exceeds max size, cannot send")
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
print("Preparing file...", end=" ")
|
print("Preparing file...", end=es)
|
||||||
|
|
||||||
temp_file.write(filename_len.to_bytes(2, "big"))
|
temp_file.write(filename_len.to_bytes(2, "big"))
|
||||||
temp_file.write(filename_bytes)
|
temp_file.write(filename_bytes)
|
||||||
temp_file.write(real_file.read())
|
temp_file.write(real_file.read())
|
||||||
temp_file.seek(0)
|
temp_file.seek(0)
|
||||||
|
|
||||||
print("\r \r", end="")
|
print(f"{erase_str}", end="")
|
||||||
|
|
||||||
reticulum = RNS.Reticulum(configdir=configdir, loglevel=targetloglevel)
|
reticulum = RNS.Reticulum(configdir=configdir, loglevel=targetloglevel)
|
||||||
|
|
||||||
@ -566,7 +644,7 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
if silent:
|
if silent:
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested")
|
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested")
|
||||||
else:
|
else:
|
||||||
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested ", end=" ")
|
print("Path to "+RNS.prettyhexrep(destination_hash)+" requested ", end=es)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
@ -583,13 +661,13 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
if silent:
|
if silent:
|
||||||
print("Path not found")
|
print("Path not found")
|
||||||
else:
|
else:
|
||||||
print("\r \rPath not found")
|
print(f"{erase_str}Path not found")
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print("Establishing link with "+RNS.prettyhexrep(destination_hash))
|
print("Establishing link with "+RNS.prettyhexrep(destination_hash))
|
||||||
else:
|
else:
|
||||||
print("\r \rEstablishing link with "+RNS.prettyhexrep(destination_hash)+" ", end=" ")
|
print(f"{erase_str}Establishing link with "+RNS.prettyhexrep(destination_hash)+" ", end=es)
|
||||||
|
|
||||||
receiver_identity = RNS.Identity.recall(destination_hash)
|
receiver_identity = RNS.Identity.recall(destination_hash)
|
||||||
receiver_destination = RNS.Destination(
|
receiver_destination = RNS.Destination(
|
||||||
@ -612,19 +690,19 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
if silent:
|
if silent:
|
||||||
print("Link establishment with "+RNS.prettyhexrep(destination_hash)+" timed out")
|
print("Link establishment with "+RNS.prettyhexrep(destination_hash)+" timed out")
|
||||||
else:
|
else:
|
||||||
print("\r \rLink establishment with "+RNS.prettyhexrep(destination_hash)+" timed out")
|
print(f"{erase_str}Link establishment with "+RNS.prettyhexrep(destination_hash)+" timed out")
|
||||||
exit(1)
|
exit(1)
|
||||||
elif not RNS.Transport.has_path(destination_hash):
|
elif not RNS.Transport.has_path(destination_hash):
|
||||||
if silent:
|
if silent:
|
||||||
print("No path found to "+RNS.prettyhexrep(destination_hash))
|
print("No path found to "+RNS.prettyhexrep(destination_hash))
|
||||||
else:
|
else:
|
||||||
print("\r \rNo path found to "+RNS.prettyhexrep(destination_hash))
|
print(f"{erase_str}No path found to "+RNS.prettyhexrep(destination_hash))
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print("Advertising file resource...")
|
print("Advertising file resource...")
|
||||||
else:
|
else:
|
||||||
print("\r \rAdvertising file resource ", end=" ")
|
print(f"{erase_str}Advertising file resource ", end=es)
|
||||||
|
|
||||||
link.identify(identity)
|
link.identify(identity)
|
||||||
resource = RNS.Resource(temp_file, link, callback = sender_progress, progress_callback = sender_progress)
|
resource = RNS.Resource(temp_file, link, callback = sender_progress, progress_callback = sender_progress)
|
||||||
@ -642,23 +720,32 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
if silent:
|
if silent:
|
||||||
print("File was not accepted by "+RNS.prettyhexrep(destination_hash))
|
print("File was not accepted by "+RNS.prettyhexrep(destination_hash))
|
||||||
else:
|
else:
|
||||||
print("\r \rFile was not accepted by "+RNS.prettyhexrep(destination_hash))
|
print(f"{erase_str}File was not accepted by "+RNS.prettyhexrep(destination_hash))
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print("Transferring file...")
|
print("Transferring file...")
|
||||||
else:
|
else:
|
||||||
print("\r \rTransferring file ", end=" ")
|
print(f"{erase_str}Transferring file ", end=es)
|
||||||
|
|
||||||
def progress_update(i, done=False):
|
def progress_update(i, done=False):
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
prg = current_resource.get_progress()
|
prg = current_resource.get_progress()
|
||||||
percent = round(prg * 100.0, 1)
|
percent = round(prg * 100.0, 1)
|
||||||
stat_str = str(percent)+"% - " + size_str(int(prg*current_resource.total_size)) + " of " + size_str(current_resource.total_size) + " - " +size_str(speed, "b")+"ps"
|
if show_phy_rates:
|
||||||
if not done:
|
pss = size_str(phy_speed, "b")
|
||||||
print("\r \rTransferring file "+syms[i]+" "+stat_str, end=" ")
|
phy_str = f" ({pss}ps at physical layer)"
|
||||||
else:
|
else:
|
||||||
print("\r \rTransfer complete "+stat_str, end=" ")
|
phy_str = ""
|
||||||
|
es = " "
|
||||||
|
cs = size_str(int(prg*current_resource.total_size))
|
||||||
|
ts = size_str(current_resource.total_size)
|
||||||
|
ss = size_str(speed, "b")
|
||||||
|
stat_str = f"{percent}% - {cs} of {ts} - {ss}ps{phy_str}"
|
||||||
|
if not done:
|
||||||
|
print(f"{erase_str}Transferring file "+syms[i]+" "+stat_str, end=es)
|
||||||
|
else:
|
||||||
|
print(f"{erase_str}Transfer complete "+stat_str, end=es)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
return i
|
return i
|
||||||
@ -674,13 +761,12 @@ def send(configdir, verbosity = 0, quietness = 0, destination = None, file = Non
|
|||||||
if silent:
|
if silent:
|
||||||
print("The transfer failed")
|
print("The transfer failed")
|
||||||
else:
|
else:
|
||||||
print("\r \rThe transfer failed")
|
print(f"{erase_str}The transfer failed")
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
if silent:
|
if silent:
|
||||||
print(str(file_path)+" copied to "+RNS.prettyhexrep(destination_hash))
|
print(str(file_path)+" copied to "+RNS.prettyhexrep(destination_hash))
|
||||||
else:
|
else:
|
||||||
# print("\r \r"+str(file_path)+" copied to "+RNS.prettyhexrep(destination_hash))
|
|
||||||
print("\n"+str(file_path)+" copied to "+RNS.prettyhexrep(destination_hash))
|
print("\n"+str(file_path)+" copied to "+RNS.prettyhexrep(destination_hash))
|
||||||
link.teardown()
|
link.teardown()
|
||||||
time.sleep(0.25)
|
time.sleep(0.25)
|
||||||
@ -701,11 +787,13 @@ def main():
|
|||||||
parser.add_argument("-F", '--allow-fetch', action='store_true', default=False, help="allow authenticated clients to fetch files")
|
parser.add_argument("-F", '--allow-fetch', action='store_true', default=False, help="allow authenticated clients to fetch files")
|
||||||
parser.add_argument("-f", '--fetch', action='store_true', default=False, help="fetch file from remote listener instead of sending")
|
parser.add_argument("-f", '--fetch', action='store_true', default=False, help="fetch file from remote listener instead of sending")
|
||||||
parser.add_argument("-j", "--jail", metavar="path", action="store", default=None, help="restrict fetch requests to specified path", type=str)
|
parser.add_argument("-j", "--jail", metavar="path", action="store", default=None, help="restrict fetch requests to specified path", type=str)
|
||||||
|
parser.add_argument("-s", "--save", metavar="path", action="store", default=None, help="save received files in specified path", type=str)
|
||||||
parser.add_argument("-b", action='store', metavar="seconds", default=-1, help="announce interval, 0 to only announce at startup", type=int)
|
parser.add_argument("-b", action='store', metavar="seconds", default=-1, help="announce interval, 0 to only announce at startup", type=int)
|
||||||
parser.add_argument('-a', metavar="allowed_hash", dest="allowed", action='append', help="allow this identity", type=str)
|
parser.add_argument('-a', metavar="allowed_hash", dest="allowed", action='append', help="allow this identity (or add in ~/.rncp/allowed_identities)", type=str)
|
||||||
parser.add_argument('-n', '--no-auth', action='store_true', default=False, help="accept requests from anyone")
|
parser.add_argument('-n', '--no-auth', action='store_true', default=False, help="accept requests from anyone")
|
||||||
parser.add_argument('-p', '--print-identity', action='store_true', default=False, help="print identity and destination info and exit")
|
parser.add_argument('-p', '--print-identity', action='store_true', default=False, help="print identity and destination info and exit")
|
||||||
parser.add_argument("-w", action="store", metavar="seconds", type=float, help="sender timeout before giving up", default=RNS.Transport.PATH_REQUEST_TIMEOUT)
|
parser.add_argument("-w", action="store", metavar="seconds", type=float, help="sender timeout before giving up", default=RNS.Transport.PATH_REQUEST_TIMEOUT)
|
||||||
|
parser.add_argument('-P', '--phy-rates', action='store_true', default=False, help="display physical layer transfer rates")
|
||||||
# parser.add_argument("--limit", action="store", metavar="files", type=float, help="maximum number of files to accept", default=None)
|
# parser.add_argument("--limit", action="store", metavar="files", type=float, help="maximum number of files to accept", default=None)
|
||||||
parser.add_argument("--version", action="version", version="rncp {version}".format(version=__version__))
|
parser.add_argument("--version", action="version", version="rncp {version}".format(version=__version__))
|
||||||
|
|
||||||
@ -719,6 +807,7 @@ def main():
|
|||||||
allowed = args.allowed,
|
allowed = args.allowed,
|
||||||
fetch_allowed = args.allow_fetch,
|
fetch_allowed = args.allow_fetch,
|
||||||
jail = args.jail,
|
jail = args.jail,
|
||||||
|
save = args.save,
|
||||||
display_identity=args.print_identity,
|
display_identity=args.print_identity,
|
||||||
# limit=args.limit,
|
# limit=args.limit,
|
||||||
disable_auth=args.no_auth,
|
disable_auth=args.no_auth,
|
||||||
@ -735,6 +824,8 @@ def main():
|
|||||||
file = args.file,
|
file = args.file,
|
||||||
timeout = args.w,
|
timeout = args.w,
|
||||||
silent = args.silent,
|
silent = args.silent,
|
||||||
|
phy_rates = args.phy_rates,
|
||||||
|
save = args.save,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print("")
|
print("")
|
||||||
@ -750,6 +841,7 @@ def main():
|
|||||||
file = args.file,
|
file = args.file,
|
||||||
timeout = args.w,
|
timeout = args.w,
|
||||||
silent = args.silent,
|
silent = args.silent,
|
||||||
|
phy_rates = args.phy_rates,
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "0.8.2"
|
__version__ = "0.8.3"
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -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: bd0a676b0f490cda5d841ab7cd7cade1
|
config: af530171c45cf8c468a96fde91201b07
|
||||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||||
|
@ -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.8.2 beta',
|
VERSION: '0.8.3 beta',
|
||||||
LANGUAGE: 'en',
|
LANGUAGE: 'en',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
BUILDER: 'html',
|
BUILDER: 'html',
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Support Reticulum" href="support.html" /><link rel="prev" title="Building Networks" href="networks.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Support Reticulum" href="support.html" /><link rel="prev" title="Building Networks" href="networks.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Code Examples - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>Code Examples - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="#" /><link rel="search" title="Search" href="search.html" />
|
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="#" /><link rel="search" title="Search" href="search.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Index - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Index - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -139,7 +139,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -165,7 +165,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Using Reticulum on Your System" href="using.html" /><link rel="prev" title="What is Reticulum?" href="whatis.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Using Reticulum on Your System" href="using.html" /><link rel="prev" title="What is Reticulum?" href="whatis.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Getting Started Fast - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>Getting Started Fast - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Configuring Interfaces" href="interfaces.html" /><link rel="prev" title="Understanding Reticulum" href="understanding.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Configuring Interfaces" href="interfaces.html" /><link rel="prev" title="Understanding Reticulum" href="understanding.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Communications Hardware - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>Communications Hardware - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="What is Reticulum?" href="whatis.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="What is Reticulum?" href="whatis.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="#"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="#"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Building Networks" href="networks.html" /><link rel="prev" title="Communications Hardware" href="hardware.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Building Networks" href="networks.html" /><link rel="prev" title="Communications Hardware" href="hardware.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Configuring Interfaces - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>Configuring Interfaces - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Code Examples" href="examples.html" /><link rel="prev" title="Configuring Interfaces" href="interfaces.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Code Examples" href="examples.html" /><link rel="prev" title="Configuring Interfaces" href="interfaces.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Building Networks - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>Building Networks - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
Binary file not shown.
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="prev" title="Support Reticulum" href="support.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="prev" title="Support Reticulum" href="support.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>API Reference - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>API Reference - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="#" />
|
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="#" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Search - Reticulum Network Stack 0.8.2 beta documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Search - Reticulum Network Stack 0.8.3 beta documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||||
@ -138,7 +138,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -164,7 +164,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="#" role="search">
|
</a><form class="sidebar-search-container" method="get" action="#" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="API Reference" href="reference.html" /><link rel="prev" title="Code Examples" href="examples.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="API Reference" href="reference.html" /><link rel="prev" title="Code Examples" href="examples.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Support Reticulum - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>Support Reticulum - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Communications Hardware" href="hardware.html" /><link rel="prev" title="Using Reticulum on Your System" href="using.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Communications Hardware" href="hardware.html" /><link rel="prev" title="Using Reticulum on Your System" href="using.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Understanding Reticulum - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>Understanding Reticulum - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Understanding Reticulum" href="understanding.html" /><link rel="prev" title="Getting Started Fast" href="gettingstartedfast.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Understanding Reticulum" href="understanding.html" /><link rel="prev" title="Getting Started Fast" href="gettingstartedfast.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Using Reticulum on Your System - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>Using Reticulum on Your System - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Getting Started Fast" href="gettingstartedfast.html" /><link rel="prev" title="Reticulum Network Stack Manual" href="index.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Getting Started Fast" href="gettingstartedfast.html" /><link rel="prev" title="Reticulum Network Stack Manual" href="index.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>What is Reticulum? - Reticulum Network Stack 0.8.2 beta documentation</title>
|
<title>What is Reticulum? - Reticulum Network Stack 0.8.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/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.2 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.3 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.2 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.3 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
Loading…
Reference in New Issue
Block a user