mirror of
https://github.com/markqvist/Reticulum.git
synced 2026-06-26 21:54:30 -07:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f242abcf75 | |||
| 51ab2d3488 | |||
| 54206d9101 | |||
| 178c69e361 |
@@ -73,7 +73,7 @@ if __name__ == "__main__":
|
||||
try:
|
||||
parser = argparse.ArgumentParser(description="Reticulum example that demonstrates sending and receiving unencrypted broadcasts")
|
||||
parser.add_argument("--config", action="store", default=None, help="path to alternative Reticulum config directory", type=str)
|
||||
parser.add_argument("--channel", action="store", default=None, help="path to alternative Reticulum config directory", type=str)
|
||||
parser.add_argument("--channel", action="store", default=None, help="broadcast channel name", type=str)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.config:
|
||||
|
||||
+1
-2
@@ -787,10 +787,9 @@ pre {
|
||||
<h2>
|
||||
<a id="user-content-what-is-currently-being-worked-on" class="anchor" href="#what-is-currently-being-worked-on" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>What is currently being worked on?</h2>
|
||||
<ul>
|
||||
<li>Delay/disruption tolerance</li>
|
||||
<li>API documentation</li>
|
||||
<li>Useful example programs and utilities</li>
|
||||
<li>A generic message transfer protocol built on Reticulum, see <a href="https://github.com/markqvist/lxmf">LXMF</a>
|
||||
<li>A delay and disruption tolerant message transfer protocol built on Reticulum, see <a href="https://github.com/markqvist/lxmf">LXMF</a>
|
||||
</li>
|
||||
<li>A few useful-in-the-real-world apps built with Reticulum</li>
|
||||
</ul>
|
||||
|
||||
@@ -54,10 +54,9 @@ Reticulum implements a range of generalised interface types that covers most of
|
||||
- UDP over IP networks
|
||||
|
||||
## What is currently being worked on?
|
||||
- Delay/disruption tolerance
|
||||
- API documentation
|
||||
- Useful example programs and utilities
|
||||
- A generic message transfer protocol built on Reticulum, see [LXMF](https://github.com/markqvist/lxmf)
|
||||
- A delay and disruption tolerant message transfer protocol built on Reticulum, see [LXMF](https://github.com/markqvist/lxmf)
|
||||
- A few useful-in-the-real-world apps built with Reticulum
|
||||
|
||||
## Can I use Reticulum on amateur radio spectrum?
|
||||
|
||||
+17
-6
@@ -43,12 +43,24 @@ class Identity:
|
||||
identity_data = Identity.known_destinations[destination_hash]
|
||||
identity = Identity(public_only=True)
|
||||
identity.loadPublicKey(identity_data[2])
|
||||
identity.app_data = identity_data[3]
|
||||
RNS.log("Found "+RNS.prettyhexrep(destination_hash)+" in known destinations", RNS.LOG_EXTREME)
|
||||
return identity
|
||||
else:
|
||||
RNS.log("Could not find "+RNS.prettyhexrep(destination_hash)+" in known destinations", RNS.LOG_EXTREME)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def recall_app_data(destination_hash):
|
||||
RNS.log("Searching for app_data for "+RNS.prettyhexrep(destination_hash)+"...", RNS.LOG_EXTREME)
|
||||
if destination_hash in Identity.known_destinations:
|
||||
app_data = Identity.known_destinations[destination_hash][3]
|
||||
RNS.log("Found "+RNS.prettyhexrep(destination_hash)+" app_data in known destinations", RNS.LOG_EXTREME)
|
||||
return app_data
|
||||
else:
|
||||
RNS.log("Could not find "+RNS.prettyhexrep(destination_hash)+" app_data in known destinations", RNS.LOG_EXTREME)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def saveKnownDestinations():
|
||||
RNS.log("Saving known destinations to storage...", RNS.LOG_VERBOSE)
|
||||
@@ -79,10 +91,6 @@ class Identity:
|
||||
|
||||
@staticmethod
|
||||
def truncatedHash(data):
|
||||
# TODO: Remove
|
||||
# digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
|
||||
# digest.update(data)
|
||||
|
||||
return Identity.fullHash(data)[:(Identity.TRUNCATED_HASHLENGTH//8)]
|
||||
|
||||
@staticmethod
|
||||
@@ -103,11 +111,14 @@ class Identity:
|
||||
|
||||
signed_data = destination_hash+public_key+random_hash+app_data
|
||||
|
||||
if not len(packet.data) > Identity.DERKEYSIZE//8+20+Identity.KEYSIZE//8:
|
||||
app_data = None
|
||||
|
||||
announced_identity = Identity(public_only=True)
|
||||
announced_identity.loadPublicKey(public_key)
|
||||
|
||||
if announced_identity.pub != None and announced_identity.validate(signature, signed_data):
|
||||
RNS.Identity.remember(packet.getHash(), destination_hash, public_key)
|
||||
RNS.Identity.remember(packet.getHash(), destination_hash, public_key, app_data)
|
||||
RNS.log("Stored valid announce from "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG)
|
||||
del announced_identity
|
||||
return True
|
||||
@@ -188,7 +199,7 @@ class Identity:
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Failed to load identity key", RNS.LOG_ERROR)
|
||||
RNS.log("The contained exception was: "+str(e))
|
||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
return False
|
||||
|
||||
def loadPublicKey(self, key):
|
||||
|
||||
+8
-1
@@ -238,6 +238,9 @@ class Link:
|
||||
def getContext(self):
|
||||
return None
|
||||
|
||||
def inactive_for(self):
|
||||
return min(time.time() - self.last_inbound, time.time() - self.last_outbound)
|
||||
|
||||
def teardown(self):
|
||||
if self.status != Link.PENDING and self.status != Link.CLOSED:
|
||||
teardown_packet = RNS.Packet(self, self.link_id, context=RNS.Packet.LINKCLOSE)
|
||||
@@ -331,6 +334,7 @@ class Link:
|
||||
if sleep_time == None or sleep_time < 0:
|
||||
RNS.log("Timing error! Tearing down link "+str(self)+" now.", RNS.LOG_ERROR)
|
||||
self.teardown()
|
||||
sleep_time = 0.1
|
||||
|
||||
sleep(sleep_time)
|
||||
|
||||
@@ -454,7 +458,10 @@ class Link:
|
||||
return plaintext
|
||||
except Exception as e:
|
||||
RNS.log("Decryption failed on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
traceback.print_exc()
|
||||
RNS.log(traceback.format_exc(), RNS.LOG_ERROR)
|
||||
# TODO: Do we really need to do this? Or can we recover somehow?
|
||||
self.teardown()
|
||||
|
||||
|
||||
def sign(self, message):
|
||||
return self.prv.sign(message, ec.ECDSA(hashes.SHA256()))
|
||||
|
||||
+5
-7
@@ -42,15 +42,15 @@ class Resource:
|
||||
HASHMAP_IS_EXHAUSTED = 0xFF
|
||||
|
||||
# Status constants
|
||||
NONE = 0x00
|
||||
QUEUED = 0x01
|
||||
ADVERTISED = 0x02
|
||||
NONE = 0x00
|
||||
QUEUED = 0x01
|
||||
ADVERTISED = 0x02
|
||||
TRANSFERRING = 0x03
|
||||
AWAITING_PROOF = 0x04
|
||||
ASSEMBLING = 0x05
|
||||
COMPLETE = 0x06
|
||||
FAILED = 0x07
|
||||
CORRUPT = 0x08
|
||||
FAILED = 0x07
|
||||
CORRUPT = 0x08
|
||||
|
||||
@staticmethod
|
||||
def accept(advertisement_packet, callback=None, progress_callback = None):
|
||||
@@ -111,8 +111,6 @@ class Resource:
|
||||
return resource
|
||||
except Exception as e:
|
||||
RNS.log("Could not decode resource advertisement, dropping resource", RNS.LOG_DEBUG)
|
||||
# TODO: Remove
|
||||
raise e
|
||||
return None
|
||||
|
||||
# Create a resource for transmission to a remote destination
|
||||
|
||||
@@ -446,6 +446,7 @@ class Transport:
|
||||
@staticmethod
|
||||
def inbound(raw, interface=None):
|
||||
while (Transport.jobs_running):
|
||||
# TODO: Decrease this for performance
|
||||
sleep(0.1)
|
||||
|
||||
Transport.jobs_locked = True
|
||||
@@ -849,6 +850,9 @@ class Transport:
|
||||
def registerDestination(destination):
|
||||
destination.MTU = RNS.Reticulum.MTU
|
||||
if destination.direction == RNS.Destination.IN:
|
||||
for registered_destination in Transport.destinations:
|
||||
if destination.hash == registered_destination.hash:
|
||||
raise KeyError("Attempt to register an already registered destination.")
|
||||
Transport.destinations.append(destination)
|
||||
|
||||
@staticmethod
|
||||
|
||||
+24
-7
@@ -3,6 +3,7 @@ import sys
|
||||
import glob
|
||||
import time
|
||||
import random
|
||||
import threading
|
||||
|
||||
from .Reticulum import Reticulum
|
||||
from .Identity import Identity
|
||||
@@ -35,6 +36,10 @@ logtimefmt = "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
random.seed(os.urandom(10))
|
||||
|
||||
_always_override_destination = False
|
||||
|
||||
logging_lock = threading.Lock()
|
||||
|
||||
def loglevelname(level):
|
||||
if (level == LOG_CRITICAL):
|
||||
return "Critical"
|
||||
@@ -55,19 +60,31 @@ def loglevelname(level):
|
||||
|
||||
return "Unknown"
|
||||
|
||||
def log(msg, level=3):
|
||||
# TODO: not thread safe
|
||||
def log(msg, level=3, _override_destination = False):
|
||||
global _always_override_destination
|
||||
|
||||
if loglevel >= level:
|
||||
timestamp = time.time()
|
||||
logstring = "["+time.strftime(logtimefmt)+"] ["+loglevelname(level)+"] "+msg
|
||||
logging_lock.acquire()
|
||||
|
||||
if (logdest == LOG_STDOUT):
|
||||
if (logdest == LOG_STDOUT or _always_override_destination):
|
||||
print(logstring)
|
||||
logging_lock.release()
|
||||
|
||||
if (logdest == LOG_FILE and logfile != None):
|
||||
file = open(logfile, "a")
|
||||
file.write(logstring+"\n")
|
||||
file.close()
|
||||
elif (logdest == LOG_FILE and logfile != None):
|
||||
try:
|
||||
file = open(logfile, "a")
|
||||
file.write(logstring+"\n")
|
||||
file.close()
|
||||
logging_lock.release()
|
||||
except Exception as e:
|
||||
logging_lock.release()
|
||||
_always_override_destination = True
|
||||
log("Exception occurred while writing log message to log file: "+str(e), LOG_CRITICAL)
|
||||
log("Dumping future log events to console!", LOG_CRITICAL)
|
||||
log(msg, level)
|
||||
|
||||
|
||||
def rand():
|
||||
result = random.random()
|
||||
|
||||
Vendored
+2
@@ -1,5 +1,7 @@
|
||||
import os
|
||||
import glob
|
||||
|
||||
__version__ = "0.1.9"
|
||||
|
||||
modules = glob.glob(os.path.dirname(__file__)+"/*.py")
|
||||
__all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')]
|
||||
|
||||
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
||||
|
||||
setuptools.setup(
|
||||
name="rns",
|
||||
version="0.1.8",
|
||||
version="0.1.9",
|
||||
author="Mark Qvist",
|
||||
author_email="mark@unsigned.io",
|
||||
description="Self-configuring, encrypted and resilient mesh networking stack for LoRa, packet radio, WiFi and everything in between",
|
||||
|
||||
Reference in New Issue
Block a user