Added bootstrap_only interface option

This commit is contained in:
Mark Qvist 2026-01-03 20:00:22 +01:00
commit 7cadb3af8b
3 changed files with 36 additions and 17 deletions

View file

@ -442,9 +442,11 @@ class InterfaceDiscovery():
while self.monitoring_autoconnects:
time.sleep(self.monitor_interval)
detached_interfaces = []
online_interfaces = 0
for interface in self.monitored_interfaces:
try:
if interface.online:
online_interfaces += 1
if hasattr(interface, "autoconnect_down") and interface.autoconnect_down != None:
RNS.log(f"Auto-discovered interface {interface} reconnected")
interface.autoconnect_down = None
@ -458,19 +460,32 @@ class InterfaceDiscovery():
down_for = time.time()-interface.autoconnect_down
if down_for >= self.detach_threshold:
RNS.log(f"Auto-discovered interface {interface} has been down for {RNS.prettytime(down_for)}, detaching", RNS.LOG_DEBUG)
interface.detach()
detached_interfaces.append(interface)
except Exception as e:
RNS.log(f"Error while checking auto-connected interface state for {interface}: {e}", RNS.LOG_ERROR)
if online_interfaces >= RNS.Reticulum.max_autoconnected_interfaces():
for interface in RNS.Transport.interfaces:
if hasattr(interface, "bootstrap_only") and interface.bootstrap_only == True:
RNS.log(f"Tearing down bootstrap-only {interface} since target connected auto-discovered interface count has been reached", RNS.LOG_INFO)
if not interface in detached_interfaces: detached_interfaces.append(interface)
if online_interfaces == 0:
RNS.log(f"No auto-discovered interfaces connected, re-enabling bootstrap interfaces", RNS.LOG_NOTICE)
# TODO: Implement
RNS.log(f"Available bootstrap configs:\n{RNS.Reticulum.get_instance().bootstrap_configs}", RNS.LOG_DEBUG)
for interface in detached_interfaces:
try:
self.monitored_interfaces.remove(interface)
RNS.Transport.interfaces.remove(interface)
try: self.teardown_interface(interface)
except Exception as e:
RNS.log(f"Error while de-registering auto-connected interface from transport: {e}", RNS.LOG_ERROR)
def teardown_interface(self, interface):
interface.detach()
RNS.Transport.interfaces.remove(interface)
self.monitored_interfaces.remove(interface)
def autoconnect_count(self):
return len([i for i in RNS.Transport.interfaces if hasattr(i, "autoconnect_hash")])

View file

@ -87,6 +87,7 @@ class Interface:
self.supports_discovery = False
self.discoverable = False
self.last_discovery_announce = 0
self.bootstrap_only = False
self.parent_interface = None
self.spawned_interfaces = None
self.tunnel_id = None

View file

@ -276,6 +276,7 @@ class Reticulum:
self.rpc_key = None
self.rpc_type = "AF_INET"
self.use_af_unix = False
self.bootstrap_configs = []
self.ifac_salt = Reticulum.IFAC_SALT
@ -704,6 +705,9 @@ class Reticulum:
if c.as_float("announce_cap") > 0 and c.as_float("announce_cap") <= 100:
announce_cap = c.as_float("announce_cap")/100.0
bootstrap_only = False
if "bootstrap_only" in c: bootstrap_only = c.as_bool("bootstrap_only")
ignore_config_warnings = False
if "ignore_config_warnings" in c: ignore_config_warnings = c.as_bool("ignore_config_warnings")
@ -753,13 +757,12 @@ class Reticulum:
try:
def interface_post_init(interface):
if interface != None:
if "outgoing" in c and c.as_bool("outgoing") == False:
interface.OUT = False
else:
interface.OUT = True
if "outgoing" in c and c.as_bool("outgoing") == False: interface.OUT = False
else: interface.OUT = True
interface.mode = interface_mode
interface.announce_cap = announce_cap
interface.bootstrap_only = bootstrap_only
if configured_bitrate: interface.bitrate = configured_bitrate
interface.optimise_mtu()
@ -894,6 +897,8 @@ class Reticulum:
interface = WeaveInterface.WeaveInterface(RNS.Transport, interface_config)
interface_post_init(interface)
if bootstrap_only: self.bootstrap_configs.append(interface_config)
if interface == None:
# Interface was not handled by any internal interface types,
# attempt to load and initialise it from user-supplied modules
@ -936,22 +941,20 @@ class Reticulum:
RNS.log("System interfaces are ready", RNS.LOG_VERBOSE)
def _add_interface(self, interface, mode = None, configured_bitrate=None, ifac_size=None, ifac_netname=None, ifac_netkey=None, announce_cap=None, announce_rate_target=None, announce_rate_grace=None, announce_rate_penalty=None):
def _add_interface(self, interface, mode = None, configured_bitrate=None, ifac_size=None, ifac_netname=None, ifac_netkey=None,
announce_cap=None, announce_rate_target=None, announce_rate_grace=None, announce_rate_penalty=None, bootstrap_only=False):
if not self.is_connected_to_shared_instance:
if interface != None and issubclass(type(interface), RNS.Interfaces.Interface.Interface):
if mode == None:
mode = Interface.Interface.MODE_FULL
if mode == None: mode = Interface.Interface.MODE_FULL
interface.mode = mode
if configured_bitrate:
interface.bitrate = configured_bitrate
if configured_bitrate: interface.bitrate = configured_bitrate
if bootstrap_only == True: interface.bootstrap_only = True
interface.optimise_mtu()
if ifac_size != None:
interface.ifac_size = ifac_size
else:
interface.ifac_size = 8
if ifac_size != None: interface.ifac_size = ifac_size
else: interface.ifac_size = 8
interface.announce_cap = announce_cap if announce_cap != None else Reticulum.ANNOUNCE_CAP/100.0
interface.announce_rate_target = announce_rate_target