diff --git a/README.md b/README.md index 096d217..caa3ecb 100755 --- a/README.md +++ b/README.md @@ -86,19 +86,19 @@ Reticulum implements a range of generalised interface types that covers most of -## Feature Roadmap - - Stream mode for links - - Globally routable multicast +## Planned Features - More interface types for even broader compatibility - ESP32 devices (ESP-Now, Bluetooth, etc.) - More LoRa transceivers - AT-compatible modems - AWDL / OWL + - HF Modems - CAN-bus - ZeroMQ - MQTT - SPI - i²c + - Globally routable multicast ## Dependencies: - Python 3.6 diff --git a/RNS/Interfaces/Interface.py b/RNS/Interfaces/Interface.py index 7e36369..d7d7e54 100755 --- a/RNS/Interfaces/Interface.py +++ b/RNS/Interfaces/Interface.py @@ -7,6 +7,10 @@ class Interface: RPT = False name = None + MODE_FULL = 0x01 + MODE_POINT_TO_POINT = 0x02 + MODE_ACCESS_POINT = 0x03 + def __init__(self): self.rxb = 0 self.txb = 0 diff --git a/RNS/Interfaces/LocalInterface.py b/RNS/Interfaces/LocalInterface.py index 78ccba7..0fa6f3f 100644 --- a/RNS/Interfaces/LocalInterface.py +++ b/RNS/Interfaces/LocalInterface.py @@ -37,6 +37,7 @@ class LocalClientInterface(Interface): self.never_connected = True self.detached = False self.name = name + self.mode = RNS.Interfaces.Interface.Interface.MODE_FULL if connected_socket != None: self.receives = True @@ -237,6 +238,7 @@ class LocalServerInterface(Interface): self.IN = True self.OUT = False self.name = "Reticulum" + self.mode = RNS.Interfaces.Interface.Interface.MODE_FULL if (bindport != None): self.receives = True diff --git a/RNS/Reticulum.py b/RNS/Reticulum.py index a70383b..6c7ab67 100755 --- a/RNS/Reticulum.py +++ b/RNS/Reticulum.py @@ -280,6 +280,16 @@ class Reticulum: if not name in interface_names: c = self.config["interfaces"][name] + interface_mode = Interface.Interface.MODE_FULL + + if "mode" in c: + if c["mode"] == "full": + interface_mode = Interface.Interface.MODE_FULL + elif c["mode"] == "accesspoint" or c["mode"] == "ap": + interface_mode = Interface.Interface.MODE_ACCESS_POINT + elif c["mode"] == "pointtopoint" or c["mode"] == "ptp": + interface_mode = Interface.Interface.MODE_POINT_TO_POINT + try: if ("interface_enabled" in c) and c.as_bool("interface_enabled") == True: if c["type"] == "AutoInterface": @@ -307,6 +317,8 @@ class Reticulum: else: interface.OUT = True + interface.mode = interface_mode + RNS.Transport.interfaces.append(interface) else: RNS.log("AutoInterface is not currently supported on Windows, disabling interface.", RNS.LOG_ERROR); @@ -343,6 +355,8 @@ class Reticulum: else: interface.OUT = True + interface.mode = interface_mode + RNS.Transport.interfaces.append(interface) @@ -370,6 +384,8 @@ class Reticulum: else: interface.OUT = True + interface.mode = interface_mode + RNS.Transport.interfaces.append(interface) @@ -394,6 +410,8 @@ class Reticulum: else: interface.OUT = True + interface.mode = interface_mode + RNS.Transport.interfaces.append(interface) @@ -414,6 +432,8 @@ class Reticulum: else: interface.OUT = True + interface.mode = interface_mode + RNS.Transport.interfaces.append(interface) @@ -442,6 +462,8 @@ class Reticulum: else: interface.OUT = True + interface.mode = interface_mode + RNS.Transport.interfaces.append(interface) if c["type"] == "KISSInterface": @@ -483,6 +505,8 @@ class Reticulum: else: interface.OUT = True + interface.mode = interface_mode + RNS.Transport.interfaces.append(interface) if c["type"] == "AX25KISSInterface": @@ -525,6 +549,8 @@ class Reticulum: else: interface.OUT = True + interface.mode = interface_mode + RNS.Transport.interfaces.append(interface) if c["type"] == "RNodeInterface": @@ -561,6 +587,8 @@ class Reticulum: else: interface.OUT = True + interface.mode = interface_mode + RNS.Transport.interfaces.append(interface) else: RNS.log("Skipping disabled interface \""+name+"\"", RNS.LOG_DEBUG) diff --git a/RNS/Transport.py b/RNS/Transport.py index 55fb8d9..e0388a3 100755 --- a/RNS/Transport.py +++ b/RNS/Transport.py @@ -35,6 +35,7 @@ class Transport: PATHFINDER_T = 10 # Retry grace period PATHFINDER_RW = 10 # Random window for announce rebroadcast PATHFINDER_E = 60*60*24*7 # Path expiration in seconds + AP_PATH_TIME = 60*60*24 # Expiration for Access Point paths # TODO: Calculate an optimal number for this in # various situations @@ -511,13 +512,19 @@ class Transport: for interface in Transport.interfaces: if interface.OUT: should_transmit = True + if packet.destination.type == RNS.Destination.LINK: if packet.destination.status == RNS.Link.CLOSED: should_transmit = False if interface != packet.destination.attached_interface: should_transmit = False + if packet.attached_interface != None and interface != packet.attached_interface: should_transmit = False + + if packet.packet_type == RNS.Packet.ANNOUNCE: + if packet.attached_interface == None and interface.mode == RNS.Interfaces.Interface.Interface.MODE_ACCESS_POINT: + should_transmit = False if should_transmit: if not stored_hash: @@ -862,12 +869,16 @@ class Transport: if should_add: now = time.time() retries = 0 - expires = now + Transport.PATHFINDER_E announce_hops = packet.hops local_rebroadcasts = 0 block_rebroadcasts = False attached_interface = None retransmit_timeout = now + math.pow(Transport.PATHFINDER_C, packet.hops) + (RNS.rand() * Transport.PATHFINDER_RW) + + if packet.receiving_interface.mode == RNS.Interfaces.Interface.Interface.MODE_ACCESS_POINT: + expires = now + Transport.AP_PATH_TIME + else: + expires = now + Transport.PATHFINDER_E random_blobs.append(random_blob)