mirror of
https://github.com/markqvist/Reticulum.git
synced 2026-07-26 09:38:14 -07:00
Refactoring work for free-threaded transport I/O. Added ingress control bypass on pending path requests.
This commit is contained in:
+12
-22
@@ -295,33 +295,26 @@ class Destination:
|
|||||||
app_data = returned_app_data
|
app_data = returned_app_data
|
||||||
|
|
||||||
signed_data = self.hash+self.identity.get_public_key()+self.name_hash+random_hash+ratchet
|
signed_data = self.hash+self.identity.get_public_key()+self.name_hash+random_hash+ratchet
|
||||||
if app_data != None:
|
if app_data != None: signed_data += app_data
|
||||||
signed_data += app_data
|
|
||||||
|
|
||||||
signature = self.identity.sign(signed_data)
|
signature = self.identity.sign(signed_data)
|
||||||
announce_data = self.identity.get_public_key()+self.name_hash+random_hash+ratchet+signature
|
announce_data = self.identity.get_public_key()+self.name_hash+random_hash+ratchet+signature
|
||||||
|
|
||||||
if app_data != None:
|
if app_data != None: announce_data += app_data
|
||||||
announce_data += app_data
|
|
||||||
|
|
||||||
self.path_responses[tag] = [time.time(), announce_data]
|
self.path_responses[tag] = [time.time(), announce_data]
|
||||||
|
|
||||||
if path_response:
|
if path_response: announce_context = RNS.Packet.PATH_RESPONSE
|
||||||
announce_context = RNS.Packet.PATH_RESPONSE
|
else: announce_context = RNS.Packet.NONE
|
||||||
else:
|
|
||||||
announce_context = RNS.Packet.NONE
|
|
||||||
|
|
||||||
if ratchet:
|
if ratchet: context_flag = RNS.Packet.FLAG_SET
|
||||||
context_flag = RNS.Packet.FLAG_SET
|
else: context_flag = RNS.Packet.FLAG_UNSET
|
||||||
else:
|
|
||||||
context_flag = RNS.Packet.FLAG_UNSET
|
|
||||||
|
|
||||||
announce_packet = RNS.Packet(self, announce_data, RNS.Packet.ANNOUNCE, context = announce_context,
|
announce_packet = RNS.Packet(self, announce_data, RNS.Packet.ANNOUNCE, context = announce_context,
|
||||||
attached_interface = attached_interface, context_flag=context_flag)
|
attached_interface = attached_interface, context_flag=context_flag)
|
||||||
if send:
|
|
||||||
announce_packet.send()
|
if send: announce_packet.send()
|
||||||
else:
|
else: return announce_packet
|
||||||
return announce_packet
|
|
||||||
|
|
||||||
def accepts_links(self, accepts = None):
|
def accepts_links(self, accepts = None):
|
||||||
"""
|
"""
|
||||||
@@ -330,13 +323,10 @@ class Destination:
|
|||||||
:param accepts: If ``True`` or ``False``, this method sets whether the destination accepts incoming link requests. If not provided or ``None``, the method returns whether the destination currently accepts link requests.
|
:param accepts: If ``True`` or ``False``, this method sets whether the destination accepts incoming link requests. If not provided or ``None``, the method returns whether the destination currently accepts link requests.
|
||||||
:returns: ``True`` or ``False`` depending on whether the destination accepts incoming link requests, if the *accepts* parameter is not provided or ``None``.
|
:returns: ``True`` or ``False`` depending on whether the destination accepts incoming link requests, if the *accepts* parameter is not provided or ``None``.
|
||||||
"""
|
"""
|
||||||
if accepts == None:
|
if accepts == None: return self.accept_link_requests
|
||||||
return self.accept_link_requests
|
|
||||||
|
|
||||||
if accepts:
|
if accepts: self.accept_link_requests = True
|
||||||
self.accept_link_requests = True
|
else: self.accept_link_requests = False
|
||||||
else:
|
|
||||||
self.accept_link_requests = False
|
|
||||||
|
|
||||||
def set_link_established_callback(self, callback):
|
def set_link_established_callback(self, callback):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ class Interface:
|
|||||||
|
|
||||||
# How many samples to use for announce
|
# How many samples to use for announce
|
||||||
# frequency calculations
|
# frequency calculations
|
||||||
IA_FREQ_SAMPLES = 12
|
IA_FREQ_SAMPLES = 128
|
||||||
OA_FREQ_SAMPLES = 12
|
OA_FREQ_SAMPLES = 128
|
||||||
|
|
||||||
# Maximum amount of ingress limited announces
|
# Maximum amount of ingress limited announces
|
||||||
# to hold at any given time.
|
# to hold at any given time.
|
||||||
@@ -66,12 +66,12 @@ class Interface:
|
|||||||
# considered to be newly created. Two
|
# considered to be newly created. Two
|
||||||
# hours by default.
|
# hours by default.
|
||||||
IC_NEW_TIME = 2*60*60
|
IC_NEW_TIME = 2*60*60
|
||||||
IC_BURST_FREQ_NEW = 3.5
|
IC_BURST_FREQ_NEW = 6
|
||||||
IC_BURST_FREQ = 12
|
IC_BURST_FREQ = 35
|
||||||
IC_BURST_HOLD = 1*60
|
IC_BURST_HOLD = 1*60
|
||||||
IC_BURST_PENALTY = 5*60
|
IC_BURST_PENALTY = 15
|
||||||
IC_HELD_RELEASE_INTERVAL = 30
|
IC_HELD_RELEASE_INTERVAL = 2
|
||||||
IC_DEQUE_MIN_SAMPLE = 8
|
IC_DEQUE_MIN_SAMPLE = 32
|
||||||
|
|
||||||
AUTOCONFIGURE_MTU = False
|
AUTOCONFIGURE_MTU = False
|
||||||
FIXED_MTU = False
|
FIXED_MTU = False
|
||||||
@@ -123,13 +123,14 @@ class Interface:
|
|||||||
if self.ic_burst_active:
|
if self.ic_burst_active:
|
||||||
if ia_freq < freq_threshold and time.time() > self.ic_burst_activated+self.ic_burst_hold:
|
if ia_freq < freq_threshold and time.time() > self.ic_burst_activated+self.ic_burst_hold:
|
||||||
self.ic_burst_active = False
|
self.ic_burst_active = False
|
||||||
self.ic_held_release = time.time() + self.ic_burst_penalty
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if ia_freq > freq_threshold:
|
if ia_freq > freq_threshold:
|
||||||
self.ic_burst_active = True
|
self.ic_burst_active = True
|
||||||
self.ic_burst_activated = time.time()
|
self.ic_burst_activated = time.time()
|
||||||
|
self.ic_held_release = time.time() + self.ic_burst_penalty
|
||||||
return True
|
return True
|
||||||
|
|
||||||
else: return False
|
else: return False
|
||||||
@@ -174,7 +175,7 @@ class Interface:
|
|||||||
|
|
||||||
def process_held_announces(self):
|
def process_held_announces(self):
|
||||||
try:
|
try:
|
||||||
if not self.should_ingress_limit() and len(self.held_announces) > 0 and time.time() > self.ic_held_release:
|
if len(self.held_announces) > 0 and time.time() > self.ic_held_release:
|
||||||
freq_threshold = self.ic_burst_freq_new if self.age() < self.ic_new_time else self.ic_burst_freq
|
freq_threshold = self.ic_burst_freq_new if self.age() < self.ic_new_time else self.ic_burst_freq
|
||||||
ia_freq = self.incoming_announce_frequency()
|
ia_freq = self.incoming_announce_frequency()
|
||||||
if ia_freq < freq_threshold:
|
if ia_freq < freq_threshold:
|
||||||
|
|||||||
+4
-8
@@ -722,12 +722,9 @@ class Link:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def link_closed(self):
|
def link_closed(self):
|
||||||
for resource in self.incoming_resources:
|
for resource in self.incoming_resources: resource.cancel()
|
||||||
resource.cancel()
|
for resource in self.outgoing_resources: resource.cancel()
|
||||||
for resource in self.outgoing_resources:
|
if self._channel: self._channel._shutdown()
|
||||||
resource.cancel()
|
|
||||||
if self._channel:
|
|
||||||
self._channel._shutdown()
|
|
||||||
|
|
||||||
self.prv = None
|
self.prv = None
|
||||||
self.pub = None
|
self.pub = None
|
||||||
@@ -741,8 +738,7 @@ class Link:
|
|||||||
self.destination.links.remove(self)
|
self.destination.links.remove(self)
|
||||||
|
|
||||||
if self.callbacks.link_closed != None:
|
if self.callbacks.link_closed != None:
|
||||||
try:
|
try: self.callbacks.link_closed(self)
|
||||||
self.callbacks.link_closed(self)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing link closed callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Error while executing link closed callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
|||||||
+137
-115
@@ -360,7 +360,7 @@ class Transport:
|
|||||||
|
|
||||||
if len(tunnel_paths) > 0:
|
if len(tunnel_paths) > 0:
|
||||||
tunnel = [tunnel_id, None, tunnel_paths, expires]
|
tunnel = [tunnel_id, None, tunnel_paths, expires]
|
||||||
Transport.tunnels[tunnel_id] = tunnel
|
with Transport.tunnels_lock: Transport.tunnels[tunnel_id] = tunnel
|
||||||
|
|
||||||
if len(Transport.path_table) == 1: specifier = "entry"
|
if len(Transport.path_table) == 1: specifier = "entry"
|
||||||
else: specifier = "entries"
|
else: specifier = "entries"
|
||||||
@@ -908,6 +908,7 @@ class Transport:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An exception occurred while running Transport jobs.", RNS.LOG_ERROR)
|
RNS.log("An exception occurred while running Transport jobs.", RNS.LOG_ERROR)
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
RNS.trace_exception(e) # TODO: Remove
|
||||||
|
|
||||||
for packet in outgoing: packet.send()
|
for packet in outgoing: packet.send()
|
||||||
|
|
||||||
@@ -1553,12 +1554,17 @@ class Transport:
|
|||||||
# potential ingress limiting. Already known
|
# potential ingress limiting. Already known
|
||||||
# destinations will have re-announces controlled
|
# destinations will have re-announces controlled
|
||||||
# by normal announce rate limiting.
|
# by normal announce rate limiting.
|
||||||
if interface.should_ingress_limit():
|
if packet.destination_hash in Transport.path_requests or packet.destination_hash in Transport.discovery_path_requests:
|
||||||
|
# RNS.log(f"Skipping ingress limit check for {RNS.prettyhexrep(packet.destination_hash)} due to waiting path requests", RNS.LOG_DEBUG)
|
||||||
|
pass
|
||||||
|
|
||||||
|
elif interface.should_ingress_limit():
|
||||||
interface.hold_announce(packet)
|
interface.hold_announce(packet)
|
||||||
return
|
return
|
||||||
|
|
||||||
with Transport.destinations_lock:
|
with Transport.destinations_lock:
|
||||||
local_destination = next((d for d in Transport.destinations if d.hash == packet.destination_hash), None)
|
local_destination = next((d for d in Transport.destinations if d.hash == packet.destination_hash), None)
|
||||||
|
|
||||||
if local_destination == None and RNS.Identity.validate_announce(packet):
|
if local_destination == None and RNS.Identity.validate_announce(packet):
|
||||||
if packet.transport_id != None:
|
if packet.transport_id != None:
|
||||||
received_from = packet.transport_id
|
received_from = packet.transport_id
|
||||||
@@ -1575,14 +1581,15 @@ class Transport:
|
|||||||
if announce_entry[IDX_AT_RETRIES] > 0:
|
if announce_entry[IDX_AT_RETRIES] > 0:
|
||||||
if announce_entry[IDX_AT_LCL_RBRD] >= Transport.LOCAL_REBROADCASTS_MAX:
|
if announce_entry[IDX_AT_LCL_RBRD] >= Transport.LOCAL_REBROADCASTS_MAX:
|
||||||
RNS.log("Completed announce processing for "+RNS.prettyhexrep(packet.destination_hash)+", local rebroadcast limit reached", RNS.LOG_EXTREME)
|
RNS.log("Completed announce processing for "+RNS.prettyhexrep(packet.destination_hash)+", local rebroadcast limit reached", RNS.LOG_EXTREME)
|
||||||
if packet.destination_hash in Transport.announce_table: Transport.announce_table.pop(packet.destination_hash)
|
with Transport.announce_table_lock:
|
||||||
|
if packet.destination_hash in Transport.announce_table: Transport.announce_table.pop(packet.destination_hash)
|
||||||
|
|
||||||
if packet.hops-1 == announce_entry[IDX_AT_HOPS]+1 and announce_entry[IDX_AT_RETRIES] > 0:
|
if packet.hops-1 == announce_entry[IDX_AT_HOPS]+1 and announce_entry[IDX_AT_RETRIES] > 0:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now < announce_entry[IDX_AT_RTRNS_TMO]:
|
if now < announce_entry[IDX_AT_RTRNS_TMO]:
|
||||||
RNS.log("Rebroadcasted announce for "+RNS.prettyhexrep(packet.destination_hash)+" has been passed on to another node, no further tries needed", RNS.LOG_EXTREME)
|
RNS.log("Rebroadcasted announce for "+RNS.prettyhexrep(packet.destination_hash)+" has been passed on to another node, no further tries needed", RNS.LOG_EXTREME)
|
||||||
if packet.destination_hash in Transport.announce_table:
|
with Transport.announce_table_lock:
|
||||||
Transport.announce_table.pop(packet.destination_hash)
|
if packet.destination_hash in Transport.announce_table: Transport.announce_table.pop(packet.destination_hash)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
received_from = packet.destination_hash
|
received_from = packet.destination_hash
|
||||||
@@ -1706,9 +1713,7 @@ class Transport:
|
|||||||
else:
|
else:
|
||||||
rate_entry["last"] = now
|
rate_entry["last"] = now
|
||||||
|
|
||||||
else:
|
else: rate_blocked = True
|
||||||
rate_blocked = True
|
|
||||||
|
|
||||||
|
|
||||||
retries = 0
|
retries = 0
|
||||||
announce_hops = packet.hops
|
announce_hops = packet.hops
|
||||||
@@ -1961,29 +1966,31 @@ class Transport:
|
|||||||
# Handling for local data packets
|
# Handling for local data packets
|
||||||
elif packet.packet_type == RNS.Packet.DATA:
|
elif packet.packet_type == RNS.Packet.DATA:
|
||||||
if packet.destination_type == RNS.Destination.LINK:
|
if packet.destination_type == RNS.Destination.LINK:
|
||||||
for link in Transport.active_links:
|
with Transport.active_links_lock:
|
||||||
if link.link_id == packet.destination_hash:
|
for link in Transport.active_links:
|
||||||
if link.attached_interface == packet.receiving_interface:
|
if link.link_id == packet.destination_hash:
|
||||||
packet.link = link
|
if link.attached_interface == packet.receiving_interface:
|
||||||
if packet.context == RNS.Packet.CACHE_REQUEST:
|
packet.link = link
|
||||||
cached_packet = Transport.get_cached_packet(packet.data)
|
if packet.context == RNS.Packet.CACHE_REQUEST:
|
||||||
if cached_packet != None:
|
cached_packet = Transport.get_cached_packet(packet.data)
|
||||||
cached_packet.unpack()
|
if cached_packet != None:
|
||||||
RNS.Packet(destination=link, data=cached_packet.data,
|
cached_packet.unpack()
|
||||||
packet_type=cached_packet.packet_type, context=cached_packet.context).send()
|
RNS.Packet(destination=link, data=cached_packet.data,
|
||||||
|
packet_type=cached_packet.packet_type, context=cached_packet.context).send()
|
||||||
|
|
||||||
else: link.receive(packet)
|
else: link.receive(packet)
|
||||||
|
break
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# In the strange and rare case that an interface
|
# In the strange and rare case that an interface
|
||||||
# is partly malfunctioning, and a link-associated
|
# is partly malfunctioning, and a link-associated
|
||||||
# packet is being received on an interface that
|
# packet is being received on an interface that
|
||||||
# has failed sending, and transport has failed over
|
# has failed sending, and transport has failed over
|
||||||
# to another path, we remove this packet hash from
|
# to another path, we remove this packet hash from
|
||||||
# the filter hashlist so the link can receive the
|
# the filter hashlist so the link can receive the
|
||||||
# packet when it finally arrives over another path.
|
# packet when it finally arrives over another path.
|
||||||
while packet.packet_hash in Transport.packet_hashlist:
|
while packet.packet_hash in Transport.packet_hashlist:
|
||||||
Transport.packet_hashlist.remove(packet.packet_hash)
|
Transport.packet_hashlist.remove(packet.packet_hash)
|
||||||
else:
|
else:
|
||||||
for destination in Transport.destinations:
|
for destination in Transport.destinations:
|
||||||
if destination.hash == packet.destination_hash and destination.type == packet.destination_type:
|
if destination.hash == packet.destination_hash and destination.type == packet.destination_type:
|
||||||
@@ -1997,6 +2004,7 @@ class Transport:
|
|||||||
if destination.callbacks.proof_requested(packet): packet.prove()
|
if destination.callbacks.proof_requested(packet): packet.prove()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing proof request callback. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Error while executing proof request callback. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
break
|
||||||
|
|
||||||
# Handling for proofs and link-request proofs
|
# Handling for proofs and link-request proofs
|
||||||
elif packet.packet_type == RNS.Packet.PROOF:
|
elif packet.packet_type == RNS.Packet.PROOF:
|
||||||
@@ -2038,48 +2046,57 @@ class Transport:
|
|||||||
RNS.log("Link request proof received on wrong interface, not transporting it.", RNS.LOG_DEBUG)
|
RNS.log("Link request proof received on wrong interface, not transporting it.", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
RNS.log("Received link request proof with hop mismatch, not transporting it", RNS.LOG_DEBUG)
|
RNS.log("Received link request proof with hop mismatch, not transporting it", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Check if we can deliver it to a local
|
# Check if we can deliver it to a local
|
||||||
# pending link
|
# pending link
|
||||||
for link in Transport.pending_links:
|
|
||||||
if link.link_id == packet.destination_hash:
|
|
||||||
# We need to also allow an expected hops value of
|
|
||||||
# PATHFINDER_M, since in some cases, the number of hops
|
|
||||||
# to the destination will be unknown at link creation
|
|
||||||
# time. The real chance of this occuring is likely to be
|
|
||||||
# extremely small, and this allowance could probably
|
|
||||||
# be discarded without major issues, but it is kept
|
|
||||||
# for now to ensure backwards compatibility.
|
|
||||||
|
|
||||||
# TODO: Probably reset check back to
|
pending_link = None
|
||||||
# if packet.hops == link.expected_hops:
|
with Transport.pending_links_lock:
|
||||||
# within one of the next releases
|
for link in Transport.pending_links:
|
||||||
|
if link.link_id == packet.destination_hash:
|
||||||
|
# We need to also allow an expected hops value of
|
||||||
|
# PATHFINDER_M, since in some cases, the number of hops
|
||||||
|
# to the destination will be unknown at link creation
|
||||||
|
# time. The real chance of this occuring is likely to be
|
||||||
|
# extremely small, and this allowance could probably
|
||||||
|
# be discarded without major issues, but it is kept
|
||||||
|
# for now to ensure backwards compatibility.
|
||||||
|
|
||||||
if packet.hops == link.expected_hops or link.expected_hops == RNS.Transport.PATHFINDER_M:
|
# TODO: Probably reset check back to
|
||||||
# Add this packet to the filter hashlist if we
|
# if packet.hops == link.expected_hops:
|
||||||
# have determined that it's actually destined
|
# within one of the next releases
|
||||||
# for this system, and then validate the proof
|
|
||||||
Transport.add_packet_hash(packet.packet_hash)
|
if packet.hops == link.expected_hops or link.expected_hops == RNS.Transport.PATHFINDER_M:
|
||||||
link.validate_proof(packet)
|
# Add this packet to the filter hashlist if we
|
||||||
|
# have determined that it's actually destined
|
||||||
|
# for this system, and then validate the proof
|
||||||
|
Transport.add_packet_hash(packet.packet_hash)
|
||||||
|
pending_link = link
|
||||||
|
break
|
||||||
|
|
||||||
|
if pending_link: pending_link.validate_proof(packet)
|
||||||
|
|
||||||
elif packet.context == RNS.Packet.RESOURCE_PRF:
|
elif packet.context == RNS.Packet.RESOURCE_PRF:
|
||||||
for link in Transport.active_links:
|
with Transport.active_links_lock:
|
||||||
if link.link_id == packet.destination_hash:
|
|
||||||
link.receive(packet)
|
|
||||||
else:
|
|
||||||
if packet.destination_type == RNS.Destination.LINK:
|
|
||||||
for link in Transport.active_links:
|
for link in Transport.active_links:
|
||||||
if link.link_id == packet.destination_hash:
|
if link.link_id == packet.destination_hash:
|
||||||
packet.link = link
|
link.receive(packet)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if packet.destination_type == RNS.Destination.LINK:
|
||||||
|
with Transport.active_links_lock:
|
||||||
|
for link in Transport.active_links:
|
||||||
|
if link.link_id == packet.destination_hash:
|
||||||
|
packet.link = link
|
||||||
|
break
|
||||||
|
|
||||||
if len(packet.data) == RNS.PacketReceipt.EXPL_LENGTH:
|
if len(packet.data) == RNS.PacketReceipt.EXPL_LENGTH: proof_hash = packet.data[:RNS.Identity.HASHLENGTH//8]
|
||||||
proof_hash = packet.data[:RNS.Identity.HASHLENGTH//8]
|
else: proof_hash = None
|
||||||
else:
|
|
||||||
proof_hash = None
|
|
||||||
|
|
||||||
# Check if this proof needs to be transported
|
# Check if this proof needs to be transported
|
||||||
if (RNS.Reticulum.transport_enabled() or from_local_client or proof_for_local_client) and packet.destination_hash in Transport.reverse_table:
|
if (RNS.Reticulum.transport_enabled() or from_local_client or proof_for_local_client) and packet.destination_hash in Transport.reverse_table:
|
||||||
reverse_entry = Transport.reverse_table.pop(packet.destination_hash)
|
with Transport.reverse_table_lock: reverse_entry = Transport.reverse_table.pop(packet.destination_hash)
|
||||||
if packet.receiving_interface == reverse_entry[IDX_RT_OUTB_IF]:
|
if packet.receiving_interface == reverse_entry[IDX_RT_OUTB_IF]:
|
||||||
RNS.log("Proof received on correct interface, transporting it via "+str(reverse_entry[IDX_RT_RCVD_IF]), RNS.LOG_EXTREME)
|
RNS.log("Proof received on correct interface, transporting it via "+str(reverse_entry[IDX_RT_RCVD_IF]), RNS.LOG_EXTREME)
|
||||||
new_raw = packet.raw[0:1]
|
new_raw = packet.raw[0:1]
|
||||||
@@ -2089,20 +2106,21 @@ class Transport:
|
|||||||
else:
|
else:
|
||||||
RNS.log("Proof received on wrong interface, not transporting it.", RNS.LOG_DEBUG)
|
RNS.log("Proof received on wrong interface, not transporting it.", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
for receipt in Transport.receipts:
|
with Transport.receipts_lock:
|
||||||
receipt_validated = False
|
for receipt in Transport.receipts:
|
||||||
if proof_hash != None:
|
receipt_validated = False
|
||||||
# Only test validation if hash matches
|
if proof_hash != None:
|
||||||
if receipt.hash == proof_hash:
|
# Only test validation if hash matches
|
||||||
|
if receipt.hash == proof_hash:
|
||||||
|
receipt_validated = receipt.validate_proof_packet(packet)
|
||||||
|
else:
|
||||||
|
# In case of an implicit proof, we have
|
||||||
|
# to check every single outstanding receipt
|
||||||
receipt_validated = receipt.validate_proof_packet(packet)
|
receipt_validated = receipt.validate_proof_packet(packet)
|
||||||
else:
|
|
||||||
# In case of an implicit proof, we have
|
|
||||||
# to check every single outstanding receipt
|
|
||||||
receipt_validated = receipt.validate_proof_packet(packet)
|
|
||||||
|
|
||||||
if receipt_validated:
|
if receipt_validated:
|
||||||
if receipt in Transport.receipts:
|
if receipt in Transport.receipts:
|
||||||
Transport.receipts.remove(receipt)
|
Transport.receipts.remove(receipt)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def synthesize_tunnel(interface):
|
def synthesize_tunnel(interface):
|
||||||
@@ -2151,9 +2169,10 @@ class Transport:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def void_tunnel_interface(tunnel_id):
|
def void_tunnel_interface(tunnel_id):
|
||||||
if tunnel_id in Transport.tunnels:
|
with Transport.tunnels_lock:
|
||||||
RNS.log(f"Voiding tunnel interface {Transport.tunnels[tunnel_id][IDX_TT_IF]}", RNS.LOG_EXTREME)
|
if tunnel_id in Transport.tunnels:
|
||||||
Transport.tunnels[tunnel_id][IDX_TT_IF] = None
|
RNS.log(f"Voiding tunnel interface {Transport.tunnels[tunnel_id][IDX_TT_IF]}", RNS.LOG_EXTREME)
|
||||||
|
Transport.tunnels[tunnel_id][IDX_TT_IF] = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handle_tunnel(tunnel_id, interface):
|
def handle_tunnel(tunnel_id, interface):
|
||||||
@@ -2161,9 +2180,10 @@ class Transport:
|
|||||||
if not tunnel_id in Transport.tunnels:
|
if not tunnel_id in Transport.tunnels:
|
||||||
RNS.log("Tunnel endpoint "+RNS.prettyhexrep(tunnel_id)+" established.", RNS.LOG_DEBUG)
|
RNS.log("Tunnel endpoint "+RNS.prettyhexrep(tunnel_id)+" established.", RNS.LOG_DEBUG)
|
||||||
paths = {}
|
paths = {}
|
||||||
tunnel_entry = [tunnel_id, interface, paths, expires]
|
with Transport.tunnels_lock:
|
||||||
interface.tunnel_id = tunnel_id
|
tunnel_entry = [tunnel_id, interface, paths, expires]
|
||||||
Transport.tunnels[tunnel_id] = tunnel_entry
|
interface.tunnel_id = tunnel_id
|
||||||
|
Transport.tunnels[tunnel_id] = tunnel_entry
|
||||||
else:
|
else:
|
||||||
RNS.log("Tunnel endpoint "+RNS.prettyhexrep(tunnel_id)+" reappeared. Restoring paths...", RNS.LOG_DEBUG)
|
RNS.log("Tunnel endpoint "+RNS.prettyhexrep(tunnel_id)+" reappeared. Restoring paths...", RNS.LOG_DEBUG)
|
||||||
tunnel_entry = Transport.tunnels[tunnel_id]
|
tunnel_entry = Transport.tunnels[tunnel_id]
|
||||||
@@ -2173,36 +2193,38 @@ class Transport:
|
|||||||
paths = tunnel_entry[IDX_TT_PATHS]
|
paths = tunnel_entry[IDX_TT_PATHS]
|
||||||
|
|
||||||
deprecated_paths = []
|
deprecated_paths = []
|
||||||
for destination_hash, path_entry in paths.items():
|
with Transport.tunnels_lock:
|
||||||
received_from = path_entry[1]
|
for destination_hash, path_entry in paths.items():
|
||||||
announce_hops = path_entry[2]
|
received_from = path_entry[1]
|
||||||
expires = path_entry[3]
|
announce_hops = path_entry[2]
|
||||||
random_blobs = list(set(path_entry[4]))
|
expires = path_entry[3]
|
||||||
receiving_interface = interface
|
random_blobs = list(set(path_entry[4]))
|
||||||
packet_hash = path_entry[6]
|
receiving_interface = interface
|
||||||
new_entry = [time.time(), received_from, announce_hops, expires, random_blobs, receiving_interface, packet_hash]
|
packet_hash = path_entry[6]
|
||||||
|
new_entry = [time.time(), received_from, announce_hops, expires, random_blobs, receiving_interface, packet_hash]
|
||||||
|
|
||||||
should_add = False
|
should_add = False
|
||||||
if destination_hash in Transport.path_table:
|
with Transport.path_table_lock:
|
||||||
old_entry = Transport.path_table[destination_hash]
|
if destination_hash in Transport.path_table:
|
||||||
old_hops = old_entry[IDX_PT_HOPS]
|
old_entry = Transport.path_table[destination_hash]
|
||||||
old_expires = old_entry[IDX_PT_EXPIRES]
|
old_hops = old_entry[IDX_PT_HOPS]
|
||||||
if announce_hops <= old_hops or time.time() > old_expires: should_add = True
|
old_expires = old_entry[IDX_PT_EXPIRES]
|
||||||
else: RNS.log("Did not restore path to "+RNS.prettyhexrep(destination_hash)+" because a newer path with fewer hops exist", RNS.LOG_DEBUG)
|
if announce_hops <= old_hops or time.time() > old_expires: should_add = True
|
||||||
|
else: RNS.log("Did not restore path to "+RNS.prettyhexrep(destination_hash)+" because a newer path with fewer hops exist", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if time.time() < expires: should_add = True
|
if time.time() < expires: should_add = True
|
||||||
else: RNS.log("Did not restore path to "+RNS.prettyhexrep(destination_hash)+" because it has expired", RNS.LOG_DEBUG)
|
else: RNS.log("Did not restore path to "+RNS.prettyhexrep(destination_hash)+" because it has expired", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
if should_add:
|
if should_add:
|
||||||
Transport.path_table[destination_hash] = new_entry
|
with Transport.path_table_lock: Transport.path_table[destination_hash] = new_entry
|
||||||
RNS.log("Restored path to "+RNS.prettyhexrep(destination_hash)+" is now "+str(announce_hops)+" hops away via "+RNS.prettyhexrep(received_from)+" on "+str(receiving_interface), RNS.LOG_DEBUG)
|
RNS.log("Restored path to "+RNS.prettyhexrep(destination_hash)+" is now "+str(announce_hops)+" hops away via "+RNS.prettyhexrep(received_from)+" on "+str(receiving_interface), RNS.LOG_DEBUG)
|
||||||
else:
|
|
||||||
deprecated_paths.append(destination_hash)
|
else: deprecated_paths.append(destination_hash)
|
||||||
|
|
||||||
for deprecated_path in deprecated_paths:
|
for deprecated_path in deprecated_paths:
|
||||||
RNS.log("Removing path to "+RNS.prettyhexrep(deprecated_path)+" from tunnel "+RNS.prettyhexrep(tunnel_id), RNS.LOG_DEBUG)
|
RNS.log("Removing path to "+RNS.prettyhexrep(deprecated_path)+" from tunnel "+RNS.prettyhexrep(tunnel_id), RNS.LOG_DEBUG)
|
||||||
paths.pop(deprecated_path)
|
with Transport.tunnels_lock: paths.pop(deprecated_path)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def register_destination(destination):
|
def register_destination(destination):
|
||||||
@@ -2302,8 +2324,8 @@ class Transport:
|
|||||||
def clean_announce_cache():
|
def clean_announce_cache():
|
||||||
st = time.time()
|
st = time.time()
|
||||||
target_path = os.path.join(RNS.Reticulum.cachepath, "announces")
|
target_path = os.path.join(RNS.Reticulum.cachepath, "announces")
|
||||||
active_paths = [Transport.path_table[dst_hash][6] for dst_hash in Transport.path_table]
|
with Transport.path_table_lock: active_paths = [Transport.path_table[dst_hash][6] for dst_hash in Transport.path_table]
|
||||||
tunnel_paths = list(set([path_dict[dst_hash][6] for path_dict in [Transport.tunnels[tunnel_id][2] for tunnel_id in Transport.tunnels] for dst_hash in path_dict]))
|
with Transport.tunnels_lock: tunnel_paths = list(set([path_dict[dst_hash][6] for path_dict in [Transport.tunnels[tunnel_id][2] for tunnel_id in Transport.tunnels] for dst_hash in path_dict]))
|
||||||
removed = 0
|
removed = 0
|
||||||
for packet_hash in os.listdir(target_path):
|
for packet_hash in os.listdir(target_path):
|
||||||
remove = False
|
remove = False
|
||||||
@@ -2314,8 +2336,7 @@ class Transport:
|
|||||||
if (not target_hash in active_paths) and (not target_hash in tunnel_paths): remove = True
|
if (not target_hash in active_paths) and (not target_hash in tunnel_paths): remove = True
|
||||||
if remove: os.unlink(full_path); removed += 1
|
if remove: os.unlink(full_path); removed += 1
|
||||||
|
|
||||||
if removed > 0:
|
if removed > 0: RNS.log(f"Removed {removed} cached announces in {RNS.prettytime(time.time()-st)}", RNS.LOG_DEBUG)
|
||||||
RNS.log(f"Removed {removed} cached announces in {RNS.prettytime(time.time()-st)}", RNS.LOG_DEBUG)
|
|
||||||
|
|
||||||
# When caching packets to storage, they are written
|
# When caching packets to storage, they are written
|
||||||
# exactly as they arrived over their interface. This
|
# exactly as they arrived over their interface. This
|
||||||
@@ -2447,8 +2468,8 @@ class Transport:
|
|||||||
if next_hop_interface != None:
|
if next_hop_interface != None:
|
||||||
if next_hop_interface.AUTOCONFIGURE_MTU or next_hop_interface.FIXED_MTU: return next_hop_interface.HW_MTU
|
if next_hop_interface.AUTOCONFIGURE_MTU or next_hop_interface.FIXED_MTU: return next_hop_interface.HW_MTU
|
||||||
else: return None
|
else: return None
|
||||||
else:
|
|
||||||
return None
|
else: return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def next_hop_per_bit_latency(destination_hash):
|
def next_hop_per_bit_latency(destination_hash):
|
||||||
@@ -2511,7 +2532,8 @@ class Transport:
|
|||||||
def path_is_unresponsive(destination_hash):
|
def path_is_unresponsive(destination_hash):
|
||||||
with Transport.path_states_lock:
|
with Transport.path_states_lock:
|
||||||
if destination_hash in Transport.path_states:
|
if destination_hash in Transport.path_states:
|
||||||
if Transport.path_states[destination_hash] == Transport.STATE_UNRESPONSIVE: return True
|
if Transport.path_states[destination_hash] == Transport.STATE_UNRESPONSIVE:
|
||||||
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -2757,7 +2779,8 @@ class Transport:
|
|||||||
held_entry = Transport.announce_table[packet.destination_hash]
|
held_entry = Transport.announce_table[packet.destination_hash]
|
||||||
Transport.held_announces[packet.destination_hash] = held_entry
|
Transport.held_announces[packet.destination_hash] = held_entry
|
||||||
|
|
||||||
Transport.announce_table[packet.destination_hash] = [now, retransmit_timeout, retries, received_from, announce_hops, packet, local_rebroadcasts, block_rebroadcasts, attached_interface]
|
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]
|
||||||
|
|
||||||
elif is_from_local_client:
|
elif is_from_local_client:
|
||||||
# Forward path request on all interfaces
|
# Forward path request on all interfaces
|
||||||
@@ -2776,7 +2799,7 @@ class Transport:
|
|||||||
# except the requestor interface
|
# except the requestor interface
|
||||||
RNS.log("Attempting to discover unknown path to "+RNS.prettyhexrep(destination_hash)+" on behalf of path request"+interface_str, RNS.LOG_DEBUG)
|
RNS.log("Attempting to discover unknown path to "+RNS.prettyhexrep(destination_hash)+" on behalf of path request"+interface_str, RNS.LOG_DEBUG)
|
||||||
pr_entry = { "destination_hash": destination_hash, "timeout": time.time()+Transport.PATH_REQUEST_TIMEOUT, "requesting_interface": attached_interface }
|
pr_entry = { "destination_hash": destination_hash, "timeout": time.time()+Transport.PATH_REQUEST_TIMEOUT, "requesting_interface": attached_interface }
|
||||||
Transport.discovery_path_requests[destination_hash] = pr_entry
|
with Transport.discovery_pr_lock: Transport.discovery_path_requests[destination_hash] = pr_entry
|
||||||
|
|
||||||
for interface in Transport.interfaces:
|
for interface in Transport.interfaces:
|
||||||
if not interface == attached_interface:
|
if not interface == attached_interface:
|
||||||
@@ -2876,11 +2899,11 @@ class Transport:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def shared_connection_disappeared():
|
def shared_connection_disappeared():
|
||||||
for link in Transport.active_links:
|
with Transport.active_links_lock:
|
||||||
link.teardown()
|
for link in Transport.active_links: link.teardown()
|
||||||
|
|
||||||
for link in Transport.pending_links:
|
with Transport.pending_links_lock:
|
||||||
link.teardown()
|
for link in Transport.pending_links: link.teardown()
|
||||||
|
|
||||||
Transport.announce_table = {}
|
Transport.announce_table = {}
|
||||||
Transport.path_table = {}
|
Transport.path_table = {}
|
||||||
@@ -2892,11 +2915,10 @@ class Transport:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def shared_connection_reappeared():
|
def shared_connection_reappeared():
|
||||||
if Transport.owner.is_connected_to_shared_instance:
|
if Transport.owner.is_connected_to_shared_instance:
|
||||||
for registered_destination in Transport.destinations:
|
for registered_destination in Transport.destinations.copy():
|
||||||
if registered_destination.type == RNS.Destination.SINGLE:
|
if registered_destination.type == RNS.Destination.SINGLE:
|
||||||
registered_destination.announce(path_response=True)
|
registered_destination.announce(path_response=True)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def drop_announce_queues():
|
def drop_announce_queues():
|
||||||
for interface in Transport.interfaces:
|
for interface in Transport.interfaces:
|
||||||
|
|||||||
Reference in New Issue
Block a user