mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-11-26 15:30:18 +00:00
Added reverse path detection
This commit is contained in:
parent
4af14a712c
commit
0db64610b1
@ -207,11 +207,12 @@ class Identity:
|
|||||||
del announced_identity
|
del announced_identity
|
||||||
|
|
||||||
if hasattr(packet, "transport_id") and packet.transport_id != None:
|
if hasattr(packet, "transport_id") and packet.transport_id != None:
|
||||||
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" received via "+RNS.prettyhexrep(packet.transport_id)+" on "+str(packet.receiving_interface), RNS.LOG_EXTREME)
|
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" "+str(packet.hops)+" hops away, received via "+RNS.prettyhexrep(packet.transport_id)+" on "+str(packet.receiving_interface), RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" received on "+str(packet.receiving_interface), RNS.LOG_EXTREME)
|
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" "+str(packet.hops)+" hops away, received on "+str(packet.receiving_interface), RNS.LOG_EXTREME)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Received invalid announce for "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG)
|
RNS.log("Received invalid announce for "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG)
|
||||||
del announced_identity
|
del announced_identity
|
||||||
|
@ -961,7 +961,7 @@ class Transport:
|
|||||||
break
|
break
|
||||||
|
|
||||||
if (now >= path_expires):
|
if (now >= path_expires):
|
||||||
# We also check that the announce hash is
|
# We also check that the announce is
|
||||||
# different from ones we've already heard,
|
# different from ones we've already heard,
|
||||||
# to avoid loops in the network
|
# to avoid loops in the network
|
||||||
if not random_blob in random_blobs:
|
if not random_blob in random_blobs:
|
||||||
@ -1532,40 +1532,51 @@ class Transport:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def request_path(destination_hash):
|
def request_path(destination_hash, on_interface=None):
|
||||||
"""
|
"""
|
||||||
Requests a path to the destination from the network. If
|
Requests a path to the destination from the network. If
|
||||||
another reachable peer on the network knows a path, it
|
another reachable peer on the network knows a path, it
|
||||||
will announce it.
|
will announce it.
|
||||||
|
|
||||||
:param destination_hash: A destination hash as *bytes*.
|
:param destination_hash: A destination hash as *bytes*.
|
||||||
|
:param on_interface: If specified, the path request will only be sent on this interface. In normal use, Reticulum handles this automatically, and this parameter should not be used.
|
||||||
"""
|
"""
|
||||||
path_request_data = destination_hash + RNS.Identity.get_random_hash()
|
if RNS.Reticulum.transport_enabled():
|
||||||
path_request_dst = RNS.Destination(None, RNS.Destination.OUT, RNS.Destination.PLAIN, Transport.APP_NAME, "path", "request")
|
path_request_data = destination_hash+Transport.identity.hash+RNS.Identity.get_random_hash()
|
||||||
packet = RNS.Packet(path_request_dst, path_request_data, packet_type = RNS.Packet.DATA, transport_type = RNS.Transport.BROADCAST, header_type = RNS.Packet.HEADER_1)
|
else:
|
||||||
packet.send()
|
path_request_data = destination_hash+RNS.Identity.get_random_hash()
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def request_path_on_interface(destination_hash, interface):
|
|
||||||
path_request_data = destination_hash + RNS.Identity.get_random_hash()
|
|
||||||
path_request_dst = RNS.Destination(None, RNS.Destination.OUT, RNS.Destination.PLAIN, Transport.APP_NAME, "path", "request")
|
path_request_dst = RNS.Destination(None, RNS.Destination.OUT, RNS.Destination.PLAIN, Transport.APP_NAME, "path", "request")
|
||||||
packet = RNS.Packet(path_request_dst, path_request_data, packet_type = RNS.Packet.DATA, transport_type = RNS.Transport.BROADCAST, header_type = RNS.Packet.HEADER_1, attached_interface = interface)
|
packet = RNS.Packet(path_request_dst, path_request_data, packet_type = RNS.Packet.DATA, transport_type = RNS.Transport.BROADCAST, header_type = RNS.Packet.HEADER_1, attached_interface = on_interface)
|
||||||
packet.send()
|
packet.send()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def path_request_handler(data, packet):
|
def path_request_handler(data, packet):
|
||||||
try:
|
try:
|
||||||
|
# If there is at least bytes enough for a destination
|
||||||
|
# hash in the packet, we assume those bytes are the
|
||||||
|
# destination being requested.
|
||||||
if len(data) >= RNS.Identity.TRUNCATED_HASHLENGTH//8:
|
if len(data) >= RNS.Identity.TRUNCATED_HASHLENGTH//8:
|
||||||
|
# If there is also enough bytes for a trasport
|
||||||
|
# instance ID and at least one random byte, we
|
||||||
|
# assume the next bytes to be the trasport ID
|
||||||
|
# of the requesting transport instance.
|
||||||
|
if len(data) > (RNS.Identity.TRUNCATED_HASHLENGTH//8)*2:
|
||||||
|
requesting_transport_instance = data[RNS.Identity.TRUNCATED_HASHLENGTH//8:(RNS.Identity.TRUNCATED_HASHLENGTH//8)*2]
|
||||||
|
else:
|
||||||
|
requesting_transport_instance = None
|
||||||
|
|
||||||
Transport.path_request(
|
Transport.path_request(
|
||||||
data[:RNS.Identity.TRUNCATED_HASHLENGTH//8],
|
data[:RNS.Identity.TRUNCATED_HASHLENGTH//8],
|
||||||
Transport.from_local_client(packet),
|
Transport.from_local_client(packet),
|
||||||
packet.receiving_interface
|
packet.receiving_interface,
|
||||||
|
requesting_transport_instance,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while handling path request. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Error while handling path request. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def path_request(destination_hash, is_from_local_client, attached_interface):
|
def path_request(destination_hash, is_from_local_client, attached_interface, requestor_transport_id=None):
|
||||||
if attached_interface != None:
|
if attached_interface != None:
|
||||||
interface_str = " on "+str(attached_interface)
|
interface_str = " on "+str(attached_interface)
|
||||||
else:
|
else:
|
||||||
@ -1590,49 +1601,59 @@ class Transport:
|
|||||||
|
|
||||||
|
|
||||||
elif (RNS.Reticulum.transport_enabled() or is_from_local_client) and (destination_hash in Transport.destination_table):
|
elif (RNS.Reticulum.transport_enabled() or is_from_local_client) and (destination_hash in Transport.destination_table):
|
||||||
RNS.log("Answering path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", path is known", RNS.LOG_DEBUG)
|
|
||||||
|
|
||||||
packet = Transport.destination_table[destination_hash][6]
|
packet = Transport.destination_table[destination_hash][6]
|
||||||
|
next_hop = Transport.destination_table[destination_hash][1]
|
||||||
received_from = Transport.destination_table[destination_hash][5]
|
received_from = Transport.destination_table[destination_hash][5]
|
||||||
|
|
||||||
now = time.time()
|
if requestor_transport_id != None and next_hop == requestor_transport_id:
|
||||||
retries = Transport.PATHFINDER_R
|
# TODO: Find a bandwidth efficient way to invalidate our
|
||||||
local_rebroadcasts = 0
|
# known path on this signal. The obvious way of signing
|
||||||
block_rebroadcasts = True
|
# path requests with transport instance keys is quite
|
||||||
announce_hops = packet.hops
|
# inefficient. There is probably a better way. Doing
|
||||||
|
# path invalidation here would decrease the network
|
||||||
if is_from_local_client:
|
# convergence time.
|
||||||
retransmit_timeout = now
|
RNS.log("Not answering path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", since next hop is the requestor", RNS.LOG_DEBUG)
|
||||||
else:
|
else:
|
||||||
# TODO: Look at this timing
|
RNS.log("Answering path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", path is known", RNS.LOG_DEBUG)
|
||||||
retransmit_timeout = now + Transport.PATH_REQUEST_GRACE # + (RNS.rand() * Transport.PATHFINDER_RW)
|
|
||||||
|
|
||||||
# This handles an edge case where a peer sends a past
|
now = time.time()
|
||||||
# request for a destination just after an announce for
|
retries = Transport.PATHFINDER_R
|
||||||
# said destination has arrived, but before it has been
|
local_rebroadcasts = 0
|
||||||
# rebroadcast locally. In such a case the actual announce
|
block_rebroadcasts = True
|
||||||
# is temporarily held, and then reinserted when the path
|
announce_hops = packet.hops
|
||||||
# request has been served to the peer.
|
|
||||||
if packet.destination_hash in Transport.announce_table:
|
if is_from_local_client:
|
||||||
held_entry = Transport.announce_table[packet.destination_hash]
|
retransmit_timeout = now
|
||||||
Transport.held_announces[packet.destination_hash] = held_entry
|
else:
|
||||||
|
# TODO: Look at this timing
|
||||||
Transport.announce_table[packet.destination_hash] = [now, retransmit_timeout, retries, received_from, announce_hops, packet, local_rebroadcasts, block_rebroadcasts, attached_interface]
|
retransmit_timeout = now + Transport.PATH_REQUEST_GRACE # + (RNS.rand() * Transport.PATHFINDER_RW)
|
||||||
|
|
||||||
|
# This handles an edge case where a peer sends a past
|
||||||
|
# request for a destination just after an announce for
|
||||||
|
# said destination has arrived, but before it has been
|
||||||
|
# rebroadcast locally. In such a case the actual announce
|
||||||
|
# is temporarily held, and then reinserted when the path
|
||||||
|
# request has been served to the peer.
|
||||||
|
if packet.destination_hash in Transport.announce_table:
|
||||||
|
held_entry = Transport.announce_table[packet.destination_hash]
|
||||||
|
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]
|
||||||
|
|
||||||
elif is_from_local_client:
|
elif is_from_local_client:
|
||||||
# Forward path request on all interfaces
|
# Forward path request on all interfaces
|
||||||
# except the local client
|
# except the local client
|
||||||
RNS.log("Forwarding path request for "+RNS.prettyhexrep(destination_hash)+interface_str+" from local client to other local clients", RNS.LOG_DEBUG)
|
RNS.log("Forwarding path request from local client for "+RNS.prettyhexrep(destination_hash)+interface_str+" to all other interfaces", RNS.LOG_DEBUG)
|
||||||
for interface in Transport.interfaces:
|
for interface in Transport.interfaces:
|
||||||
if not interface == attached_interface:
|
if not interface == attached_interface:
|
||||||
Transport.request_path_on_interface(destination_hash, interface)
|
Transport.request_path(destination_hash, interface)
|
||||||
|
|
||||||
elif not is_from_local_client and len(Transport.local_client_interfaces) > 0:
|
elif not is_from_local_client and len(Transport.local_client_interfaces) > 0:
|
||||||
# Forward the path request on all local
|
# Forward the path request on all local
|
||||||
# client interfaces
|
# client interfaces
|
||||||
RNS.log("Forwarding path request for "+RNS.prettyhexrep(destination_hash)+interface_str+" to local clients", RNS.LOG_DEBUG)
|
RNS.log("Forwarding path request for "+RNS.prettyhexrep(destination_hash)+interface_str+" to local clients", RNS.LOG_DEBUG)
|
||||||
for interface in Transport.local_client_interfaces:
|
for interface in Transport.local_client_interfaces:
|
||||||
Transport.request_path_on_interface(destination_hash, interface)
|
Transport.request_path(destination_hash, interface)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Ignoring path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", no path known", RNS.LOG_DEBUG)
|
RNS.log("Ignoring path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", no path known", RNS.LOG_DEBUG)
|
||||||
|
@ -119,7 +119,7 @@ def program_setup(configdir, dispall=False, verbosity = 0):
|
|||||||
print(" Traffic : {txb}↑\n {rxb}↓".format(rxb=size_str(ifstat["rxb"]), txb=size_str(ifstat["txb"])))
|
print(" Traffic : {txb}↑\n {rxb}↓".format(rxb=size_str(ifstat["rxb"]), txb=size_str(ifstat["txb"])))
|
||||||
|
|
||||||
if "transport_id" in stats and stats["transport_id"] != None:
|
if "transport_id" in stats and stats["transport_id"] != None:
|
||||||
print("\n Transport Instance "+RNS.prettyhexrep(stats["transport_id"])+" running")
|
print("\n Reticulum Transport Instance "+RNS.prettyhexrep(stats["transport_id"])+" running")
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user