Compare commits

...

30 Commits

Author SHA1 Message Date
Lucas
9bad8370da
Merge 221493d816 into ba2feaa211 2024-05-21 01:16:29 +00:00
Mark Qvist
ba2feaa211 Updated changelog 2024-05-18 18:51:17 +02:00
Mark Qvist
097d2b0dd9 Updated changelog 2024-05-18 18:48:32 +02:00
Mark Qvist
bb0ce4faca Added T3S3 flashing, fixed Heltec V3 autoinstaller menu 2024-05-18 18:40:21 +02:00
Mark Qvist
5915228f5b Updated documentation 2024-05-18 18:38:06 +02:00
Mark Qvist
0b66649158 Avoid nRF52 hard reset after EEPROM wipe 2024-05-18 00:18:54 +02:00
markqvist
e28dd6e14a
Merge pull request #502 from jacobeva/master
Extend RAK4631 support
2024-05-18 00:15:48 +02:00
markqvist
0a15b4c6c1
Merge branch 'master' into master 2024-05-18 00:15:13 +02:00
markqvist
62db09571d
Merge pull request #504 from jacobeva/hash-feature
Add ability to get target and calculated firmware hash from device
2024-05-18 00:04:24 +02:00
Mark Qvist
444ae0206b Added better handling on Windows of interfaces that are non-adoptable for AutoInterface 2024-05-17 23:54:48 +02:00
Mark Qvist
4b07e30b9d Updated version 2024-05-17 23:54:04 +02:00
markqvist
583e65419e
Merge pull request #506 from liamcottle/feature/windows-auto-interface
Implement AutoInterface support on Windows
2024-05-17 16:32:33 +02:00
liamcottle
1564930a51 auto interface working on windows 2024-05-17 04:09:11 +12:00
markqvist
b81b1de4eb
Merge pull request #500 from faragher/master
Windows DTR timing fix
2024-05-15 20:06:36 +02:00
jacob.eva
746a38f818
Add ability to get target and calculated firmware hash from device 2024-05-13 22:55:49 +01:00
jacob.eva
c230eceaa6
Extend RAK4631 support 2024-05-13 21:49:57 +01:00
faragher
3551662187 Changing log levels 2024-05-08 02:19:59 -05:00
faragher
f7f34e0ea3 Windows DTR timing adjustments 2024-05-08 02:14:29 -05:00
nothingbutlucas
221493d816
Revert "refactor(rnodeconf): Replace string concatenation"
This reverts commit e47dcae54e.
2024-05-05 17:07:55 -03:00
nothingbutlucas
e47dcae54e
refactor(rnodeconf): Replace string concatenation
Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-05-04 14:29:56 -03:00
nothingbutlucas
acd893a6e6
refactor: Replace string concatenation with joins
Same as previous commits. "".join() is better that "string" + "another_string" + "another_string_2", because strings are immutable.
Also, changed for loops with list comprehension. This is much faster and would improve performance.

Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-04-24 15:37:10 -03:00
nothingbutlucas
c032a2e438
refactor(if/elif): Add elif's on if "questions"
The variable sorting can have only 1 value at a time. So does not make sense to ask on every if statement the value of sorting. If one statement is True, then, the other would be False.

Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-04-24 12:11:43 -03:00
nothingbutlucas
1f6a494e14
refactor: Change loop for dictionary comprehension
This will improve code execution because nested loops are slower than list/dictionary comprehensions.

Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-04-24 12:08:23 -03:00
nothingbutlucas
059c2381b5
refactor(if/else/return): Remove indentation
This may seems like a lot, but the only think that I change here was the if/else block. I move the else statement at the beginning and if that condition is true, will exit the function. This is just for code clarity, I think that this change should not improve the speed or performance of the code.

Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-04-24 11:52:02 -03:00
nothingbutlucas
541d3cde48
style: Format the code a little bit
This will remove the unnecesary import of time, and a little bit of format

Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-04-24 11:28:00 -03:00
nothingbutlucas
87ff1808a2
refactor(main): Reduce complexity of main function
This will make it easier for us to maintain and understand the main function. Also deleting duplicated code

Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-04-24 11:04:26 -03:00
nothingbutlucas
8d1a000378
refactor: Change method for string concatenations
Strings in Python are immutable so, the "+" operation means that we need to create the string again and attaching the old content. Per "+". We can replace this by using join() or built-in functions or arguments of functions, like "sep" in print()

Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-04-24 10:30:07 -03:00
nothingbutlucas
794a5f4401
refactor: Remove unused code
Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-04-24 00:34:08 -03:00
nothingbutlucas
7159e6a523
style: Change comparations according PEP8
According PEP8 this is the recommended way to do it. I'm 99% sure that this does not speed up the code, but we are comparing identity, not equality, so "is" and "is not" must be used.

Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-04-24 00:32:11 -03:00
nothingbutlucas
cf41187e2f
refactor: Change for loop to list comprehensions
Not only more concise and shorter, it's notably faster

