Compare commits

...

10 Commits

Author SHA1 Message Date
Mark Qvist e1340e87eb Prepare release 2026-04-21 17:02:37 +02:00
Mark Qvist e9bfef2131 Cleanup 2026-04-21 16:55:59 +02:00
Mark Qvist b408699e65 Periodically clean known destinations data based on local relevance 2026-04-21 13:21:23 +02:00
Mark Qvist 3d1c508868 Improved BackboneInterface error handling 2026-04-21 00:24:00 +02:00
Mark Qvist 84e0746c9c Updated version 2026-04-20 23:49:24 +02:00
Mark Qvist b5658c4865 Keep track of which known destinations are actually in use, so irrelevant destination data can be cleaned 2026-04-20 23:48:57 +02:00
Mark Qvist d413a4bc53 Improved resource transfer timing calculations 2026-04-20 23:44:55 +02:00
Mark Qvist ce5ab902b6 Updated docs 2026-04-20 11:38:14 +02:00
Mark Qvist 294408b0bb Run non-background data persist synchronously 2026-04-19 01:32:12 +02:00
Mark Qvist 53372fbe4c Updated docs 2026-04-18 17:27:42 +02:00
31 changed files with 318 additions and 119 deletions
+21
View File
@@ -1,3 +1,24 @@
### 2026-04-21: RNS 1.1.7
**Changes**
- Added periodic known destination data cleaning based on local relevance.
- Improved resource transfer sequencing timing calculations and reliability.
- Improved BackboneInterface error handling on EPOLL errors.
- Ensured non-background data persist runs synchronously.
**Release Hashes**
```
4d9702c5d9bb8a3c8b94766cb51cccad5afd78d615af9a6b146730347044e6f0 rns-1.1.7-py3-none-any.whl
172dede7656b41b85e4319354ed04649b518e58c54586da7e443579c620a0a5b rnspure-1.1.7-py3-none-any.whl
```
**Release Signatures**
Release artifacts include `rsg` signature files that can be validated against the RNS release signing identity `<bc7291552be7a58f361522990465165c>` using `rnid`:
```sh
rnid -i bc7291552be7a58f361522990465165c -V rns-1.1.7-py3-none-any.whl.rsg
```
### 2026-04-18: RNS 1.1.6
**Changes**
+1 -3
View File
@@ -411,9 +411,7 @@ class Destination:
else:
if packet.packet_type == RNS.Packet.DATA:
if self.callbacks.packet != None:
try:
def job(): self.callbacks.packet(plaintext, packet)
threading.Thread(target=job, daemon=True).start()
try: self.callbacks.packet(plaintext, packet)
except Exception as e:
RNS.log("Error while executing receive callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
+128 -28
View File
@@ -94,17 +94,25 @@ class Identity:
known_ratchets = {}
ratchet_persist_lock = threading.Lock()
known_destinations_lock = threading.Lock()
@staticmethod
def remember(packet_hash, destination_hash, public_key, app_data = None):
if len(public_key) != Identity.KEYSIZE//8:
raise TypeError("Can't remember "+RNS.prettyhexrep(destination_hash)+", the public key size of "+str(len(public_key))+" is not valid.", RNS.LOG_ERROR)
else:
Identity.known_destinations[destination_hash] = [time.time(), packet_hash, public_key, app_data]
with Identity.known_destinations_lock:
if not destination_hash in Identity.known_destinations:
Identity.known_destinations[destination_hash] = [time.time(), packet_hash, public_key, app_data, 0]
else:
entry = Identity.known_destinations[destination_hash]
entry[0] = time.time()
entry[1] = packet_hash
entry[2] = public_key
entry[3] = app_data
@staticmethod
def recall(target_hash, from_identity_hash=False):
def recall(target_hash, from_identity_hash=False, _no_use=False):
"""
Recall identity for a destination or identity hash. By default, this function
will return the identity associated with a given *destination* hash. As an
@@ -120,6 +128,7 @@ class Identity:
if from_identity_hash:
for destination_hash in Identity.known_destinations:
if target_hash == Identity.truncated_hash(Identity.known_destinations[destination_hash][2]):
if not _no_use: RNS.Reticulum.get_instance()._used_destination_data(destination_hash)
identity_data = Identity.known_destinations[destination_hash]
identity = Identity(create_keys=False)
identity.load_public_key(identity_data[2])
@@ -130,6 +139,7 @@ class Identity:
else:
if target_hash in Identity.known_destinations:
if not _no_use: RNS.Reticulum.get_instance()._used_destination_data(target_hash)
identity_data = Identity.known_destinations[target_hash]
identity = Identity(create_keys=False)
identity.load_public_key(identity_data[2])
@@ -146,7 +156,7 @@ class Identity:
return None
@staticmethod
def recall_app_data(destination_hash):
def recall_app_data(destination_hash, _no_use=False):
"""
Recall last heard app_data for a destination hash.
@@ -154,13 +164,14 @@ class Identity:
:returns: *Bytes* containing app_data, or *None* if the destination is unknown.
"""
if destination_hash in Identity.known_destinations:
if not _no_use: RNS.Reticulum.get_instance()._used_destination_data(destination_hash)
app_data = Identity.known_destinations[destination_hash][3]
return app_data
else:
return None
else: return None
@staticmethod
def save_known_destinations(background=False):
def save_known_destinations(background=False, recombine=True):
# TODO: Improve the storage method so we don't have to
# deserialize and serialize the entire table on every
# save, but the only changes. It might be possible to
@@ -181,32 +192,33 @@ class Identity:
Identity.saving_known_destinations = True
save_start = time.time()
storage_known_destinations = {}
if os.path.isfile(RNS.Reticulum.storagepath+"/known_destinations"):
if recombine:
storage_known_destinations = {}
if os.path.isfile(RNS.Reticulum.storagepath+"/known_destinations"):
try:
with open(RNS.Reticulum.storagepath+"/known_destinations","rb") as file:
storage_known_destinations = umsgpack.load(file)
except: pass
try:
with open(RNS.Reticulum.storagepath+"/known_destinations","rb") as file:
storage_known_destinations = umsgpack.load(file)
except: pass
for destination_hash in storage_known_destinations:
if not destination_hash in Identity.known_destinations:
with Identity.known_destinations_lock:
Identity.known_destinations[destination_hash] = storage_known_destinations[destination_hash]
except Exception as e:
RNS.log("Skipped recombining known destinations from disk, since an error occurred: "+str(e), RNS.LOG_WARNING)
try:
for destination_hash in storage_known_destinations:
if not destination_hash in Identity.known_destinations:
Identity.known_destinations[destination_hash] = storage_known_destinations[destination_hash]
except Exception as e:
RNS.log("Skipped recombining known destinations from disk, since an error occurred: "+str(e), RNS.LOG_WARNING)
RNS.log("Saving "+str(len(Identity.known_destinations))+" known destinations to storage...", RNS.LOG_DEBUG)
RNS.log("Saving "+str(len(Identity.known_destinations))+" known destinations to storage...", RNS.LOG_VERBOSE)
with open(RNS.Reticulum.storagepath+"/known_destinations","wb") as file:
umsgpack.dump(Identity.known_destinations.copy(), file)
save_time = time.time() - save_start
if save_time < 1:
time_str = str(round(save_time*1000,2))+"ms"
else:
time_str = str(round(save_time,2))+"s"
if save_time < 1: time_str = str(round(save_time*1000,2))+"ms"
else: time_str = str(round(save_time,2))+"s"
RNS.log("Saved known destinations to storage in "+time_str, RNS.LOG_DEBUG)
RNS.log("Saved known destinations to storage in "+time_str, RNS.LOG_VERBOSE)
except Exception as e:
RNS.log("Error while saving known destinations to disk, the contained exception was: "+str(e), RNS.LOG_ERROR)
@@ -217,6 +229,7 @@ class Identity:
@staticmethod
def load_known_destinations():
if os.path.isfile(RNS.Reticulum.storagepath+"/known_destinations"):
st = time.time()
try:
with open(RNS.Reticulum.storagepath+"/known_destinations","rb") as file:
loaded_known_destinations = umsgpack.load(file)
@@ -224,15 +237,102 @@ class Identity:
Identity.known_destinations = {}
for known_destination in loaded_known_destinations:
if len(known_destination) == RNS.Reticulum.TRUNCATED_HASHLENGTH//8:
Identity.known_destinations[known_destination] = loaded_known_destinations[known_destination]
if len(loaded_known_destinations[known_destination]) < 5:
e = loaded_known_destinations[known_destination]
loaded_known_destinations[known_destination] = [e[0], e[1], e[2], e[3], 0]
RNS.log("Loaded "+str(len(Identity.known_destinations))+" known destination from storage", RNS.LOG_VERBOSE)
with Identity.known_destinations_lock:
Identity.known_destinations[known_destination] = loaded_known_destinations[known_destination]
RNS.log(f"Loaded {len(Identity.known_destinations)} known destination from storage in {RNS.prettyshorttime(time.time()-st)}", RNS.LOG_VERBOSE)
except Exception as e:
RNS.log("Error loading known destinations from disk, file will be recreated on exit", RNS.LOG_ERROR)
RNS.trace_exception(e)
else:
RNS.log("Destinations file does not exist, no known destinations loaded", RNS.LOG_VERBOSE)
@staticmethod
def _used_destination_data(destination_hash):
with Identity.known_destinations_lock:
if destination_hash in Identity.known_destinations:
if not Identity.known_destinations[destination_hash][4] < 0:
Identity.known_destinations[destination_hash][4] = time.time()
return True
return False
@staticmethod
def _retain_destination_data(destination_hash):
with Identity.known_destinations_lock:
if destination_hash in Identity.known_destinations:
Identity.known_destinations[destination_hash][4] = -1
return True
return False
@staticmethod
def _unretain_destination_data(destination_hash):
with Identity.known_destinations_lock:
if destination_hash in Identity.known_destinations:
Identity.known_destinations[destination_hash][4] = time.time()
return True
return False
@staticmethod
def clean_known_destinations():
now = time.time()
st = now
total = len(Identity.known_destinations)
stale = []
no_path = 0
retained = 0
never_used = 0
for destination_hash in Identity.known_destinations:
try:
if RNS.Transport.has_path(destination_hash): has_path = True
else:
has_path = False
no_path += 1
with Identity.known_destinations_lock:
if destination_hash in Identity.known_destinations:
last_announce = Identity.known_destinations[destination_hash][0]
last_use = 0
was_used = False
is_retained = False
if Identity.known_destinations[destination_hash][4] > 0:
was_used = True
last_use = Identity.known_destinations[destination_hash][4]
elif Identity.known_destinations[destination_hash][4] == 0:
was_used = False
never_used += 1
elif Identity.known_destinations[destination_hash][4] == -1:
is_retained = True
retained += 1
unused_for = time.time() - Identity.known_destinations[destination_hash][4]
if not is_retained and not has_path:
if not was_used and now - last_announce > RNS.Transport.UNUSED_DESTINATION_LINGER: stale.append(destination_hash)
elif unused_for > RNS.Transport.DESTINATION_TIMEOUT*1.25: stale.append(destination_hash)
except Exception as e: RNS.log(f"Faulty entry for {RNS.prettyhexrep(destination_hash)} while cleaning known destinations: {e}", RNS.LOG_DEBUG)
removed = 0
for destination_hash in stale:
with Identity.known_destinations_lock:
if destination_hash in Identity.known_destinations:
Identity.known_destinations.pop(destination_hash)
removed += 1
# RNS.log(f"Total destinations: {total}, stale: {len(stale)}, removed: {removed}, no path: {no_path}, never used: {never_used}, with path: {total-no_path}, used: {total-never_used}, retained: {retained}. Completed in {RNS.prettyshorttime(time.time()-st)}", RNS.LOG_WARNING) # TODO: Remove
if not RNS.Transport.owner.is_connected_to_shared_instance: Identity.save_known_destinations(recombine=False)
@staticmethod
def full_hash(data):
"""
+5 -1
View File
@@ -292,7 +292,11 @@ class BackboneInterface(Interface):
spawned_interface.receive(b"")
spawned_interface.transmit_buffer = spawned_interface.transmit_buffer[written:]
if len(spawned_interface.transmit_buffer) == 0: BackboneInterface.epoll.modify(fileno, select.EPOLLIN)
try:
if len(spawned_interface.transmit_buffer) == 0: BackboneInterface.epoll.modify(fileno, select.EPOLLIN)
except Exception as e:
RNS.log(f"Error while setting EPOLLIN on {spawned_interface}: {e}", RNS.LOG_ERROR)
spawned_interface.txb += written
if spawned_interface.parent_interface: spawned_interface.parent_interface.txb += written
+5 -2
View File
@@ -126,6 +126,7 @@ class Resource:
PART_TIMEOUT_FACTOR = 4
PART_TIMEOUT_FACTOR_AFTER_RTT = 2
PROOF_TIMEOUT_FACTOR = 3
HMU_WAIT_FACTOR = 3.5
MAX_RETRIES = 16
MAX_ADV_RETRIES = 4
SENDER_GRACE_TIME = 10.0
@@ -594,15 +595,16 @@ class Resource:
extra_wait = retries_used * Resource.PER_RETRY_DELAY
self.update_eifr()
expected_hmu_wait_remaining = (self.sdu*8*self.HMU_WAIT_FACTOR)/self.eifr if self.waiting_for_hmu or self.outstanding_parts == 0 else 0
expected_tof_remaining = (self.outstanding_parts*self.sdu*8)/self.eifr
if self.req_resp_rtt_rate != 0:
sleep_time = self.last_activity + self.part_timeout_factor*expected_tof_remaining + Resource.RETRY_GRACE_TIME + extra_wait - time.time()
sleep_time = self.last_activity + self.part_timeout_factor*expected_tof_remaining + expected_hmu_wait_remaining + Resource.RETRY_GRACE_TIME + extra_wait - time.time()
else:
sleep_time = self.last_activity + self.part_timeout_factor*((3*self.sdu)/self.eifr) + Resource.RETRY_GRACE_TIME + extra_wait - time.time()
# TODO: Remove debug at some point
# RNS.log(f"EIFR {RNS.prettyspeed(self.eifr)}, ETOF {RNS.prettyshorttime(expected_tof_remaining)} ", RNS.LOG_DEBUG, pt=True)
# RNS.log(f"EIFR {RNS.prettyspeed(self.eifr)}, ETOF {RNS.prettyshorttime(expected_tof_remaining)}, EHWR {RNS.prettyshorttime(expected_hmu_wait_remaining)}", RNS.LOG_DEBUG, pt=True)
# RNS.log(f"Resource ST {RNS.prettyshorttime(sleep_time)}, RTT {RNS.prettyshorttime(self.rtt or self.link.rtt)}, {self.outstanding_parts} left", RNS.LOG_DEBUG, pt=True)
if sleep_time < 0:
@@ -959,6 +961,7 @@ class Resource:
self.last_activity = time.time()
self.req_sent = self.last_activity
self.req_sent_bytes = len(request_packet.raw)
self.rtt_rxd_bytes_at_part_req = self.rtt_rxd_bytes
self.req_resp = None
except Exception as e:
+36 -1
View File
@@ -999,7 +999,8 @@ class Reticulum:
def _should_persist_data(self, background=False):
if time.time() > self.last_data_persist+Reticulum.GRACIOUS_PERSIST_INTERVAL:
def job(): self.__persist_data(background=background)
threading.Thread(target=job, daemon=True).start()
if background: threading.Thread(target=job, daemon=True).start()
else: job()
def __persist_data(self, background=False):
if Reticulum.gracious_persist_lock.locked(): return
@@ -1086,6 +1087,13 @@ class Reticulum:
identity_hash = call["unblackhole_identity"]
rpc_connection.send(self.unblackhole_identity(identity_hash))
if "destination_data" in call:
operation = call["destination_data"]
destination_hash = call["destination_hash"]
if operation == "used": rpc_connection.send(self._used_destination_data(destination_hash))
elif operation == "retain": rpc_connection.send(self._retain_destination_data(destination_hash))
elif operation == "unretain": rpc_connection.send(self._unretain_destination_data(destination_hash))
rpc_connection.close()
except Exception as e:
@@ -1093,6 +1101,33 @@ class Reticulum:
def get_rpc_client(self): return multiprocessing.connection.Client(self.rpc_addr, family=self.rpc_type, authkey=self.rpc_key)
def _used_destination_data(self, destination_hash):
if self.is_connected_to_shared_instance:
rpc_connection = self.get_rpc_client()
rpc_connection.send({"destination_data": "used", "destination_hash": destination_hash})
response = rpc_connection.recv()
return response
else: return RNS.Identity._used_destination_data(destination_hash)
def _retain_destination_data(self, destination_hash):
if self.is_connected_to_shared_instance:
rpc_connection = self.get_rpc_client()
rpc_connection.send({"destination_data": "retain", "destination_hash": destination_hash})
response = rpc_connection.recv()
return response
else: return RNS.Identity._retain_destination_data(destination_hash)
def _unretain_destination_data(self, destination_hash):
if self.is_connected_to_shared_instance:
rpc_connection = self.get_rpc_client()
rpc_connection.send({"destination_data": "unretain", "destination_hash": destination_hash})
response = rpc_connection.recv()
return response
else: return RNS.Identity._unretain_destination_data(destination_hash)
def get_interface_stats(self):
if self.is_connected_to_shared_instance:
rpc_connection = self.get_rpc_client()
+48 -10
View File
@@ -76,6 +76,7 @@ class Transport:
LOCAL_REBROADCASTS_MAX = 2 # How many local rebroadcasts of an announce is allowed
PATH_REQUEST_TIMEOUT = 15 # Default timeout for client path requests in seconds
PATH_REQUEST_GATE_TIMEOUT = 120 # Default timeout for client path request gate control in seconds
PATH_REQUEST_GRACE = 0.4 # Grace time before a path announcement is made, allows directly reachable peers to respond first
PATH_REQUEST_RG = 1.5 # Extra grace time for roaming-mode interfaces to allow more suitable peers to respond first
PATH_REQUEST_MI = 20 # Minimum interval in seconds for automated path requests
@@ -87,6 +88,7 @@ class Transport:
LINK_TIMEOUT = RNS.Link.STALE_TIME * 1.25
REVERSE_TIMEOUT = 8*60 # Reverse table entries are removed after 8 minutes
DESTINATION_TIMEOUT = 60*60*24*7 # Destination table entries are removed if unused for one week
UNUSED_DESTINATION_LINGER = 6*60 # Linger time for pathless and never used destinations
TUNNEL_TIMEOUT = 60*60*8 # Tunnel table entries are removed if unused for eight hours
TUNNEL_PATH_TIMEOUT = 60*60*8 # Tunnel path table entries are removed if unused for eight hours
MAX_RECEIPTS = 1024 # Maximum number of receipts to keep track of
@@ -177,6 +179,8 @@ class Transport:
pending_prs_check_interval = 30.0
cache_last_cleaned = 0.0
cache_clean_interval = 5*60
destinations_last_cleaned = 0.0
known_destinations_interval = 5*60
tables_last_culled = 0.0
tables_cull_interval = 5.0
interface_last_jobs = 0.0
@@ -263,6 +267,9 @@ class Transport:
# Defer cleaning packet cache for 60 seconds
Transport.cache_last_cleaned = time.time() + 60
# Defer cleaning known destinations
Transport.destinations_last_cleaned = time.time()
# Defer sending management announces for 15 seconds
Transport.last_mgmt_announce = time.time() - Transport.mgmt_announce_interval + 15
@@ -297,7 +304,7 @@ class Transport:
blackholed = False
if len(Transport.blackholed_identities) > 0:
path_identity = RNS.Identity.recall(destination_hash)
path_identity = RNS.Identity.recall(destination_hash, _no_use=True)
if path_identity in Transport.blackholed_identities: blackholed = True
del path_identity
@@ -566,7 +573,7 @@ class Transport:
announce_context = RNS.Packet.NONE
if block_rebroadcasts: announce_context = RNS.Packet.PATH_RESPONSE
announce_data = packet.data
announce_identity = RNS.Identity.recall(packet.destination_hash)
announce_identity = RNS.Identity.recall(packet.destination_hash, _no_use=True)
announce_destination = RNS.Destination(announce_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, "unknown", "unknown");
announce_destination.hash = packet.destination_hash
announce_destination.hexhash = announce_destination.hash.hex()
@@ -756,6 +763,14 @@ class Transport:
should_collect = True
RNS.log("Path to "+RNS.prettyhexrep(destination_hash)+" was removed since the attached interface no longer exists", RNS.LOG_DEBUG)
# Cull the pending path requests table
stale_path_requests = []
with Transport.path_requests_lock:
for destination_hash in Transport.path_requests:
if time.time() > Transport.path_requests[destination_hash] + Transport.PATH_REQUEST_GATE_TIMEOUT:
stale_path_requests.append(destination_hash)
RNS.log("Path request entry for "+RNS.prettyhexrep(destination_hash)+" timed out and was removed", RNS.LOG_EXTREME)
# Cull the pending discovery path requests table
stale_discovery_path_requests = []
with Transport.discovery_pr_lock:
@@ -849,6 +864,16 @@ class Transport:
if i == 1: RNS.log("Removed "+str(i)+" path", RNS.LOG_EXTREME)
else: RNS.log("Removed "+str(i)+" paths", RNS.LOG_EXTREME)
i = 0
with Transport.path_requests_lock:
for destination_hash in stale_path_requests:
Transport.path_requests.pop(destination_hash)
i += 1
if i > 0:
if i == 1: RNS.log("Removed "+str(i)+" path request entry", RNS.LOG_EXTREME)
else: RNS.log("Removed "+str(i)+" path request entries", RNS.LOG_EXTREME)
i = 0
with Transport.discovery_pr_lock:
for destination_hash in stale_discovery_path_requests:
@@ -897,6 +922,12 @@ class Transport:
def job(): Transport.clean_cache()
threading.Thread(target=job, daemon=True).start()
# Clean known destinations
if time.time() > Transport.destinations_last_cleaned+Transport.known_destinations_interval:
Transport.destinations_last_cleaned = time.time()
def job(): RNS.Identity.clean_known_destinations()
threading.Thread(target=job, daemon=True).start()
# Send announces for management destinations
if time.time() > Transport.last_mgmt_announce+Transport.mgmt_announce_interval:
try:
@@ -1824,7 +1855,7 @@ class Transport:
# If we have any local clients connected, we re-
# transmit the announce to them immediately
if (len(Transport.local_client_interfaces)):
announce_identity = RNS.Identity.recall(packet.destination_hash)
announce_identity = RNS.Identity.recall(packet.destination_hash, _no_use=True)
announce_destination = RNS.Destination(announce_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, "unknown", "unknown");
announce_destination.hash = packet.destination_hash
announce_destination.hexhash = announce_destination.hash.hex()
@@ -1878,7 +1909,7 @@ class Transport:
interface_str = " on "+str(attached_interface)
RNS.log("Got matching announce, answering waiting discovery path request for "+RNS.prettyhexrep(packet.destination_hash)+interface_str, RNS.LOG_DEBUG)
announce_identity = RNS.Identity.recall(packet.destination_hash)
announce_identity = RNS.Identity.recall(packet.destination_hash, _no_use=False)
announce_destination = RNS.Destination(announce_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, "unknown", "unknown");
announce_destination.hash = packet.destination_hash
announce_destination.hexhash = announce_destination.hash.hex()
@@ -1904,6 +1935,8 @@ class Transport:
path_table_entry = [now, received_from, announce_hops, expires, random_blobs, packet.receiving_interface, packet.packet_hash]
with Transport.path_table_lock: Transport.path_table[packet.destination_hash] = path_table_entry
RNS.log("Destination "+RNS.prettyhexrep(packet.destination_hash)+" is now "+str(announce_hops)+" hops away via "+RNS.prettyhexrep(received_from)+" on "+str(packet.receiving_interface), RNS.LOG_DEBUG)
if packet.destination_hash in Transport.path_requests:
RNS.Reticulum.get_instance()._used_destination_data(packet.destination_hash)
# If the receiving interface is a tunnel, we add the
# announce to the tunnels table
@@ -1927,7 +1960,7 @@ class Transport:
# Check that the announced destination matches
# the handlers aspect filter
execute_callback = False
announce_identity = RNS.Identity.recall(packet.destination_hash)
announce_identity = RNS.Identity.recall(packet.destination_hash, _no_use=True)
if handler.aspect_filter == None:
# If the handlers aspect filter is set to
# None, we execute the callback in all cases
@@ -1947,14 +1980,14 @@ class Transport:
def job(handler=handler, packet=packet, announce_identity=announce_identity):
handler.received_announce(destination_hash=packet.destination_hash,
announced_identity=announce_identity,
app_data=RNS.Identity.recall_app_data(packet.destination_hash))
app_data=RNS.Identity.recall_app_data(packet.destination_hash, _no_use=True))
threading.Thread(target=job, daemon=True).start()
elif len(inspect.signature(handler.received_announce).parameters) == 4:
def job(handler=handler, packet=packet, announce_identity=announce_identity):
handler.received_announce(destination_hash=packet.destination_hash,
announced_identity=announce_identity,
app_data=RNS.Identity.recall_app_data(packet.destination_hash),
app_data=RNS.Identity.recall_app_data(packet.destination_hash, _no_use=True),
announce_packet_hash = packet.packet_hash)
threading.Thread(target=job, daemon=True).start()
@@ -1962,7 +1995,7 @@ class Transport:
def job(handler=handler, packet=packet, announce_identity=announce_identity):
handler.received_announce(destination_hash=packet.destination_hash,
announced_identity=announce_identity,
app_data=RNS.Identity.recall_app_data(packet.destination_hash),
app_data=RNS.Identity.recall_app_data(packet.destination_hash, _no_use=True),
announce_packet_hash = packet.packet_hash,
is_path_response = packet.context == RNS.Packet.PATH_RESPONSE)
threading.Thread(target=job, daemon=True).start()
@@ -2070,7 +2103,7 @@ class Transport:
signalling_bytes = RNS.Link.signalling_bytes(RNS.Link.mtu_from_lp_packet(packet), RNS.Link.mode_from_lp_packet(packet))
peer_pub_bytes = packet.data[RNS.Identity.SIGLENGTH//8:RNS.Identity.SIGLENGTH//8+RNS.Link.ECPUBSIZE//2]
peer_identity = RNS.Identity.recall(link_entry[IDX_LT_DSTHASH])
peer_identity = RNS.Identity.recall(link_entry[IDX_LT_DSTHASH], _no_use=True)
peer_sig_pub_bytes = peer_identity.get_public_key()[RNS.Link.ECPUBSIZE//2:RNS.Link.ECPUBSIZE]
signed_data = packet.destination_hash+peer_pub_bytes+peer_sig_pub_bytes+signalling_bytes
@@ -2083,6 +2116,8 @@ class Transport:
new_raw += packet.raw[2:]
Transport.link_table[packet.destination_hash][IDX_LT_VALIDATED] = True
Transport.transmit(link_entry[IDX_LT_RCVD_IF], new_raw)
if not Transport.owner.is_connected_to_shared_instance:
RNS.Identity._used_destination_data(link_entry[IDX_LT_DSTHASH])
else:
RNS.log("Invalid link request proof in transport for link "+RNS.prettyhexrep(packet.destination_hash)+", dropping proof.", RNS.LOG_DEBUG)
@@ -2814,6 +2849,7 @@ class Transport:
destination_exists_on_local_client = True
with Transport.pending_local_prs_lock:
Transport.pending_local_path_requests[destination_hash] = attached_interface
RNS.Reticulum.get_instance()._used_destination_data(destination_hash)
local_destination = None
with Transport.destinations_map_lock:
@@ -2884,6 +2920,8 @@ class Transport:
with Transport.announce_table_lock:
Transport.announce_table[packet.destination_hash] = [now, retransmit_timeout, retries, received_from, announce_hops, packet, local_rebroadcasts, block_rebroadcasts, attached_interface]
if not Transport.owner.is_connected_to_shared_instance: RNS.Identity._used_destination_data(packet.destination_hash)
elif is_from_local_client:
# Forward path request on all interfaces
# except the local client
@@ -3326,7 +3364,7 @@ class Transport:
drop_destinations = []
for destination_hash in Transport.path_table.copy():
try:
associated_identity = RNS.Identity.recall(destination_hash)
associated_identity = RNS.Identity.recall(destination_hash, _no_use=True)
if associated_identity and associated_identity.hash in Transport.blackholed_identities:
if not destination_hash in drop_destinations: drop_destinations.append(destination_hash)
except Exception as e:
+1 -1
View File
@@ -1 +1 @@
__version__ = "1.1.6"
__version__ = "1.1.7"
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 76bb8ae3fb1a993b055966a4ef5900e1
config: 93f6eab163a291fbdb28b0b7666c1971
tags: 645f666f9bcd5a90fca523b33c5a78b7
+1 -1
View File
@@ -1,5 +1,5 @@
const DOCUMENTATION_OPTIONS = {
VERSION: '1.1.6',
VERSION: '1.1.7',
LANGUAGE: 'en',
COLLAPSE_INDEX: false,
BUILDER: 'html',
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Code Examples - Reticulum Network Stack 1.1.6 documentation</title>
<title>Code Examples - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -3663,7 +3663,7 @@ will be fully on-par with natively included interfaces, including all supported
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 1.1.6 documentation</title>
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -294,7 +294,7 @@
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -5,7 +5,7 @@
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="#"><link rel="search" title="Search" href="search.html">
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 --><title>Index - Reticulum Network Stack 1.1.6 documentation</title>
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 --><title>Index - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -178,7 +178,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -202,7 +202,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -836,7 +836,7 @@
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Getting Started Fast - Reticulum Network Stack 1.1.6 documentation</title>
<title>Getting Started Fast - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -966,7 +966,7 @@ All other available modules will still be loaded when needed.</p>
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Communications Hardware - Reticulum Network Stack 1.1.6 documentation</title>
<title>Communications Hardware - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -674,7 +674,7 @@ can be used with Reticulum. This includes virtual software modems such as
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Reticulum Network Stack 1.1.6 documentation</title>
<title>Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="#"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="#"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -631,7 +631,7 @@ to participate in the development of Reticulum itself.</p>
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Configuring Interfaces - Reticulum Network Stack 1.1.6 documentation</title>
<title>Configuring Interfaces - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -1684,7 +1684,7 @@ to <code class="docutils literal notranslate"><span class="pre">30</span></code>
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Reticulum License - Reticulum Network Stack 1.1.6 documentation</title>
<title>Reticulum License - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -343,7 +343,7 @@ SOFTWARE.
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Building Networks - Reticulum Network Stack 1.1.6 documentation</title>
<title>Building Networks - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -662,7 +662,7 @@ differently than a mobile device roaming between radio cells.</p>
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
Binary file not shown.
+6 -6
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>API Reference - Reticulum Network Stack 1.1.6 documentation</title>
<title>API Reference - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -506,7 +506,7 @@ for addressable hashes and other purposes. Non-configurable.</p>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.Identity.recall">
<em class="property"><span class="k"><span class="pre">static</span></span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">recall</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">target_hash</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">from_identity_hash</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.Identity.recall" title="Link to this definition"></a></dt>
<em class="property"><span class="k"><span class="pre">static</span></span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">recall</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">target_hash</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">from_identity_hash</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">_no_use</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.Identity.recall" title="Link to this definition"></a></dt>
<dd><p>Recall identity for a destination or identity hash. By default, this function
will return the identity associated with a given <em>destination</em> hash. As an
example, if you know the <code class="docutils literal notranslate"><span class="pre">lxmf.delivery</span></code> destination hash of an endpoint,
@@ -528,7 +528,7 @@ search for an identity from a known <em>identity hash</em>, by setting the
<dl class="py method">
<dt class="sig sig-object py" id="RNS.Identity.recall_app_data">
<em class="property"><span class="k"><span class="pre">static</span></span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">recall_app_data</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.Identity.recall_app_data" title="Link to this definition"></a></dt>
<em class="property"><span class="k"><span class="pre">static</span></span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">recall_app_data</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">destination_hash</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">_no_use</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.Identity.recall_app_data" title="Link to this definition"></a></dt>
<dd><p>Recall last heard app_data for a destination hash.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
@@ -2472,7 +2472,7 @@ will announce it.</p>
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -8,7 +8,7 @@
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<meta name="robots" content="noindex" />
<title>Search - Reticulum Network Stack 1.1.6 documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<title>Search - Reticulum Network Stack 1.1.7 documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?v=8dab3a3b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="#" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -302,7 +302,7 @@
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Programs Using Reticulum - Reticulum Network Stack 1.1.6 documentation</title>
<title>Programs Using Reticulum - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -533,7 +533,7 @@ using LXMF.</p>
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Support Reticulum - Reticulum Network Stack 1.1.6 documentation</title>
<title>Support Reticulum - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -381,7 +381,7 @@ circumstances, so we rely on old-fashioned human feedback.</p>
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Understanding Reticulum - Reticulum Network Stack 1.1.6 documentation</title>
<title>Understanding Reticulum - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -1336,7 +1336,7 @@ those risks are acceptable to you.</p>
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Using Reticulum on Your System - Reticulum Network Stack 1.1.6 documentation</title>
<title>Using Reticulum on Your System - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -1395,7 +1395,7 @@ systemctl --user enable rnsd.service
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>What is Reticulum? - Reticulum Network Stack 1.1.6 documentation</title>
<title>What is Reticulum? - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -503,7 +503,7 @@ network, and vice versa.</p>
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>
+4 -4
View File
@@ -7,7 +7,7 @@
<link rel="prefetch" href="_static/rns_logo_512.png" as="image">
<!-- Generated with Sphinx 8.2.3 and Furo 2025.09.25.dev1 -->
<title>Zen of Reticulum - Reticulum Network Stack 1.1.6 documentation</title>
<title>Zen of Reticulum - Reticulum Network Stack 1.1.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d111a655" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?v=580074bf" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
@@ -180,7 +180,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.6 documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 1.1.7 documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@@ -204,7 +204,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.6 documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 1.1.7 documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
@@ -675,7 +675,7 @@ Imagine a messaging app. You write it once. It works on a laptop connected to fi
</aside>
</div>
</div><script src="_static/documentation_options.js?v=937269b5"></script>
</div><script src="_static/documentation_options.js?v=370aedac"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/scripts/furo.js?v=46bd48cc"></script>