mirror of
https://github.com/markqvist/Reticulum.git
synced 2026-06-23 12:24:30 -07:00
Compare commits
87 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 35e9a0b38a | |||
| 3d7f3825fb | |||
| 04b67a545d | |||
| 61c2fbd0da | |||
| 1aba4ec43a | |||
| 841a3daa26 | |||
| d98f03f245 | |||
| 878e67f69d | |||
| e582a6d6d1 | |||
| a948afb816 | |||
| 86a294388f | |||
| 429a0b1bd3 | |||
| ee8bb42633 | |||
| c659388a2c | |||
| eaa8199988 | |||
| 4f890e7e8a | |||
| a37e039424 | |||
| 8e1e2a9c54 | |||
| e4f94c9d0b | |||
| b007530123 | |||
| 4066bba303 | |||
| 8951517d01 | |||
| ae1d962b9b | |||
| a2caa47334 | |||
| 9f43da9105 | |||
| 038c696db9 | |||
| 8fa6ec144c | |||
| a8ccff7c55 | |||
| a5783da407 | |||
| bec3cee425 | |||
| b15bd19de5 | |||
| 38390fd021 | |||
| 40e0eee64f | |||
| af4cbb1baf | |||
| d3f4192fe3 | |||
| 47ef62ac11 | |||
| d15ddc7a49 | |||
| d67c8eb1cd | |||
| f4de5d5199 | |||
| 34e42988ea | |||
| 81d5d41149 | |||
| 6b3f3a37f0 | |||
| 60a604f635 | |||
| 55a2daf379 | |||
| 2dbde13321 | |||
| 6620dcde6b | |||
| 60966d5bb1 | |||
| ea22a53bf2 | |||
| 7b9526b4ed | |||
| 676074187a | |||
| 5dd2c31caf | |||
| 2db400a1a0 | |||
| b68dbaf15e | |||
| 84febcdf95 | |||
| c972ef90c8 | |||
| 19a74e3130 | |||
| 5ba789f782 | |||
| 58b5501e17 | |||
| b584832b8f | |||
| fc0cf17c4d | |||
| 001dd369ec | |||
| 9ce2ea4a5c | |||
| eec8814c22 | |||
| 7a6ed68482 | |||
| cd9e23f2de | |||
| ffa84de0bc | |||
| 89d3cdba17 | |||
| 2ba5843f22 | |||
| c4d0f08767 | |||
| db1cdec2a2 | |||
| 1eea1a6a22 | |||
| 4a69ce5a98 | |||
| 8d653cba9b | |||
| a6126a6bc5 | |||
| 957c2b3bc1 | |||
| 494bde4e79 | |||
| 5e39136dff | |||
| 4b26a86a73 | |||
| 43a6e280c0 | |||
| 237a45b2ca | |||
| b161650ced | |||
| 24975eac31 | |||
| 5d1ff36565 | |||
| 628777900e | |||
| 12e87425dc | |||
| 873f049e20 | |||
| 2ea963ed03 |
+127
-1
@@ -1,3 +1,129 @@
|
||||
### 2024-02-14: RNS β 0.7.1
|
||||
|
||||
This release adds support for RNodes based on SX1262, SX1268 and SX1280 modems, and fixes a number of bugs. Thanks to @jacobeva, who contributed to this release!
|
||||
|
||||
**Changes**
|
||||
- Added support for SX1262, SX1268 and SX1280 based RNodes
|
||||
- Updated `rnodeconf` to allow flashing T-Beam devices with SX126x chips
|
||||
- Fixed an invalid RSSI offset reference
|
||||
|
||||
**Release Hashes**
|
||||
```
|
||||
8ecfbb42b6a699fd4ac5374ab5640e4bb164e80bb9ab4401ea82da132e497877 rns-0.7.1-py3-none-any.whl
|
||||
e0ab487305ba1aee2d16044640e7eb72d332bbf51aeb0b8bf984d037a64cb493 rnspure-0.7.1-py3-none-any.whl
|
||||
```
|
||||
|
||||
### 2024-01-17: RNS β 0.7.0
|
||||
|
||||
This maintenance release fixes a number of bugs. Thanks to @jooray and @jacobeva, who contributed to this release!
|
||||
|
||||
**Changes**
|
||||
- Fixed large resource transfers failing under some conditions
|
||||
- Fixed a potential division by zero
|
||||
- Fixed a missing check on malformed advertisement packets
|
||||
- Fixed a formatting issue in `rnprobe`
|
||||
- Improved resource timeout calculations
|
||||
|
||||
**Release Hashes**
|
||||
```
|
||||
0dc2abe5373b9afadfba7ec05bf7ddeff659c004aa339a94001ebed5b46f5b47 rns-0.7.0-py3-none-any.whl
|
||||
97f6e65a20b53bbdccd54b4d2bdaa36dc1712e144a55f40800c63fe7113819a5 rnspure-0.7.0-py3-none-any.whl
|
||||
```
|
||||
|
||||
### 2023-12-07: RNS β 0.6.9
|
||||
|
||||
This release adds a few convenience functions to the `rnid` utility, and improves roaming support on Android.
|
||||
|
||||
**Changes**
|
||||
- Added identity import and export in hex, base32 and base64 formats to the `rnid` utility.
|
||||
- Added better carrier change detection for AutoInterface on Android.
|
||||
|
||||
**Release Hashes**
|
||||
```
|
||||
258daf22cb6e72c6cd04fe94447daedf51dfd968eb2f3370eab9c71ad0898dd0 rns-0.6.9-py3-none-any.whl
|
||||
3644b64af5b4efd3969172bf0cf95ae1afba6c8ea99ce47d8e49e31a832bbaf8 rnspure-0.6.9-py3-none-any.whl
|
||||
```
|
||||
|
||||
### 2023-11-14: RNS β 0.6.8
|
||||
|
||||
This maintenance release fixes a single bug.
|
||||
|
||||
**Bugfixes**
|
||||
- Fixed packet receipts not being initialised in time for arriving proofs on fast interfaces
|
||||
|
||||
**Release Hashes**
|
||||
```
|
||||
3ffb01f3f45e35105ea30e60e5e493ba50528df38b4ea62672c9e1c093073b1c rns-0.6.8-py3-none-any.whl
|
||||
de372814082ef7db59f4b2745b1f22b2ef9d97815190ec16c0596ba20406e0fb rnspure-0.6.8-py3-none-any.whl
|
||||
```
|
||||
|
||||
### 2023-11-06: RNS β 0.6.7
|
||||
|
||||
This maintenance release improves tranport performance and fixes a logging bug.
|
||||
|
||||
**Changes**
|
||||
- Improved local and remote transport performance by approximately 6x on faster links
|
||||
- Significantly decreased latency over faster links
|
||||
|
||||
**Bugfixes**
|
||||
- Fixed logging an error message when local clients connect while shared instance is still starting up
|
||||
|
||||
**Release Hashes**
|
||||
```
|
||||
c37dd1f59e037841f69ec518deecdae6719f978947de2473f04e7d95247805ac rns-0.6.7-py3-none-any.whl
|
||||
1e2dcb44ec7271a4d26180db138fc54dce6d0d3cf3f816432d4d6a4b1cf83868 rnspure-0.6.7-py3-none-any.whl
|
||||
```
|
||||
|
||||
### 2023-11-04: RNS β 0.6.6
|
||||
|
||||
This maintenance release improves transfers over unreliable links and fixes a bug in requests.
|
||||
|
||||
**Changes**
|
||||
- Improved reliability of resource transfers over very slow and unreliable links
|
||||
|
||||
**Bugfixes**
|
||||
- Fixed a bug that could cause requests to timeout prematurely
|
||||
|
||||
**Release Hashes**
|
||||
```
|
||||
b1127745750a43cd7389212d31aa09ccc735ab2d69e3b80bd28874f10082c322 rns-0.6.6-py3-none-any.whl
|
||||
bf5ba5da4f37b93c14817367952cda63787ec88bbe601e41c13fcbb3fc22b6b6 rnspure-0.6.6-py3-none-any.whl
|
||||
```
|
||||
|
||||
### 2023-11-02: RNS β 0.6.5
|
||||
|
||||
This release fixes a bug in path rediscovery for shared instance clients.
|
||||
|
||||
**Bugfixes**
|
||||
- Fixed a bug in path rediscovery for shared instance clients
|
||||
|
||||
**Release Hashes**
|
||||
```
|
||||
5d54a5cfebe907c759351357a8f7d771670c895ff57f1325bf7fec42bcb46ba3 rns-0.6.5-py3-none-any.whl
|
||||
accd2855e18ff06455b9454957388089e293073ec7093c64dee0dc7aa46ecb46 rnspure-0.6.5-py3-none-any.whl
|
||||
```
|
||||
|
||||
### 2023-11-02: RNS β 0.6.4
|
||||
|
||||
This release fixes a number of bugs that had crept in while adding the new ultra low bandwidth link timing and faster path rediscovery mechanisms.
|
||||
|
||||
**Changes**
|
||||
- Adjusted link timings for better support of very slow mediums
|
||||
- Adjusted bluetooth read timeouts to account for occasional high latency in congested 2.4GHz environments
|
||||
- Added a probe count option to the `rnprobe` utility.
|
||||
|
||||
**Bugfixes**
|
||||
- Fixed a missing timeout calculation
|
||||
- Fixed a redundant path request on path rediscovery
|
||||
- Fixed missing path state resetting on stale path rediscovery
|
||||
- Fixed a bug that could cause an attribute to be uninitialised
|
||||
|
||||
**Release Hashes**
|
||||
```
|
||||
566c725f68aa154eaca0880c894a39503027bf91714f17691e51d047800444c0 rns-0.6.4-py3-none-any.whl
|
||||
a3a447fd40bf02fdb982523de0e4e9933e8e4cd4d4bd478254ea7dcac29e3fc1 rnspure-0.6.4-py3-none-any.whl
|
||||
```
|
||||
|
||||
### 2023-10-31: RNS β 0.6.3
|
||||
|
||||
This release brings a series of under-the-hood reliability improvements and bugfixes. But most notably, Reticulum can now establish links over even ultra low bandwidth mediums, all the way down to 5 bits per second.
|
||||
@@ -969,4 +1095,4 @@ This was the first publicly available pre-release alpha of Reticulum.
|
||||
|
||||
### 2016-05-29: Inintial Repository Commit
|
||||
|
||||
The first commit to the Reticulum reference implementation was 9a9630cfd29e11ace3f12716ddb4dff0e5419b4b, which occurred on Sunday, the 22nd of May 2016.
|
||||
The first commit to the Reticulum reference implementation was 9a9630cfd29e11ace3f12716ddb4dff0e5419b4b, which occurred on Sunday, the 29th of May 2016.
|
||||
|
||||
+14
-6
@@ -2,21 +2,29 @@
|
||||
|
||||
Welcome, and thank you for your interest in contributing to Reticulum!
|
||||
|
||||
Apart from writing code, there are many ways in which you can contribute. Before getting started, please read these guidelines.
|
||||
Apart from writing code, there are many ways in which you can contribute. Before interacting with this community, read these short and simple guidelines.
|
||||
|
||||
## Expected Conduct
|
||||
|
||||
First and foremost, there is one simple requirement for taking part in this community: While we primarily interact virtually, your actions matter and have real consequences. Therefore: **Act like a responsible, civilized person** - also in the face of disputes and heated disagreements. Speak your mind here, discussions are welcome. Just do so in the spirit of being face-to-face with everyone else. Thank you.
|
||||
|
||||
## Asking Questions
|
||||
|
||||
If you want to ask a question, do not open an issue.
|
||||
If you want to ask a question, **do not open an issue**. The issue tracker is used by people *working on Reticulum* to track bugs, issues and improvements.
|
||||
|
||||
Instead, ask away on the [discussions](https://github.com/markqvist/Reticulum/discussions) or on the [Reticulum Matrix channel](https://unsigned.io/contact.html#reticulum:matrix.org) at `#reticulum:matrix.org`
|
||||
Instead, ask away on the [discussions](https://github.com/markqvist/Reticulum/discussions) or on the [Reticulum Matrix channel](https://matrix.to/#/#reticulum:matrix.org) at `#reticulum:matrix.org`
|
||||
|
||||
## Providing Feedback
|
||||
## Providing Feedback & Ideas
|
||||
|
||||
Likewise, feedback, ideas and feature requests are a very welcome way to contribute, and should also be posted on the [discussions](https://github.com/markqvist/Reticulum/discussions), or on the [Reticulum Matrix channel](https://unsigned.io/contact.html#reticulum:matrix.org) at `#reticulum:matrix.org`
|
||||
Likewise, feedback, ideas and feature requests are a very welcome way to contribute, and should also be posted on the [discussions](https://github.com/markqvist/Reticulum/discussions), or on the [Reticulum Matrix channel](https://matrix.to/#/#reticulum:matrix.org) at `#reticulum:matrix.org`.
|
||||
|
||||
Please do not post feature requests or general ideas on the issue tracker, or in direct messages to the primary developers. You are much more likely to get a response and start a constructive discussion by posting your ideas in the public channels created for these purposes.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
If you have found a bug or issue in Reticulum, please report it on the [issue tracker](https://github.com/markqvist/Reticulum/issues).
|
||||
If you have found a bug or issue in this project, please report it using the [issue tracker](https://github.com/markqvist/Reticulum/issues). If at all possible, be sure to include details on how to reproduce the bug.
|
||||
|
||||
Anything submitted to the issue tracker that does not follow these guidelines will be closed and removed without comments or explanation.
|
||||
|
||||
## Writing Code
|
||||
|
||||
|
||||
@@ -449,8 +449,7 @@ def link_established(link):
|
||||
# And set up a small job to check for
|
||||
# a potential timeout in receiving the
|
||||
# file list
|
||||
thread = threading.Thread(target=filelist_timeout_job)
|
||||
thread.setDaemon(True)
|
||||
thread = threading.Thread(target=filelist_timeout_job, daemon=True)
|
||||
thread.start()
|
||||
|
||||
# This job just sleeps for the specified
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
ko_fi: markqvist
|
||||
custom: "https://unsigned.io/donate"
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License, unless otherwise noted
|
||||
|
||||
Copyright (c) 2016-2022 Mark Qvist / unsigned.io
|
||||
Copyright (c) 2016-2023 Mark Qvist / unsigned.io
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -192,7 +192,7 @@ provide a dynamic performance envelope from 250 bits per second, to 1 gigabit
|
||||
per second on normal hardware.
|
||||
|
||||
Currently, the usable performance envelope is approximately 150 bits per second
|
||||
to 20 megabits per second, with physical mediums faster than that not being
|
||||
to 40 megabits per second, with physical mediums faster than that not being
|
||||
saturated. Performance beyond the current level is intended for future
|
||||
upgrades, but not highly prioritised at this point in time.
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ class AndroidBluetoothManager():
|
||||
if self.bt_enabled():
|
||||
return self.bt_adapter.getDefaultAdapter().getBondedDevices()
|
||||
else:
|
||||
RNS.log("Could not query paired devices, Bluetooth is disabled", RNS.LOG_DEBUG)
|
||||
RNS.log("Could not query paired devices, Bluetooth is disabled", RNS.LOG_EXTREME)
|
||||
return []
|
||||
|
||||
def get_potential_devices(self):
|
||||
@@ -167,8 +167,8 @@ class AndroidBluetoothManager():
|
||||
raise IOError("The Bluetooth RFcomm socket could not be connected: "+str(e))
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Could not create and connect Bluetooth RFcomm socket for "+str(device.getName())+" "+str(device.getAddress()), RNS.LOG_DEBUG)
|
||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG)
|
||||
RNS.log("Could not create and connect Bluetooth RFcomm socket for "+str(device.getName())+" "+str(device.getAddress()), RNS.LOG_EXTREME)
|
||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_EXTREME)
|
||||
|
||||
def close(self):
|
||||
if self.connected:
|
||||
@@ -602,8 +602,11 @@ class RNodeInterface(Interface):
|
||||
raise IOError("Invalid device firmware")
|
||||
|
||||
if self.serial != None and self.port != None:
|
||||
self.timeout = 200
|
||||
RNS.log("Serial port "+self.port+" is now open")
|
||||
|
||||
if self.bt_manager != None and self.bt_manager.connected:
|
||||
self.timeout = 1500
|
||||
RNS.log("Bluetooth connection to RNode now open")
|
||||
|
||||
RNS.log("Configuring RNode interface...", RNS.LOG_VERBOSE)
|
||||
@@ -1170,7 +1173,7 @@ class RNodeInterface(Interface):
|
||||
if got == 0:
|
||||
time_since_last = int(time.time()*1000) - last_read_ms
|
||||
if len(data_buffer) > 0 and time_since_last > self.timeout:
|
||||
RNS.log(str(self)+" serial read timeout", RNS.LOG_DEBUG)
|
||||
RNS.log(str(self)+" serial read timeout in command "+str(command), RNS.LOG_WARNING)
|
||||
data_buffer = b""
|
||||
in_frame = False
|
||||
command = KISS.CMD_UNKNOWN
|
||||
|
||||
@@ -334,6 +334,8 @@ class AutoInterface(Interface):
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
self.carrier_changed = True
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Could not get device information while updating link-local addresses for "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ class Interface:
|
||||
self.txb = 0
|
||||
self.created = time.time()
|
||||
self.online = False
|
||||
self.bitrate = 1e6
|
||||
|
||||
self.ingress_control = True
|
||||
self.ic_max_held_announces = Interface.MAX_HELD_ANNOUNCES
|
||||
|
||||
@@ -78,6 +78,7 @@ class LocalClientInterface(Interface):
|
||||
self.target_ip = None
|
||||
self.target_port = None
|
||||
self.socket = connected_socket
|
||||
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
|
||||
self.is_connected_to_shared_instance = False
|
||||
|
||||
@@ -108,6 +109,7 @@ class LocalClientInterface(Interface):
|
||||
|
||||
def connect(self):
|
||||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
self.socket.connect((self.target_ip, self.target_port))
|
||||
|
||||
self.online = True
|
||||
@@ -270,7 +272,8 @@ class LocalClientInterface(Interface):
|
||||
RNS.Transport.local_client_interfaces.remove(self)
|
||||
if hasattr(self, "parent_interface") and self.parent_interface != None:
|
||||
self.parent_interface.clients -= 1
|
||||
RNS.Transport.owner._should_persist_data()
|
||||
if hasattr(RNS.Transport, "owner") and RNS.Transport.owner != None:
|
||||
RNS.Transport.owner._should_persist_data()
|
||||
|
||||
if nowarning == False:
|
||||
RNS.log("The interface "+str(self)+" experienced an unrecoverable error and is being torn down. Restart Reticulum to attempt to open this interface again.", RNS.LOG_ERROR)
|
||||
@@ -339,6 +342,8 @@ class LocalServerInterface(Interface):
|
||||
spawned_interface.target_port = str(handler.client_address[1])
|
||||
spawned_interface.parent_interface = self
|
||||
spawned_interface.bitrate = self.bitrate
|
||||
if hasattr(self, "_force_bitrate"):
|
||||
spawned_interface._force_bitrate = self._force_bitrate
|
||||
# RNS.log("Accepting new connection to shared instance: "+str(spawned_interface), RNS.LOG_EXTREME)
|
||||
RNS.Transport.interfaces.append(spawned_interface)
|
||||
RNS.Transport.local_client_interfaces.append(spawned_interface)
|
||||
|
||||
@@ -92,7 +92,7 @@ class RNodeInterface(Interface):
|
||||
MAX_CHUNK = 32768
|
||||
|
||||
FREQ_MIN = 137000000
|
||||
FREQ_MAX = 1020000000
|
||||
FREQ_MAX = 3000000000
|
||||
|
||||
RSSI_OFFSET = 157
|
||||
|
||||
@@ -109,7 +109,7 @@ class RNodeInterface(Interface):
|
||||
|
||||
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):
|
||||
if RNS.vendor.platformutils.is_android():
|
||||
raise SystemError("Invlaid 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")
|
||||
|
||||
import importlib
|
||||
if importlib.util.find_spec('serial') != None:
|
||||
@@ -190,15 +190,15 @@ class RNodeInterface(Interface):
|
||||
RNS.log("Invalid frequency configured for "+str(self), RNS.LOG_ERROR)
|
||||
self.validcfg = False
|
||||
|
||||
if (self.txpower < 0 or self.txpower > 17):
|
||||
if (self.txpower < 0 or self.txpower > 22):
|
||||
RNS.log("Invalid TX power configured for "+str(self), RNS.LOG_ERROR)
|
||||
self.validcfg = False
|
||||
|
||||
if (self.bandwidth < 7800 or self.bandwidth > 500000):
|
||||
if (self.bandwidth < 7800 or self.bandwidth > 1625000):
|
||||
RNS.log("Invalid bandwidth configured for "+str(self), RNS.LOG_ERROR)
|
||||
self.validcfg = False
|
||||
|
||||
if (self.sf < 7 or self.sf > 12):
|
||||
if (self.sf < 5 or self.sf > 12):
|
||||
RNS.log("Invalid spreading factor configured for "+str(self), RNS.LOG_ERROR)
|
||||
self.validcfg = False
|
||||
|
||||
@@ -799,7 +799,7 @@ class RNodeInterface(Interface):
|
||||
else:
|
||||
time_since_last = int(time.time()*1000) - last_read_ms
|
||||
if len(data_buffer) > 0 and time_since_last > self.timeout:
|
||||
RNS.log(str(self)+" serial read timeout", RNS.LOG_DEBUG)
|
||||
RNS.log(str(self)+" serial read timeout in command "+str(command), RNS.LOG_WARNING)
|
||||
data_buffer = b""
|
||||
in_frame = False
|
||||
command = KISS.CMD_UNKNOWN
|
||||
|
||||
@@ -116,6 +116,8 @@ class TCPClientInterface(Interface):
|
||||
elif platform.system() == "Darwin":
|
||||
self.set_timeouts_osx()
|
||||
|
||||
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
|
||||
elif target_ip != None and target_port != None:
|
||||
self.receives = True
|
||||
self.target_ip = target_ip
|
||||
@@ -200,6 +202,7 @@ class TCPClientInterface(Interface):
|
||||
|
||||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.socket.settimeout(TCPClientInterface.INITIAL_CONNECT_TIMEOUT)
|
||||
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
self.socket.connect((self.target_ip, self.target_port))
|
||||
self.socket.settimeout(None)
|
||||
self.online = True
|
||||
|
||||
+36
-38
@@ -352,7 +352,7 @@ class Link:
|
||||
packed_request = umsgpack.packb(unpacked_request)
|
||||
|
||||
if timeout == None:
|
||||
timeout = self.rtt * self.traffic_timeout_factor + RNS.Resource.RESPONSE_MAX_GRACE_TIME/4.0
|
||||
timeout = self.rtt * self.traffic_timeout_factor + RNS.Resource.RESPONSE_MAX_GRACE_TIME*1.125
|
||||
|
||||
if len(packed_request) <= Link.MDU:
|
||||
request_packet = RNS.Packet(self, packed_request, RNS.Packet.DATA, context = RNS.Packet.REQUEST)
|
||||
@@ -687,7 +687,9 @@ class Link:
|
||||
remove = pending_request
|
||||
try:
|
||||
pending_request.response_size = response_size
|
||||
pending_request.response_transfer_size = response_transfer_size
|
||||
if pending_request.response_transfer_size == None:
|
||||
pending_request.response_transfer_size = 0
|
||||
pending_request.response_transfer_size += response_transfer_size
|
||||
pending_request.response_received(response_data)
|
||||
except Exception as e:
|
||||
RNS.log("Error occurred while handling response. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
@@ -834,10 +836,17 @@ class Link:
|
||||
request_id = RNS.ResourceAdvertisement.read_request_id(packet)
|
||||
for pending_request in self.pending_requests:
|
||||
if pending_request.request_id == request_id:
|
||||
RNS.Resource.accept(packet, callback=self.response_resource_concluded, progress_callback=pending_request.response_resource_progress, request_id = request_id)
|
||||
pending_request.response_size = RNS.ResourceAdvertisement.read_size(packet)
|
||||
pending_request.response_transfer_size = RNS.ResourceAdvertisement.read_transfer_size(packet)
|
||||
pending_request.started_at = time.time()
|
||||
response_resource = RNS.Resource.accept(packet, callback=self.response_resource_concluded, progress_callback=pending_request.response_resource_progress, request_id = request_id)
|
||||
if response_resource != None:
|
||||
if pending_request.response_size == None:
|
||||
pending_request.response_size = RNS.ResourceAdvertisement.read_size(packet)
|
||||
if pending_request.response_transfer_size == None:
|
||||
pending_request.response_transfer_size = 0
|
||||
pending_request.response_transfer_size += RNS.ResourceAdvertisement.read_transfer_size(packet)
|
||||
if pending_request.started_at == None:
|
||||
pending_request.started_at = time.time()
|
||||
pending_request.response_resource_progress(response_resource)
|
||||
|
||||
elif self.resource_strategy == Link.ACCEPT_NONE:
|
||||
pass
|
||||
elif self.resource_strategy == Link.ACCEPT_APP:
|
||||
@@ -907,20 +916,6 @@ class Link:
|
||||
if not self._channel:
|
||||
RNS.log(f"Channel data received without open channel", RNS.LOG_DEBUG)
|
||||
else:
|
||||
# TODO: Remove packet loss simulator ######
|
||||
# if not hasattr(self, "drop_counter"):
|
||||
# self.drop_counter = 0
|
||||
# self.drop_counter += 1
|
||||
|
||||
# if self.drop_counter%6 == 0:
|
||||
# RNS.log("Dropping channel packet for testing", RNS.LOG_DEBUG)
|
||||
# else:
|
||||
# packet.prove()
|
||||
# plaintext = self.decrypt(packet.data)
|
||||
# if plaintext != None:
|
||||
# self._channel._receive(plaintext)
|
||||
############################################
|
||||
|
||||
packet.prove()
|
||||
plaintext = self.decrypt(packet.data)
|
||||
if plaintext != None:
|
||||
@@ -1144,7 +1139,8 @@ class RequestReceipt():
|
||||
def request_resource_concluded(self, resource):
|
||||
if resource.status == RNS.Resource.COMPLETE:
|
||||
RNS.log("Request "+RNS.prettyhexrep(self.request_id)+" successfully sent as resource.", RNS.LOG_DEBUG)
|
||||
self.started_at = time.time()
|
||||
if self.started_at == None:
|
||||
self.started_at = time.time()
|
||||
self.status = RequestReceipt.DELIVERED
|
||||
self.__resource_response_timeout = time.time()+self.timeout
|
||||
response_timeout_thread = threading.Thread(target=self.__response_timeout_job)
|
||||
@@ -1185,24 +1181,26 @@ class RequestReceipt():
|
||||
|
||||
|
||||
def response_resource_progress(self, resource):
|
||||
if not self.status == RequestReceipt.FAILED:
|
||||
self.status = RequestReceipt.RECEIVING
|
||||
if self.packet_receipt != None:
|
||||
self.packet_receipt.status = RNS.PacketReceipt.DELIVERED
|
||||
self.packet_receipt.proved = True
|
||||
self.packet_receipt.concluded_at = time.time()
|
||||
if self.packet_receipt.callbacks.delivery != None:
|
||||
self.packet_receipt.callbacks.delivery(self.packet_receipt)
|
||||
if resource != None:
|
||||
if not self.status == RequestReceipt.FAILED:
|
||||
self.status = RequestReceipt.RECEIVING
|
||||
if self.packet_receipt != None:
|
||||
if self.packet_receipt.status != RNS.PacketReceipt.DELIVERED:
|
||||
self.packet_receipt.status = RNS.PacketReceipt.DELIVERED
|
||||
self.packet_receipt.proved = True
|
||||
self.packet_receipt.concluded_at = time.time()
|
||||
if self.packet_receipt.callbacks.delivery != None:
|
||||
self.packet_receipt.callbacks.delivery(self.packet_receipt)
|
||||
|
||||
self.progress = resource.get_progress()
|
||||
|
||||
if self.callbacks.progress != None:
|
||||
try:
|
||||
self.callbacks.progress(self)
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing response progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
else:
|
||||
resource.cancel()
|
||||
self.progress = resource.get_progress()
|
||||
|
||||
if self.callbacks.progress != None:
|
||||
try:
|
||||
self.callbacks.progress(self)
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing response progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
else:
|
||||
resource.cancel()
|
||||
|
||||
|
||||
def response_received(self, response):
|
||||
|
||||
+121
-95
@@ -25,7 +25,9 @@ import os
|
||||
import bz2
|
||||
import math
|
||||
import time
|
||||
import tempfile
|
||||
import threading
|
||||
from threading import Lock
|
||||
from .vendor import umsgpack as umsgpack
|
||||
from time import sleep
|
||||
|
||||
@@ -47,7 +49,7 @@ class Resource:
|
||||
WINDOW = 4
|
||||
|
||||
# Absolute minimum window size during transfer
|
||||
WINDOW_MIN = 1
|
||||
WINDOW_MIN = 2
|
||||
|
||||
# The maximum window size for transfers on slow links
|
||||
WINDOW_MAX_SLOW = 10
|
||||
@@ -103,9 +105,10 @@ class Resource:
|
||||
|
||||
PART_TIMEOUT_FACTOR = 4
|
||||
PART_TIMEOUT_FACTOR_AFTER_RTT = 2
|
||||
MAX_RETRIES = 8
|
||||
MAX_RETRIES = 16
|
||||
MAX_ADV_RETRIES = 4
|
||||
SENDER_GRACE_TIME = 10
|
||||
SENDER_GRACE_TIME = 10.0
|
||||
PROCESSING_GRACE = 1.0
|
||||
RETRY_GRACE_TIME = 0.25
|
||||
PER_RETRY_DELAY = 0.5
|
||||
|
||||
@@ -167,10 +170,8 @@ class Resource:
|
||||
resource.hashmap = [None] * resource.total_parts
|
||||
resource.hashmap_height = 0
|
||||
resource.waiting_for_hmu = False
|
||||
|
||||
resource.receiving_part = False
|
||||
|
||||
resource.consecutive_completed_height = 0
|
||||
resource.consecutive_completed_height = -1
|
||||
|
||||
if not resource.link.has_incoming_resource(resource):
|
||||
resource.link.register_incoming_resource(resource)
|
||||
@@ -204,9 +205,19 @@ class Resource:
|
||||
resource_data = None
|
||||
self.assembly_lock = False
|
||||
|
||||
if data != None:
|
||||
if not hasattr(data, "read") and len(data) > Resource.MAX_EFFICIENT_SIZE:
|
||||
original_data = data
|
||||
data_size = len(original_data)
|
||||
data = tempfile.TemporaryFile()
|
||||
data.write(original_data)
|
||||
del original_data
|
||||
|
||||
if hasattr(data, "read"):
|
||||
data_size = os.stat(data.name).st_size
|
||||
self.total_size = data_size
|
||||
if data_size == None:
|
||||
data_size = os.stat(data.name).st_size
|
||||
|
||||
self.total_size = data_size
|
||||
self.grand_total_parts = math.ceil(data_size/Resource.SDU)
|
||||
|
||||
if data_size <= Resource.MAX_EFFICIENT_SIZE:
|
||||
@@ -279,7 +290,7 @@ class Resource:
|
||||
self.uncompressed_data = data
|
||||
|
||||
compression_began = time.time()
|
||||
if (auto_compress and len(self.uncompressed_data) < Resource.AUTO_COMPRESS_MAX_SIZE):
|
||||
if (auto_compress and len(self.uncompressed_data) <= Resource.AUTO_COMPRESS_MAX_SIZE):
|
||||
RNS.log("Compressing resource data...", RNS.LOG_DEBUG)
|
||||
self.compressed_data = bz2.compress(self.uncompressed_data)
|
||||
RNS.log("Compression completed in "+str(round(time.time()-compression_began, 3))+" seconds", RNS.LOG_DEBUG)
|
||||
@@ -366,7 +377,8 @@ class Resource:
|
||||
if advertise:
|
||||
self.advertise()
|
||||
else:
|
||||
pass
|
||||
self.receive_lock = Lock()
|
||||
|
||||
|
||||
def hashmap_update_packet(self, plaintext):
|
||||
if not self.status == Resource.FAILED:
|
||||
@@ -440,7 +452,7 @@ class Resource:
|
||||
sleep_time = None
|
||||
|
||||
if self.status == Resource.ADVERTISED:
|
||||
sleep_time = (self.adv_sent+self.timeout)-time.time()
|
||||
sleep_time = (self.adv_sent+self.timeout+Resource.PROCESSING_GRACE)-time.time()
|
||||
if sleep_time < 0:
|
||||
if self.retries_left <= 0:
|
||||
RNS.log("Resource transfer timeout after sending advertisement", RNS.LOG_DEBUG)
|
||||
@@ -456,7 +468,7 @@ class Resource:
|
||||
self.adv_sent = self.last_activity
|
||||
sleep_time = 0.001
|
||||
except Exception as e:
|
||||
RNS.log("Could not resend advertisement packet, cancelling resource", RNS.LOG_VERBOSE)
|
||||
RNS.log("Could not resend advertisement packet, cancelling resource. The contained exception was: "+str(e), RNS.LOG_VERBOSE)
|
||||
self.cancel()
|
||||
|
||||
|
||||
@@ -612,10 +624,26 @@ class Resource:
|
||||
self.callback(self)
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing resource concluded callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
finally:
|
||||
try:
|
||||
if hasattr(self, "input_file"):
|
||||
if hasattr(self.input_file, "close") and callable(self.input_file.close):
|
||||
self.input_file.close()
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Error while closing resource input file: "+str(e), RNS.LOG_ERROR)
|
||||
else:
|
||||
# Otherwise we'll recursively create the
|
||||
# next segment of the resource
|
||||
Resource(self.input_file, self.link, callback = self.callback, segment_index = self.segment_index+1, original_hash=self.original_hash, progress_callback = self.__progress_callback)
|
||||
Resource(
|
||||
self.input_file, self.link,
|
||||
callback = self.callback,
|
||||
segment_index = self.segment_index+1,
|
||||
original_hash=self.original_hash,
|
||||
progress_callback = self.__progress_callback,
|
||||
request_id = self.request_id,
|
||||
is_response = self.is_response,
|
||||
)
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
@@ -623,99 +651,99 @@ class Resource:
|
||||
|
||||
|
||||
def receive_part(self, packet):
|
||||
while self.receiving_part:
|
||||
sleep(0.001)
|
||||
with self.receive_lock:
|
||||
|
||||
self.receiving_part = True
|
||||
self.last_activity = time.time()
|
||||
self.retries_left = self.max_retries
|
||||
self.receiving_part = True
|
||||
self.last_activity = time.time()
|
||||
self.retries_left = self.max_retries
|
||||
|
||||
if self.req_resp == None:
|
||||
self.req_resp = self.last_activity
|
||||
rtt = self.req_resp-self.req_sent
|
||||
|
||||
self.part_timeout_factor = Resource.PART_TIMEOUT_FACTOR_AFTER_RTT
|
||||
if self.rtt == None:
|
||||
self.rtt = self.link.rtt
|
||||
self.watchdog_job()
|
||||
elif rtt < self.rtt:
|
||||
self.rtt = max(self.rtt - self.rtt*0.05, rtt)
|
||||
elif rtt > self.rtt:
|
||||
self.rtt = min(self.rtt + self.rtt*0.05, rtt)
|
||||
if self.req_resp == None:
|
||||
self.req_resp = self.last_activity
|
||||
rtt = self.req_resp-self.req_sent
|
||||
|
||||
self.part_timeout_factor = Resource.PART_TIMEOUT_FACTOR_AFTER_RTT
|
||||
if self.rtt == None:
|
||||
self.rtt = self.link.rtt
|
||||
self.watchdog_job()
|
||||
elif rtt < self.rtt:
|
||||
self.rtt = max(self.rtt - self.rtt*0.05, rtt)
|
||||
elif rtt > self.rtt:
|
||||
self.rtt = min(self.rtt + self.rtt*0.05, rtt)
|
||||
|
||||
if rtt > 0:
|
||||
req_resp_cost = len(packet.raw)+self.req_sent_bytes
|
||||
self.req_resp_rtt_rate = req_resp_cost / rtt
|
||||
if rtt > 0:
|
||||
req_resp_cost = len(packet.raw)+self.req_sent_bytes
|
||||
self.req_resp_rtt_rate = req_resp_cost / rtt
|
||||
|
||||
if self.req_resp_rtt_rate > Resource.RATE_FAST and self.fast_rate_rounds < Resource.FAST_RATE_THRESHOLD:
|
||||
self.fast_rate_rounds += 1
|
||||
if self.req_resp_rtt_rate > Resource.RATE_FAST and self.fast_rate_rounds < Resource.FAST_RATE_THRESHOLD:
|
||||
self.fast_rate_rounds += 1
|
||||
|
||||
if self.fast_rate_rounds == Resource.FAST_RATE_THRESHOLD:
|
||||
self.window_max = Resource.WINDOW_MAX_FAST
|
||||
if self.fast_rate_rounds == Resource.FAST_RATE_THRESHOLD:
|
||||
self.window_max = Resource.WINDOW_MAX_FAST
|
||||
|
||||
if not self.status == Resource.FAILED:
|
||||
self.status = Resource.TRANSFERRING
|
||||
part_data = packet.data
|
||||
part_hash = self.get_map_hash(part_data)
|
||||
if not self.status == Resource.FAILED:
|
||||
self.status = Resource.TRANSFERRING
|
||||
part_data = packet.data
|
||||
part_hash = self.get_map_hash(part_data)
|
||||
|
||||
i = self.consecutive_completed_height
|
||||
for map_hash in self.hashmap[self.consecutive_completed_height:self.consecutive_completed_height+self.window]:
|
||||
if map_hash == part_hash:
|
||||
if self.parts[i] == None:
|
||||
consecutive_index = self.consecutive_completed_height if self.consecutive_completed_height >= 0 else 0
|
||||
i = consecutive_index
|
||||
for map_hash in self.hashmap[consecutive_index:consecutive_index+self.window]:
|
||||
if map_hash == part_hash:
|
||||
if self.parts[i] == None:
|
||||
|
||||
# Insert data into parts list
|
||||
self.parts[i] = part_data
|
||||
self.rtt_rxd_bytes += len(part_data)
|
||||
self.received_count += 1
|
||||
self.outstanding_parts -= 1
|
||||
# Insert data into parts list
|
||||
self.parts[i] = part_data
|
||||
self.rtt_rxd_bytes += len(part_data)
|
||||
self.received_count += 1
|
||||
self.outstanding_parts -= 1
|
||||
|
||||
# Update consecutive completed pointer
|
||||
if i == self.consecutive_completed_height + 1:
|
||||
self.consecutive_completed_height = i
|
||||
|
||||
cp = self.consecutive_completed_height + 1
|
||||
while cp < len(self.parts) and self.parts[cp] != None:
|
||||
self.consecutive_completed_height = cp
|
||||
cp += 1
|
||||
# Update consecutive completed pointer
|
||||
if i == self.consecutive_completed_height + 1:
|
||||
self.consecutive_completed_height = i
|
||||
|
||||
cp = self.consecutive_completed_height + 1
|
||||
while cp < len(self.parts) and self.parts[cp] != None:
|
||||
self.consecutive_completed_height = cp
|
||||
cp += 1
|
||||
|
||||
if self.__progress_callback != None:
|
||||
try:
|
||||
self.__progress_callback(self)
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
if self.__progress_callback != None:
|
||||
try:
|
||||
self.__progress_callback(self)
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
i += 1
|
||||
i += 1
|
||||
|
||||
self.receiving_part = False
|
||||
self.receiving_part = False
|
||||
|
||||
if self.received_count == self.total_parts and not self.assembly_lock:
|
||||
self.assembly_lock = True
|
||||
self.assemble()
|
||||
elif self.outstanding_parts == 0:
|
||||
# TODO: Figure out if there is a mathematically
|
||||
# optimal way to adjust windows
|
||||
if self.window < self.window_max:
|
||||
self.window += 1
|
||||
if (self.window - self.window_min) > (self.window_flexibility-1):
|
||||
self.window_min += 1
|
||||
if self.received_count == self.total_parts and not self.assembly_lock:
|
||||
self.assembly_lock = True
|
||||
self.assemble()
|
||||
elif self.outstanding_parts == 0:
|
||||
# TODO: Figure out if there is a mathematically
|
||||
# optimal way to adjust windows
|
||||
if self.window < self.window_max:
|
||||
self.window += 1
|
||||
if (self.window - self.window_min) > (self.window_flexibility-1):
|
||||
self.window_min += 1
|
||||
|
||||
if self.req_sent != 0:
|
||||
rtt = time.time()-self.req_sent
|
||||
req_transferred = self.rtt_rxd_bytes - self.rtt_rxd_bytes_at_part_req
|
||||
if self.req_sent != 0:
|
||||
rtt = time.time()-self.req_sent
|
||||
req_transferred = self.rtt_rxd_bytes - self.rtt_rxd_bytes_at_part_req
|
||||
|
||||
if rtt != 0:
|
||||
self.req_data_rtt_rate = req_transferred/rtt
|
||||
self.rtt_rxd_bytes_at_part_req = self.rtt_rxd_bytes
|
||||
if rtt != 0:
|
||||
self.req_data_rtt_rate = req_transferred/rtt
|
||||
self.rtt_rxd_bytes_at_part_req = self.rtt_rxd_bytes
|
||||
|
||||
if self.req_data_rtt_rate > Resource.RATE_FAST and self.fast_rate_rounds < Resource.FAST_RATE_THRESHOLD:
|
||||
self.fast_rate_rounds += 1
|
||||
if self.req_data_rtt_rate > Resource.RATE_FAST and self.fast_rate_rounds < Resource.FAST_RATE_THRESHOLD:
|
||||
self.fast_rate_rounds += 1
|
||||
|
||||
if self.fast_rate_rounds == Resource.FAST_RATE_THRESHOLD:
|
||||
self.window_max = Resource.WINDOW_MAX_FAST
|
||||
if self.fast_rate_rounds == Resource.FAST_RATE_THRESHOLD:
|
||||
self.window_max = Resource.WINDOW_MAX_FAST
|
||||
|
||||
self.request_next()
|
||||
else:
|
||||
self.receiving_part = False
|
||||
self.request_next()
|
||||
else:
|
||||
self.receiving_part = False
|
||||
|
||||
# Called on incoming resource to send a request for more data
|
||||
def request_next(self):
|
||||
@@ -728,11 +756,11 @@ class Resource:
|
||||
hashmap_exhausted = Resource.HASHMAP_IS_NOT_EXHAUSTED
|
||||
requested_hashes = b""
|
||||
|
||||
offset = (1 if self.consecutive_completed_height > 0 else 0)
|
||||
i = 0; pn = self.consecutive_completed_height+offset
|
||||
i = 0; pn = self.consecutive_completed_height+1
|
||||
search_start = pn
|
||||
|
||||
for part in self.parts[search_start:search_start+self.window]:
|
||||
search_size = self.window
|
||||
|
||||
for part in self.parts[search_start:search_start+search_size]:
|
||||
if part == None:
|
||||
part_hash = self.hashmap[pn]
|
||||
if part_hash != None:
|
||||
@@ -752,7 +780,6 @@ class Resource:
|
||||
hmu_part += last_map_hash
|
||||
self.waiting_for_hmu = True
|
||||
|
||||
requested_data = b""
|
||||
request_data = hmu_part + self.hash + requested_hashes
|
||||
request_packet = RNS.Packet(self.link, request_data, context = RNS.Packet.RESOURCE_REQ)
|
||||
|
||||
@@ -908,8 +935,7 @@ class Resource:
|
||||
else:
|
||||
self.progress_total_parts = float(self.total_parts)
|
||||
|
||||
|
||||
progress = self.processed_parts / self.progress_total_parts
|
||||
progress = min(1.0, self.processed_parts / self.progress_total_parts)
|
||||
return progress
|
||||
|
||||
def get_transfer_size(self):
|
||||
|
||||
+9
-4
@@ -119,7 +119,7 @@ class Reticulum:
|
||||
|
||||
# TODO: Let Reticulum somehow continously build a map of per-hop
|
||||
# latencies and use this map for global timeout calculation.
|
||||
DEFAULT_PER_HOP_TIMEOUT = 4
|
||||
DEFAULT_PER_HOP_TIMEOUT = 6
|
||||
|
||||
# Length of truncated hashes in bits.
|
||||
TRUNCATED_HASHLENGTH = 128
|
||||
@@ -321,9 +321,8 @@ class Reticulum:
|
||||
interface.OUT = True
|
||||
if hasattr(Reticulum, "_force_shared_instance_bitrate"):
|
||||
interface.bitrate = Reticulum._force_shared_instance_bitrate
|
||||
interface._force_bitrate = True
|
||||
RNS.log(f"Forcing shared instance bitrate of {RNS.prettyspeed(interface.bitrate)}ps", RNS.LOG_WARNING)
|
||||
interface._force_bitrate = Reticulum._force_shared_instance_bitrate
|
||||
RNS.log(f"Forcing shared instance bitrate of {RNS.prettyspeed(interface.bitrate)}", RNS.LOG_WARNING)
|
||||
RNS.Transport.interfaces.append(interface)
|
||||
|
||||
self.is_shared_instance = True
|
||||
@@ -341,7 +340,7 @@ class Reticulum:
|
||||
if hasattr(Reticulum, "_force_shared_instance_bitrate"):
|
||||
interface.bitrate = Reticulum._force_shared_instance_bitrate
|
||||
interface._force_bitrate = True
|
||||
RNS.log(f"Forcing shared instance bitrate of {RNS.prettyspeed(interface.bitrate)}ps", RNS.LOG_WARNING)
|
||||
RNS.log(f"Forcing shared instance bitrate of {RNS.prettyspeed(interface.bitrate)}", RNS.LOG_WARNING)
|
||||
RNS.Transport.interfaces.append(interface)
|
||||
self.is_shared_instance = False
|
||||
self.is_standalone_instance = False
|
||||
@@ -1329,6 +1328,12 @@ class Reticulum:
|
||||
rpc_connection = multiprocessing.connection.Client(self.rpc_addr, authkey=self.rpc_key)
|
||||
rpc_connection.send({"get": "first_hop_timeout", "destination_hash": destination})
|
||||
response = rpc_connection.recv()
|
||||
|
||||
if self.is_connected_to_shared_instance and hasattr(self, "_force_shared_instance_bitrate") and self._force_shared_instance_bitrate:
|
||||
simulated_latency = ((1/self._force_shared_instance_bitrate)*8)*RNS.Reticulum.MTU
|
||||
RNS.log("Adding simulated latency of "+RNS.prettytime(simulated_latency)+" to first hop timeout", RNS.LOG_DEBUG)
|
||||
response += simulated_latency
|
||||
|
||||
return response
|
||||
except Exception as e:
|
||||
RNS.log("An error occurred while getting first hop timeout from shared instance: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
+72
-35
@@ -66,7 +66,7 @@ class Transport:
|
||||
PATH_REQUEST_TIMEOUT = 15 # Default timuout for client path requests in seconds
|
||||
PATH_REQUEST_GRACE = 0.35 # Grace time before a path announcement is made, allows directly reachable peers to respond first
|
||||
PATH_REQUEST_RW = 2 # Path request random window
|
||||
PATH_REQUEST_MI = 5 # Minimum interval in seconds for automated path requests
|
||||
PATH_REQUEST_MI = 20 # Minimum interval in seconds for automated path requests
|
||||
|
||||
STATE_UNKNOWN = 0x00
|
||||
STATE_UNRESPONSIVE = 0x01
|
||||
@@ -305,7 +305,8 @@ class Transport:
|
||||
@staticmethod
|
||||
def jobs():
|
||||
outgoing = []
|
||||
path_requests = []
|
||||
path_requests = {}
|
||||
blocked_if = None
|
||||
Transport.jobs_running = True
|
||||
|
||||
try:
|
||||
@@ -333,7 +334,8 @@ class Transport:
|
||||
if time.time() - last_path_request > Transport.PATH_REQUEST_MI:
|
||||
RNS.log("Trying to rediscover path for "+RNS.prettyhexrep(link.destination.hash)+" since an attempted link was never established", RNS.LOG_DEBUG)
|
||||
if not link.destination.hash in path_requests:
|
||||
path_requests.append(link.destination.hash)
|
||||
blocked_if = None
|
||||
path_requests[link.destination.hash] = blocked_if
|
||||
|
||||
Transport.pending_links.remove(link)
|
||||
|
||||
@@ -482,14 +484,16 @@ class Transport:
|
||||
elif not path_request_throttle and Transport.hops_to(link_entry[6]) == 1:
|
||||
RNS.log("Trying to rediscover path for "+RNS.prettyhexrep(link_entry[6])+" since an attempted link was never established, and destination was previously local to an interface on this instance", RNS.LOG_DEBUG)
|
||||
path_request_conditions = True
|
||||
blocked_if = link_entry[4]
|
||||
|
||||
# If the link initiator was previously only 1 hop
|
||||
# away, this likely means that network topology has
|
||||
# If the link initiator is only 1 hop away,
|
||||
# this likely means that network topology has
|
||||
# changed. In that case, we try to discover a new path,
|
||||
# and mark the old one as potentially unresponsive.
|
||||
elif not path_request_throttle and lr_taken_hops == 1:
|
||||
RNS.log("Trying to rediscover path for "+RNS.prettyhexrep(link_entry[6])+" since an attempted link was never established, and link initiator is local to an interface on this instance", RNS.LOG_DEBUG)
|
||||
path_request_conditions = True
|
||||
blocked_if = link_entry[4]
|
||||
|
||||
if RNS.Reticulum.transport_enabled():
|
||||
if hasattr(link_entry[4], "mode") and link_entry[4].mode != RNS.Interfaces.Interface.Interface.MODE_BOUNDARY:
|
||||
@@ -497,7 +501,7 @@ class Transport:
|
||||
|
||||
if path_request_conditions:
|
||||
if not link_entry[6] in path_requests:
|
||||
path_requests.append(link_entry[6])
|
||||
path_requests[link_entry[6]] = blocked_if
|
||||
|
||||
if not RNS.Reticulum.transport_enabled():
|
||||
# Drop current path if we are not a transport instance, to
|
||||
@@ -652,7 +656,17 @@ class Transport:
|
||||
packet.send()
|
||||
|
||||
for destination_hash in path_requests:
|
||||
Transport.request_path(destination_hash)
|
||||
blocked_if = path_requests[destination_hash]
|
||||
if blocked_if == None:
|
||||
Transport.request_path(destination_hash)
|
||||
else:
|
||||
for interface in Transport.interfaces:
|
||||
if interface != blocked_if:
|
||||
# RNS.log("Transmitting path request on "+str(interface), RNS.LOG_DEBUG)
|
||||
Transport.request_path(destination_hash, on_interface=interface)
|
||||
else:
|
||||
pass
|
||||
# RNS.log("Blocking path request on "+str(interface), RNS.LOG_DEBUG)
|
||||
|
||||
@staticmethod
|
||||
def transmit(interface, raw):
|
||||
@@ -709,6 +723,29 @@ class Transport:
|
||||
sent = False
|
||||
outbound_time = time.time()
|
||||
|
||||
generate_receipt = False
|
||||
if (packet.create_receipt == True and
|
||||
# Only generate receipts for DATA packets
|
||||
packet.packet_type == RNS.Packet.DATA and
|
||||
# Don't generate receipts for PLAIN destinations
|
||||
packet.destination.type != RNS.Destination.PLAIN and
|
||||
# Don't generate receipts for link-related packets
|
||||
not (packet.context >= RNS.Packet.KEEPALIVE and packet.context <= RNS.Packet.LRPROOF) and
|
||||
# Don't generate receipts for resource packets
|
||||
not (packet.context >= RNS.Packet.RESOURCE and packet.context <= RNS.Packet.RESOURCE_RCL)):
|
||||
|
||||
generate_receipt = True
|
||||
|
||||
def packet_sent(packet):
|
||||
packet.sent = True
|
||||
packet.sent_at = time.time()
|
||||
|
||||
if generate_receipt:
|
||||
packet.receipt = RNS.PacketReceipt(packet)
|
||||
Transport.receipts.append(packet.receipt)
|
||||
|
||||
Transport.cache(packet)
|
||||
|
||||
# Check if we have a known path for the destination in the path table
|
||||
if packet.packet_type != RNS.Packet.ANNOUNCE and packet.destination.type != RNS.Destination.PLAIN and packet.destination.type != RNS.Destination.GROUP and packet.destination_hash in Transport.destination_table:
|
||||
outbound_interface = Transport.destination_table[packet.destination_hash][5]
|
||||
@@ -726,6 +763,7 @@ class Transport:
|
||||
new_raw += packet.raw[1:2]
|
||||
new_raw += Transport.destination_table[packet.destination_hash][1]
|
||||
new_raw += packet.raw[2:]
|
||||
packet_sent(packet)
|
||||
Transport.transmit(outbound_interface, new_raw)
|
||||
Transport.destination_table[packet.destination_hash][0] = time.time()
|
||||
sent = True
|
||||
@@ -745,6 +783,7 @@ class Transport:
|
||||
new_raw += packet.raw[1:2]
|
||||
new_raw += Transport.destination_table[packet.destination_hash][1]
|
||||
new_raw += packet.raw[2:]
|
||||
packet_sent(packet)
|
||||
Transport.transmit(outbound_interface, new_raw)
|
||||
Transport.destination_table[packet.destination_hash][0] = time.time()
|
||||
sent = True
|
||||
@@ -753,6 +792,7 @@ class Transport:
|
||||
# directly reachable, and also on which interface, so we
|
||||
# simply transmit the packet directly on that one.
|
||||
else:
|
||||
packet_sent(packet)
|
||||
Transport.transmit(outbound_interface, packet.raw)
|
||||
sent = True
|
||||
|
||||
@@ -836,7 +876,7 @@ class Transport:
|
||||
interface.announce_queue = []
|
||||
|
||||
queued_announces = True if len(interface.announce_queue) > 0 else False
|
||||
if not queued_announces and outbound_time > interface.announce_allowed_at:
|
||||
if not queued_announces and outbound_time > interface.announce_allowed_at and interface.bitrate != None and interface.bitrate != 0:
|
||||
tx_time = (len(packet.raw)*8) / interface.bitrate
|
||||
wait_time = (tx_time / interface.announce_cap)
|
||||
interface.announce_allowed_at = outbound_time + wait_time
|
||||
@@ -919,28 +959,9 @@ class Transport:
|
||||
Transport.transmit(interface, packet.raw)
|
||||
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
||||
interface.sent_announce()
|
||||
packet_sent(packet)
|
||||
sent = True
|
||||
|
||||
if sent:
|
||||
packet.sent = True
|
||||
packet.sent_at = time.time()
|
||||
|
||||
# Don't generate receipt if it has been explicitly disabled
|
||||
if (packet.create_receipt == True and
|
||||
# Only generate receipts for DATA packets
|
||||
packet.packet_type == RNS.Packet.DATA and
|
||||
# Don't generate receipts for PLAIN destinations
|
||||
packet.destination.type != RNS.Destination.PLAIN and
|
||||
# Don't generate receipts for link-related packets
|
||||
not (packet.context >= RNS.Packet.KEEPALIVE and packet.context <= RNS.Packet.LRPROOF) and
|
||||
# Don't generate receipts for resource packets
|
||||
not (packet.context >= RNS.Packet.RESOURCE and packet.context <= RNS.Packet.RESOURCE_RCL)):
|
||||
|
||||
packet.receipt = RNS.PacketReceipt(packet)
|
||||
Transport.receipts.append(packet.receipt)
|
||||
|
||||
Transport.cache(packet)
|
||||
|
||||
Transport.jobs_locked = False
|
||||
return sent
|
||||
|
||||
@@ -1335,6 +1356,7 @@ class Transport:
|
||||
# TODO: Check whether this approach works
|
||||
# under all circumstances
|
||||
if not random_blob in random_blobs:
|
||||
Transport.mark_path_unknown_state(packet.destination_hash)
|
||||
should_add = True
|
||||
else:
|
||||
should_add = False
|
||||
@@ -1362,6 +1384,7 @@ class Transport:
|
||||
# TODO: Check that this ^ approach actually
|
||||
# works under all circumstances
|
||||
RNS.log("Replacing destination table entry for "+str(RNS.prettyhexrep(packet.destination_hash))+" with new announce due to expired path", RNS.LOG_DEBUG)
|
||||
Transport.mark_path_unknown_state(packet.destination_hash)
|
||||
should_add = True
|
||||
else:
|
||||
should_add = False
|
||||
@@ -1372,6 +1395,7 @@ class Transport:
|
||||
if (announce_emitted > path_announce_emitted):
|
||||
if not random_blob in random_blobs:
|
||||
RNS.log("Replacing destination table entry for "+str(RNS.prettyhexrep(packet.destination_hash))+" with new announce, since it was more recently emitted", RNS.LOG_DEBUG)
|
||||
Transport.mark_path_unknown_state(packet.destination_hash)
|
||||
should_add = True
|
||||
else:
|
||||
should_add = False
|
||||
@@ -1720,9 +1744,6 @@ class Transport:
|
||||
if receipt.hash == proof_hash:
|
||||
receipt_validated = receipt.validate_proof_packet(packet)
|
||||
else:
|
||||
# TODO: This looks like it should actually
|
||||
# be rewritten when implicit proofs are added.
|
||||
|
||||
# In case of an implicit proof, we have
|
||||
# to check every single outstanding receipt
|
||||
receipt_validated = receipt.validate_proof_packet(packet)
|
||||
@@ -2045,9 +2066,9 @@ class Transport:
|
||||
|
||||
@staticmethod
|
||||
def next_hop_per_byte_latency(destination_hash):
|
||||
per_byte_latency = Transport.next_hop_per_bit_latency(destination_hash)
|
||||
if per_byte_latency != None:
|
||||
return per_byte_latency*8
|
||||
per_bit_latency = Transport.next_hop_per_bit_latency(destination_hash)
|
||||
if per_bit_latency != None:
|
||||
return per_bit_latency*8
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -2055,7 +2076,7 @@ class Transport:
|
||||
def first_hop_timeout(destination_hash):
|
||||
latency = Transport.next_hop_per_byte_latency(destination_hash)
|
||||
if latency != None:
|
||||
return RNS.Reticulum.MTU * latency
|
||||
return RNS.Reticulum.MTU * latency + RNS.Reticulum.DEFAULT_PER_HOP_TIMEOUT
|
||||
else:
|
||||
return RNS.Reticulum.DEFAULT_PER_HOP_TIMEOUT
|
||||
|
||||
@@ -2083,6 +2104,22 @@ class Transport:
|
||||
else:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def mark_path_responsive(destination_hash):
|
||||
if destination_hash in Transport.destination_table:
|
||||
Transport.path_states[destination_hash] = Transport.STATE_RESPONSIVE
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def mark_path_unknown_state(destination_hash):
|
||||
if destination_hash in Transport.destination_table:
|
||||
Transport.path_states[destination_hash] = Transport.STATE_UNKNOWN
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def path_is_unresponsive(destination_hash):
|
||||
if destination_hash in Transport.path_states:
|
||||
if Transport.path_states[destination_hash] == Transport.STATE_UNRESPONSIVE:
|
||||
|
||||
+89
-8
@@ -64,19 +64,22 @@ def main():
|
||||
|
||||
parser.add_argument("--config", metavar="path", action="store", default=None, help="path to alternative Reticulum config directory", type=str)
|
||||
parser.add_argument("-i", "--identity", metavar="identity", action="store", default=None, help="hexadecimal Reticulum Destination hash or path to Identity file", type=str)
|
||||
parser.add_argument("-g", "--generate", metavar="path", action="store", default=None, help="generate a new Identity")
|
||||
parser.add_argument("-g", "--generate", metavar="file", action="store", default=None, help="generate a new Identity")
|
||||
parser.add_argument("-m", "--import", dest="import_str", metavar="identity_data", action="store", default=None, help="import Reticulum identity in hex, base32 or base64 format", type=str)
|
||||
parser.add_argument("-x", "--export", action="store_true", default=None, help="export identity to hex, base32 or base64 format")
|
||||
|
||||
parser.add_argument("-v", "--verbose", action="count", default=0, help="increase verbosity")
|
||||
parser.add_argument("-q", "--quiet", action="count", default=0, help="decrease verbosity")
|
||||
|
||||
parser.add_argument("-a", "--announce", metavar="aspects", action="store", default=None, help="announce a destination based on this Identity")
|
||||
parser.add_argument("-H", "--hash", metavar="aspects", action="store", default=None, help="show destination hashes for other aspects for this Identity")
|
||||
parser.add_argument("-e", "--encrypt", metavar="path", action="store", default=None, help="encrypt file")
|
||||
parser.add_argument("-d", "--decrypt", metavar="path", action="store", default=None, help="decrypt file")
|
||||
parser.add_argument("-e", "--encrypt", metavar="file", action="store", default=None, help="encrypt file")
|
||||
parser.add_argument("-d", "--decrypt", metavar="file", action="store", default=None, help="decrypt file")
|
||||
parser.add_argument("-s", "--sign", metavar="path", action="store", default=None, help="sign file")
|
||||
parser.add_argument("-V", "--validate", metavar="path", action="store", default=None, help="validate signature")
|
||||
|
||||
parser.add_argument("-r", "--read", metavar="path", action="store", default=None, help="input file path", type=str)
|
||||
parser.add_argument("-w", "--write", metavar="path", action="store", default=None, help="output file path", type=str)
|
||||
parser.add_argument("-r", "--read", metavar="file", action="store", default=None, help="input file path", type=str)
|
||||
parser.add_argument("-w", "--write", metavar="file", action="store", default=None, help="output file path", type=str)
|
||||
parser.add_argument("-f", "--force", action="store_true", default=None, help="write output even if it overwrites existing files")
|
||||
parser.add_argument("-I", "--stdin", action="store_true", default=False, help=argparse.SUPPRESS) # "read input from STDIN instead of file"
|
||||
parser.add_argument("-O", "--stdout", action="store_true", default=False, help=argparse.SUPPRESS) # help="write output to STDOUT instead of file",
|
||||
@@ -86,7 +89,8 @@ def main():
|
||||
parser.add_argument("-p", "--print-identity", action="store_true", default=False, help="print identity info and exit")
|
||||
parser.add_argument("-P", "--print-private", action="store_true", default=False, help="allow displaying private keys")
|
||||
|
||||
parser.add_argument("-b", "--base64", action="store_true", default=False, help=argparse.SUPPRESS) # help="Use base64-encoded input and output")
|
||||
parser.add_argument("-b", "--base64", action="store_true", default=False, help="Use base64-encoded input and output")
|
||||
parser.add_argument("-B", "--base32", action="store_true", default=False, help="Use base32-encoded input and output")
|
||||
|
||||
parser.add_argument("--version", action="version", version="rnid {version}".format(version=__version__))
|
||||
|
||||
@@ -110,6 +114,59 @@ def main():
|
||||
args.read = args.sign
|
||||
|
||||
identity_str = args.identity
|
||||
if args.import_str:
|
||||
identity_bytes = None
|
||||
try:
|
||||
if args.base64:
|
||||
identity_bytes = base64.urlsafe_b64decode(args.import_str)
|
||||
elif args.base32:
|
||||
identity_bytes = base64.b32decode(args.import_str)
|
||||
else:
|
||||
identity_bytes = bytes.fromhex(args.import_str)
|
||||
except Exception as e:
|
||||
print("Invalid identity data specified for import: "+str(e))
|
||||
exit(41)
|
||||
|
||||
try:
|
||||
identity = RNS.Identity.from_bytes(identity_bytes)
|
||||
except Exception as e:
|
||||
print("Could not create Reticulum identity from specified data: "+str(e))
|
||||
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")
|
||||
|
||||
if args.write:
|
||||
try:
|
||||
wp = os.path.expanduser(args.write)
|
||||
if not os.path.isfile(wp) or args.force:
|
||||
identity.to_file(wp)
|
||||
RNS.log("Wrote imported identity to "+str(args.write))
|
||||
else:
|
||||
print("File "+str(wp)+" already exists, not overwriting")
|
||||
exit(43)
|
||||
|
||||
except Exception as e:
|
||||
print("Error while writing imported identity to file: "+str(e))
|
||||
exit(44)
|
||||
|
||||
exit(0)
|
||||
|
||||
if not args.generate and not identity_str:
|
||||
print("\nNo identity provided, cannot continue\n")
|
||||
parser.print_help()
|
||||
@@ -246,14 +303,38 @@ def main():
|
||||
exit(0)
|
||||
|
||||
if args.print_identity:
|
||||
RNS.log("Public Key : "+RNS.hexrep(identity.pub_bytes, delimit=False))
|
||||
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:
|
||||
RNS.log("Private Key : "+RNS.hexrep(identity.prv_bytes, delimit=False))
|
||||
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")
|
||||
exit(0)
|
||||
|
||||
if args.export:
|
||||
if identity.prv:
|
||||
if args.base64:
|
||||
RNS.log("Exported Identity : "+base64.urlsafe_b64encode(identity.get_private_key()).decode("utf-8"))
|
||||
elif args.base32:
|
||||
RNS.log("Exported Identity : "+base64.b32encode(identity.get_private_key()).decode("utf-8"))
|
||||
else:
|
||||
RNS.log("Exported Identity : "+RNS.hexrep(identity.get_private_key(), delimit=False))
|
||||
else:
|
||||
RNS.log("Identity doesn't hold a private key, cannot export")
|
||||
exit(50)
|
||||
|
||||
exit(0)
|
||||
|
||||
if args.validate:
|
||||
if not args.read and args.validate.lower().endswith("."+SIG_EXT):
|
||||
args.read = str(args.validate).replace("."+SIG_EXT, "")
|
||||
|
||||
+200
-66
@@ -120,12 +120,16 @@ class KISS():
|
||||
class ROM():
|
||||
PLATFORM_AVR = 0x90
|
||||
PLATFORM_ESP32 = 0x80
|
||||
PLATFORM_NRF52 = 0x70
|
||||
|
||||
MCU_1284P = 0x91
|
||||
MCU_2560 = 0x92
|
||||
MCU_ESP32 = 0x81
|
||||
MCU_NRF52 = 0x71
|
||||
|
||||
PRODUCT_RNODE = 0x03
|
||||
MODEL_A1 = 0xA1
|
||||
MODEL_A6 = 0xA6
|
||||
MODEL_A4 = 0xA4
|
||||
MODEL_A9 = 0xA9
|
||||
MODEL_A3 = 0xA3
|
||||
@@ -152,6 +156,8 @@ class ROM():
|
||||
PRODUCT_TBEAM = 0xE0
|
||||
MODEL_E4 = 0xE4
|
||||
MODEL_E9 = 0xE9
|
||||
MODEL_E3 = 0xE3
|
||||
MODEL_E8 = 0xE8
|
||||
|
||||
PRODUCT_HMBRW = 0xF0
|
||||
MODEL_FF = 0xFF
|
||||
@@ -182,6 +188,7 @@ class ROM():
|
||||
BOARD_GENERIC_ESP32 = 0x35
|
||||
BOARD_LORA32_V2_0 = 0x36
|
||||
BOARD_LORA32_V2_1 = 0x37
|
||||
BOARD_RAK4630 = 0x51
|
||||
|
||||
mapped_product = ROM.PRODUCT_RNODE
|
||||
products = {
|
||||
@@ -197,33 +204,39 @@ products = {
|
||||
platforms = {
|
||||
ROM.PLATFORM_AVR: "AVR",
|
||||
ROM.PLATFORM_ESP32:"ESP32",
|
||||
ROM.PLATFORM_NRF52:"NRF52",
|
||||
}
|
||||
|
||||
mcus = {
|
||||
ROM.MCU_1284P: "ATmega1284P",
|
||||
ROM.MCU_2560:"ATmega2560",
|
||||
ROM.MCU_ESP32:"Espressif Systems ESP32",
|
||||
ROM.MCU_NRF52:"Nordic nRF52840",
|
||||
}
|
||||
|
||||
models = {
|
||||
0xA4: [410000000, 525000000, 14, "410 - 525 MHz", "rnode_firmware.hex"],
|
||||
0xA9: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware.hex"],
|
||||
0xA2: [410000000, 525000000, 17, "410 - 525 MHz", "rnode_firmware_ng21.zip"],
|
||||
0xA7: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware_ng21.zip"],
|
||||
0xA3: [410000000, 525000000, 17, "410 - 525 MHz", "rnode_firmware_ng20.zip"],
|
||||
0xA8: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware_ng20.zip"],
|
||||
0xB3: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v20.zip"],
|
||||
0xB8: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v20.zip"],
|
||||
0xB4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v21.zip"],
|
||||
0xB9: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v21.zip"],
|
||||
0xBA: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v10.zip"],
|
||||
0xBB: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v10.zip"],
|
||||
0xC4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_heltec32v2.zip"],
|
||||
0xC9: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_heltec32v2.zip"],
|
||||
0xE4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_tbeam.zip"],
|
||||
0xE9: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_tbeam.zip"],
|
||||
0xFE: [100000000, 1100000000, 17, "(Band capabilities unknown)", None],
|
||||
0xFF: [100000000, 1100000000, 14, "(Band capabilities unknown)", None],
|
||||
0xA4: [410000000, 525000000, 14, "410 - 525 MHz", "rnode_firmware.hex", "SX1278"],
|
||||
0xA9: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware.hex", "SX1276"],
|
||||
0xA1: [410000000, 525000000, 22, "410 - 525 MHz", "rnode_firmware_t3s3.zip", "SX1268"],
|
||||
0xA6: [820000000, 1020000000, 22, "820 - 960 MHz", "rnode_firmware_t3s3.zip", "SX1262"],
|
||||
0xA2: [410000000, 525000000, 17, "410 - 525 MHz", "rnode_firmware_ng21.zip", "SX1278"],
|
||||
0xA7: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware_ng21.zip", "SX1276"],
|
||||
0xA3: [410000000, 525000000, 17, "410 - 525 MHz", "rnode_firmware_ng20.zip", "SX1278"],
|
||||
0xA8: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware_ng20.zip", "SX1276"],
|
||||
0xB3: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v20.zip", "SX1278"],
|
||||
0xB8: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v20.zip", "SX1276"],
|
||||
0xB4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v21.zip", "SX1278"],
|
||||
0xB9: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v21.zip", "SX1276"],
|
||||
0xBA: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v10.zip", "SX1278"],
|
||||
0xBB: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v10.zip", "SX1276"],
|
||||
0xC4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_heltec32v2.zip", "SX1278"],
|
||||
0xC9: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_heltec32v2.zip", "SX1276"],
|
||||
0xE4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_tbeam.zip", "SX1278"],
|
||||
0xE9: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_tbeam.zip", "SX1276"],
|
||||
0xE3: [420000000, 520000000, 22, "420 - 520 MHz", "rnode_firmware_tbeam_sx1262.zip", "SX1268"],
|
||||
0xE8: [850000000, 950000000, 22, "850 - 950 MHz", "rnode_firmware_tbeam_sx1262.zip", "SX1262"],
|
||||
0xFE: [100000000, 1100000000, 17, "(Band capabilities unknown)", None, "Unknown"],
|
||||
0xFF: [100000000, 1100000000, 14, "(Band capabilities unknown)", None, "Unknown"],
|
||||
}
|
||||
|
||||
CNF_DIR = None
|
||||
@@ -516,7 +529,7 @@ class RNode():
|
||||
if (len(command_buffer) == 4):
|
||||
self.r_stat_tx = ord(command_buffer[0]) << 24 | ord(command_buffer[1]) << 16 | ord(command_buffer[2]) << 8 | ord(command_buffer[3])
|
||||
elif (command == KISS.CMD_STAT_RSSI):
|
||||
self.r_stat_rssi = byte-RNodeInterface.RSSI_OFFSET
|
||||
self.r_stat_rssi = byte-157 # RSSI Offset
|
||||
elif (command == KISS.CMD_STAT_SNR):
|
||||
self.r_stat_snr = int.from_bytes(bytes([byte]), byteorder="big", signed=True) * 0.25
|
||||
elif (command == KISS.CMD_RANDOM):
|
||||
@@ -928,6 +941,7 @@ class RNode():
|
||||
except Exception as e:
|
||||
self.provisioned = False
|
||||
RNS.log("Invalid EEPROM data, could not parse device EEPROM.")
|
||||
RNS.log("The contained exception was: "+str(e))
|
||||
|
||||
|
||||
def device_probe(self):
|
||||
@@ -1018,6 +1032,10 @@ def ensure_firmware_file(fw_filename):
|
||||
file = open(UPD_DIR+"/"+fw_filename+".version.latest", "rb")
|
||||
release_info = file.read().decode("utf-8").strip()
|
||||
selected_version = release_info.split()[0]
|
||||
if selected_version == "not":
|
||||
RNS.log("No valid version found for this board, exiting.")
|
||||
exit(199)
|
||||
|
||||
selected_hash = release_info.split()[1]
|
||||
if not os.path.isdir(UPD_DIR+"/"+selected_version):
|
||||
os.makedirs(UPD_DIR+"/"+selected_version)
|
||||
@@ -1497,6 +1515,7 @@ def main():
|
||||
print("[5] LilyGO LoRa32 v1.0")
|
||||
print("[6] LilyGO T-Beam")
|
||||
print("[7] Heltec LoRa32 v2")
|
||||
print("[8] LilyGO LoRa T3S3")
|
||||
print(" .")
|
||||
print(" / \\ Select one of these options if you want to easily turn")
|
||||
print(" | a supported development board into an RNode.")
|
||||
@@ -1507,7 +1526,8 @@ def main():
|
||||
selected_product = None
|
||||
try:
|
||||
c_dev = int(input())
|
||||
if c_dev < 1 or c_dev > 7:
|
||||
c_mod = False
|
||||
if c_dev < 1 or c_dev > 8:
|
||||
raise ValueError()
|
||||
elif c_dev == 1:
|
||||
selected_product = ROM.PRODUCT_RNODE
|
||||
@@ -1536,8 +1556,7 @@ def main():
|
||||
print(" T-Beam RNode Installer")
|
||||
print("")
|
||||
print("The RNode firmware can currently be installed on T-Beam devices using the")
|
||||
print("SX1276 and SX1278 transceiver chips. Support for devices with the newer")
|
||||
print("SX1262 and SX1268 chips is in development.")
|
||||
print("SX1276, SX1278, SX1262 and SX1268 transceiver chips.")
|
||||
print("")
|
||||
print("Important! Using RNode firmware on T-Beam devices should currently be")
|
||||
print("considered experimental. It is not intended for production or critical use.")
|
||||
@@ -1608,6 +1627,23 @@ def main():
|
||||
print("who would like to experiment with it. Hit enter to continue.")
|
||||
print("---------------------------------------------------------------------------")
|
||||
input()
|
||||
elif c_dev == 8:
|
||||
selected_product = ROM.PRODUCT_RNODE
|
||||
c_mod = True
|
||||
clear()
|
||||
print("")
|
||||
print("---------------------------------------------------------------------------")
|
||||
print(" LilyGO LoRa32 T3S3 RNode Installer")
|
||||
print("")
|
||||
print("Important! Using RNode firmware on T3S3 devices should currently be")
|
||||
print("considered experimental. It is not intended for production or critical use.")
|
||||
print("")
|
||||
print("Please note that Bluetooth is currently not implemented on this board.")
|
||||
print("")
|
||||
print("The currently supplied firmware is provided AS-IS as a courtesey to those")
|
||||
print("who would like to experiment with it. Hit enter to continue.")
|
||||
print("---------------------------------------------------------------------------")
|
||||
input()
|
||||
except Exception as e:
|
||||
print("That device type does not exist, exiting now.")
|
||||
exit()
|
||||
@@ -1660,53 +1696,86 @@ def main():
|
||||
|
||||
|
||||
elif selected_product == ROM.PRODUCT_RNODE:
|
||||
selected_mcu = ROM.MCU_1284P
|
||||
print("\nWhat model is this RNode?\n")
|
||||
print("[1] Handheld v2.x RNode, 410 - 525 MHz")
|
||||
print("[2] Handheld v2.x RNode, 820 - 1020 MHz")
|
||||
print("")
|
||||
print("[3] Original v1.x RNode, 410 - 525 MHz")
|
||||
print("[4] Original v1.x RNode, 820 - 1020 MHz")
|
||||
# print("[5] Prototype v2 RNode, 410 - 525 MHz")
|
||||
# print("[6] Prototype v2 RNode, 820 - 1020 MHz")
|
||||
print("\n? ", end="")
|
||||
try:
|
||||
c_model = int(input())
|
||||
if c_model < 1 or c_model > 6:
|
||||
raise ValueError()
|
||||
elif c_model == 3:
|
||||
selected_model = ROM.MODEL_A4
|
||||
selected_platform = ROM.PLATFORM_AVR
|
||||
elif c_model == 4:
|
||||
selected_model = ROM.MODEL_A9
|
||||
selected_platform = ROM.PLATFORM_AVR
|
||||
elif c_model == 1:
|
||||
selected_model = ROM.MODEL_A2
|
||||
selected_mcu = ROM.MCU_ESP32
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
elif c_model == 2:
|
||||
selected_model = ROM.MODEL_A7
|
||||
selected_mcu = ROM.MCU_ESP32
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
# elif c_model == 5:
|
||||
# selected_model = ROM.MODEL_A3
|
||||
# selected_mcu = ROM.MCU_ESP32
|
||||
# selected_platform = ROM.PLATFORM_ESP32
|
||||
# elif c_model == 6:
|
||||
# selected_model = ROM.MODEL_A8
|
||||
# selected_mcu = ROM.MCU_ESP32
|
||||
# selected_platform = ROM.PLATFORM_ESP32
|
||||
except Exception as e:
|
||||
print("That model does not exist, exiting now.")
|
||||
exit()
|
||||
if not c_mod:
|
||||
selected_mcu = ROM.MCU_1284P
|
||||
print("\nWhat model is this RNode?\n")
|
||||
print("[1] Handheld v2.1 RNode, 410 - 525 MHz")
|
||||
print("[2] Handheld v2.1 RNode, 820 - 1020 MHz")
|
||||
print("")
|
||||
print("[3] Original v1.x RNode, 410 - 525 MHz")
|
||||
print("[4] Original v1.x RNode, 820 - 1020 MHz")
|
||||
print("")
|
||||
print("[5] Prototype v2.2 RNode, 410 - 525 MHz")
|
||||
print("[6] Prototype v2.2 RNode, 820 - 1020 MHz")
|
||||
# print("[5] Prototype v2 RNode, 410 - 525 MHz")
|
||||
# print("[6] Prototype v2 RNode, 820 - 1020 MHz")
|
||||
print("\n? ", end="")
|
||||
try:
|
||||
c_model = int(input())
|
||||
if c_model < 1 or c_model > 6:
|
||||
raise ValueError()
|
||||
elif c_model == 1:
|
||||
selected_model = ROM.MODEL_A2
|
||||
selected_mcu = ROM.MCU_ESP32
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
elif c_model == 2:
|
||||
selected_model = ROM.MODEL_A7
|
||||
selected_mcu = ROM.MCU_ESP32
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
elif c_model == 3:
|
||||
selected_model = ROM.MODEL_A4
|
||||
selected_platform = ROM.PLATFORM_AVR
|
||||
elif c_model == 4:
|
||||
selected_model = ROM.MODEL_A9
|
||||
selected_platform = ROM.PLATFORM_AVR
|
||||
elif c_model == 5:
|
||||
selected_model = ROM.MODEL_A1
|
||||
selected_mcu = ROM.MCU_ESP32
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
elif c_model == 6:
|
||||
selected_model = ROM.MODEL_A6
|
||||
selected_mcu = ROM.MCU_ESP32
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
# elif c_model == 5:
|
||||
# selected_model = ROM.MODEL_A3
|
||||
# selected_mcu = ROM.MCU_ESP32
|
||||
# selected_platform = ROM.PLATFORM_ESP32
|
||||
# elif c_model == 6:
|
||||
# selected_model = ROM.MODEL_A8
|
||||
# selected_mcu = ROM.MCU_ESP32
|
||||
# selected_platform = ROM.PLATFORM_ESP32
|
||||
except Exception as e:
|
||||
print("That model does not exist, exiting now.")
|
||||
exit()
|
||||
else:
|
||||
print("\nWhat model is this T3S3?\n")
|
||||
print("[1] 410 - 525 MHz (with SX1268 chip)")
|
||||
print("[2] 820 - 1020 MHz (with SX1268 chip)")
|
||||
print("\n? ", end="")
|
||||
try:
|
||||
c_model = int(input())
|
||||
if c_model < 1 or c_model > 2:
|
||||
raise ValueError()
|
||||
elif c_model == 1:
|
||||
selected_model = ROM.MODEL_A1
|
||||
selected_mcu = ROM.MCU_ESP32
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
elif c_model == 2:
|
||||
selected_model = ROM.MODEL_A6
|
||||
selected_mcu = ROM.MCU_ESP32
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
except Exception as e:
|
||||
print("That model does not exist, exiting now.")
|
||||
exit()
|
||||
|
||||
elif selected_product == ROM.PRODUCT_TBEAM:
|
||||
selected_mcu = ROM.MCU_ESP32
|
||||
print("\nWhat band is this T-Beam for?\n")
|
||||
print("[1] 433 MHz")
|
||||
print("[2] 868 MHz")
|
||||
print("[3] 915 MHz")
|
||||
print("[4] 923 MHz")
|
||||
print("[1] 433 MHz (with SX1278 chip)")
|
||||
print("[2] 868/915/923 MHz (with SX1276 chip)")
|
||||
print("");
|
||||
print("[3] 433 MHz (with SX1268 chip)")
|
||||
print("[4] 868/915/923 MHz (with SX1262 chip)")
|
||||
print("\n? ", end="")
|
||||
try:
|
||||
c_model = int(input())
|
||||
@@ -1715,9 +1784,15 @@ def main():
|
||||
elif c_model == 1:
|
||||
selected_model = ROM.MODEL_E4
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
elif c_model > 1:
|
||||
elif c_model == 2:
|
||||
selected_model = ROM.MODEL_E9
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
elif c_model == 3:
|
||||
selected_model = ROM.MODEL_E3
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
elif c_model == 4:
|
||||
selected_model = ROM.MODEL_E8
|
||||
selected_platform = ROM.PLATFORM_ESP32
|
||||
except Exception as e:
|
||||
print("That band does not exist, exiting now.")
|
||||
exit()
|
||||
@@ -2098,6 +2173,42 @@ def main():
|
||||
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam.bin",
|
||||
"0x8000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam.partitions",
|
||||
]
|
||||
elif fw_filename == "rnode_firmware_tbeam_sx1262.zip":
|
||||
if numeric_version >= 1.55:
|
||||
return [
|
||||
sys.executable, flasher,
|
||||
"--chip", "esp32",
|
||||
"--port", args.port,
|
||||
"--baud", args.baud_flash,
|
||||
"--before", "default_reset",
|
||||
"--after", "hard_reset",
|
||||
"write_flash", "-z",
|
||||
"--flash_mode", "dio",
|
||||
"--flash_freq", "80m",
|
||||
"--flash_size", "4MB",
|
||||
"0xe000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam_sx1262.boot_app0",
|
||||
"0x1000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam_sx1262.bootloader",
|
||||
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam_sx1262.bin",
|
||||
"0x210000",UPD_DIR+"/"+selected_version+"/console_image.bin",
|
||||
"0x8000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam_sx1262.partitions",
|
||||
]
|
||||
else:
|
||||
return [
|
||||
sys.executable, flasher,
|
||||
"--chip", "esp32",
|
||||
"--port", args.port,
|
||||
"--baud", args.baud_flash,
|
||||
"--before", "default_reset",
|
||||
"--after", "hard_reset",
|
||||
"write_flash", "-z",
|
||||
"--flash_mode", "dio",
|
||||
"--flash_freq", "80m",
|
||||
"--flash_size", "4MB",
|
||||
"0xe000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam.boot_app0",
|
||||
"0x1000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam.bootloader",
|
||||
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam.bin",
|
||||
"0x8000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam.partitions",
|
||||
]
|
||||
elif fw_filename == "rnode_firmware_lora32v10.zip":
|
||||
if numeric_version >= 1.59:
|
||||
return [
|
||||
@@ -2386,6 +2497,24 @@ def main():
|
||||
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_ng21.bin",
|
||||
"0x8000", UPD_DIR+"/"+selected_version+"/rnode_firmware_ng21.partitions",
|
||||
]
|
||||
elif fw_filename == "rnode_firmware_t3s3.zip":
|
||||
return [
|
||||
sys.executable, flasher,
|
||||
"--chip", "esp32s3",
|
||||
"--port", args.port,
|
||||
"--baud", args.baud_flash,
|
||||
"--before", "default_reset",
|
||||
"--after", "hard_reset",
|
||||
"write_flash", "-z",
|
||||
"--flash_mode", "dio",
|
||||
"--flash_freq", "80m",
|
||||
"--flash_size", "4MB",
|
||||
"0xe000", UPD_DIR+"/"+selected_version+"/rnode_firmware_t3s3.boot_app0",
|
||||
"0x1000", UPD_DIR+"/"+selected_version+"/rnode_firmware_t3s3.bootloader",
|
||||
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_t3s3.bin",
|
||||
"0x210000",UPD_DIR+"/"+selected_version+"/console_image.bin",
|
||||
"0x8000", UPD_DIR+"/"+selected_version+"/rnode_firmware_t3s3.partitions",
|
||||
]
|
||||
elif fw_filename == "extracted_rnode_firmware.zip":
|
||||
return [
|
||||
sys.executable, flasher,
|
||||
@@ -2770,6 +2899,7 @@ def main():
|
||||
RNS.log("\tFirmware version : "+rnode.version)
|
||||
RNS.log("\tHardware revision : "+str(int(rnode.hw_rev)))
|
||||
RNS.log("\tSerial number : "+RNS.hexrep(rnode.serialno))
|
||||
RNS.log("\tModem chip : "+str(models[rnode.model][5]))
|
||||
RNS.log("\tFrequency range : "+str(rnode.min_freq/1e6)+" MHz - "+str(rnode.max_freq/1e6)+" MHz")
|
||||
RNS.log("\tMax TX power : "+str(rnode.max_output)+" dBm")
|
||||
RNS.log("\tManufactured : "+timestring)
|
||||
@@ -2857,6 +2987,10 @@ def main():
|
||||
model = ROM.MODEL_A4
|
||||
elif args.model == "a9":
|
||||
model = ROM.MODEL_A9
|
||||
elif args.model == "a1":
|
||||
model = ROM.MODEL_A1
|
||||
elif args.model == "a6":
|
||||
model = ROM.MODEL_A6
|
||||
elif args.model == "e4":
|
||||
model = ROM.MODEL_E4
|
||||
elif args.model == "e9":
|
||||
|
||||
+100
-79
@@ -33,7 +33,7 @@ from RNS._version import __version__
|
||||
DEFAULT_PROBE_SIZE = 16
|
||||
DEFAULT_TIMEOUT = 12
|
||||
|
||||
def program_setup(configdir, destination_hexhash, size=None, full_name = None, verbosity = 0, timeout=None):
|
||||
def program_setup(configdir, destination_hexhash, size=None, full_name = None, verbosity = 0, timeout=None, wait=0, probes=1):
|
||||
if size == None: size = DEFAULT_PROBE_SIZE
|
||||
if full_name == None:
|
||||
print("The full destination name including application name aspects must be specified for the destination")
|
||||
@@ -96,90 +96,106 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
||||
*aspects
|
||||
)
|
||||
|
||||
try:
|
||||
probe = RNS.Packet(request_destination, os.urandom(size))
|
||||
probe.pack()
|
||||
except OSError:
|
||||
print("Error: Probe packet size of "+str(len(probe.raw))+" bytes exceed MTU of "+str(RNS.Reticulum.MTU)+" bytes")
|
||||
exit(3)
|
||||
sent = 0
|
||||
replies = 0
|
||||
while probes:
|
||||
|
||||
receipt = probe.send()
|
||||
if sent > 0:
|
||||
time.sleep(wait)
|
||||
|
||||
if more_output:
|
||||
nhd = reticulum.get_next_hop(destination_hash)
|
||||
via_str = " via "+RNS.prettyhexrep(nhd) if nhd != None else ""
|
||||
if_str = " on "+str(reticulum.get_next_hop_if_name(destination_hash)) if reticulum.get_next_hop_if_name(destination_hash) != "None" else ""
|
||||
more = via_str+if_str
|
||||
else:
|
||||
more = ""
|
||||
try:
|
||||
probe = RNS.Packet(request_destination, os.urandom(size))
|
||||
probe.pack()
|
||||
except OSError:
|
||||
print("Error: Probe packet size of "+str(len(probe.raw))+" bytes exceed MTU of "+str(RNS.Reticulum.MTU)+" bytes")
|
||||
exit(3)
|
||||
|
||||
print("\rSent "+str(size)+" byte probe to "+RNS.prettyhexrep(destination_hash)+more+" ", end=" ")
|
||||
receipt = probe.send()
|
||||
sent += 1
|
||||
|
||||
_timeout = time.time() + (timeout or DEFAULT_TIMEOUT)
|
||||
i = 0
|
||||
while receipt.status == RNS.PacketReceipt.SENT and not time.time() > _timeout:
|
||||
time.sleep(0.1)
|
||||
print(("\b\b"+syms[i]+" "), end="")
|
||||
sys.stdout.flush()
|
||||
i = (i+1)%len(syms)
|
||||
if more_output:
|
||||
nhd = reticulum.get_next_hop(destination_hash)
|
||||
via_str = " via "+RNS.prettyhexrep(nhd) if nhd != None else ""
|
||||
if_str = " on "+str(reticulum.get_next_hop_if_name(destination_hash)) if reticulum.get_next_hop_if_name(destination_hash) != "None" else ""
|
||||
more = via_str+if_str
|
||||
else:
|
||||
more = ""
|
||||
|
||||
if time.time() > _timeout:
|
||||
print("\r \rProbe timed out")
|
||||
print("\rSent probe "+str(sent)+" ("+str(size)+" bytes) to "+RNS.prettyhexrep(destination_hash)+more+" ", end=" ")
|
||||
|
||||
_timeout = time.time() + (timeout or DEFAULT_TIMEOUT+reticulum.get_first_hop_timeout(destination_hash))
|
||||
i = 0
|
||||
while receipt.status == RNS.PacketReceipt.SENT and not time.time() > _timeout:
|
||||
time.sleep(0.1)
|
||||
print(("\b\b"+syms[i]+" "), end="")
|
||||
sys.stdout.flush()
|
||||
i = (i+1)%len(syms)
|
||||
|
||||
if time.time() > _timeout:
|
||||
print("\r \rProbe timed out")
|
||||
|
||||
else:
|
||||
print("\b\b ")
|
||||
sys.stdout.flush()
|
||||
|
||||
if receipt.status == RNS.PacketReceipt.DELIVERED:
|
||||
replies += 1
|
||||
hops = RNS.Transport.hops_to(destination_hash)
|
||||
if hops != 1:
|
||||
ms = "s"
|
||||
else:
|
||||
ms = ""
|
||||
|
||||
rtt = receipt.get_rtt()
|
||||
if (rtt >= 1):
|
||||
rtt = round(rtt, 3)
|
||||
rttstring = str(rtt)+" seconds"
|
||||
else:
|
||||
rtt = round(rtt*1000, 3)
|
||||
rttstring = str(rtt)+" milliseconds"
|
||||
|
||||
reception_stats = ""
|
||||
if reticulum.is_connected_to_shared_instance:
|
||||
reception_rssi = reticulum.get_packet_rssi(receipt.proof_packet.packet_hash)
|
||||
reception_snr = reticulum.get_packet_snr(receipt.proof_packet.packet_hash)
|
||||
reception_q = reticulum.get_packet_q(receipt.proof_packet.packet_hash)
|
||||
|
||||
if reception_rssi != None:
|
||||
reception_stats += " [RSSI "+str(reception_rssi)+" dBm]"
|
||||
|
||||
if reception_snr != None:
|
||||
reception_stats += " [SNR "+str(reception_snr)+" dB]"
|
||||
|
||||
if reception_q != None:
|
||||
reception_stats += " [Link Quality "+str(reception_q)+"%]"
|
||||
|
||||
else:
|
||||
if receipt.proof_packet != None:
|
||||
if receipt.proof_packet.rssi != None:
|
||||
reception_stats += " [RSSI "+str(receipt.proof_packet.rssi)+" dBm]"
|
||||
|
||||
if receipt.proof_packet.snr != None:
|
||||
reception_stats += " [SNR "+str(receipt.proof_packet.snr)+" dB]"
|
||||
|
||||
print(
|
||||
"Valid reply from "+
|
||||
RNS.prettyhexrep(receipt.destination.hash)+
|
||||
"\nRound-trip time is "+rttstring+
|
||||
" over "+str(hops)+" hop"+ms+
|
||||
reception_stats+"\n"
|
||||
)
|
||||
|
||||
else:
|
||||
print("\r \rProbe timed out")
|
||||
|
||||
probes -= 1
|
||||
|
||||
loss = round((1-(replies/sent))*100, 2)
|
||||
print(f"Sent {sent}, received {replies}, packet loss {loss}%")
|
||||
if loss > 0:
|
||||
exit(2)
|
||||
|
||||
print("\b\b ")
|
||||
sys.stdout.flush()
|
||||
|
||||
if receipt.status == RNS.PacketReceipt.DELIVERED:
|
||||
hops = RNS.Transport.hops_to(destination_hash)
|
||||
if hops != 1:
|
||||
ms = "s"
|
||||
else:
|
||||
ms = ""
|
||||
|
||||
rtt = receipt.get_rtt()
|
||||
if (rtt >= 1):
|
||||
rtt = round(rtt, 3)
|
||||
rttstring = str(rtt)+" seconds"
|
||||
else:
|
||||
rtt = round(rtt*1000, 3)
|
||||
rttstring = str(rtt)+" milliseconds"
|
||||
|
||||
reception_stats = ""
|
||||
if reticulum.is_connected_to_shared_instance:
|
||||
reception_rssi = reticulum.get_packet_rssi(receipt.proof_packet.packet_hash)
|
||||
reception_snr = reticulum.get_packet_snr(receipt.proof_packet.packet_hash)
|
||||
reception_q = reticulum.get_packet_q(receipt.proof_packet.packet_hash)
|
||||
|
||||
if reception_rssi != None:
|
||||
reception_stats += " [RSSI "+str(reception_rssi)+" dBm]"
|
||||
|
||||
if reception_snr != None:
|
||||
reception_stats += " [SNR "+str(reception_snr)+" dB]"
|
||||
|
||||
if reception_q != None:
|
||||
reception_stats += " [Link Quality "+str(reception_q)+"%]"
|
||||
|
||||
else:
|
||||
if receipt.proof_packet != None:
|
||||
if receipt.proof_packet.rssi != None:
|
||||
reception_stats += " [RSSI "+str(receipt.proof_packet.rssi)+" dBm]"
|
||||
|
||||
if receipt.proof_packet.snr != None:
|
||||
reception_stats += " [SNR "+str(receipt.proof_packet.snr)+" dB]"
|
||||
|
||||
print(
|
||||
"Valid reply received from "+
|
||||
RNS.prettyhexrep(receipt.destination.hash)+
|
||||
"\nRound-trip time is "+rttstring+
|
||||
" over "+str(hops)+" hop"+ms+
|
||||
reception_stats
|
||||
)
|
||||
|
||||
else:
|
||||
print("\r \rProbe timed out")
|
||||
exit(2)
|
||||
|
||||
exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
@@ -188,7 +204,9 @@ def main():
|
||||
|
||||
parser.add_argument("--config", action="store", default=None, help="path to alternative Reticulum config directory", type=str)
|
||||
parser.add_argument("-s", "--size", action="store", default=None, help="size of probe packet payload in bytes", type=int)
|
||||
parser.add_argument("-n", "--probes", action="store", default=1, help="number of probes to send", type=int)
|
||||
parser.add_argument("-t", "--timeout", metavar="seconds", action="store", default=None, help="timeout before giving up", type=float)
|
||||
parser.add_argument("-w", "--wait", metavar="seconds", action="store", default=0, help="time between each probe", type=float)
|
||||
parser.add_argument("--version", action="version", version="rnprobe {version}".format(version=__version__))
|
||||
parser.add_argument("full_name", nargs="?", default=None, help="full destination name in dotted notation", type=str)
|
||||
parser.add_argument("destination_hash", nargs="?", default=None, help="hexadecimal hash of the destination", type=str)
|
||||
@@ -212,7 +230,10 @@ def main():
|
||||
destination_hexhash = args.destination_hash,
|
||||
size = args.size,
|
||||
full_name = args.full_name,
|
||||
verbosity = args.verbose
|
||||
verbosity = args.verbose,
|
||||
probes = args.probes,
|
||||
wait = args.wait,
|
||||
timeout = args.timeout,
|
||||
)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
|
||||
@@ -144,6 +144,12 @@ def rand():
|
||||
result = instance_random.random()
|
||||
return result
|
||||
|
||||
def trace_exception(e):
|
||||
import traceback
|
||||
exception_info = "".join(traceback.TracebackException.from_exception(e).format())
|
||||
log(f"An unhandled {str(type(e))} exception occurred: {str(e)}", LOG_ERROR)
|
||||
log(exception_info, LOG_ERROR)
|
||||
|
||||
def hexrep(data, delimit=True):
|
||||
try:
|
||||
iter(data)
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
__version__ = "0.6.3"
|
||||
__version__ = "0.7.1"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -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: 0b876c3067e5139f29cbcb2f2791dd69
|
||||
config: ea2e78e752b7110746ccd0d4052a8cac
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||
VERSION: '0.6.3 beta',
|
||||
VERSION: '0.7.1 beta',
|
||||
LANGUAGE: 'en',
|
||||
COLLAPSE_INDEX: false,
|
||||
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" />
|
||||
|
||||
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>Code Examples - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>Code Examples - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -3084,8 +3084,7 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
|
||||
<span class="c1"># And set up a small job to check for</span>
|
||||
<span class="c1"># a potential timeout in receiving the</span>
|
||||
<span class="c1"># file list</span>
|
||||
<span class="n">thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">filelist_timeout_job</span><span class="p">)</span>
|
||||
<span class="n">thread</span><span class="o">.</span><span class="n">setDaemon</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="n">thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">filelist_timeout_job</span><span class="p">,</span> <span class="n">daemon</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="n">thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||||
|
||||
<span class="c1"># This job just sleeps for the specified</span>
|
||||
@@ -3322,7 +3321,7 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -257,7 +257,7 @@
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/><title>Index - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/><title>Index - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -139,7 +139,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -735,7 +735,7 @@
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>Getting Started Fast - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>Getting Started Fast - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -758,7 +758,7 @@ section of this manual.</p>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>Communications Hardware - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>Communications Hardware - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -519,7 +519,7 @@ can be used with Reticulum. This includes virtual software modems such as
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="#"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="#"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -468,7 +468,7 @@ to participate in the development of Reticulum itself.</p>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>Configuring Interfaces - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>Configuring Interfaces - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -1106,7 +1106,7 @@ to <code class="docutils literal notranslate"><span class="pre">30</span></code>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>Building Networks - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>Building Networks - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -467,7 +467,7 @@ connected outliers are now an integral part of the network.</p>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
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" />
|
||||
|
||||
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>API Reference - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>API Reference - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -1006,7 +1006,7 @@ and encrypted connectivity with the specified destination.</p>
|
||||
|
||||
<dl class="py attribute">
|
||||
<dt class="sig sig-object py" id="RNS.Link.ESTABLISHMENT_TIMEOUT_PER_HOP">
|
||||
<span class="sig-name descname"><span class="pre">ESTABLISHMENT_TIMEOUT_PER_HOP</span></span><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">4</span></em><a class="headerlink" href="#RNS.Link.ESTABLISHMENT_TIMEOUT_PER_HOP" title="Permalink to this definition">#</a></dt>
|
||||
<span class="sig-name descname"><span class="pre">ESTABLISHMENT_TIMEOUT_PER_HOP</span></span><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">6</span></em><a class="headerlink" href="#RNS.Link.ESTABLISHMENT_TIMEOUT_PER_HOP" title="Permalink to this definition">#</a></dt>
|
||||
<dd><p>Timeout for link establishment in seconds per hop to destination.</p>
|
||||
</dd></dl>
|
||||
|
||||
@@ -2078,7 +2078,7 @@ will announce it.</p>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/><title>Search - Reticulum Network Stack 0.6.3 beta documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/><title>Search - Reticulum Network Stack 0.7.1 beta documentation</title><link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
<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.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -262,7 +262,7 @@
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
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" />
|
||||
|
||||
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>Support Reticulum - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>Support Reticulum - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -330,7 +330,7 @@ report issues, suggest functionality and contribute code to Reticulum.</p>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>Understanding Reticulum - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>Understanding Reticulum - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -1196,7 +1196,7 @@ those risks are acceptable to you.</p>
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>Using Reticulum on Your System - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>Using Reticulum on Your System - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -1057,7 +1057,7 @@ systemctl --user enable rnsd.service
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
@@ -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-7.1.2, furo 2022.09.29.dev1"/>
|
||||
<title>What is Reticulum? - Reticulum Network Stack 0.6.3 beta documentation</title>
|
||||
<title>What is Reticulum? - Reticulum Network Stack 0.7.1 beta documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||||
@@ -141,7 +141,7 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="header-center">
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.3 beta documentation</div></a>
|
||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.1 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.6.3 beta documentation</span>
|
||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.1 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">
|
||||
@@ -434,7 +434,7 @@ want to help out with this, or can help sponsor an audit, please do get in touch
|
||||
|
||||
</aside>
|
||||
</div>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=b3dc24d1"></script>
|
||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=2ae4a12b"></script>
|
||||
<script src="_static/doctools.js?v=888ff710"></script>
|
||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||
|
||||
+29
-4
@@ -140,6 +140,7 @@ class TestLink(unittest.TestCase):
|
||||
pstart = time.time()
|
||||
print("Sending "+str(num_packets)+" link packets of "+str(packet_size)+" bytes...")
|
||||
for i in range(0, num_packets):
|
||||
time.sleep(0.003)
|
||||
b += packet_size
|
||||
data = os.urandom(packet_size)
|
||||
start = time.time()
|
||||
@@ -188,6 +189,9 @@ class TestLink(unittest.TestCase):
|
||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||
self.assertEqual(id1.hash, bytes.fromhex(fixed_keys[0][1]))
|
||||
|
||||
RNS.Transport.request_path(bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||
time.sleep(0.2)
|
||||
|
||||
dest = RNS.Destination(id1, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, "link", "establish")
|
||||
|
||||
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||
@@ -203,6 +207,7 @@ class TestLink(unittest.TestCase):
|
||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||
start = time.time()
|
||||
|
||||
# This is a hack, don't do it. Use the callbacks instead.
|
||||
while resource.status < RNS.Resource.COMPLETE:
|
||||
time.sleep(0.01)
|
||||
|
||||
@@ -224,6 +229,9 @@ class TestLink(unittest.TestCase):
|
||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||
self.assertEqual(id1.hash, bytes.fromhex(fixed_keys[0][1]))
|
||||
|
||||
RNS.Transport.request_path(bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||
time.sleep(0.2)
|
||||
|
||||
dest = RNS.Destination(id1, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, "link", "establish")
|
||||
|
||||
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||
@@ -239,6 +247,7 @@ class TestLink(unittest.TestCase):
|
||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||
start = time.time()
|
||||
|
||||
# This is a hack, don't do it. Use the callbacks instead.
|
||||
while resource.status < RNS.Resource.COMPLETE:
|
||||
time.sleep(0.01)
|
||||
|
||||
@@ -260,6 +269,9 @@ class TestLink(unittest.TestCase):
|
||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||
self.assertEqual(id1.hash, bytes.fromhex(fixed_keys[0][1]))
|
||||
|
||||
RNS.Transport.request_path(bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||
time.sleep(0.2)
|
||||
|
||||
dest = RNS.Destination(id1, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, "link", "establish")
|
||||
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||
|
||||
@@ -274,6 +286,7 @@ class TestLink(unittest.TestCase):
|
||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||
start = time.time()
|
||||
|
||||
# This is a hack, don't do it. Use the callbacks instead.
|
||||
while resource.status < RNS.Resource.COMPLETE:
|
||||
time.sleep(0.01)
|
||||
|
||||
@@ -300,6 +313,9 @@ class TestLink(unittest.TestCase):
|
||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||
self.assertEqual(id1.hash, bytes.fromhex(fixed_keys[0][1]))
|
||||
|
||||
RNS.Transport.request_path(bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||
time.sleep(0.2)
|
||||
|
||||
dest = RNS.Destination(id1, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, "link", "establish")
|
||||
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||
|
||||
@@ -314,6 +330,7 @@ class TestLink(unittest.TestCase):
|
||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||
start = time.time()
|
||||
|
||||
# This is a hack, don't do it. Use the callbacks instead.
|
||||
while resource.status < RNS.Resource.COMPLETE:
|
||||
time.sleep(0.01)
|
||||
|
||||
@@ -325,6 +342,10 @@ class TestLink(unittest.TestCase):
|
||||
time.sleep(0.5)
|
||||
self.assertEqual(l1.status, RNS.Link.CLOSED)
|
||||
|
||||
large_resource_status = None
|
||||
def lr_callback(self, resource):
|
||||
TestLink.large_resource_status = resource.status
|
||||
|
||||
@skipIf(os.getenv('SKIP_NORMAL_TESTS') != None, "Skipping")
|
||||
def test_9_large_resource(self):
|
||||
if RNS.Cryptography.backend() == "internal":
|
||||
@@ -339,6 +360,9 @@ class TestLink(unittest.TestCase):
|
||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||
self.assertEqual(id1.hash, bytes.fromhex(fixed_keys[0][1]))
|
||||
|
||||
RNS.Transport.request_path(bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||
time.sleep(0.2)
|
||||
|
||||
dest = RNS.Destination(id1, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, "link", "establish")
|
||||
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||
|
||||
@@ -347,17 +371,18 @@ class TestLink(unittest.TestCase):
|
||||
self.assertEqual(l1.status, RNS.Link.ACTIVE)
|
||||
|
||||
resource_timeout = 120
|
||||
resource_size = 35*1000*1000
|
||||
resource_size = 50*1000*1000
|
||||
data = os.urandom(resource_size)
|
||||
print("Sending "+self.size_str(resource_size)+" resource...")
|
||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||
resource = RNS.Resource(data, l1, timeout=resource_timeout, callback=self.lr_callback)
|
||||
start = time.time()
|
||||
|
||||
while resource.status < RNS.Resource.COMPLETE:
|
||||
TestLink.large_resource_status = resource.status
|
||||
while TestLink.large_resource_status < RNS.Resource.COMPLETE:
|
||||
time.sleep(0.01)
|
||||
|
||||
t = time.time() - start
|
||||
self.assertEqual(resource.status, RNS.Resource.COMPLETE)
|
||||
self.assertEqual(TestLink.large_resource_status, RNS.Resource.COMPLETE)
|
||||
print("Resource completed at "+self.size_str(resource_size/t, "b")+"ps")
|
||||
|
||||
l1.teardown()
|
||||
|
||||
Reference in New Issue
Block a user