Signed-off-by: nothingbutlucas <69118979+nothingbutlucas@users.noreply.github.com>
2024-04-24 00:24:22 -03:00
29 changed files with 894 additions and 605 deletions

View File

@ -1,3 +1,22 @@
### 2024-05-18: RNS β 0.7.5
This release adds support for AutoInterface on Windows platforms, fixes a number of bugs and adds several new supported boards to `rnodeconf`. Thanks to @faragher, @jacobeva and @liamcottle who contributed to this release!
**Changes**
- Added support for AutoInterface on Windows
- Added support for recursive path resolution for clients on roaming-mode interfaces
- Added RAK4631 support to `rnodeconf`
- Added LilyGO T3S3 support to `rnodeconf`
- Added ability to get target and calculated hashes via `rnodeconf`
- Fixed DTR timing making flashing fail on Windows in `rnodeconf`
- Fixed various output and menu bugs in `rnodeconf`
**Release Hashes**
```
99ec876966afdea45fcf164242c8e76c284f9e3edf09fb907638fba76e1324b1 rns-0.7.5-py3-none-any.whl
11156f6301707e4d17ff2ca6d58059bc8ba6fe1bbc4dc3de165dd96dc41ee75f rnspure-0.7.5-py3-none-any.whl
```
### 2024-05-05: RNS β 0.7.4
This maintenance release fixes a number of bugs, improves path requests and responses, and adds several useful features and capabilities. Thanks to @cobraPA, @jschulthess, @thiaguetz and @nothingbutlucas who contributed to this release!

View File

