mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-11-22 21:50:18 +00:00
Compare commits
25 Commits
8be98dd5e7
...
d35fe30599
Author | SHA1 | Date | |
---|---|---|---|
|
d35fe30599 | ||
|
a762af035a | ||
|
760ab981d0 | ||
|
7b43ff0cef | ||
|
996161e2f4 | ||
|
bf633bba5d | ||
|
8337a5945d | ||
|
a736b3adfc | ||
|
25127cd3c9 | ||
|
ebf084cff0 | ||
|
cd8fe95d91 | ||
|
e2efc61208 | ||
|
5de63d5bf2 | ||
|
c9d744f88a | ||
|
18e0dbddfa | ||
|
52c816cb27 | ||
|
582d2b91f5 | ||
|
28a0dbb0e0 | ||
|
2895806541 | ||
|
5b8de73143 | ||
|
212af2f43b | ||
|
1282061701 | ||
|
49dba483a9 | ||
|
ebec63487f | ||
|
9373819234 |
@ -59,6 +59,7 @@ class AX25():
|
|||||||
class AX25KISSInterface(Interface):
|
class AX25KISSInterface(Interface):
|
||||||
MAX_CHUNK = 32768
|
MAX_CHUNK = 32768
|
||||||
BITRATE_GUESS = 1200
|
BITRATE_GUESS = 1200
|
||||||
|
DEFAULT_IFAC_SIZE = 8
|
||||||
|
|
||||||
owner = None
|
owner = None
|
||||||
port = None
|
port = None
|
||||||
@ -68,7 +69,7 @@ class AX25KISSInterface(Interface):
|
|||||||
stopbits = None
|
stopbits = None
|
||||||
serial = None
|
serial = None
|
||||||
|
|
||||||
def __init__(self, owner, name, callsign, ssid, port, speed, databits, parity, stopbits, preamble, txtail, persistence, slottime, flow_control):
|
def __init__(self, owner, configuration):
|
||||||
import importlib
|
import importlib
|
||||||
if importlib.util.find_spec('serial') != None:
|
if importlib.util.find_spec('serial') != None:
|
||||||
import serial
|
import serial
|
||||||
@ -79,6 +80,25 @@ class AX25KISSInterface(Interface):
|
|||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
preamble = int(c["preamble"]) if "preamble" in c else None
|
||||||
|
txtail = int(c["txtail"]) if "txtail" in c else None
|
||||||
|
persistence = int(c["persistence"]) if "persistence" in c else None
|
||||||
|
slottime = int(c["slottime"]) if "slottime" in c else None
|
||||||
|
flow_control = c.as_bool("flow_control") if "flow_control" in c else False
|
||||||
|
port = c["port"] if "port" in c else None
|
||||||
|
speed = int(c["speed"]) if "speed" in c else 9600
|
||||||
|
databits = int(c["databits"]) if "databits" in c else 8
|
||||||
|
parity = c["parity"] if "parity" in c else "N"
|
||||||
|
stopbits = int(c["stopbits"]) if "stopbits" in c else 1
|
||||||
|
|
||||||
|
callsign = c["callsign"] if "callsign" in c else ""
|
||||||
|
ssid = int(c["ssid"]) if "ssid" in c else -1
|
||||||
|
|
||||||
|
if port == None:
|
||||||
|
raise ValueError("No port specified for serial interface")
|
||||||
|
|
||||||
self.HW_MTU = 564
|
self.HW_MTU = 564
|
||||||
|
|
||||||
self.pyserial = serial
|
self.pyserial = serial
|
||||||
|
@ -52,6 +52,7 @@ class KISS():
|
|||||||
class KISSInterface(Interface):
|
class KISSInterface(Interface):
|
||||||
MAX_CHUNK = 32768
|
MAX_CHUNK = 32768
|
||||||
BITRATE_GUESS = 1200
|
BITRATE_GUESS = 1200
|
||||||
|
DEFAULT_IFAC_SIZE = 8
|
||||||
|
|
||||||
owner = None
|
owner = None
|
||||||
port = None
|
port = None
|
||||||
@ -61,7 +62,7 @@ class KISSInterface(Interface):
|
|||||||
stopbits = None
|
stopbits = None
|
||||||
serial = None
|
serial = None
|
||||||
|
|
||||||
def __init__(self, owner, name, port, speed, databits, parity, stopbits, preamble, txtail, persistence, slottime, flow_control, beacon_interval, beacon_data):
|
def __init__(self, owner, configuration):
|
||||||
import importlib
|
import importlib
|
||||||
if RNS.vendor.platformutils.is_android():
|
if RNS.vendor.platformutils.is_android():
|
||||||
self.on_android = True
|
self.on_android = True
|
||||||
@ -84,6 +85,21 @@ class KISSInterface(Interface):
|
|||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
preamble = int(c["preamble"]) if "preamble" in c else None
|
||||||
|
txtail = int(c["txtail"]) if "txtail" in c else None
|
||||||
|
persistence = int(c["persistence"]) if "persistence" in c else None
|
||||||
|
slottime = int(c["slottime"]) if "slottime" in c else None
|
||||||
|
flow_control = c.as_bool("flow_control") if "flow_control" in c else False
|
||||||
|
port = c["port"] if "port" in c else None
|
||||||
|
speed = int(c["speed"]) if "speed" in c else 9600
|
||||||
|
databits = int(c["databits"]) if "databits" in c else 8
|
||||||
|
parity = c["parity"] if "parity" in c else "N"
|
||||||
|
stopbits = int(c["stopbits"]) if "stopbits" in c else 1
|
||||||
|
beacon_interval = int(c["beacon_interval"]) if "beacon_interval" in c else None
|
||||||
|
beacon_data = c["beacon_data"] if "beacon_data" in c else None
|
||||||
|
|
||||||
self.HW_MTU = 564
|
self.HW_MTU = 564
|
||||||
|
|
||||||
if beacon_data == None:
|
if beacon_data == None:
|
||||||
|
@ -238,6 +238,7 @@ class AndroidBluetoothManager():
|
|||||||
|
|
||||||
class RNodeInterface(Interface):
|
class RNodeInterface(Interface):
|
||||||
MAX_CHUNK = 32768
|
MAX_CHUNK = 32768
|
||||||
|
DEFAULT_IFAC_SIZE = 8
|
||||||
|
|
||||||
FREQ_MIN = 137000000
|
FREQ_MIN = 137000000
|
||||||
FREQ_MAX = 1020000000
|
FREQ_MAX = 1020000000
|
||||||
@ -341,12 +342,27 @@ class RNodeInterface(Interface):
|
|||||||
serial.close()
|
serial.close()
|
||||||
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, owner, configuration):
|
||||||
self, owner, name, port, frequency = None, bandwidth = None, txpower = None,
|
c = Interface.get_config_obj(configuration)
|
||||||
sf = None, cr = None, flow_control = False, id_interval = None,
|
name = c["name"]
|
||||||
allow_bluetooth = False, target_device_name = None,
|
allow_bluetooth = c["allow_bluetooth"]
|
||||||
target_device_address = None, id_callsign = None, st_alock = None, lt_alock = None,
|
target_device_name = c["target_device_name"]
|
||||||
ble_addr = None, ble_name = None, force_ble=False):
|
target_device_address = c["target_device_address"]
|
||||||
|
ble_name = c["ble_name"]
|
||||||
|
ble_addr = c["ble_addr"]
|
||||||
|
force_ble = c["force_ble"]
|
||||||
|
frequency = int(c["frequency"]) if "frequency" in c else None
|
||||||
|
bandwidth = int(c["bandwidth"]) if "bandwidth" in c else None
|
||||||
|
txpower = int(c["txpower"]) if "txpower" in c else None
|
||||||
|
sf = int(c["spreadingfactor"]) if "spreadingfactor" in c else None
|
||||||
|
cr = int(c["codingrate"]) if "codingrate" in c else None
|
||||||
|
flow_control = c.as_bool("flow_control") if "flow_control" in c else False
|
||||||
|
id_interval = int(c["id_interval"]) if "id_interval" in c else None
|
||||||
|
id_callsign = c["id_callsign"] if "id_callsign" in c else None
|
||||||
|
st_alock = float(c["airtime_limit_short"]) if "airtime_limit_short" in c else None
|
||||||
|
lt_alock = float(c["airtime_limit_long"]) if "airtime_limit_long" in c else None
|
||||||
|
port = c["port"] if "port" in c else None
|
||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
if RNS.vendor.platformutils.is_android():
|
if RNS.vendor.platformutils.is_android():
|
||||||
self.on_android = True
|
self.on_android = True
|
||||||
|
@ -42,6 +42,7 @@ class HDLC():
|
|||||||
|
|
||||||
class SerialInterface(Interface):
|
class SerialInterface(Interface):
|
||||||
MAX_CHUNK = 32768
|
MAX_CHUNK = 32768
|
||||||
|
DEFAULT_IFAC_SIZE = 8
|
||||||
|
|
||||||
owner = None
|
owner = None
|
||||||
port = None
|
port = None
|
||||||
@ -51,7 +52,7 @@ class SerialInterface(Interface):
|
|||||||
stopbits = None
|
stopbits = None
|
||||||
serial = None
|
serial = None
|
||||||
|
|
||||||
def __init__(self, owner, name, port, speed, databits, parity, stopbits):
|
def __init__(self, owner, configuration):
|
||||||
import importlib
|
import importlib
|
||||||
if RNS.vendor.platformutils.is_android():
|
if RNS.vendor.platformutils.is_android():
|
||||||
self.on_android = True
|
self.on_android = True
|
||||||
@ -74,6 +75,17 @@ class SerialInterface(Interface):
|
|||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
port = c["port"] if "port" in c else None
|
||||||
|
speed = int(c["speed"]) if "speed" in c else 9600
|
||||||
|
databits = int(c["databits"]) if "databits" in c else 8
|
||||||
|
parity = c["parity"] if "parity" in c else "N"
|
||||||
|
stopbits = int(c["stopbits"]) if "stopbits" in c else 1
|
||||||
|
|
||||||
|
if port == None:
|
||||||
|
raise ValueError("No port specified for serial interface")
|
||||||
|
|
||||||
self.HW_MTU = 564
|
self.HW_MTU = 564
|
||||||
|
|
||||||
self.pyserial = serial
|
self.pyserial = serial
|
||||||
|
@ -36,6 +36,7 @@ class AutoInterface(Interface):
|
|||||||
DEFAULT_DISCOVERY_PORT = 29716
|
DEFAULT_DISCOVERY_PORT = 29716
|
||||||
DEFAULT_DATA_PORT = 42671
|
DEFAULT_DATA_PORT = 42671
|
||||||
DEFAULT_GROUP_ID = "reticulum".encode("utf-8")
|
DEFAULT_GROUP_ID = "reticulum".encode("utf-8")
|
||||||
|
DEFAULT_IFAC_SIZE = 16
|
||||||
|
|
||||||
SCOPE_LINK = "2"
|
SCOPE_LINK = "2"
|
||||||
SCOPE_ADMIN = "4"
|
SCOPE_ADMIN = "4"
|
||||||
@ -86,7 +87,18 @@ class AutoInterface(Interface):
|
|||||||
|
|
||||||
return socket.if_nametoindex(ifname)
|
return socket.if_nametoindex(ifname)
|
||||||
|
|
||||||
def __init__(self, owner, name, group_id=None, discovery_scope=None, discovery_port=None, multicast_address_type=None, data_port=None, allowed_interfaces=None, ignored_interfaces=None, configured_bitrate=None):
|
def __init__(self, owner, configuration):
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
group_id = c["group_id"] if "group_id" in c else None
|
||||||
|
discovery_scope = c["discovery_scope"] if "discovery_scope" in c else None
|
||||||
|
discovery_port = int(c["discovery_port"]) if "discovery_port" in c else None
|
||||||
|
multicast_address_type = c["multicast_address_type"] if "multicast_address_type" in c else None
|
||||||
|
data_port = int(c["data_port"]) if "data_port" in c else None
|
||||||
|
allowed_interfaces = c.as_list("devices") if "devices" in c else None
|
||||||
|
ignored_interfaces = c.as_list("ignored_devices") if "ignored_devices" in c else None
|
||||||
|
configured_bitrate = c["configured_bitrate"] if "configured_bitrate" in c else None
|
||||||
|
|
||||||
from RNS.vendor.ifaddr import niwrapper
|
from RNS.vendor.ifaddr import niwrapper
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.netinfo = niwrapper
|
self.netinfo = niwrapper
|
||||||
|
@ -829,10 +829,20 @@ class I2PInterfacePeer(Interface):
|
|||||||
|
|
||||||
class I2PInterface(Interface):
|
class I2PInterface(Interface):
|
||||||
BITRATE_GUESS = 256*1000
|
BITRATE_GUESS = 256*1000
|
||||||
|
DEFAULT_IFAC_SIZE = 16
|
||||||
|
|
||||||
def __init__(self, owner, name, rns_storagepath, peers, connectable = False, ifac_size = 16, ifac_netname = None, ifac_netkey = None):
|
def __init__(self, owner, configuration):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
rns_storagepath = c["storagepath"]
|
||||||
|
peers = c.as_list("peers") if "peers" in c else None
|
||||||
|
connectable = c.as_bool("connectable") if "connectable" in c else False
|
||||||
|
ifac_size = c["ifac_size"] if "ifac_size" in c else None
|
||||||
|
ifac_netname = c["ifac_netname"] if "ifac_netname" in c else None
|
||||||
|
ifac_netkey = c["ifac_netkey"] if "ifac_netkey" in c else None
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
self.online = False
|
self.online = False
|
||||||
|
@ -24,6 +24,7 @@ import RNS
|
|||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
from RNS.vendor.configobj import ConfigObj
|
||||||
|
|
||||||
class Interface:
|
class Interface:
|
||||||
IN = False
|
IN = False
|
||||||
@ -239,3 +240,14 @@ class Interface:
|
|||||||
|
|
||||||
def detach(self):
|
def detach(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_config_obj(config_in):
|
||||||
|
if type(config_in) == ConfigObj:
|
||||||
|
return config_in
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
return ConfigObj(config_in)
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log(f"Could not parse supplied configuration data. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
raise SystemError("Invalid configuration data supplied")
|
@ -52,6 +52,7 @@ class KISS():
|
|||||||
class KISSInterface(Interface):
|
class KISSInterface(Interface):
|
||||||
MAX_CHUNK = 32768
|
MAX_CHUNK = 32768
|
||||||
BITRATE_GUESS = 1200
|
BITRATE_GUESS = 1200
|
||||||
|
DEFAULT_IFAC_SIZE = 8
|
||||||
|
|
||||||
owner = None
|
owner = None
|
||||||
port = None
|
port = None
|
||||||
@ -61,7 +62,7 @@ class KISSInterface(Interface):
|
|||||||
stopbits = None
|
stopbits = None
|
||||||
serial = None
|
serial = None
|
||||||
|
|
||||||
def __init__(self, owner, name, port, speed, databits, parity, stopbits, preamble, txtail, persistence, slottime, flow_control, beacon_interval, beacon_data):
|
def __init__(self, owner, configuration):
|
||||||
import importlib
|
import importlib
|
||||||
if importlib.util.find_spec('serial') != None:
|
if importlib.util.find_spec('serial') != None:
|
||||||
import serial
|
import serial
|
||||||
@ -72,6 +73,24 @@ class KISSInterface(Interface):
|
|||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
preamble = int(c["preamble"]) if "preamble" in c else None
|
||||||
|
txtail = int(c["txtail"]) if "txtail" in c else None
|
||||||
|
persistence = int(c["persistence"]) if "persistence" in c else None
|
||||||
|
slottime = int(c["slottime"]) if "slottime" in c else None
|
||||||
|
flow_control = c.as_bool("flow_control") if "flow_control" in c else False
|
||||||
|
port = c["port"] if "port" in c else None
|
||||||
|
speed = int(c["speed"]) if "speed" in c else 9600
|
||||||
|
databits = int(c["databits"]) if "databits" in c else 8
|
||||||
|
parity = c["parity"] if "parity" in c else "N"
|
||||||
|
stopbits = int(c["stopbits"]) if "stopbits" in c else 1
|
||||||
|
beacon_interval = int(c["id_interval"]) if "id_interval" in c else None
|
||||||
|
beacon_data = c["id_callsign"] if "id_callsign" in c else None
|
||||||
|
|
||||||
|
if port == None:
|
||||||
|
raise ValueError("No port specified for serial interface")
|
||||||
|
|
||||||
self.HW_MTU = 564
|
self.HW_MTU = 564
|
||||||
|
|
||||||
if beacon_data == None:
|
if beacon_data == None:
|
||||||
|
@ -46,16 +46,25 @@ class HDLC():
|
|||||||
class PipeInterface(Interface):
|
class PipeInterface(Interface):
|
||||||
MAX_CHUNK = 32768
|
MAX_CHUNK = 32768
|
||||||
BITRATE_GUESS = 1*1000*1000
|
BITRATE_GUESS = 1*1000*1000
|
||||||
|
DEFAULT_IFAC_SIZE = 8
|
||||||
|
|
||||||
owner = None
|
owner = None
|
||||||
command = None
|
command = None
|
||||||
|
|
||||||
def __init__(self, owner, name, command, respawn_delay):
|
def __init__(self, owner, configuration):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
command = c["command"] if "command" in c else None
|
||||||
|
respawn_delay = c.as_float("respawn_delay") if "respawn_delay" in c else None
|
||||||
|
|
||||||
|
if command == None:
|
||||||
|
raise ValueError("No command specified for PipeInterface")
|
||||||
|
|
||||||
if respawn_delay == None:
|
if respawn_delay == None:
|
||||||
respawn_delay = 5
|
respawn_delay = 5
|
||||||
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
|
@ -95,6 +95,7 @@ class KISS():
|
|||||||
|
|
||||||
class RNodeInterface(Interface):
|
class RNodeInterface(Interface):
|
||||||
MAX_CHUNK = 32768
|
MAX_CHUNK = 32768
|
||||||
|
DEFAULT_IFAC_SIZE = 8
|
||||||
|
|
||||||
FREQ_MIN = 137000000
|
FREQ_MIN = 137000000
|
||||||
FREQ_MAX = 3000000000
|
FREQ_MAX = 3000000000
|
||||||
@ -117,7 +118,7 @@ class RNodeInterface(Interface):
|
|||||||
BATTERY_STATE_CHARGING = 0x02
|
BATTERY_STATE_CHARGING = 0x02
|
||||||
BATTERY_STATE_CHARGED = 0x03
|
BATTERY_STATE_CHARGED = 0x03
|
||||||
|
|
||||||
def __init__(self, owner, name, port, frequency = None, bandwidth = None, txpower = None, sf = None, cr = None, flow_control = False, id_interval = None, id_callsign = None, st_alock = None, lt_alock = None, ble_addr = None, ble_name = None, force_ble=False):
|
def __init__(self, owner, configuration):
|
||||||
if RNS.vendor.platformutils.is_android():
|
if RNS.vendor.platformutils.is_android():
|
||||||
raise SystemError("Invalid interface type. The Android-specific RNode interface must be used on Android")
|
raise SystemError("Invalid interface type. The Android-specific RNode interface must be used on Android")
|
||||||
|
|
||||||
@ -131,6 +132,41 @@ class RNodeInterface(Interface):
|
|||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
frequency = int(c["frequency"]) if "frequency" in c else None
|
||||||
|
bandwidth = int(c["bandwidth"]) if "bandwidth" in c else None
|
||||||
|
txpower = int(c["txpower"]) if "txpower" in c else None
|
||||||
|
sf = int(c["spreadingfactor"]) if "spreadingfactor" in c else None
|
||||||
|
cr = int(c["codingrate"]) if "codingrate" in c else None
|
||||||
|
flow_control = c.as_bool("flow_control") if "flow_control" in c else False
|
||||||
|
id_interval = int(c["id_interval"]) if "id_interval" in c else None
|
||||||
|
id_callsign = c["id_callsign"] if "id_callsign" in c else None
|
||||||
|
st_alock = float(c["airtime_limit_short"]) if "airtime_limit_short" in c else None
|
||||||
|
lt_alock = float(c["airtime_limit_long"]) if "airtime_limit_long" in c else None
|
||||||
|
|
||||||
|
force_ble = False
|
||||||
|
ble_name = None
|
||||||
|
ble_addr = None
|
||||||
|
|
||||||
|
port = c["port"] if "port" in c else None
|
||||||
|
|
||||||
|
if port == None:
|
||||||
|
raise ValueError("No port specified for RNode interface")
|
||||||
|
|
||||||
|
if port != None:
|
||||||
|
ble_uri_scheme = "ble://"
|
||||||
|
if port.lower().startswith(ble_uri_scheme):
|
||||||
|
force_ble = True
|
||||||
|
ble_string = port[len(ble_uri_scheme):]
|
||||||
|
port = None
|
||||||
|
if len(ble_string) == 0:
|
||||||
|
pass
|
||||||
|
elif len(ble_string.split(":")) == 6 and len(ble_string) == 17:
|
||||||
|
ble_addr = ble_string
|
||||||
|
else:
|
||||||
|
ble_name = ble_string
|
||||||
|
|
||||||
self.HW_MTU = 508
|
self.HW_MTU = 508
|
||||||
|
|
||||||
self.pyserial = serial
|
self.pyserial = serial
|
||||||
|
@ -163,6 +163,7 @@ class KISS():
|
|||||||
|
|
||||||
class RNodeMultiInterface(Interface):
|
class RNodeMultiInterface(Interface):
|
||||||
MAX_CHUNK = 32768
|
MAX_CHUNK = 32768
|
||||||
|
DEFAULT_IFAC_SIZE = 8
|
||||||
|
|
||||||
CALLSIGN_MAX_LEN = 32
|
CALLSIGN_MAX_LEN = 32
|
||||||
|
|
||||||
@ -173,7 +174,7 @@ class RNodeMultiInterface(Interface):
|
|||||||
|
|
||||||
MAX_SUBINTERFACES = 11
|
MAX_SUBINTERFACES = 11
|
||||||
|
|
||||||
def __init__(self, owner, name, port, subint_config, id_interval = None, id_callsign = None):
|
def __init__(self, owner, configuration):
|
||||||
if RNS.vendor.platformutils.is_android():
|
if RNS.vendor.platformutils.is_android():
|
||||||
raise SystemError("Invalid interface type. The Android-specific RNode interface must be used on Android")
|
raise SystemError("Invalid interface type. The Android-specific RNode interface must be used on Android")
|
||||||
|
|
||||||
@ -187,6 +188,77 @@ class RNodeMultiInterface(Interface):
|
|||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
enabled_count = 0
|
||||||
|
|
||||||
|
# Count how many interfaces are in the file
|
||||||
|
for subinterface in c:
|
||||||
|
# if the retrieved entry is not a string, it must be a dictionary, which is what we want
|
||||||
|
if not isinstance(c[subinterface], str):
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
# Count how many interfaces are enabled to allow for appropriate matrix sizing
|
||||||
|
for subinterface in c:
|
||||||
|
# if the retrieved entry is not a string, it must be a dictionary, which is what we want
|
||||||
|
if not isinstance(c[subinterface], str):
|
||||||
|
subinterface_config = self.config["interfaces"][name][subinterface]
|
||||||
|
if (("interface_enabled" in subinterface_config) and subinterface_config.as_bool("interface_enabled") == True) or (("enabled" in c) and c.as_bool("enabled") == True):
|
||||||
|
enabled_count += 1
|
||||||
|
|
||||||
|
# Create an array with a row for each subinterface
|
||||||
|
subint_config = [[0 for x in range(11)] for y in range(enabled_count)]
|
||||||
|
subint_index = 0
|
||||||
|
|
||||||
|
for subinterface in c:
|
||||||
|
# If the retrieved entry is not a string, it must be a dictionary, which is what we want
|
||||||
|
if not isinstance(c[subinterface], str):
|
||||||
|
subinterface_config = self.config["interfaces"][name][subinterface]
|
||||||
|
if (("interface_enabled" in subinterface_config) and subinterface_config.as_bool("interface_enabled") == True) or (("enabled" in c) and c.as_bool("enabled") == True):
|
||||||
|
subint_config[subint_index][0] = subinterface
|
||||||
|
|
||||||
|
subint_vport = subinterface_config["vport"] if "vport" in subinterface_config else None
|
||||||
|
subint_config[subint_index][1] = subint_vport
|
||||||
|
|
||||||
|
frequency = int(subinterface_config["frequency"]) if "frequency" in subinterface_config else None
|
||||||
|
subint_config[subint_index][2] = frequency
|
||||||
|
bandwidth = int(subinterface_config["bandwidth"]) if "bandwidth" in subinterface_config else None
|
||||||
|
subint_config[subint_index][3] = bandwidth
|
||||||
|
txpower = int(subinterface_config["txpower"]) if "txpower" in subinterface_config else None
|
||||||
|
subint_config[subint_index][4] = txpower
|
||||||
|
spreadingfactor = int(subinterface_config["spreadingfactor"]) if "spreadingfactor" in subinterface_config else None
|
||||||
|
subint_config[subint_index][5] = spreadingfactor
|
||||||
|
codingrate = int(subinterface_config["codingrate"]) if "codingrate" in subinterface_config else None
|
||||||
|
subint_config[subint_index][6] = codingrate
|
||||||
|
flow_control = subinterface_config.as_bool("flow_control") if "flow_control" in subinterface_config else False
|
||||||
|
subint_config[subint_index][7] = flow_control
|
||||||
|
st_alock = float(subinterface_config["airtime_limit_short"]) if "airtime_limit_short" in subinterface_config else None
|
||||||
|
subint_config[subint_index][8] = st_alock
|
||||||
|
lt_alock = float(subinterface_config["airtime_limit_long"]) if "airtime_limit_long" in subinterface_config else None
|
||||||
|
subint_config[subint_index][9] = lt_alock
|
||||||
|
|
||||||
|
if "outgoing" in subinterface_config and subinterface_config.as_bool("outgoing") == False:
|
||||||
|
subint_config[subint_index][10] = False
|
||||||
|
else:
|
||||||
|
subint_config[subint_index][10] = True
|
||||||
|
subint_index += 1
|
||||||
|
|
||||||
|
# if no subinterfaces are defined
|
||||||
|
if count == 0:
|
||||||
|
raise ValueError("No subinterfaces configured for "+name)
|
||||||
|
# if no subinterfaces are enabled
|
||||||
|
elif enabled_count == 0:
|
||||||
|
raise ValueError("No subinterfaces enabled for "+name)
|
||||||
|
|
||||||
|
id_interval = int(c["id_interval"]) if "id_interval" in c else None
|
||||||
|
id_callsign = c["id_callsign"] if "id_callsign" in c else None
|
||||||
|
port = c["port"] if "port" in c else None
|
||||||
|
|
||||||
|
if port == None:
|
||||||
|
raise ValueError("No port specified for "+name)
|
||||||
|
|
||||||
self.HW_MTU = 508
|
self.HW_MTU = 508
|
||||||
|
|
||||||
self.clients = 0
|
self.clients = 0
|
||||||
|
@ -42,6 +42,7 @@ class HDLC():
|
|||||||
|
|
||||||
class SerialInterface(Interface):
|
class SerialInterface(Interface):
|
||||||
MAX_CHUNK = 32768
|
MAX_CHUNK = 32768
|
||||||
|
DEFAULT_IFAC_SIZE = 8
|
||||||
|
|
||||||
owner = None
|
owner = None
|
||||||
port = None
|
port = None
|
||||||
@ -51,7 +52,7 @@ class SerialInterface(Interface):
|
|||||||
stopbits = None
|
stopbits = None
|
||||||
serial = None
|
serial = None
|
||||||
|
|
||||||
def __init__(self, owner, name, port, speed, databits, parity, stopbits):
|
def __init__(self, owner, configuration):
|
||||||
import importlib
|
import importlib
|
||||||
if importlib.util.find_spec('serial') != None:
|
if importlib.util.find_spec('serial') != None:
|
||||||
import serial
|
import serial
|
||||||
@ -62,6 +63,17 @@ class SerialInterface(Interface):
|
|||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
port = c["port"] if "port" in c else None
|
||||||
|
speed = int(c["speed"]) if "speed" in c else 9600
|
||||||
|
databits = int(c["databits"]) if "databits" in c else 8
|
||||||
|
parity = c["parity"] if "parity" in c else "N"
|
||||||
|
stopbits = int(c["stopbits"]) if "stopbits" in c else 1
|
||||||
|
|
||||||
|
if port == None:
|
||||||
|
raise ValueError("No port specified for serial interface")
|
||||||
|
|
||||||
self.HW_MTU = 564
|
self.HW_MTU = 564
|
||||||
|
|
||||||
self.pyserial = serial
|
self.pyserial = serial
|
||||||
|
@ -58,8 +58,12 @@ class KISS():
|
|||||||
class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class ThreadingTCP6Server(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
||||||
|
address_family = socket.AF_INET6
|
||||||
|
|
||||||
class TCPClientInterface(Interface):
|
class TCPClientInterface(Interface):
|
||||||
BITRATE_GUESS = 10*1000*1000
|
BITRATE_GUESS = 10*1000*1000
|
||||||
|
DEFAULT_IFAC_SIZE = 16
|
||||||
|
|
||||||
RECONNECT_WAIT = 5
|
RECONNECT_WAIT = 5
|
||||||
RECONNECT_MAX_TRIES = None
|
RECONNECT_MAX_TRIES = None
|
||||||
@ -78,9 +82,20 @@ class TCPClientInterface(Interface):
|
|||||||
I2P_PROBE_INTERVAL = 9
|
I2P_PROBE_INTERVAL = 9
|
||||||
I2P_PROBES = 5
|
I2P_PROBES = 5
|
||||||
|
|
||||||
def __init__(self, owner, name, target_ip=None, target_port=None, connected_socket=None, max_reconnect_tries=None, kiss_framing=False, i2p_tunneled = False, connect_timeout = None):
|
def __init__(self, owner, configuration, connected_socket=None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
target_ip = c["target_host"] if "target_host" in c else None
|
||||||
|
target_port = int(c["target_port"]) if "target_port" in c else None
|
||||||
|
kiss_framing = False
|
||||||
|
if "kiss_framing" in c and c.as_bool("kiss_framing") == True:
|
||||||
|
kiss_framing = True
|
||||||
|
i2p_tunneled = c.as_bool("i2p_tunneled") if "i2p_tunneled" in c else False
|
||||||
|
connect_timeout = c.as_int("connect_timeout") if "connect_timeout" in c else None
|
||||||
|
max_reconnect_tries = c.as_int("max_reconnect_tries") if "max_reconnect_tries" in c else None
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
self.IN = True
|
self.IN = True
|
||||||
@ -200,12 +215,14 @@ class TCPClientInterface(Interface):
|
|||||||
if initial:
|
if initial:
|
||||||
RNS.log("Establishing TCP connection for "+str(self)+"...", RNS.LOG_DEBUG)
|
RNS.log("Establishing TCP connection for "+str(self)+"...", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
addrInfo=socket.getaddrinfo(self.target_ip, self.target_port)
|
address_info = socket.getaddrinfo(self.target_ip, self.target_port, proto=socket.IPPROTO_TCP)[0]
|
||||||
addrFam=addrInfo[0]
|
address_family = address_info[0]
|
||||||
self.socket = socket.socket(addrFam, socket.SOCK_STREAM)
|
target_address = address_info[4]
|
||||||
|
|
||||||
|
self.socket = socket.socket(address_family, socket.SOCK_STREAM)
|
||||||
self.socket.settimeout(TCPClientInterface.INITIAL_CONNECT_TIMEOUT)
|
self.socket.settimeout(TCPClientInterface.INITIAL_CONNECT_TIMEOUT)
|
||||||
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||||
self.socket.connect((self.target_ip, self.target_port))
|
self.socket.connect(target_address)
|
||||||
self.socket.settimeout(None)
|
self.socket.settimeout(None)
|
||||||
self.online = True
|
self.online = True
|
||||||
|
|
||||||
@ -404,32 +421,65 @@ class TCPClientInterface(Interface):
|
|||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "TCPInterface["+str(self.name)+"/"+str(self.target_ip)+":"+str(self.target_port)+"]"
|
if ":" in self.target_ip:
|
||||||
|
ip_str = f"[{self.target_ip}]"
|
||||||
|
else:
|
||||||
|
ip_str = f"{self.target_ip}"
|
||||||
|
|
||||||
|
return "TCPInterface["+str(self.name)+"/"+ip_str+":"+str(self.target_port)+"]"
|
||||||
|
|
||||||
|
|
||||||
class TCPServerInterface(Interface):
|
class TCPServerInterface(Interface):
|
||||||
BITRATE_GUESS = 10*1000*1000
|
BITRATE_GUESS = 10*1000*1000
|
||||||
|
DEFAULT_IFAC_SIZE = 16
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_address_for_if(name):
|
def get_address_for_if(name, bind_port, prefer_ipv6=False):
|
||||||
import RNS.vendor.ifaddr.niwrapper as netinfo
|
import RNS.vendor.ifaddr.niwrapper as netinfo
|
||||||
ifaddr = netinfo.ifaddresses(name)
|
ifaddr = netinfo.ifaddresses(name)
|
||||||
|
if len(ifaddr) < 1:
|
||||||
|
raise SystemError(f"No addresses available on specified kernel interface \"{name}\" for TCPServerInterface to bind to")
|
||||||
|
|
||||||
# IPv6 preference (if present)
|
if (prefer_ipv6 or not netinfo.AF_INET in ifaddr) and netinfo.AF_INET6 in ifaddr:
|
||||||
if(netinfo.AF_INET6 in ifaddr):
|
bind_ip = ifaddr[netinfo.AF_INET6][0]["addr"]
|
||||||
return ifaddr[netinfo.AF_INET6][0]["addr"]
|
if bind_ip.lower().startswith("fe80::"):
|
||||||
|
# We'll need to add the interface as scope for link-local addresses
|
||||||
return ifaddr[netinfo.AF_INET][0]["addr"]
|
return TCPServerInterface.get_address_for_host(f"{bind_ip}%{name}", bind_port)
|
||||||
|
else:
|
||||||
|
return TCPServerInterface.get_address_for_host(bind_ip, bind_port)
|
||||||
|
elif netinfo.AF_INET in ifaddr:
|
||||||
|
bind_ip = ifaddr[netinfo.AF_INET][0]["addr"]
|
||||||
|
return (bind_ip, bind_port)
|
||||||
|
else:
|
||||||
|
raise SystemError(f"No addresses available on specified kernel interface \"{name}\" for TCPServerInterface to bind to")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_broadcast_for_if(name):
|
def get_address_for_host(name, bind_port):
|
||||||
import RNS.vendor.ifaddr.niwrapper as netinfo
|
address_info = socket.getaddrinfo(name, bind_port, proto=socket.IPPROTO_TCP)[0]
|
||||||
ifaddr = netinfo.ifaddresses(name)
|
if address_info[0] == socket.AF_INET6:
|
||||||
return ifaddr[netinfo.AF_INET][0]["broadcast"]
|
return (name, bind_port, address_info[4][2], address_info[4][3])
|
||||||
|
elif address_info[0] == socket.AF_INET:
|
||||||
|
return (name, bind_port)
|
||||||
|
else:
|
||||||
|
raise SystemError(f"No suitable kernel interface available for address \"{name}\" for TCPServerInterface to bind to")
|
||||||
|
|
||||||
def __init__(self, owner, name, device=None, bindip=None, bindport=None, i2p_tunneled=False):
|
|
||||||
|
# def __init__(self, owner, name, device=None, bindip=None, bindport=None, i2p_tunneled=False, prefer_ipv6=False):
|
||||||
|
def __init__(self, owner, configuration):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
device = c["device"] if "device" in c else None
|
||||||
|
port = int(c["port"]) if "port" in c else None
|
||||||
|
bindip = c["listen_ip"] if "listen_ip" in c else None
|
||||||
|
bindport = int(c["listen_port"]) if "listen_port" in c else None
|
||||||
|
i2p_tunneled = c.as_bool("i2p_tunneled") if "i2p_tunneled" in c else False
|
||||||
|
prefer_ipv6 = c.as_bool("prefer_ipv6") if "prefer_ipv6" in c else False
|
||||||
|
|
||||||
|
if port != None:
|
||||||
|
bindport = port
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
self.online = False
|
self.online = False
|
||||||
@ -443,24 +493,40 @@ class TCPServerInterface(Interface):
|
|||||||
self.i2p_tunneled = i2p_tunneled
|
self.i2p_tunneled = i2p_tunneled
|
||||||
self.mode = RNS.Interfaces.Interface.Interface.MODE_FULL
|
self.mode = RNS.Interfaces.Interface.Interface.MODE_FULL
|
||||||
|
|
||||||
if device != None:
|
if bindport == None:
|
||||||
bindip = TCPServerInterface.get_address_for_if(device)
|
raise SystemError(f"No TCP port configured for interface \"{name}\"")
|
||||||
|
else:
|
||||||
if (bindip != None and bindport != None):
|
|
||||||
self.receives = True
|
|
||||||
self.bind_ip = bindip
|
|
||||||
self.bind_port = bindport
|
self.bind_port = bindport
|
||||||
|
|
||||||
|
bind_address = None
|
||||||
|
if device != None:
|
||||||
|
bind_address = TCPServerInterface.get_address_for_if(device, self.bind_port, prefer_ipv6)
|
||||||
|
else:
|
||||||
|
if bindip == None:
|
||||||
|
raise SystemError(f"No TCP bind IP configured for interface \"{name}\"")
|
||||||
|
bind_address = TCPServerInterface.get_address_for_host(bindip, self.bind_port)
|
||||||
|
|
||||||
|
if bind_address != None:
|
||||||
|
self.receives = True
|
||||||
|
self.bind_ip = bind_address[0]
|
||||||
|
|
||||||
def handlerFactory(callback):
|
def handlerFactory(callback):
|
||||||
def createHandler(*args, **keys):
|
def createHandler(*args, **keys):
|
||||||
return TCPInterfaceHandler(callback, *args, **keys)
|
return TCPInterfaceHandler(callback, *args, **keys)
|
||||||
return createHandler
|
return createHandler
|
||||||
|
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
address = (self.bind_ip, self.bind_port)
|
|
||||||
|
|
||||||
ThreadingTCPServer.allow_reuse_address = True
|
if len(bind_address) == 4:
|
||||||
self.server = ThreadingTCPServer(address, handlerFactory(self.incoming_connection))
|
try:
|
||||||
|
ThreadingTCP6Server.allow_reuse_address = True
|
||||||
|
self.server = ThreadingTCP6Server(bind_address, handlerFactory(self.incoming_connection))
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log(f"Error while binding IPv6 socket for interface, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
raise SystemError("Could not bind IPv6 socket for interface. Please check the specified \"listen_ip\" configuration option")
|
||||||
|
else:
|
||||||
|
ThreadingTCPServer.allow_reuse_address = True
|
||||||
|
self.server = ThreadingTCPServer(bind_address, handlerFactory(self.incoming_connection))
|
||||||
|
|
||||||
self.bitrate = TCPServerInterface.BITRATE_GUESS
|
self.bitrate = TCPServerInterface.BITRATE_GUESS
|
||||||
|
|
||||||
@ -470,11 +536,13 @@ class TCPServerInterface(Interface):
|
|||||||
|
|
||||||
self.online = True
|
self.online = True
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise SystemError("Insufficient parameters to create TCP listener")
|
||||||
|
|
||||||
def incoming_connection(self, handler):
|
def incoming_connection(self, handler):
|
||||||
RNS.log("Accepting incoming TCP connection", RNS.LOG_VERBOSE)
|
RNS.log("Accepting incoming TCP connection", RNS.LOG_VERBOSE)
|
||||||
interface_name = "Client on "+self.name
|
spawned_configuration = {"name": "Client on "+self.name, "target_host": None, "target_port": None, "i2p_tunneled": self.i2p_tunneled}
|
||||||
spawned_interface = TCPClientInterface(self.owner, interface_name, target_ip=None, target_port=None, connected_socket=handler.request, i2p_tunneled=self.i2p_tunneled)
|
spawned_interface = TCPClientInterface(self.owner, spawned_configuration, connected_socket=handler.request)
|
||||||
spawned_interface.OUT = self.OUT
|
spawned_interface.OUT = self.OUT
|
||||||
spawned_interface.IN = self.IN
|
spawned_interface.IN = self.IN
|
||||||
spawned_interface.target_ip = handler.client_address[0]
|
spawned_interface.target_ip = handler.client_address[0]
|
||||||
@ -538,7 +606,12 @@ class TCPServerInterface(Interface):
|
|||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "TCPServerInterface["+self.name+"/"+self.bind_ip+":"+str(self.bind_port)+"]"
|
if ":" in self.bind_ip:
|
||||||
|
ip_str = f"[{self.bind_ip}]"
|
||||||
|
else:
|
||||||
|
ip_str = f"{self.bind_ip}"
|
||||||
|
|
||||||
|
return "TCPServerInterface["+self.name+"/"+ip_str+":"+str(self.bind_port)+"]"
|
||||||
|
|
||||||
|
|
||||||
class TCPInterfaceHandler(socketserver.BaseRequestHandler):
|
class TCPInterfaceHandler(socketserver.BaseRequestHandler):
|
||||||
|
@ -31,6 +31,7 @@ import RNS
|
|||||||
|
|
||||||
class UDPInterface(Interface):
|
class UDPInterface(Interface):
|
||||||
BITRATE_GUESS = 10*1000*1000
|
BITRATE_GUESS = 10*1000*1000
|
||||||
|
DEFAULT_IFAC_SIZE = 16
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_address_for_if(name):
|
def get_address_for_if(name):
|
||||||
@ -44,9 +45,24 @@ class UDPInterface(Interface):
|
|||||||
ifaddr = netinfo.ifaddresses(name)
|
ifaddr = netinfo.ifaddresses(name)
|
||||||
return ifaddr[netinfo.AF_INET][0]["broadcast"]
|
return ifaddr[netinfo.AF_INET][0]["broadcast"]
|
||||||
|
|
||||||
def __init__(self, owner, name, device=None, bindip=None, bindport=None, forwardip=None, forwardport=None):
|
def __init__(self, owner, configuration):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
c = Interface.get_config_obj(configuration)
|
||||||
|
name = c["name"]
|
||||||
|
device = c["device"] if "device" in c else None
|
||||||
|
port = int(c["port"]) if "port" in c else None
|
||||||
|
bindip = c["listen_ip"] if "listen_ip" in c else None
|
||||||
|
bindport = int(c["listen_port"]) if "listen_port" in c else None
|
||||||
|
forwardip = c["forward_ip"] if "forward_ip" in c else None
|
||||||
|
forwardport = int(c["forward_port"]) if "forward_port" in c else None
|
||||||
|
|
||||||
|
if port != None:
|
||||||
|
if bindport == None:
|
||||||
|
bindport = port
|
||||||
|
if forwardport == None:
|
||||||
|
forwardport = port
|
||||||
|
|
||||||
self.HW_MTU = 1064
|
self.HW_MTU = 1064
|
||||||
|
|
||||||
self.IN = True
|
self.IN = True
|
||||||
|
526
RNS/Reticulum.py
526
RNS/Reticulum.py
@ -446,14 +446,7 @@ class Reticulum:
|
|||||||
if "interfaces" in self.config:
|
if "interfaces" in self.config:
|
||||||
for name in self.config["interfaces"]:
|
for name in self.config["interfaces"]:
|
||||||
if not name in interface_names:
|
if not name in interface_names:
|
||||||
# TODO: We really need to generalise this way of instantiating
|
|
||||||
# and configuring interfaces. Ideally, interfaces should just
|
|
||||||
# have a conrfig dict passed to their init method, and return
|
|
||||||
# a ready interface, onto which this routine can configure any
|
|
||||||
# generic or extra parameters.
|
|
||||||
|
|
||||||
c = self.config["interfaces"][name]
|
c = self.config["interfaces"][name]
|
||||||
|
|
||||||
interface_mode = Interface.Interface.MODE_FULL
|
interface_mode = Interface.Interface.MODE_FULL
|
||||||
|
|
||||||
if "interface_mode" in c:
|
if "interface_mode" in c:
|
||||||
@ -556,514 +549,87 @@ class Reticulum:
|
|||||||
announce_cap = c.as_float("announce_cap")/100.0
|
announce_cap = c.as_float("announce_cap")/100.0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
def interface_post_init(interface):
|
||||||
|
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
|
||||||
|
if configured_bitrate:
|
||||||
|
interface.bitrate = configured_bitrate
|
||||||
|
if ifac_size != None:
|
||||||
|
interface.ifac_size = ifac_size
|
||||||
|
else:
|
||||||
|
interface.ifac_size = interface.DEFAULT_IFAC_SIZE
|
||||||
|
|
||||||
interface = None
|
interface = None
|
||||||
|
|
||||||
if (("interface_enabled" in c) and c.as_bool("interface_enabled") == True) or (("enabled" in c) and c.as_bool("enabled") == True):
|
if (("interface_enabled" in c) and c.as_bool("interface_enabled") == True) or (("enabled" in c) and c.as_bool("enabled") == True):
|
||||||
|
interface_config = c
|
||||||
|
interface_config["name"] = name
|
||||||
|
interface_config["configured_bitrate"] = configured_bitrate
|
||||||
|
|
||||||
if c["type"] == "AutoInterface":
|
if c["type"] == "AutoInterface":
|
||||||
group_id = c["group_id"] if "group_id" in c else None
|
interface = AutoInterface.AutoInterface(RNS.Transport, interface_config)
|
||||||
discovery_scope = c["discovery_scope"] if "discovery_scope" in c else None
|
interface_post_init(interface)
|
||||||
discovery_port = int(c["discovery_port"]) if "discovery_port" in c else None
|
|
||||||
multicast_address_type = c["multicast_address_type"] if "multicast_address_type" in c else None
|
|
||||||
data_port = int(c["data_port"]) if "data_port" in c else None
|
|
||||||
allowed_interfaces = c.as_list("devices") if "devices" in c else None
|
|
||||||
ignored_interfaces = c.as_list("ignored_devices") if "ignored_devices" in c else None
|
|
||||||
|
|
||||||
interface = AutoInterface.AutoInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
group_id,
|
|
||||||
discovery_scope,
|
|
||||||
discovery_port,
|
|
||||||
multicast_address_type,
|
|
||||||
data_port,
|
|
||||||
allowed_interfaces,
|
|
||||||
ignored_interfaces
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
if configured_bitrate:
|
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
if ifac_size != None:
|
|
||||||
interface.ifac_size = ifac_size
|
|
||||||
else:
|
|
||||||
interface.ifac_size = 16
|
|
||||||
|
|
||||||
if c["type"] == "UDPInterface":
|
if c["type"] == "UDPInterface":
|
||||||
device = c["device"] if "device" in c else None
|
interface = UDPInterface.UDPInterface(RNS.Transport, interface_config)
|
||||||
port = int(c["port"]) if "port" in c else None
|
interface_post_init(interface)
|
||||||
listen_ip = c["listen_ip"] if "listen_ip" in c else None
|
|
||||||
listen_port = int(c["listen_port"]) if "listen_port" in c else None
|
|
||||||
forward_ip = c["forward_ip"] if "forward_ip" in c else None
|
|
||||||
forward_port = int(c["forward_port"]) if "forward_port" in c else None
|
|
||||||
|
|
||||||
if port != None:
|
|
||||||
if listen_port == None:
|
|
||||||
listen_port = port
|
|
||||||
if forward_port == None:
|
|
||||||
forward_port = port
|
|
||||||
|
|
||||||
interface = UDPInterface.UDPInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
device,
|
|
||||||
listen_ip,
|
|
||||||
listen_port,
|
|
||||||
forward_ip,
|
|
||||||
forward_port
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
if configured_bitrate:
|
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
if ifac_size != None:
|
|
||||||
interface.ifac_size = ifac_size
|
|
||||||
else:
|
|
||||||
interface.ifac_size = 16
|
|
||||||
|
|
||||||
if c["type"] == "TCPServerInterface":
|
if c["type"] == "TCPServerInterface":
|
||||||
device = c["device"] if "device" in c else None
|
|
||||||
port = int(c["port"]) if "port" in c else None
|
|
||||||
listen_ip = c["listen_ip"] if "listen_ip" in c else None
|
|
||||||
listen_port = int(c["listen_port"]) if "listen_port" in c else None
|
|
||||||
i2p_tunneled = c.as_bool("i2p_tunneled") if "i2p_tunneled" in c else False
|
|
||||||
|
|
||||||
if port != None:
|
|
||||||
listen_port = port
|
|
||||||
|
|
||||||
interface = TCPInterface.TCPServerInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
device,
|
|
||||||
listen_ip,
|
|
||||||
listen_port,
|
|
||||||
i2p_tunneled
|
|
||||||
)
|
|
||||||
|
|
||||||
if "outgoing" in c and c.as_bool("outgoing") == False:
|
|
||||||
interface.OUT = False
|
|
||||||
else:
|
|
||||||
interface.OUT = True
|
|
||||||
|
|
||||||
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
||||||
RNS.log(str(interface)+" does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
RNS.log(str(interface)+" does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
||||||
interface_mode = Interface.Interface.MODE_FULL
|
interface_mode = Interface.Interface.MODE_FULL
|
||||||
|
|
||||||
interface.mode = interface_mode
|
interface = TCPInterface.TCPServerInterface(RNS.Transport, interface_config)
|
||||||
|
interface_post_init(interface)
|
||||||
interface.announce_cap = announce_cap
|
|
||||||
if configured_bitrate:
|
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
if ifac_size != None:
|
|
||||||
interface.ifac_size = ifac_size
|
|
||||||
else:
|
|
||||||
interface.ifac_size = 16
|
|
||||||
|
|
||||||
if c["type"] == "TCPClientInterface":
|
if c["type"] == "TCPClientInterface":
|
||||||
kiss_framing = False
|
|
||||||
if "kiss_framing" in c and c.as_bool("kiss_framing") == True:
|
|
||||||
kiss_framing = True
|
|
||||||
i2p_tunneled = c.as_bool("i2p_tunneled") if "i2p_tunneled" in c else False
|
|
||||||
tcp_connect_timeout = c.as_int("connect_timeout") if "connect_timeout" in c else None
|
|
||||||
|
|
||||||
|
|
||||||
interface = TCPInterface.TCPClientInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
c["target_host"],
|
|
||||||
int(c["target_port"]),
|
|
||||||
kiss_framing = kiss_framing,
|
|
||||||
i2p_tunneled = i2p_tunneled,
|
|
||||||
connect_timeout = tcp_connect_timeout,
|
|
||||||
)
|
|
||||||
|
|
||||||
if "outgoing" in c and c.as_bool("outgoing") == False:
|
|
||||||
interface.OUT = False
|
|
||||||
else:
|
|
||||||
interface.OUT = True
|
|
||||||
|
|
||||||
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
||||||
RNS.log(str(interface)+" does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
RNS.log(str(interface)+" does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
||||||
interface_mode = Interface.Interface.MODE_FULL
|
interface_mode = Interface.Interface.MODE_FULL
|
||||||
|
|
||||||
interface.mode = interface_mode
|
interface = TCPInterface.TCPClientInterface(RNS.Transport, interface_config)
|
||||||
|
interface_post_init(interface)
|
||||||
interface.announce_cap = announce_cap
|
|
||||||
if configured_bitrate:
|
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
if ifac_size != None:
|
|
||||||
interface.ifac_size = ifac_size
|
|
||||||
else:
|
|
||||||
interface.ifac_size = 16
|
|
||||||
|
|
||||||
if c["type"] == "I2PInterface":
|
if c["type"] == "I2PInterface":
|
||||||
i2p_peers = c.as_list("peers") if "peers" in c else None
|
|
||||||
connectable = c.as_bool("connectable") if "connectable" in c else False
|
|
||||||
|
|
||||||
if ifac_size == None:
|
|
||||||
ifac_size = 16
|
|
||||||
|
|
||||||
interface = I2PInterface.I2PInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
Reticulum.storagepath,
|
|
||||||
i2p_peers,
|
|
||||||
connectable = connectable,
|
|
||||||
ifac_size = ifac_size,
|
|
||||||
ifac_netname = ifac_netname,
|
|
||||||
ifac_netkey = ifac_netkey,
|
|
||||||
)
|
|
||||||
|
|
||||||
if "outgoing" in c and c.as_bool("outgoing") == False:
|
|
||||||
interface.OUT = False
|
|
||||||
else:
|
|
||||||
interface.OUT = True
|
|
||||||
|
|
||||||
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
if interface_mode == Interface.Interface.MODE_ACCESS_POINT:
|
||||||
RNS.log(str(interface)+" does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
RNS.log(str(interface)+" does not support Access Point mode, reverting to default mode: Full", RNS.LOG_WARNING)
|
||||||
interface_mode = Interface.Interface.MODE_FULL
|
interface_mode = Interface.Interface.MODE_FULL
|
||||||
|
|
||||||
interface.mode = interface_mode
|
interface_config["storagepath"] = Reticulum.storagepath
|
||||||
|
interface_config["ifac_netname"] = ifac_netname
|
||||||
|
interface_config["ifac_netkey"] = ifac_netkey
|
||||||
|
interface_config["ifac_size"] = ifac_size
|
||||||
|
|
||||||
interface.announce_cap = announce_cap
|
interface = I2PInterface.I2PInterface(RNS.Transport, interface_config)
|
||||||
if configured_bitrate:
|
interface_post_init(interface)
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
|
|
||||||
if c["type"] == "SerialInterface":
|
if c["type"] == "SerialInterface":
|
||||||
port = c["port"] if "port" in c else None
|
interface = SerialInterface.SerialInterface(RNS.Transport, interface_config)
|
||||||
speed = int(c["speed"]) if "speed" in c else 9600
|
interface_post_init(interface)
|
||||||
databits = int(c["databits"]) if "databits" in c else 8
|
|
||||||
parity = c["parity"] if "parity" in c else "N"
|
|
||||||
stopbits = int(c["stopbits"]) if "stopbits" in c else 1
|
|
||||||
|
|
||||||
if port == None:
|
|
||||||
raise ValueError("No port specified for serial interface")
|
|
||||||
|
|
||||||
interface = SerialInterface.SerialInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
port,
|
|
||||||
speed,
|
|
||||||
databits,
|
|
||||||
parity,
|
|
||||||
stopbits
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
if configured_bitrate:
|
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
if ifac_size != None:
|
|
||||||
interface.ifac_size = ifac_size
|
|
||||||
else:
|
|
||||||
interface.ifac_size = 8
|
|
||||||
|
|
||||||
if c["type"] == "PipeInterface":
|
if c["type"] == "PipeInterface":
|
||||||
command = c["command"] if "command" in c else None
|
interface = PipeInterface.PipeInterface(RNS.Transport, interface_config)
|
||||||
respawn_delay = c.as_float("respawn_delay") if "respawn_delay" in c else None
|
interface_post_init(interface)
|
||||||
|
|
||||||
if command == None:
|
|
||||||
raise ValueError("No command specified for PipeInterface")
|
|
||||||
|
|
||||||
interface = PipeInterface.PipeInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
command,
|
|
||||||
respawn_delay,
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
if configured_bitrate:
|
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
if ifac_size != None:
|
|
||||||
interface.ifac_size = ifac_size
|
|
||||||
else:
|
|
||||||
interface.ifac_size = 8
|
|
||||||
|
|
||||||
if c["type"] == "KISSInterface":
|
if c["type"] == "KISSInterface":
|
||||||
preamble = int(c["preamble"]) if "preamble" in c else None
|
interface = KISSInterface.KISSInterface(RNS.Transport, interface_config)
|
||||||
txtail = int(c["txtail"]) if "txtail" in c else None
|
interface_post_init(interface)
|
||||||
persistence = int(c["persistence"]) if "persistence" in c else None
|
|
||||||
slottime = int(c["slottime"]) if "slottime" in c else None
|
|
||||||
flow_control = c.as_bool("flow_control") if "flow_control" in c else False
|
|
||||||
port = c["port"] if "port" in c else None
|
|
||||||
speed = int(c["speed"]) if "speed" in c else 9600
|
|
||||||
databits = int(c["databits"]) if "databits" in c else 8
|
|
||||||
parity = c["parity"] if "parity" in c else "N"
|
|
||||||
stopbits = int(c["stopbits"]) if "stopbits" in c else 1
|
|
||||||
beacon_interval = int(c["id_interval"]) if "id_interval" in c else None
|
|
||||||
beacon_data = c["id_callsign"] if "id_callsign" in c else None
|
|
||||||
|
|
||||||
if port == None:
|
|
||||||
raise ValueError("No port specified for serial interface")
|
|
||||||
|
|
||||||
interface = KISSInterface.KISSInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
port,
|
|
||||||
speed,
|
|
||||||
databits,
|
|
||||||
parity,
|
|
||||||
stopbits,
|
|
||||||
preamble,
|
|
||||||
txtail,
|
|
||||||
persistence,
|
|
||||||
slottime,
|
|
||||||
flow_control,
|
|
||||||
beacon_interval,
|
|
||||||
beacon_data
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
if configured_bitrate:
|
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
if ifac_size != None:
|
|
||||||
interface.ifac_size = ifac_size
|
|
||||||
else:
|
|
||||||
interface.ifac_size = 8
|
|
||||||
|
|
||||||
if c["type"] == "AX25KISSInterface":
|
if c["type"] == "AX25KISSInterface":
|
||||||
preamble = int(c["preamble"]) if "preamble" in c else None
|
interface = AX25KISSInterface.AX25KISSInterface(RNS.Transport, interface_config)
|
||||||
txtail = int(c["txtail"]) if "txtail" in c else None
|
interface_post_init(interface)
|
||||||
persistence = int(c["persistence"]) if "persistence" in c else None
|
|
||||||
slottime = int(c["slottime"]) if "slottime" in c else None
|
|
||||||
flow_control = c.as_bool("flow_control") if "flow_control" in c else False
|
|
||||||
port = c["port"] if "port" in c else None
|
|
||||||
speed = int(c["speed"]) if "speed" in c else 9600
|
|
||||||
databits = int(c["databits"]) if "databits" in c else 8
|
|
||||||
parity = c["parity"] if "parity" in c else "N"
|
|
||||||
stopbits = int(c["stopbits"]) if "stopbits" in c else 1
|
|
||||||
|
|
||||||
callsign = c["callsign"] if "callsign" in c else ""
|
|
||||||
ssid = int(c["ssid"]) if "ssid" in c else -1
|
|
||||||
|
|
||||||
if port == None:
|
|
||||||
raise ValueError("No port specified for serial interface")
|
|
||||||
|
|
||||||
interface = AX25KISSInterface.AX25KISSInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
callsign,
|
|
||||||
ssid,
|
|
||||||
port,
|
|
||||||
speed,
|
|
||||||
databits,
|
|
||||||
parity,
|
|
||||||
stopbits,
|
|
||||||
preamble,
|
|
||||||
txtail,
|
|
||||||
persistence,
|
|
||||||
slottime,
|
|
||||||
flow_control
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
if configured_bitrate:
|
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
if ifac_size != None:
|
|
||||||
interface.ifac_size = ifac_size
|
|
||||||
else:
|
|
||||||
interface.ifac_size = 8
|
|
||||||
|
|
||||||
if c["type"] == "RNodeInterface":
|
if c["type"] == "RNodeInterface":
|
||||||
frequency = int(c["frequency"]) if "frequency" in c else None
|
interface = RNodeInterface.RNodeInterface(RNS.Transport, interface_config)
|
||||||
bandwidth = int(c["bandwidth"]) if "bandwidth" in c else None
|
interface_post_init(interface)
|
||||||
txpower = int(c["txpower"]) if "txpower" in c else None
|
|
||||||
spreadingfactor = int(c["spreadingfactor"]) if "spreadingfactor" in c else None
|
|
||||||
codingrate = int(c["codingrate"]) if "codingrate" in c else None
|
|
||||||
flow_control = c.as_bool("flow_control") if "flow_control" in c else False
|
|
||||||
id_interval = int(c["id_interval"]) if "id_interval" in c else None
|
|
||||||
id_callsign = c["id_callsign"] if "id_callsign" in c else None
|
|
||||||
st_alock = float(c["airtime_limit_short"]) if "airtime_limit_short" in c else None
|
|
||||||
lt_alock = float(c["airtime_limit_long"]) if "airtime_limit_long" in c else None
|
|
||||||
|
|
||||||
force_ble = False
|
|
||||||
ble_name = None
|
|
||||||
ble_addr = None
|
|
||||||
|
|
||||||
port = c["port"] if "port" in c else None
|
|
||||||
|
|
||||||
if port == None:
|
|
||||||
raise ValueError("No port specified for RNode interface")
|
|
||||||
|
|
||||||
if port != None:
|
|
||||||
ble_uri_scheme = "ble://"
|
|
||||||
if port.lower().startswith(ble_uri_scheme):
|
|
||||||
force_ble = True
|
|
||||||
ble_string = port[len(ble_uri_scheme):]
|
|
||||||
port = None
|
|
||||||
if len(ble_string) == 0:
|
|
||||||
pass
|
|
||||||
elif len(ble_string.split(":")) == 6 and len(ble_string) == 17:
|
|
||||||
ble_addr = ble_string
|
|
||||||
else:
|
|
||||||
ble_name = ble_string
|
|
||||||
|
|
||||||
interface = RNodeInterface.RNodeInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
port,
|
|
||||||
frequency = frequency,
|
|
||||||
bandwidth = bandwidth,
|
|
||||||
txpower = txpower,
|
|
||||||
sf = spreadingfactor,
|
|
||||||
cr = codingrate,
|
|
||||||
flow_control = flow_control,
|
|
||||||
id_interval = id_interval,
|
|
||||||
id_callsign = id_callsign,
|
|
||||||
st_alock = st_alock,
|
|
||||||
lt_alock = lt_alock,
|
|
||||||
ble_addr = ble_addr,
|
|
||||||
ble_name = ble_name,
|
|
||||||
force_ble = force_ble,
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
if configured_bitrate:
|
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
if ifac_size != None:
|
|
||||||
interface.ifac_size = ifac_size
|
|
||||||
else:
|
|
||||||
interface.ifac_size = 8
|
|
||||||
|
|
||||||
if c["type"] == "RNodeMultiInterface":
|
if c["type"] == "RNodeMultiInterface":
|
||||||
count = 0
|
interface = RNodeMultiInterface.RNodeMultiInterface(RNS.Transport, interface_config)
|
||||||
enabled_count = 0
|
interface_post_init(interface)
|
||||||
|
|
||||||
# Count how many interfaces are in the file
|
|
||||||
for subinterface in c:
|
|
||||||
# if the retrieved entry is not a string, it must be a dictionary, which is what we want
|
|
||||||
if not isinstance(c[subinterface], str):
|
|
||||||
count += 1
|
|
||||||
|
|
||||||
# Count how many interfaces are enabled to allow for appropriate matrix sizing
|
|
||||||
for subinterface in c:
|
|
||||||
# if the retrieved entry is not a string, it must be a dictionary, which is what we want
|
|
||||||
if not isinstance(c[subinterface], str):
|
|
||||||
subinterface_config = self.config["interfaces"][name][subinterface]
|
|
||||||
if (("interface_enabled" in subinterface_config) and subinterface_config.as_bool("interface_enabled") == True) or (("enabled" in c) and c.as_bool("enabled") == True):
|
|
||||||
enabled_count += 1
|
|
||||||
|
|
||||||
# Create an array with a row for each subinterface
|
|
||||||
subint_config = [[0 for x in range(11)] for y in range(enabled_count)]
|
|
||||||
subint_index = 0
|
|
||||||
|
|
||||||
for subinterface in c:
|
|
||||||
# If the retrieved entry is not a string, it must be a dictionary, which is what we want
|
|
||||||
if not isinstance(c[subinterface], str):
|
|
||||||
subinterface_config = self.config["interfaces"][name][subinterface]
|
|
||||||
if (("interface_enabled" in subinterface_config) and subinterface_config.as_bool("interface_enabled") == True) or (("enabled" in c) and c.as_bool("enabled") == True):
|
|
||||||
subint_config[subint_index][0] = subinterface
|
|
||||||
|
|
||||||
subint_vport = subinterface_config["vport"] if "vport" in subinterface_config else None
|
|
||||||
subint_config[subint_index][1] = subint_vport
|
|
||||||
|
|
||||||
frequency = int(subinterface_config["frequency"]) if "frequency" in subinterface_config else None
|
|
||||||
subint_config[subint_index][2] = frequency
|
|
||||||
bandwidth = int(subinterface_config["bandwidth"]) if "bandwidth" in subinterface_config else None
|
|
||||||
subint_config[subint_index][3] = bandwidth
|
|
||||||
txpower = int(subinterface_config["txpower"]) if "txpower" in subinterface_config else None
|
|
||||||
subint_config[subint_index][4] = txpower
|
|
||||||
spreadingfactor = int(subinterface_config["spreadingfactor"]) if "spreadingfactor" in subinterface_config else None
|
|
||||||
subint_config[subint_index][5] = spreadingfactor
|
|
||||||
codingrate = int(subinterface_config["codingrate"]) if "codingrate" in subinterface_config else None
|
|
||||||
subint_config[subint_index][6] = codingrate
|
|
||||||
flow_control = subinterface_config.as_bool("flow_control") if "flow_control" in subinterface_config else False
|
|
||||||
subint_config[subint_index][7] = flow_control
|
|
||||||
st_alock = float(subinterface_config["airtime_limit_short"]) if "airtime_limit_short" in subinterface_config else None
|
|
||||||
subint_config[subint_index][8] = st_alock
|
|
||||||
lt_alock = float(subinterface_config["airtime_limit_long"]) if "airtime_limit_long" in subinterface_config else None
|
|
||||||
subint_config[subint_index][9] = lt_alock
|
|
||||||
|
|
||||||
if "outgoing" in subinterface_config and subinterface_config.as_bool("outgoing") == False:
|
|
||||||
subint_config[subint_index][10] = False
|
|
||||||
else:
|
|
||||||
subint_config[subint_index][10] = True
|
|
||||||
subint_index += 1
|
|
||||||
|
|
||||||
# if no subinterfaces are defined
|
|
||||||
if count == 0:
|
|
||||||
raise ValueError("No subinterfaces configured for "+name)
|
|
||||||
# if no subinterfaces are enabled
|
|
||||||
elif enabled_count == 0:
|
|
||||||
raise ValueError("No subinterfaces enabled for "+name)
|
|
||||||
|
|
||||||
id_interval = int(c["id_interval"]) if "id_interval" in c else None
|
|
||||||
id_callsign = c["id_callsign"] if "id_callsign" in c else None
|
|
||||||
port = c["port"] if "port" in c else None
|
|
||||||
|
|
||||||
if port == None:
|
|
||||||
raise ValueError("No port specified for "+name)
|
|
||||||
|
|
||||||
interface = RNodeMultiInterface.RNodeMultiInterface(
|
|
||||||
RNS.Transport,
|
|
||||||
name,
|
|
||||||
port,
|
|
||||||
subint_config,
|
|
||||||
id_interval = id_interval,
|
|
||||||
id_callsign = id_callsign
|
|
||||||
)
|
|
||||||
|
|
||||||
interface.IN = False
|
|
||||||
interface.OUT = False
|
|
||||||
|
|
||||||
interface.mode = interface_mode
|
|
||||||
|
|
||||||
interface.announce_cap = announce_cap
|
|
||||||
if configured_bitrate:
|
|
||||||
interface.bitrate = configured_bitrate
|
|
||||||
if ifac_size != None:
|
|
||||||
interface.ifac_size = ifac_size
|
|
||||||
else:
|
|
||||||
interface.ifac_size = 8
|
|
||||||
|
|
||||||
|
|
||||||
if interface != None:
|
if interface != None:
|
||||||
interface.announce_rate_target = announce_rate_target
|
interface.announce_rate_target = announce_rate_target
|
||||||
@ -1119,7 +685,7 @@ class Reticulum:
|
|||||||
|
|
||||||
RNS.log("System interfaces are ready", RNS.LOG_VERBOSE)
|
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):
|
||||||
if not self.is_connected_to_shared_instance:
|
if not self.is_connected_to_shared_instance:
|
||||||
if interface != None and issubclass(type(interface), RNS.Interfaces.Interface.Interface):
|
if interface != None and issubclass(type(interface), RNS.Interfaces.Interface.Interface):
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "0.8.5"
|
__version__ = "0.8.6"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Sphinx build info version 1
|
# Sphinx build info version 1
|
||||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||||
config: 068d3fe32e7f0c111ab64548184dd063
|
config: a6abb7db1df16737cc5d923272a50d50
|
||||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||||
|
@ -171,7 +171,7 @@ TCP Server Interface
|
|||||||
====================
|
====================
|
||||||
|
|
||||||
The TCP Server interface is suitable for allowing other peers to connect over
|
The TCP Server interface is suitable for allowing other peers to connect over
|
||||||
the Internet or private IP networks. When a TCP server interface has been
|
the Internet or private IPv4 and IPv6 networks. When a TCP server interface has been
|
||||||
configured, other Reticulum peers can connect to it with a TCP Client interface.
|
configured, other Reticulum peers can connect to it with a TCP Client interface.
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
@ -200,6 +200,34 @@ configured, other Reticulum peers can connect to it with a TCP Client interface.
|
|||||||
# device = eth0
|
# device = eth0
|
||||||
# port = 4242
|
# port = 4242
|
||||||
|
|
||||||
|
If you are using the interface on a device which has both IPv4 and IPv6 addresses available,
|
||||||
|
you can use the ``prefer_ipv6`` option to bind to the IPv6 address:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
# This example demonstrates a TCP server interface.
|
||||||
|
# It will listen for incoming connections on the
|
||||||
|
# specified IP address and port number.
|
||||||
|
|
||||||
|
[[TCP Server Interface]]
|
||||||
|
type = TCPServerInterface
|
||||||
|
interface_enabled = True
|
||||||
|
|
||||||
|
device = eth0
|
||||||
|
port = 4242
|
||||||
|
prefer_ipv6 = True
|
||||||
|
|
||||||
|
To use the TCP Server Interface over `Yggdrasil <https://yggdrasil-network.github.io/>`_, you
|
||||||
|
can simply specify the Yggdrasil ``tun`` device and a listening port, like so:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
[[Yggdrasil TCP Server Interface]]
|
||||||
|
type = TCPServerInterface
|
||||||
|
interface_enabled = yes
|
||||||
|
device = tun0
|
||||||
|
listen_port = 4343
|
||||||
|
|
||||||
**Please Note!** The TCP interfaces support tunneling over I2P, but to do so reliably,
|
**Please Note!** The TCP interfaces support tunneling over I2P, but to do so reliably,
|
||||||
you must use the i2p_tunneled option:
|
you must use the i2p_tunneled option:
|
||||||
|
|
||||||
@ -231,7 +259,7 @@ and restore connectivity after a failure, once the other end of a TCP interface
|
|||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
# Here's an example of a TCP Client interface. The
|
# Here's an example of a TCP Client interface. The
|
||||||
# target_host can either be an IP address or a hostname.
|
# target_host can be a hostname or an IPv4 or IPv6 address.
|
||||||
|
|
||||||
[[TCP Client Interface]]
|
[[TCP Client Interface]]
|
||||||
type = TCPClientInterface
|
type = TCPClientInterface
|
||||||
@ -239,6 +267,17 @@ and restore connectivity after a failure, once the other end of a TCP interface
|
|||||||
target_host = 127.0.0.1
|
target_host = 127.0.0.1
|
||||||
target_port = 4242
|
target_port = 4242
|
||||||
|
|
||||||
|
To use the TCP Client Interface over `Yggdrasil <https://yggdrasil-network.github.io/>`_, simply
|
||||||
|
specify the target Yggdrasil IPv6 address and port, like so:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
[[Yggdrasil TCP Client Interface]]
|
||||||
|
type = TCPClientInterface
|
||||||
|
interface_enabled = yes
|
||||||
|
target_host = 201:5d78:af73:5caf:a4de:a79f:3278:71e5
|
||||||
|
target_port = 4343
|
||||||
|
|
||||||
It is also possible to use this interface type to connect via other programs
|
It is also possible to use this interface type to connect via other programs
|
||||||
or hardware devices that expose a KISS interface on a TCP port, for example
|
or hardware devices that expose a KISS interface on a TCP port, for example
|
||||||
software-based soundmodems. To do this, use the ``kiss_framing`` option:
|
software-based soundmodems. To do this, use the ``kiss_framing`` option:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||||
VERSION: '0.8.5 beta',
|
VERSION: '0.8.6 beta',
|
||||||
LANGUAGE: 'en',
|
LANGUAGE: 'en',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
BUILDER: 'html',
|
BUILDER: 'html',
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Support Reticulum" href="support.html" /><link rel="prev" title="Building Networks" href="networks.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Support Reticulum" href="support.html" /><link rel="prev" title="Building Networks" href="networks.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Code Examples - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>Code Examples - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="#" /><link rel="search" title="Search" href="search.html" />
|
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="#" /><link rel="search" title="Search" href="search.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Index - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Index - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -139,7 +139,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -165,7 +165,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Using Reticulum on Your System" href="using.html" /><link rel="prev" title="What is Reticulum?" href="whatis.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Using Reticulum on Your System" href="using.html" /><link rel="prev" title="What is Reticulum?" href="whatis.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Getting Started Fast - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>Getting Started Fast - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Configuring Interfaces" href="interfaces.html" /><link rel="prev" title="Understanding Reticulum" href="understanding.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Configuring Interfaces" href="interfaces.html" /><link rel="prev" title="Understanding Reticulum" href="understanding.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Communications Hardware - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>Communications Hardware - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="What is Reticulum?" href="whatis.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="What is Reticulum?" href="whatis.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="#"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="#"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Building Networks" href="networks.html" /><link rel="prev" title="Communications Hardware" href="hardware.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Building Networks" href="networks.html" /><link rel="prev" title="Communications Hardware" href="hardware.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Configuring Interfaces - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>Configuring Interfaces - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@ -360,7 +360,7 @@ use-cases.</p>
|
|||||||
<section id="tcp-server-interface">
|
<section id="tcp-server-interface">
|
||||||
<span id="interfaces-tcps"></span><h2>TCP Server Interface<a class="headerlink" href="#tcp-server-interface" title="Permalink to this heading">#</a></h2>
|
<span id="interfaces-tcps"></span><h2>TCP Server Interface<a class="headerlink" href="#tcp-server-interface" title="Permalink to this heading">#</a></h2>
|
||||||
<p>The TCP Server interface is suitable for allowing other peers to connect over
|
<p>The TCP Server interface is suitable for allowing other peers to connect over
|
||||||
the Internet or private IP networks. When a TCP server interface has been
|
the Internet or private IPv4 and IPv6 networks. When a TCP server interface has been
|
||||||
configured, other Reticulum peers can connect to it with a TCP Client interface.</p>
|
configured, other Reticulum peers can connect to it with a TCP Client interface.</p>
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># This example demonstrates a TCP server interface.</span>
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># This example demonstrates a TCP server interface.</span>
|
||||||
<span class="c1"># It will listen for incoming connections on the</span>
|
<span class="c1"># It will listen for incoming connections on the</span>
|
||||||
@ -387,6 +387,30 @@ configured, other Reticulum peers can connect to it with a TCP Client interface.
|
|||||||
<span class="c1"># port = 4242</span>
|
<span class="c1"># port = 4242</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
|
<p>If you are using the interface on a device which has both IPv4 and IPv6 addresses available,
|
||||||
|
you can use the <code class="docutils literal notranslate"><span class="pre">prefer_ipv6</span></code> option to bind to the IPv6 address:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># This example demonstrates a TCP server interface.</span>
|
||||||
|
<span class="c1"># It will listen for incoming connections on the</span>
|
||||||
|
<span class="c1"># specified IP address and port number.</span>
|
||||||
|
|
||||||
|
<span class="p">[[</span><span class="n">TCP</span> <span class="n">Server</span> <span class="n">Interface</span><span class="p">]]</span>
|
||||||
|
<span class="nb">type</span> <span class="o">=</span> <span class="n">TCPServerInterface</span>
|
||||||
|
<span class="n">interface_enabled</span> <span class="o">=</span> <span class="kc">True</span>
|
||||||
|
|
||||||
|
<span class="n">device</span> <span class="o">=</span> <span class="n">eth0</span>
|
||||||
|
<span class="n">port</span> <span class="o">=</span> <span class="mi">4242</span>
|
||||||
|
<span class="n">prefer_ipv6</span> <span class="o">=</span> <span class="kc">True</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>To use the TCP Server Interface over <a class="reference external" href="https://yggdrasil-network.github.io/">Yggdrasil</a>, you
|
||||||
|
can simply specify the Yggdrasil <code class="docutils literal notranslate"><span class="pre">tun</span></code> device and a listening port, like so:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[[</span><span class="n">Yggdrasil</span> <span class="n">TCP</span> <span class="n">Server</span> <span class="n">Interface</span><span class="p">]]</span>
|
||||||
|
<span class="nb">type</span> <span class="o">=</span> <span class="n">TCPServerInterface</span>
|
||||||
|
<span class="n">interface_enabled</span> <span class="o">=</span> <span class="n">yes</span>
|
||||||
|
<span class="n">device</span> <span class="o">=</span> <span class="n">tun0</span>
|
||||||
|
<span class="n">listen_port</span> <span class="o">=</span> <span class="mi">4343</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
<p><strong>Please Note!</strong> The TCP interfaces support tunneling over I2P, but to do so reliably,
|
<p><strong>Please Note!</strong> The TCP interfaces support tunneling over I2P, but to do so reliably,
|
||||||
you must use the i2p_tunneled option:</p>
|
you must use the i2p_tunneled option:</p>
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[[</span><span class="n">TCP</span> <span class="n">Server</span> <span class="n">on</span> <span class="n">I2P</span><span class="p">]]</span>
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[[</span><span class="n">TCP</span> <span class="n">Server</span> <span class="n">on</span> <span class="n">I2P</span><span class="p">]]</span>
|
||||||
@ -409,7 +433,7 @@ same TCP Server interface at the same time.</p>
|
|||||||
This means that Reticulum will gracefully handle IP links that go up and down,
|
This means that Reticulum will gracefully handle IP links that go up and down,
|
||||||
and restore connectivity after a failure, once the other end of a TCP interface reappears.</p>
|
and restore connectivity after a failure, once the other end of a TCP interface reappears.</p>
|
||||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Here's an example of a TCP Client interface. The</span>
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Here's an example of a TCP Client interface. The</span>
|
||||||
<span class="c1"># target_host can either be an IP address or a hostname.</span>
|
<span class="c1"># target_host can be a hostname or an IPv4 or IPv6 address.</span>
|
||||||
|
|
||||||
<span class="p">[[</span><span class="n">TCP</span> <span class="n">Client</span> <span class="n">Interface</span><span class="p">]]</span>
|
<span class="p">[[</span><span class="n">TCP</span> <span class="n">Client</span> <span class="n">Interface</span><span class="p">]]</span>
|
||||||
<span class="nb">type</span> <span class="o">=</span> <span class="n">TCPClientInterface</span>
|
<span class="nb">type</span> <span class="o">=</span> <span class="n">TCPClientInterface</span>
|
||||||
@ -418,6 +442,15 @@ and restore connectivity after a failure, once the other end of a TCP interface
|
|||||||
<span class="n">target_port</span> <span class="o">=</span> <span class="mi">4242</span>
|
<span class="n">target_port</span> <span class="o">=</span> <span class="mi">4242</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
|
<p>To use the TCP Client Interface over <a class="reference external" href="https://yggdrasil-network.github.io/">Yggdrasil</a>, simply
|
||||||
|
specify the target Yggdrasil IPv6 address and port, like so:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[[</span><span class="n">Yggdrasil</span> <span class="n">TCP</span> <span class="n">Client</span> <span class="n">Interface</span><span class="p">]]</span>
|
||||||
|
<span class="nb">type</span> <span class="o">=</span> <span class="n">TCPClientInterface</span>
|
||||||
|
<span class="n">interface_enabled</span> <span class="o">=</span> <span class="n">yes</span>
|
||||||
|
<span class="n">target_host</span> <span class="o">=</span> <span class="mi">201</span><span class="p">:</span><span class="mi">5</span><span class="n">d78</span><span class="p">:</span><span class="n">af73</span><span class="p">:</span><span class="mi">5</span><span class="n">caf</span><span class="p">:</span><span class="n">a4de</span><span class="p">:</span><span class="n">a79f</span><span class="p">:</span><span class="mi">3278</span><span class="p">:</span><span class="mf">71e5</span>
|
||||||
|
<span class="n">target_port</span> <span class="o">=</span> <span class="mi">4343</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
<p>It is also possible to use this interface type to connect via other programs
|
<p>It is also possible to use this interface type to connect via other programs
|
||||||
or hardware devices that expose a KISS interface on a TCP port, for example
|
or hardware devices that expose a KISS interface on a TCP port, for example
|
||||||
software-based soundmodems. To do this, use the <code class="docutils literal notranslate"><span class="pre">kiss_framing</span></code> option:</p>
|
software-based soundmodems. To do this, use the <code class="docutils literal notranslate"><span class="pre">kiss_framing</span></code> option:</p>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Code Examples" href="examples.html" /><link rel="prev" title="Configuring Interfaces" href="interfaces.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Code Examples" href="examples.html" /><link rel="prev" title="Configuring Interfaces" href="interfaces.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Building Networks - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>Building Networks - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
Binary file not shown.
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="prev" title="Support Reticulum" href="support.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="prev" title="Support Reticulum" href="support.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>API Reference - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>API Reference - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
||||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="#" />
|
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="#" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Search - Reticulum Network Stack 0.8.5 beta documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Search - Reticulum Network Stack 0.8.6 beta documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||||
@ -138,7 +138,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -164,7 +164,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="#" role="search">
|
</a><form class="sidebar-search-container" method="get" action="#" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
File diff suppressed because one or more lines are too long
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="API Reference" href="reference.html" /><link rel="prev" title="Code Examples" href="examples.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="API Reference" href="reference.html" /><link rel="prev" title="Code Examples" href="examples.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Support Reticulum - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>Support Reticulum - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Communications Hardware" href="hardware.html" /><link rel="prev" title="Using Reticulum on Your System" href="using.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Communications Hardware" href="hardware.html" /><link rel="prev" title="Using Reticulum on Your System" href="using.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Understanding Reticulum - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>Understanding Reticulum - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Understanding Reticulum" href="understanding.html" /><link rel="prev" title="Getting Started Fast" href="gettingstartedfast.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Understanding Reticulum" href="understanding.html" /><link rel="prev" title="Getting Started Fast" href="gettingstartedfast.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>Using Reticulum on Your System - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>Using Reticulum on Your System - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Getting Started Fast" href="gettingstartedfast.html" /><link rel="prev" title="Reticulum Network Stack Manual" href="index.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Getting Started Fast" href="gettingstartedfast.html" /><link rel="prev" title="Reticulum Network Stack Manual" href="index.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
|
||||||
<title>What is Reticulum? - Reticulum Network Stack 0.8.5 beta documentation</title>
|
<title>What is Reticulum? - Reticulum Network Stack 0.8.6 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
|
||||||
@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.5 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.8.6 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.5 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.8.6 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
|
@ -171,7 +171,7 @@ TCP Server Interface
|
|||||||
====================
|
====================
|
||||||
|
|
||||||
The TCP Server interface is suitable for allowing other peers to connect over
|
The TCP Server interface is suitable for allowing other peers to connect over
|
||||||
the Internet or private IP networks. When a TCP server interface has been
|
the Internet or private IPv4 and IPv6 networks. When a TCP server interface has been
|
||||||
configured, other Reticulum peers can connect to it with a TCP Client interface.
|
configured, other Reticulum peers can connect to it with a TCP Client interface.
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
@ -200,6 +200,34 @@ configured, other Reticulum peers can connect to it with a TCP Client interface.
|
|||||||
# device = eth0
|
# device = eth0
|
||||||
# port = 4242
|
# port = 4242
|
||||||
|
|
||||||
|
If you are using the interface on a device which has both IPv4 and IPv6 addresses available,
|
||||||
|
you can use the ``prefer_ipv6`` option to bind to the IPv6 address:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
# This example demonstrates a TCP server interface.
|
||||||
|
# It will listen for incoming connections on the
|
||||||
|
# specified IP address and port number.
|
||||||
|
|
||||||
|
[[TCP Server Interface]]
|
||||||
|
type = TCPServerInterface
|
||||||
|
interface_enabled = True
|
||||||
|
|
||||||
|
device = eth0
|
||||||
|
port = 4242
|
||||||
|
prefer_ipv6 = True
|
||||||
|
|
||||||
|
To use the TCP Server Interface over `Yggdrasil <https://yggdrasil-network.github.io/>`_, you
|
||||||
|
can simply specify the Yggdrasil ``tun`` device and a listening port, like so:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
[[Yggdrasil TCP Server Interface]]
|
||||||
|
type = TCPServerInterface
|
||||||
|
interface_enabled = yes
|
||||||
|
device = tun0
|
||||||
|
listen_port = 4343
|
||||||
|
|
||||||
**Please Note!** The TCP interfaces support tunneling over I2P, but to do so reliably,
|
**Please Note!** The TCP interfaces support tunneling over I2P, but to do so reliably,
|
||||||
you must use the i2p_tunneled option:
|
you must use the i2p_tunneled option:
|
||||||
|
|
||||||
@ -231,7 +259,7 @@ and restore connectivity after a failure, once the other end of a TCP interface
|
|||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
# Here's an example of a TCP Client interface. The
|
# Here's an example of a TCP Client interface. The
|
||||||
# target_host can either be an IP address or a hostname.
|
# target_host can be a hostname or an IPv4 or IPv6 address.
|
||||||
|
|
||||||
[[TCP Client Interface]]
|
[[TCP Client Interface]]
|
||||||
type = TCPClientInterface
|
type = TCPClientInterface
|
||||||
@ -239,6 +267,17 @@ and restore connectivity after a failure, once the other end of a TCP interface
|
|||||||
target_host = 127.0.0.1
|
target_host = 127.0.0.1
|
||||||
target_port = 4242
|
target_port = 4242
|
||||||
|
|
||||||
|
To use the TCP Client Interface over `Yggdrasil <https://yggdrasil-network.github.io/>`_, simply
|
||||||
|
specify the target Yggdrasil IPv6 address and port, like so:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
[[Yggdrasil TCP Client Interface]]
|
||||||
|
type = TCPClientInterface
|
||||||
|
interface_enabled = yes
|
||||||
|
target_host = 201:5d78:af73:5caf:a4de:a79f:3278:71e5
|
||||||
|
target_port = 4343
|
||||||
|
|
||||||
It is also possible to use this interface type to connect via other programs
|
It is also possible to use this interface type to connect via other programs
|
||||||
or hardware devices that expose a KISS interface on a TCP port, for example
|
or hardware devices that expose a KISS interface on a TCP port, for example
|
||||||
software-based soundmodems. To do this, use the ``kiss_framing`` option:
|
software-based soundmodems. To do this, use the ``kiss_framing`` option:
|
||||||
@ -454,89 +493,89 @@ Multi interface can be used to configure sub-interfaces individually.
|
|||||||
# id_interval = 600
|
# id_interval = 600
|
||||||
|
|
||||||
# A subinterface
|
# A subinterface
|
||||||
[[[HIGHDATARATE]]]
|
[[[High Datarate]]]
|
||||||
# Subinterfaces can be enabled and disabled in of themselves
|
# Subinterfaces can be enabled and disabled in of themselves
|
||||||
interface_enabled = True
|
interface_enabled = True
|
||||||
|
|
||||||
# Set frequency to 2.4GHz
|
# Set frequency to 2.4GHz
|
||||||
frequency = 2400000000
|
frequency = 2400000000
|
||||||
|
|
||||||
# Set LoRa bandwidth to 1625 KHz
|
# Set LoRa bandwidth to 1625 KHz
|
||||||
bandwidth = 1625000
|
bandwidth = 1625000
|
||||||
|
|
||||||
# Set TX power to 0 dBm (0.12 mW)
|
# Set TX power to 0 dBm (0.12 mW)
|
||||||
txpower = 0
|
txpower = 0
|
||||||
|
|
||||||
# The virtual port, only the manufacturer
|
# The virtual port, only the manufacturer
|
||||||
# or the person who wrote the board config
|
# or the person who wrote the board config
|
||||||
# can tell you what it will be for which
|
# can tell you what it will be for which
|
||||||
# physical hardware interface
|
# physical hardware interface
|
||||||
vport = 1
|
vport = 1
|
||||||
|
|
||||||
# Select spreading factor 5. Valid
|
# Select spreading factor 5. Valid
|
||||||
# range is 5 through 12, with 5
|
# range is 5 through 12, with 5
|
||||||
# being the fastest and 12 having
|
# being the fastest and 12 having
|
||||||
# the longest range.
|
# the longest range.
|
||||||
spreadingfactor = 5
|
spreadingfactor = 5
|
||||||
|
|
||||||
# Select coding rate 5. Valid range
|
# Select coding rate 5. Valid range
|
||||||
# is 5 throough 8, with 5 being the
|
# is 5 throough 8, with 5 being the
|
||||||
# fastest, and 8 the longest range.
|
# fastest, and 8 the longest range.
|
||||||
codingrate = 5
|
codingrate = 5
|
||||||
|
|
||||||
# It is possible to limit the airtime
|
# It is possible to limit the airtime
|
||||||
# utilisation of an RNode by using the
|
# utilisation of an RNode by using the
|
||||||
# following two configuration options.
|
# following two configuration options.
|
||||||
# The short-term limit is applied in a
|
# The short-term limit is applied in a
|
||||||
# window of approximately 15 seconds,
|
# window of approximately 15 seconds,
|
||||||
# and the long-term limit is enforced
|
# and the long-term limit is enforced
|
||||||
# over a rolling 60 minute window. Both
|
# over a rolling 60 minute window. Both
|
||||||
# options are specified in percent.
|
# options are specified in percent.
|
||||||
|
|
||||||
# airtime_limit_long = 100
|
# airtime_limit_long = 100
|
||||||
# airtime_limit_short = 100
|
# airtime_limit_short = 100
|
||||||
|
|
||||||
[[[LOWDATARATE]]]
|
[[[Low Datarate]]]
|
||||||
# Subinterfaces can be enabled and disabled in of themselves
|
# Subinterfaces can be enabled and disabled in of themselves
|
||||||
interface_enabled = True
|
interface_enabled = True
|
||||||
|
|
||||||
# Set frequency to 865.6 MHz
|
# Set frequency to 865.6 MHz
|
||||||
frequency = 865600000
|
frequency = 865600000
|
||||||
|
|
||||||
# The virtual port, only the manufacturer
|
# The virtual port, only the manufacturer
|
||||||
# or the person who wrote the board config
|
# or the person who wrote the board config
|
||||||
# can tell you what it will be for which
|
# can tell you what it will be for which
|
||||||
# physical hardware interface
|
# physical hardware interface
|
||||||
vport = 0
|
vport = 0
|
||||||
|
|
||||||
# Set LoRa bandwidth to 125 KHz
|
# Set LoRa bandwidth to 125 KHz
|
||||||
bandwidth = 125000
|
bandwidth = 125000
|
||||||
|
|
||||||
# Set TX power to 0 dBm (0.12 mW)
|
# Set TX power to 0 dBm (0.12 mW)
|
||||||
txpower = 0
|
txpower = 0
|
||||||
|
|
||||||
# Select spreading factor 7. Valid
|
# Select spreading factor 7. Valid
|
||||||
# range is 5 through 12, with 5
|
# range is 5 through 12, with 5
|
||||||
# being the fastest and 12 having
|
# being the fastest and 12 having
|
||||||
# the longest range.
|
# the longest range.
|
||||||
spreadingfactor = 7
|
spreadingfactor = 7
|
||||||
|
|
||||||
# Select coding rate 5. Valid range
|
# Select coding rate 5. Valid range
|
||||||
# is 5 throough 8, with 5 being the
|
# is 5 throough 8, with 5 being the
|
||||||
# fastest, and 8 the longest range.
|
# fastest, and 8 the longest range.
|
||||||
codingrate = 5
|
codingrate = 5
|
||||||
|
|
||||||
# It is possible to limit the airtime
|
# It is possible to limit the airtime
|
||||||
# utilisation of an RNode by using the
|
# utilisation of an RNode by using the
|
||||||
# following two configuration options.
|
# following two configuration options.
|
||||||
# The short-term limit is applied in a
|
# The short-term limit is applied in a
|
||||||
# window of approximately 15 seconds,
|
# window of approximately 15 seconds,
|
||||||
# and the long-term limit is enforced
|
# and the long-term limit is enforced
|
||||||
# over a rolling 60 minute window. Both
|
# over a rolling 60 minute window. Both
|
||||||
# options are specified in percent.
|
# options are specified in percent.
|
||||||
|
|
||||||
# airtime_limit_long = 100
|
# airtime_limit_long = 100
|
||||||
# airtime_limit_short = 100
|
# airtime_limit_short = 100
|
||||||
|
|
||||||
.. _interfaces-serial:
|
.. _interfaces-serial:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user