@ -77,6 +77,15 @@ class AutoInterface(Interface):
ifas = self.netinfo.ifaddresses(ifname)
return ifas
def interface_name_to_index(self, ifname):
# socket.if_nametoindex doesn't work with uuid interface names on windows, it wants the ethernet_0 style
# we will just get the index from netinfo instead as it seems to work
if RNS.vendor.platformutils.is_windows():
return self.netinfo.interface_names_to_indexes()[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):
from RNS.vendor.ifaddr import niwrapper
super().__init__()
@ -172,6 +181,7 @@ class AutoInterface(Interface):
suitable_interfaces = 0
for ifname in self.list_interfaces():
try:
if RNS.vendor.platformutils.is_darwin() and ifname in AutoInterface.DARWIN_IGNORE_IFS and not ifname in self.allowed_interfaces:
RNS.log(str(self)+" skipping Darwin AWDL or tethering interface "+str(ifname), RNS.LOG_EXTREME)
elif RNS.vendor.platformutils.is_darwin() and ifname == "lo0":
@ -196,7 +206,11 @@ class AutoInterface(Interface):
self.link_local_addresses.append(link_local_addr)
self.adopted_interfaces[ifname] = link_local_addr
self.multicast_echoes[ifname] = time.time()
RNS.log(str(self)+" Selecting link-local address "+str(link_local_addr)+" for interface "+str(ifname), RNS.LOG_EXTREME)
nice_name = self.netinfo.interface_name_to_nice_name(ifname)
if nice_name != None and nice_name != ifname:
RNS.log(f"{self} Selecting link-local address {link_local_addr} for interface {nice_name} / {ifname}", RNS.LOG_EXTREME)
else:
RNS.log(f"{self} Selecting link-local address {link_local_addr} for interface {ifname}", RNS.LOG_EXTREME)
if link_local_addr == None:
RNS.log(str(self)+" No link-local IPv6 address configured for "+str(ifname)+", skipping interface", RNS.LOG_EXTREME)
@ -205,7 +219,7 @@ class AutoInterface(Interface):
RNS.log(str(self)+" Creating multicast discovery listener on "+str(ifname)+" with address "+str(mcast_addr), RNS.LOG_EXTREME)
# Struct with interface index
if_struct = struct.pack("I", socket.if_nametoindex(ifname))
if_struct = struct.pack("I", self.interface_name_to_index(ifname))
# Set up multicast socket
discovery_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
@ -219,6 +233,15 @@ class AutoInterface(Interface):
discovery_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mcast_group)
# Bind socket
if RNS.vendor.platformutils.is_windows():
# window throws "[WinError 10049] The requested address is not valid in its context"
# when trying to use the multicast address as host, or when providing interface index
# passing an empty host appears to work, but probably not exactly how we want it to...
discovery_socket.bind(('', self.discovery_port))
else:
if self.discovery_scope == AutoInterface.SCOPE_LINK:
addr_info = socket.getaddrinfo(mcast_addr+"%"+ifname, self.discovery_port, socket.AF_INET6, socket.SOCK_DGRAM)
else:
@ -236,6 +259,13 @@ class AutoInterface(Interface):
suitable_interfaces += 1
except Exception as e:
nice_name = self.netinfo.interface_name_to_nice_name(ifname)
if nice_name != None and nice_name != ifname:
RNS.log(f"Could not configure the system interface {nice_name} / {ifname} for use with {self}, skipping it. The contained exception was: {e}", RNS.LOG_ERROR)
else:
RNS.log(f"Could not configure the system interface {ifname} for use with {self}, skipping it. The contained exception was: {e}", RNS.LOG_ERROR)
if suitable_interfaces == 0:
RNS.log(str(self)+" could not autoconfigure. This interface currently provides no connectivity.", RNS.LOG_WARNING)
else:
@ -253,7 +283,7 @@ class AutoInterface(Interface):
socketserver.UDPServer.address_family = socket.AF_INET6
for ifname in self.adopted_interfaces:
local_addr = self.adopted_interfaces[ifname]+"%"+ifname
local_addr = self.adopted_interfaces[ifname]+"%"+str(self.interface_name_to_index(ifname))
addr_info = socket.getaddrinfo(local_addr, self.data_port, socket.AF_INET6, socket.SOCK_DGRAM)
address = addr_info[0][4]
@ -380,7 +410,7 @@ class AutoInterface(Interface):
announce_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
addr_info = socket.getaddrinfo(self.mcast_discovery_address, self.discovery_port, socket.AF_INET6, socket.SOCK_DGRAM)
ifis = struct.pack("I", socket.if_nametoindex(ifname))
ifis = struct.pack("I", self.interface_name_to_index(ifname))
announce_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, ifis)
announce_socket.sendto(discovery_token, addr_info[0][4])
announce_socket.close()
@ -434,7 +464,7 @@ class AutoInterface(Interface):
if self.outbound_udp_socket == None:
self.outbound_udp_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
peer_addr = str(peer)+"%"+str(self.peers[peer][0])
peer_addr = str(peer)+"%"+str(self.interface_name_to_index(self.peers[peer][0]))
addr_info = socket.getaddrinfo(peer_addr, self.data_port, socket.AF_INET6, socket.SOCK_DGRAM)
self.outbound_udp_socket.sendto(data, addr_info[0][4])

View File

@ -536,7 +536,6 @@ class Reticulum:
if (("interface_enabled" in c) and c.as_bool("interface_enabled") == True) or (("enabled" in c) and c.as_bool("enabled") == True):
if c["type"] == "AutoInterface":
if not RNS.vendor.platformutils.is_windows():
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
@ -572,11 +571,6 @@ class Reticulum:
else:
interface.ifac_size = 16
else:
RNS.log("AutoInterface is not currently supported on Windows, disabling interface.", RNS.LOG_ERROR);
RNS.log("Please remove this AutoInterface instance from your configuration file.", RNS.LOG_ERROR);
RNS.log("You will have to manually configure other interfaces for connectivity.", RNS.LOG_ERROR);
if c["type"] == "UDPInterface":
device = c["device"] if "device" in c else None
port = int(c["port"]) if "port" in c else None

View File

@ -37,26 +37,48 @@ SIG_EXT = "rsg"
ENCRYPT_EXT = "rfe"
CHUNK_SIZE = 16*1024*1024
def spin(until=None, msg=None, timeout=None):
def spin(until=None, msg="", timeout=None):
i = 0
syms = "⢄⢂⢁⡁⡈⡐⡠"
if timeout != None:
if timeout is not None:
timeout = time.time()+timeout
print(msg+" ", end=" ")
while (timeout == None or time.time()<timeout) and not until():
print(msg, end=" ")
while (timeout is None or time.time()<timeout) and not until():
time.sleep(0.1)
print(("\b\b"+syms[i]+" "), end="")
print(("\b\b", syms[i]), end=" ", sep="")
sys.stdout.flush()
i = (i+1)%len(syms)
print("\r"+" "*len(msg)+" \r", end="")
print("\r", *len(msg), "\r", end="", sep="")
if timeout != None and time.time() > timeout:
if timeout is not None and time.time() > timeout:
return False
else:
return True
def get_keys(args: argparse.Namespace, identity) -> None:
"""Get public or/and private keys"""
if args.base64:
RNS.log("Public Key : " + base64.urlsafe_b64encode(identity.get_public_key()).decode("utf-8"))
elif args.base32:
RNS.log("Public Key : " + base64.b32encode(identity.get_public_key()).decode("utf-8"))
else:
RNS.log("Public Key : " + RNS.hexrep(identity.get_public_key(), delimit=False))
if identity.prv:
if args.print_private:
if args.base64:
RNS.log("Private Key : " + base64.urlsafe_b64encode(identity.get_private_key()).decode("utf-8"))
elif args.base32:
RNS.log("Private Key : " + base64.b32encode(identity.get_private_key()).decode("utf-8"))
else:
RNS.log("Private Key : " + RNS.hexrep(identity.get_private_key(), delimit=False))
else:
RNS.log("Private Key : Hidden")
def main():
try:
parser = argparse.ArgumentParser(description="Reticulum Identity & Encryption Utility")
@ -96,11 +118,7 @@ def main():
args = parser.parse_args()
ops = 0;
for t in [args.encrypt, args.decrypt, args.validate, args.sign]:
if t:
ops += 1
ops = sum(1 for t in [args.encrypt, args.decrypt, args.validate, args.sign] if t)
if ops > 1:
RNS.log("This utility currently only supports one of the encrypt, decrypt, sign or verify operations per invocation", RNS.LOG_ERROR)
exit(1)
@ -134,22 +152,8 @@ def main():
exit(42)
RNS.log("Identity imported")
if args.base64:
RNS.log("Public Key : "+base64.urlsafe_b64encode(identity.get_public_key()).decode("utf-8"))
elif args.base32:
RNS.log("Public Key : "+base64.b32encode(identity.get_public_key()).decode("utf-8"))
else:
RNS.log("Public Key : "+RNS.hexrep(identity.get_public_key(), delimit=False))
if identity.prv:
if args.print_private:
if args.base64:
RNS.log("Private Key : "+base64.urlsafe_b64encode(identity.get_private_key()).decode("utf-8"))
elif args.base32:
RNS.log("Private Key : "+base64.b32encode(identity.get_private_key()).decode("utf-8"))
else:
RNS.log("Private Key : "+RNS.hexrep(identity.get_private_key(), delimit=False))
else:
RNS.log("Private Key : Hidden")
get_keys(args, identity)
if args.write:
try:
@ -208,7 +212,7 @@ def main():
destination_hash = bytes.fromhex(identity_str)
identity = RNS.Identity.recall(destination_hash)
if identity == None:
if identity is None:
if not args.request:
RNS.log("Could not recall Identity for "+RNS.prettyhexrep(destination_hash)+".", RNS.LOG_ERROR)
RNS.log("You can query the network for unknown Identities with the -R option.", RNS.LOG_ERROR)
@ -216,7 +220,7 @@ def main():
else:
RNS.Transport.request_path(destination_hash)
def spincheck():
return RNS.Identity.recall(destination_hash) != None
return RNS.Identity.recall(destination_hash) is not None
spin(spincheck, "Requesting unknown Identity for "+RNS.prettyhexrep(destination_hash), args.t)
if not spincheck():
@ -224,17 +228,15 @@ def main():
exit(6)
else:
identity = RNS.Identity.recall(destination_hash)
RNS.log("Received Identity "+str(identity)+" for destination "+RNS.prettyhexrep(destination_hash)+" from the network")
RNS.log(" ".join(["Received Identity", str(identity), "for destination", RNS.prettyhexrep(destination_hash), "from the network"]))
else:
RNS.log("Recalled Identity "+str(identity)+" for destination "+RNS.prettyhexrep(destination_hash))
RNS.log(" ".join(["Recalled Identity", str(identity), "for destination", RNS.prettyhexrep(destination_hash)]))
except Exception as e:
RNS.log("Invalid hexadecimal hash provided", RNS.LOG_ERROR)
exit(7)
else:
# Try loading Identity from file
if not os.path.isfile(identity_str):
@ -243,13 +245,13 @@ def main():
else:
try:
identity = RNS.Identity.from_file(identity_str)
RNS.log("Loaded Identity "+str(identity)+" from "+str(identity_str))
RNS.log(" ".join(["Loaded Identity", str(identity), "from", str(identity_str)]))
except Exception as e:
RNS.log("Could not decode Identity from specified file")
exit(9)
if identity != None:
if identity is not None:
if args.hash:
try:
aspects = args.hash.split(".")
@ -259,9 +261,9 @@ def main():
else:
app_name = aspects[0]
aspects = aspects[1:]
if identity.pub != None:
if identity.pub is not None:
destination = RNS.Destination(identity, RNS.Destination.OUT, RNS.Destination.SINGLE, app_name, *aspects)
RNS.log("The "+str(args.hash)+" destination for this Identity is "+RNS.prettyhexrep(destination.hash))
RNS.log(" ".join(["The", str(args.hash), "destination for this Identity is", RNS.prettyhexrep(destination.hash)]))
RNS.log("The full destination specifier is "+str(destination))
time.sleep(0.25)
exit(0)
@ -282,7 +284,7 @@ def main():
else:
app_name = aspects[0]
aspects = aspects[1:]
if identity.prv != None:
if identity.prv is not None:
destination = RNS.Destination(identity, RNS.Destination.IN, RNS.Destination.SINGLE, app_name, *aspects)
RNS.log("Created destination "+str(destination))
RNS.log("Announcing destination "+RNS.prettyhexrep(destination.hash))
@ -291,7 +293,7 @@ def main():
exit(0)
else:
destination = RNS.Destination(identity, RNS.Destination.OUT, RNS.Destination.SINGLE, app_name, *aspects)
RNS.log("The "+str(args.announce)+" destination for this Identity is "+RNS.prettyhexrep(destination.hash))
RNS.log(" ".join(["The", str(args.announce), "destination for this Identity is", RNS.prettyhexrep(destination.hash)]))
RNS.log("The full destination specifier is "+str(destination))
RNS.log("Cannot announce this destination, since the private key is not held")
time.sleep(0.25)
@ -303,22 +305,7 @@ def main():
exit(0)
if args.print_identity:
if args.base64:
RNS.log("Public Key : "+base64.urlsafe_b64encode(identity.get_public_key()).decode("utf-8"))
elif args.base32:
RNS.log("Public Key : "+base64.b32encode(identity.get_public_key()).decode("utf-8"))
else:
RNS.log("Public Key : "+RNS.hexrep(identity.get_public_key(), delimit=False))
if identity.prv:
if args.print_private:
if args.base64:
RNS.log("Private Key : "+base64.urlsafe_b64encode(identity.get_private_key()).decode("utf-8"))
elif args.base32:
RNS.log("Private Key : "+base64.b32encode(identity.get_private_key()).decode("utf-8"))
else:
RNS.log("Private Key : "+RNS.hexrep(identity.get_private_key(), delimit=False))
else:
RNS.log("Private Key : Hidden")
get_keys(args, identity)
exit(0)
if args.export:
@ -373,7 +360,7 @@ def main():
if args.decrypt and not args.write and not args.stdout and args.read and args.read.lower().endswith("."+ENCRYPT_EXT):
args.write = str(args.read).replace("."+ENCRYPT_EXT, "")
if args.sign and identity.prv == None:
if args.sign and identity.prv is None:
RNS.log("Specified Identity does not hold a private key. Cannot sign.", RNS.LOG_ERROR)
exit(14)
@ -399,7 +386,7 @@ def main():
# data_output = sys.stdout
if args.sign:
if identity.prv == None:
if identity.prv is None:
RNS.log("Specified Identity does not hold a private key. Cannot sign.", RNS.LOG_ERROR)
exit(16)
@ -423,7 +410,7 @@ def main():
if not args.stdout:
if args.read:
RNS.log("File "+str(args.read)+" signed with "+str(identity)+" to "+str(args.write))
RNS.log(" ".join([ "File", str(args.read), "signed with", str(identity), "to", str(args.write) ]))
exit(0)
except Exception as e:
@ -457,18 +444,17 @@ def main():
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
exit(21)
validated = identity.validate(sig_input.read(), data_input.read())
sig_input.close()
data_input.close()
if not validated:
if not args.stdout:
RNS.log("Signature "+str(args.validate)+" for file "+str(args.read)+" is invalid", RNS.LOG_ERROR)
RNS.log(" ".join(["Signature", str(args.validate), "for file", str(args.read), "is invalid"]), RNS.LOG_ERROR)
exit(22)
else:
if not args.stdout:
RNS.log("Signature "+str(args.validate)+" for file "+str(args.read)+" made by Identity "+str(identity)+" is valid")
RNS.log(" ".join(["Signature", str(args.validate), "for file", str(args.read), "made by Identity", str(identity), "is valid"]))
exit(0)
except Exception as e:
@ -511,7 +497,7 @@ def main():
data_input.close()
if not args.stdout:
if args.read:
RNS.log("File "+str(args.read)+" encrypted for "+str(identity)+" to "+str(args.write))
RNS.log(" ".join(["File", str(args.read), "encrypted for", str(identity), "to", str(args.write)]))
exit(0)
except Exception as e:
@ -529,7 +515,7 @@ def main():
exit(26)
if args.decrypt:
if identity.prv == None:
if identity.prv is None:
RNS.log("Specified Identity does not hold a private key. Cannot decrypt.", RNS.LOG_ERROR)
exit(27)
@ -544,7 +530,7 @@ def main():
exit(29)
if not args.stdout:
RNS.log("Decrypting "+str(args.read)+"...")
RNS.log("".join(["Decrypting ", str(args.read), "..."]))
try:
more_data = True
@ -552,7 +538,7 @@ def main():
chunk = data_input.read(CHUNK_SIZE)
if chunk:
plaintext = identity.decrypt(chunk)
if plaintext == None:
if plaintext is None:
if not args.stdout:
RNS.log("Data could not be decrypted with the specified Identity")
exit(30)
@ -564,7 +550,7 @@ def main():
data_input.close()
if not args.stdout:
if args.read:
RNS.log("File "+str(args.read)+" decrypted with "+str(identity)+" to "+str(args.write))
RNS.log(" ".join(["File", str(args.read), "decrypted with", str(identity), "to", str(args.write)]))
exit(0)
except Exception as e:
@ -581,20 +567,10 @@ def main():
pass
exit(31)
if True:
pass
elif False:
pass
else:
print("")
parser.print_help()
print("")
except KeyboardInterrupt:
print("")
exit(255)
if __name__ == "__main__":
main()

View File

@ -24,7 +24,6 @@
import RNS
import argparse
import time
from RNS._version import __version__
@ -38,9 +37,10 @@ def program_setup(configdir, verbosity = 0, quietness = 0, service = False):
else:
targetlogdest = RNS.LOG_STDOUT
reticulum = RNS.Reticulum(configdir=configdir, verbosity=targetverbosity, logdest=targetlogdest)
RNS.Reticulum(configdir=configdir, verbosity=targetverbosity, logdest=targetlogdest)
exit(0)
def main():
try:
parser = argparse.ArgumentParser(description="Reticulum Distributed Identity Resolver")
@ -49,17 +49,15 @@ def main():
parser.add_argument('-q', '--quiet', action='count', default=0)
parser.add_argument("--exampleconfig", action='store_true', default=False, help="print verbose configuration example to stdout and exit")
parser.add_argument("--version", action="version", version="ir {version}".format(version=__version__))
args = parser.parse_args()
if args.exampleconfig:
print(__example_rns_config__)
exit()
configarg = None
if args.config:
configarg = args.config
else:
configarg = None
program_setup(configdir=configarg, verbosity=args.verbose, quietness=args.quiet)
@ -67,6 +65,7 @@ def main():
print("")
exit()
__example_rns_config__ = '''# This is an example Identity Resolver file.
'''

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@ import argparse
from RNS._version import __version__
def size_str(num, suffix='B'):
units = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']
last_unit = 'Y'
@ -46,6 +47,14 @@ def size_str(num, suffix='B'):
return "%.2f%s%s" % (num, last_unit, suffix)
def convert_bytes_to_hex(value_obj):
if isinstance(value_obj, bytes):
return RNS.hexrep(value_obj, delimit=False)
elif isinstance(value_obj, dict):
return {key: convert_bytes_to_hex(value) for key, value in value_obj.items()}
return value_obj
def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=False, astats=False, sorting=None, sort_reverse=False):
reticulum = RNS.Reticulum(configdir = configdir, loglevel = 3+verbosity)
@ -55,44 +64,37 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
except Exception as e:
pass
if stats != None:
if stats is None:
print("Could not get RNS status")
return
if json:
import json
for s in stats:
if isinstance(stats[s], bytes):
stats[s] = RNS.hexrep(stats[s], delimit=False)
if isinstance(stats[s], dict):
for i in stats[s]:
if isinstance(i, dict):
for k in i:
if isinstance(i[k], bytes):
i[k] = RNS.hexrep(i[k], delimit=False)
for s, value in stats.items():
stats[s] = convert_bytes_to_hex(value)
print(json.dumps(stats))
exit()
interfaces = stats["interfaces"]
if sorting != None and isinstance(sorting, str):
if sorting is not None and isinstance(sorting, str):
sorting = sorting.lower()
if sorting == "rate" or sorting == "bitrate":
interfaces.sort(key=lambda i: i["bitrate"], reverse=not sort_reverse)
if sorting == "rx":
elif sorting == "rx":
interfaces.sort(key=lambda i: i["rxb"], reverse=not sort_reverse)
if sorting == "tx":
elif sorting == "tx":
interfaces.sort(key=lambda i: i["txb"], reverse=not sort_reverse)
if sorting == "traffic":
elif sorting == "traffic":
interfaces.sort(key=lambda i: i["rxb"]+i["txb"], reverse=not sort_reverse)
if sorting == "announces" or sorting == "announce":
elif sorting == "announces" or sorting == "announce":
interfaces.sort(key=lambda i: i["incoming_announce_frequency"]+i["outgoing_announce_frequency"], reverse=not sort_reverse)
if sorting == "arx":
elif sorting == "arx":
interfaces.sort(key=lambda i: i["incoming_announce_frequency"], reverse=not sort_reverse)
if sorting == "atx":
elif sorting == "atx":
interfaces.sort(key=lambda i: i["outgoing_announce_frequency"], reverse=not sort_reverse)
if sorting == "held":
elif sorting == "held":
interfaces.sort(key=lambda i: i["held_announces"], reverse=not sort_reverse)
for ifstat in interfaces:
name = ifstat["name"]
@ -125,8 +127,7 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
else:
modestr = "Full"
if ifstat["clients"] != None:
if ifstat["clients"] is not None:
clients = ifstat["clients"]
if name.startswith("Shared Instance["):
cnum = max(clients-1,0)
@ -216,8 +217,6 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
print("")
else:
print("Could not get RNS status")
def main():
try:
@ -292,6 +291,7 @@ def main():
print("")
exit()
def speed_str(num, suffix='bps'):
units = ['','k','M','G','T','P','E','Z']
last_unit = 'Y'
@ -308,5 +308,6 @@ def speed_str(num, suffix='bps'):
return "%.2f %s%s" % (num, last_unit, suffix)
if __name__ == "__main__":
main()

View File

@ -28,7 +28,7 @@ import argparse
import shlex
import time
import sys
import tty
# import tty # Commented this because commented lines below use it
import os
from RNS._version import __version__
@ -39,9 +39,10 @@ reticulum = None
allow_all = False
allowed_identity_hashes = []
def prepare_identity(identity_path):
global identity
if identity_path == None:
if identity_path is None:
identity_path = RNS.Reticulum.identitypath+"/"+APP_NAME
if os.path.isfile(identity_path):
@ -52,6 +53,7 @@ def prepare_identity(identity_path):
identity = RNS.Identity()
identity.to_file(identity_path)
def listen(configdir, identitypath = None, verbosity = 0, quietness = 0, allowed = [], print_identity = False, disable_auth = None, disable_announce=False):
global identity, allow_all, allowed_identity_hashes, reticulum
@ -69,7 +71,7 @@ def listen(configdir, identitypath = None, verbosity = 0, quietness = 0, allowed
if disable_auth:
allow_all = True
else:
if allowed != None:
if allowed is not None:
for a in allowed:
try:
dest_len = (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2
@ -297,6 +299,7 @@ def remote_execution_progress(request_receipt):
link = None
listener_destination = None
remote_exec_grace = 2.0
def execute(configdir, identitypath = None, verbosity = 0, quietness = 0, detailed = False, mirror = False, noid = False, destination = None, command = None, stdin = None, stdoutl = None, stderrl = None, timeout = RNS.Transport.PATH_REQUEST_TIMEOUT, result_timeout = None, interactive = False):
global identity, reticulum, link, listener_destination, remote_exec_grace
@ -548,7 +551,6 @@ def main():
parser.add_argument("--stdout", action='store', default=None, help="max size in bytes of returned stdout", type=int)
parser.add_argument("--stderr", action='store', default=None, help="max size in bytes of returned stderr", type=int)
parser.add_argument("--version", action="version", version="rnx {version}".format(version=__version__))
args = parser.parse_args()
if args.listen or args.print_identity:
@ -668,6 +670,7 @@ def size_str(num, suffix='B'):
return "%.2f%s%s" % (num, last_unit, suffix)
def pretty_time(time, verbose=False):
days = int(time // (24 * 3600))
time = time % (24 * 3600)
@ -684,31 +687,24 @@ def pretty_time(time, verbose=False):
components = []
if days > 0:
components.append(str(days)+" day"+sd if verbose else str(days)+"d")
components.append("".join([str(days), " day", sd if verbose else str(days), "d"]))
if hours > 0:
components.append(str(hours)+" hour"+sh if verbose else str(hours)+"h")
components.append("".join([str(hours), " hour", sh if verbose else str(hours), "h"]))
if minutes > 0:
components.append(str(minutes)+" minute"+sm if verbose else str(minutes)+"m")
components.append("".join([str(minutes), " minute", sm if verbose else str(minutes), "m"]))
if seconds > 0:
components.append(str(seconds)+" second"+ss if verbose else str(seconds)+"s")
components.append("".join([str(seconds), " second", ss if verbose else str(seconds), "s"]))
i = 0
tstr = ""
for c in components:
i += 1
if i == 1:
pass
elif i < len(components):
tstr += ", "
elif i == len(components):
tstr += " and "
if len(components) > 1:
time_string = "".join([", ".join(components[:-1]), " and ", components[-1]])
else:
time_string = components[0] if components else ""
tstr += c
return time_string
return tstr
if __name__ == "__main__":
main()

View File

@ -1 +1 @@
__version__ = "0.7.4"
__version__ = "0.7.5"

View File

@ -11,6 +11,25 @@ def interfaces() -> List[str]:
adapters = RNS.vendor.ifaddr.get_adapters(include_unconfigured=True)
return [a.name for a in adapters]
def interface_names_to_indexes() -> dict:
adapters = RNS.vendor.ifaddr.get_adapters(include_unconfigured=True)
results = {}
for adapter in adapters:
results[adapter.name] = adapter.index
return results
def interface_name_to_nice_name(ifname) -> str:
try:
adapters = RNS.vendor.ifaddr.get_adapters(include_unconfigured=True)
for adapter in adapters:
if adapter.name == ifname:
if hasattr(adapter, "nice_name"):
return adapter.nice_name
except:
return None
return None
def ifaddresses(ifname) -> dict:
adapters = RNS.vendor.ifaddr.get_adapters(include_unconfigured=True)
ifa = {}

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +1,4 @@
# 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.
config: 541171817b95d649201365804faf729c
config: e6cf914f5d96347d4f64d2e8bcefb841
tags: 645f666f9bcd5a90fca523b33c5a78b7

View File

@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '0.7.4 beta',
VERSION: '0.7.5 beta',
LANGUAGE: 'en',
COLLAPSE_INDEX: false,
BUILDER: 'html',

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>Code Examples - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>Code Examples - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -6,7 +6,7 @@
<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"/>
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -4,7 +4,7 @@
<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="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Index - Reticulum Network Stack 0.7.4 beta documentation</title>
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Index - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -139,7 +139,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -165,7 +165,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>Getting Started Fast - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>Getting Started Fast - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>Communications Hardware - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>Communications Hardware - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>Reticulum Network Stack 0.7.4 beta documentation</title>
<title>Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="#"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="#"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>Configuring Interfaces - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>Configuring Interfaces - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>Building Networks - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>Building Networks - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

Binary file not shown.

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>API Reference - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>API Reference - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -4,7 +4,7 @@
<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="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/><title>Search - Reticulum Network Stack 0.7.4 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.7.5 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/copybutton.css" />
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
@ -138,7 +138,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -164,7 +164,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="#" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>Support Reticulum - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>Support Reticulum - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>Understanding Reticulum - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>Understanding Reticulum - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>Using Reticulum on Your System - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>Using Reticulum on Your System - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">

View File

@ -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" />
<meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
<title>What is Reticulum? - Reticulum Network Stack 0.7.4 beta documentation</title>
<title>What is Reticulum? - Reticulum Network Stack 0.7.5 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/copybutton.css" />
@ -141,7 +141,7 @@
</label>
</div>
<div class="header-center">
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.4 beta documentation</div></a>
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.5 beta documentation</div></a>
</div>
<div class="header-right">
<div class="theme-toggle-container theme-toggle-header">
@ -167,7 +167,7 @@
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
</div>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.4 beta documentation</span>
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.5 beta documentation</span>
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">