mirror of
https://github.com/markqvist/Reticulum.git
synced 2026-07-19 14:48:09 -07:00
Compare commits
91 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ace0d997d4 | |||
| 798c252284 | |||
| 7da22c8580 | |||
| eefbb89cde | |||
| 18f50ff1ae | |||
| 05e97ac0db | |||
| c2c3a144d2 | |||
| ea369015ee | |||
| 9745842862 | |||
| 246289c52d | |||
| ff71cb2f98 | |||
| 5ca1ef1777 | |||
| 2b764b4af8 | |||
| a62843cd75 | |||
| 633435390d | |||
| 1e207ef972 | |||
| 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 |
@@ -0,0 +1,11 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: ✨ Feature Request or Idea
|
||||||
|
url: https://github.com/markqvist/Reticulum/discussions/new?category=ideas
|
||||||
|
about: Propose and discuss features and ideas
|
||||||
|
- name: 💬 Questions, Help & Discussion
|
||||||
|
about: Ask anything, or get help
|
||||||
|
url: https://github.com/markqvist/Reticulum/discussions/new/choose
|
||||||
|
- name: 📖 Read the Reticulum Manual
|
||||||
|
url: https://markqvist.github.io/Reticulum/manual/
|
||||||
|
about: The complete documentation for Reticulum
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
name: "\U0001F41B Bug Report"
|
||||||
|
about: Report a reproducible bug
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Read the Contribution Guidelines**
|
||||||
|
Before creating a bug report on this issue tracker, you **must** read the [Contribution Guidelines](https://github.com/markqvist/Reticulum/blob/master/Contributing.md). Issues that do not follow the contribution guidelines **will be deleted without comment**.
|
||||||
|
|
||||||
|
- The issue tracker is used by developers of this project. **Do not use it to ask general questions, or for support requests**.
|
||||||
|
- Ideas and feature requests can be made on the [Discussions](https://github.com/markqvist/Reticulum/discussions). **Only** feature requests accepted by maintainers and developers are tracked and included on the issue tracker. **Do not post feature requests here**.
|
||||||
|
- After reading the [Contribution Guidelines](https://github.com/markqvist/Reticulum/blob/master/Contributing.md), delete this section from your bug report.
|
||||||
|
|
||||||
|
**Describe the Bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Describe in detail how to reproduce the bug.
|
||||||
|
|
||||||
|
**Expected Behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Logs & Screenshots**
|
||||||
|
Please include any relevant log output. If applicable, also add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**System Information**
|
||||||
|
- OS and version
|
||||||
|
- Python version
|
||||||
|
- Program version
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
+121
-1
@@ -1,3 +1,123 @@
|
|||||||
|
### 2024-03-02: RNS β 0.7.2
|
||||||
|
|
||||||
|
This maintenance release improves memory consumption, fixes a few bugs, and adds ability to flash new boards with `rnodeconf`.
|
||||||
|
|
||||||
|
**Changes**
|
||||||
|
- Added ability to flash new boards with `rnodeconf`, including T3 boards with TCXOs
|
||||||
|
- Improved memory consumption on Transport Instances with many interfaces
|
||||||
|
- Fixed a bug that could cause the on-disk known destinations store to become corrupted
|
||||||
|
|
||||||
|
**Release Hashes**
|
||||||
|
```
|
||||||
|
3ce3ba80d5ae8d19c6b55bd51f44bd4beccbcea31554cb1f0d65428e4587b3d6 rns-0.7.2-py3-none-any.whl
|
||||||
|
83f914aaba2a8929a8cee95830a847e190197232a0cca4e7b906b15c6bbf8296 rnspure-0.7.2-py3-none-any.whl
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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
|
### 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.
|
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.
|
||||||
@@ -990,4 +1110,4 @@ This was the first publicly available pre-release alpha of Reticulum.
|
|||||||
|
|
||||||
### 2016-05-29: Inintial Repository Commit
|
### 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!
|
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
|
## 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
|
## 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
|
## Writing Code
|
||||||
|
|
||||||
|
|||||||
@@ -449,8 +449,7 @@ def link_established(link):
|
|||||||
# And set up a small job to check for
|
# And set up a small job to check for
|
||||||
# a potential timeout in receiving the
|
# a potential timeout in receiving the
|
||||||
# file list
|
# file list
|
||||||
thread = threading.Thread(target=filelist_timeout_job)
|
thread = threading.Thread(target=filelist_timeout_job, daemon=True)
|
||||||
thread.setDaemon(True)
|
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
# This job just sleeps for the specified
|
# 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
|
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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
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.
|
per second on normal hardware.
|
||||||
|
|
||||||
Currently, the usable performance envelope is approximately 150 bits per second
|
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
|
saturated. Performance beyond the current level is intended for future
|
||||||
upgrades, but not highly prioritised at this point in time.
|
upgrades, but not highly prioritised at this point in time.
|
||||||
|
|
||||||
@@ -273,16 +273,16 @@ The testnet also contains a number of [Nomad Network](https://github.com/markqvi
|
|||||||
You can help support the continued development of open, free and private communications systems by donating via one of the following channels:
|
You can help support the continued development of open, free and private communications systems by donating via one of the following channels:
|
||||||
|
|
||||||
- Monero:
|
- Monero:
|
||||||
```
|
```
|
||||||
84FpY1QbxHcgdseePYNmhTHcrgMX4nFfBYtz2GKYToqHVVhJp8Eaw1Z1EedRnKD19b3B8NiLCGVxzKV17UMmmeEsCrPyA5w
|
84FpY1QbxHcgdseePYNmhTHcrgMX4nFfBYtz2GKYToqHVVhJp8Eaw1Z1EedRnKD19b3B8NiLCGVxzKV17UMmmeEsCrPyA5w
|
||||||
```
|
```
|
||||||
- Ethereum
|
- Ethereum
|
||||||
```
|
```
|
||||||
0x81F7B979fEa6134bA9FD5c701b3501A2e61E897a
|
0xFDabC71AC4c0C78C95aDDDe3B4FA19d6273c5E73
|
||||||
```
|
```
|
||||||
- Bitcoin
|
- Bitcoin
|
||||||
```
|
```
|
||||||
3CPmacGm34qYvR6XWLVEJmi2aNe3PZqUuq
|
35G9uWVzrpJJibzUwpNUQGQNFzLirhrYAH
|
||||||
```
|
```
|
||||||
- Ko-Fi: https://ko-fi.com/markqvist
|
- Ko-Fi: https://ko-fi.com/markqvist
|
||||||
|
|
||||||
|
|||||||
+9
-4
@@ -145,9 +145,12 @@ class Identity:
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
for destination_hash in storage_known_destinations:
|
try:
|
||||||
if not destination_hash in Identity.known_destinations:
|
for destination_hash in storage_known_destinations:
|
||||||
Identity.known_destinations[destination_hash] = storage_known_destinations[destination_hash]
|
if not destination_hash in Identity.known_destinations:
|
||||||
|
Identity.known_destinations[destination_hash] = storage_known_destinations[destination_hash]
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("Skipped recombining known destinations from disk, since an error occurred: "+str(e), RNS.LOG_WARNING)
|
||||||
|
|
||||||
RNS.log("Saving "+str(len(Identity.known_destinations))+" known destinations to storage...", RNS.LOG_DEBUG)
|
RNS.log("Saving "+str(len(Identity.known_destinations))+" known destinations to storage...", RNS.LOG_DEBUG)
|
||||||
file = open(RNS.Reticulum.storagepath+"/known_destinations","wb")
|
file = open(RNS.Reticulum.storagepath+"/known_destinations","wb")
|
||||||
@@ -164,6 +167,7 @@ class Identity:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while saving known destinations to disk, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Error while saving known destinations to disk, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
RNS.trace_exception(e)
|
||||||
|
|
||||||
Identity.saving_known_destinations = False
|
Identity.saving_known_destinations = False
|
||||||
|
|
||||||
@@ -181,7 +185,8 @@ class Identity:
|
|||||||
Identity.known_destinations[known_destination] = loaded_known_destinations[known_destination]
|
Identity.known_destinations[known_destination] = loaded_known_destinations[known_destination]
|
||||||
|
|
||||||
RNS.log("Loaded "+str(len(Identity.known_destinations))+" known destination from storage", RNS.LOG_VERBOSE)
|
RNS.log("Loaded "+str(len(Identity.known_destinations))+" known destination from storage", RNS.LOG_VERBOSE)
|
||||||
except:
|
|
||||||
|
except Exception as e:
|
||||||
RNS.log("Error loading known destinations from disk, file will be recreated on exit", RNS.LOG_ERROR)
|
RNS.log("Error loading known destinations from disk, file will be recreated on exit", RNS.LOG_ERROR)
|
||||||
else:
|
else:
|
||||||
RNS.log("Destinations file does not exist, no known destinations loaded", RNS.LOG_VERBOSE)
|
RNS.log("Destinations file does not exist, no known destinations loaded", RNS.LOG_VERBOSE)
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class AndroidBluetoothManager():
|
|||||||
if self.bt_enabled():
|
if self.bt_enabled():
|
||||||
return self.bt_adapter.getDefaultAdapter().getBondedDevices()
|
return self.bt_adapter.getDefaultAdapter().getBondedDevices()
|
||||||
else:
|
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 []
|
return []
|
||||||
|
|
||||||
def get_potential_devices(self):
|
def get_potential_devices(self):
|
||||||
@@ -167,8 +167,8 @@ class AndroidBluetoothManager():
|
|||||||
raise IOError("The Bluetooth RFcomm socket could not be connected: "+str(e))
|
raise IOError("The Bluetooth RFcomm socket could not be connected: "+str(e))
|
||||||
|
|
||||||
except Exception as 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("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_DEBUG)
|
RNS.log("The contained exception was: "+str(e), RNS.LOG_EXTREME)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.connected:
|
if self.connected:
|
||||||
|
|||||||
@@ -334,6 +334,8 @@ class AutoInterface(Interface):
|
|||||||
thread.daemon = True
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
self.carrier_changed = True
|
||||||
|
|
||||||
except Exception as e:
|
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)
|
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.txb = 0
|
||||||
self.created = time.time()
|
self.created = time.time()
|
||||||
self.online = False
|
self.online = False
|
||||||
|
self.bitrate = 1e6
|
||||||
|
|
||||||
self.ingress_control = True
|
self.ingress_control = True
|
||||||
self.ic_max_held_announces = Interface.MAX_HELD_ANNOUNCES
|
self.ic_max_held_announces = Interface.MAX_HELD_ANNOUNCES
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ class LocalClientInterface(Interface):
|
|||||||
self.target_ip = None
|
self.target_ip = None
|
||||||
self.target_port = None
|
self.target_port = None
|
||||||
self.socket = connected_socket
|
self.socket = connected_socket
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||||
|
|
||||||
self.is_connected_to_shared_instance = False
|
self.is_connected_to_shared_instance = False
|
||||||
|
|
||||||
@@ -108,6 +109,7 @@ class LocalClientInterface(Interface):
|
|||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
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.socket.connect((self.target_ip, self.target_port))
|
||||||
|
|
||||||
self.online = True
|
self.online = True
|
||||||
@@ -270,7 +272,8 @@ class LocalClientInterface(Interface):
|
|||||||
RNS.Transport.local_client_interfaces.remove(self)
|
RNS.Transport.local_client_interfaces.remove(self)
|
||||||
if hasattr(self, "parent_interface") and self.parent_interface != None:
|
if hasattr(self, "parent_interface") and self.parent_interface != None:
|
||||||
self.parent_interface.clients -= 1
|
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:
|
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)
|
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)
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class RNodeInterface(Interface):
|
|||||||
MAX_CHUNK = 32768
|
MAX_CHUNK = 32768
|
||||||
|
|
||||||
FREQ_MIN = 137000000
|
FREQ_MIN = 137000000
|
||||||
FREQ_MAX = 1020000000
|
FREQ_MAX = 3000000000
|
||||||
|
|
||||||
RSSI_OFFSET = 157
|
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):
|
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():
|
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
|
import importlib
|
||||||
if importlib.util.find_spec('serial') != None:
|
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)
|
RNS.log("Invalid frequency configured for "+str(self), RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
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)
|
RNS.log("Invalid TX power configured for "+str(self), RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
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)
|
RNS.log("Invalid bandwidth configured for "+str(self), RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
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)
|
RNS.log("Invalid spreading factor configured for "+str(self), RNS.LOG_ERROR)
|
||||||
self.validcfg = False
|
self.validcfg = False
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,8 @@ class TCPClientInterface(Interface):
|
|||||||
elif platform.system() == "Darwin":
|
elif platform.system() == "Darwin":
|
||||||
self.set_timeouts_osx()
|
self.set_timeouts_osx()
|
||||||
|
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||||
|
|
||||||
elif target_ip != None and target_port != None:
|
elif target_ip != None and target_port != None:
|
||||||
self.receives = True
|
self.receives = True
|
||||||
self.target_ip = target_ip
|
self.target_ip = target_ip
|
||||||
@@ -200,6 +202,7 @@ class TCPClientInterface(Interface):
|
|||||||
|
|
||||||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.socket.settimeout(TCPClientInterface.INITIAL_CONNECT_TIMEOUT)
|
self.socket.settimeout(TCPClientInterface.INITIAL_CONNECT_TIMEOUT)
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||||
self.socket.connect((self.target_ip, self.target_port))
|
self.socket.connect((self.target_ip, self.target_port))
|
||||||
self.socket.settimeout(None)
|
self.socket.settimeout(None)
|
||||||
self.online = True
|
self.online = True
|
||||||
|
|||||||
+54
-45
@@ -124,7 +124,7 @@ class Link:
|
|||||||
link.last_inbound = time.time()
|
link.last_inbound = time.time()
|
||||||
link.start_watchdog()
|
link.start_watchdog()
|
||||||
|
|
||||||
RNS.log("Incoming link request "+str(link)+" accepted", RNS.LOG_VERBOSE)
|
RNS.log("Incoming link request "+str(link)+" accepted", RNS.LOG_DEBUG)
|
||||||
return link
|
return link
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -133,7 +133,7 @@ class Link:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
RNS.log("Invalid link request payload size, dropping request", RNS.LOG_VERBOSE)
|
RNS.log("Invalid link request payload size, dropping request", RNS.LOG_DEBUG)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -150,6 +150,7 @@ class Link:
|
|||||||
self.last_inbound = 0
|
self.last_inbound = 0
|
||||||
self.last_outbound = 0
|
self.last_outbound = 0
|
||||||
self.last_proof = 0
|
self.last_proof = 0
|
||||||
|
self.last_data = 0
|
||||||
self.tx = 0
|
self.tx = 0
|
||||||
self.rx = 0
|
self.rx = 0
|
||||||
self.txbytes = 0
|
self.txbytes = 0
|
||||||
@@ -352,7 +353,7 @@ class Link:
|
|||||||
packed_request = umsgpack.packb(unpacked_request)
|
packed_request = umsgpack.packb(unpacked_request)
|
||||||
|
|
||||||
if timeout == None:
|
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:
|
if len(packed_request) <= Link.MDU:
|
||||||
request_packet = RNS.Packet(self, packed_request, RNS.Packet.DATA, context = RNS.Packet.REQUEST)
|
request_packet = RNS.Packet(self, packed_request, RNS.Packet.DATA, context = RNS.Packet.REQUEST)
|
||||||
@@ -460,7 +461,7 @@ class Link:
|
|||||||
|
|
||||||
def no_inbound_for(self):
|
def no_inbound_for(self):
|
||||||
"""
|
"""
|
||||||
:returns: The time in seconds since last inbound packet on the link.
|
:returns: The time in seconds since last inbound packet on the link. This includes keepalive packets.
|
||||||
"""
|
"""
|
||||||
activated_at = self.activated_at if self.activated_at != None else 0
|
activated_at = self.activated_at if self.activated_at != None else 0
|
||||||
last_inbound = max(self.last_inbound, activated_at)
|
last_inbound = max(self.last_inbound, activated_at)
|
||||||
@@ -468,13 +469,19 @@ class Link:
|
|||||||
|
|
||||||
def no_outbound_for(self):
|
def no_outbound_for(self):
|
||||||
"""
|
"""
|
||||||
:returns: The time in seconds since last outbound packet on the link.
|
:returns: The time in seconds since last outbound packet on the link. This includes keepalive packets.
|
||||||
"""
|
"""
|
||||||
return time.time() - self.last_outbound
|
return time.time() - self.last_outbound
|
||||||
|
|
||||||
|
def no_data_for(self):
|
||||||
|
"""
|
||||||
|
:returns: The time in seconds since payload data traversed the link. This excludes keepalive packets.
|
||||||
|
"""
|
||||||
|
return time.time() - self.last_data
|
||||||
|
|
||||||
def inactive_for(self):
|
def inactive_for(self):
|
||||||
"""
|
"""
|
||||||
:returns: The time in seconds since activity on the link.
|
:returns: The time in seconds since activity on the link. This includes keepalive packets.
|
||||||
"""
|
"""
|
||||||
return min(self.no_inbound_for(), self.no_outbound_for())
|
return min(self.no_inbound_for(), self.no_outbound_for())
|
||||||
|
|
||||||
@@ -484,8 +491,10 @@ class Link:
|
|||||||
"""
|
"""
|
||||||
return self.__remote_identity
|
return self.__remote_identity
|
||||||
|
|
||||||
def had_outbound(self):
|
def had_outbound(self, is_keepalive=False):
|
||||||
self.last_outbound = time.time()
|
self.last_outbound = time.time()
|
||||||
|
if not is_keepalive:
|
||||||
|
self.last_data = self.last_outbound
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
"""
|
"""
|
||||||
@@ -636,7 +645,7 @@ class Link:
|
|||||||
def send_keepalive(self):
|
def send_keepalive(self):
|
||||||
keepalive_packet = RNS.Packet(self, bytes([0xFF]), context=RNS.Packet.KEEPALIVE)
|
keepalive_packet = RNS.Packet(self, bytes([0xFF]), context=RNS.Packet.KEEPALIVE)
|
||||||
keepalive_packet.send()
|
keepalive_packet.send()
|
||||||
self.had_outbound()
|
self.had_outbound(is_keepalive = True)
|
||||||
|
|
||||||
def handle_request(self, request_id, unpacked_request):
|
def handle_request(self, request_id, unpacked_request):
|
||||||
if self.status == Link.ACTIVE:
|
if self.status == Link.ACTIVE:
|
||||||
@@ -687,7 +696,9 @@ class Link:
|
|||||||
remove = pending_request
|
remove = pending_request
|
||||||
try:
|
try:
|
||||||
pending_request.response_size = response_size
|
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)
|
pending_request.response_received(response_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error occurred while handling response. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Error occurred while handling response. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
@@ -740,6 +751,8 @@ class Link:
|
|||||||
RNS.log("Link-associated packet received on unexpected interface! Someone might be trying to manipulate your communication!", RNS.LOG_ERROR)
|
RNS.log("Link-associated packet received on unexpected interface! Someone might be trying to manipulate your communication!", RNS.LOG_ERROR)
|
||||||
else:
|
else:
|
||||||
self.last_inbound = time.time()
|
self.last_inbound = time.time()
|
||||||
|
if packet.context != RNS.Packet.KEEPALIVE:
|
||||||
|
self.last_data = self.last_inbound
|
||||||
self.rx += 1
|
self.rx += 1
|
||||||
self.rxbytes += len(packet.data)
|
self.rxbytes += len(packet.data)
|
||||||
if self.status == Link.STALE:
|
if self.status == Link.STALE:
|
||||||
@@ -834,10 +847,17 @@ class Link:
|
|||||||
request_id = RNS.ResourceAdvertisement.read_request_id(packet)
|
request_id = RNS.ResourceAdvertisement.read_request_id(packet)
|
||||||
for pending_request in self.pending_requests:
|
for pending_request in self.pending_requests:
|
||||||
if pending_request.request_id == request_id:
|
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)
|
response_resource = 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)
|
if response_resource != None:
|
||||||
pending_request.response_transfer_size = RNS.ResourceAdvertisement.read_transfer_size(packet)
|
if pending_request.response_size == None:
|
||||||
pending_request.started_at = time.time()
|
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:
|
elif self.resource_strategy == Link.ACCEPT_NONE:
|
||||||
pass
|
pass
|
||||||
elif self.resource_strategy == Link.ACCEPT_APP:
|
elif self.resource_strategy == Link.ACCEPT_APP:
|
||||||
@@ -891,7 +911,7 @@ class Link:
|
|||||||
if not self.initiator and packet.data == bytes([0xFF]):
|
if not self.initiator and packet.data == bytes([0xFF]):
|
||||||
keepalive_packet = RNS.Packet(self, bytes([0xFE]), context=RNS.Packet.KEEPALIVE)
|
keepalive_packet = RNS.Packet(self, bytes([0xFE]), context=RNS.Packet.KEEPALIVE)
|
||||||
keepalive_packet.send()
|
keepalive_packet.send()
|
||||||
self.had_outbound()
|
self.had_outbound(is_keepalive = True)
|
||||||
|
|
||||||
|
|
||||||
# TODO: find the most efficient way to allow multiple
|
# TODO: find the most efficient way to allow multiple
|
||||||
@@ -907,20 +927,6 @@ class Link:
|
|||||||
if not self._channel:
|
if not self._channel:
|
||||||
RNS.log(f"Channel data received without open channel", RNS.LOG_DEBUG)
|
RNS.log(f"Channel data received without open channel", RNS.LOG_DEBUG)
|
||||||
else:
|
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()
|
packet.prove()
|
||||||
plaintext = self.decrypt(packet.data)
|
plaintext = self.decrypt(packet.data)
|
||||||
if plaintext != None:
|
if plaintext != None:
|
||||||
@@ -1144,7 +1150,8 @@ class RequestReceipt():
|
|||||||
def request_resource_concluded(self, resource):
|
def request_resource_concluded(self, resource):
|
||||||
if resource.status == RNS.Resource.COMPLETE:
|
if resource.status == RNS.Resource.COMPLETE:
|
||||||
RNS.log("Request "+RNS.prettyhexrep(self.request_id)+" successfully sent as resource.", RNS.LOG_DEBUG)
|
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.status = RequestReceipt.DELIVERED
|
||||||
self.__resource_response_timeout = time.time()+self.timeout
|
self.__resource_response_timeout = time.time()+self.timeout
|
||||||
response_timeout_thread = threading.Thread(target=self.__response_timeout_job)
|
response_timeout_thread = threading.Thread(target=self.__response_timeout_job)
|
||||||
@@ -1185,24 +1192,26 @@ class RequestReceipt():
|
|||||||
|
|
||||||
|
|
||||||
def response_resource_progress(self, resource):
|
def response_resource_progress(self, resource):
|
||||||
if not self.status == RequestReceipt.FAILED:
|
if resource != None:
|
||||||
self.status = RequestReceipt.RECEIVING
|
if not self.status == RequestReceipt.FAILED:
|
||||||
if self.packet_receipt != None:
|
self.status = RequestReceipt.RECEIVING
|
||||||
self.packet_receipt.status = RNS.PacketReceipt.DELIVERED
|
if self.packet_receipt != None:
|
||||||
self.packet_receipt.proved = True
|
if self.packet_receipt.status != RNS.PacketReceipt.DELIVERED:
|
||||||
self.packet_receipt.concluded_at = time.time()
|
self.packet_receipt.status = RNS.PacketReceipt.DELIVERED
|
||||||
if self.packet_receipt.callbacks.delivery != None:
|
self.packet_receipt.proved = True
|
||||||
self.packet_receipt.callbacks.delivery(self.packet_receipt)
|
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()
|
self.progress = resource.get_progress()
|
||||||
|
|
||||||
if self.callbacks.progress != None:
|
if self.callbacks.progress != None:
|
||||||
try:
|
try:
|
||||||
self.callbacks.progress(self)
|
self.callbacks.progress(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing response progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Error while executing response progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
else:
|
else:
|
||||||
resource.cancel()
|
resource.cancel()
|
||||||
|
|
||||||
|
|
||||||
def response_received(self, response):
|
def response_received(self, response):
|
||||||
|
|||||||
+118
-92
@@ -25,7 +25,9 @@ import os
|
|||||||
import bz2
|
import bz2
|
||||||
import math
|
import math
|
||||||
import time
|
import time
|
||||||
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
|
from threading import Lock
|
||||||
from .vendor import umsgpack as umsgpack
|
from .vendor import umsgpack as umsgpack
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
@@ -47,7 +49,7 @@ class Resource:
|
|||||||
WINDOW = 4
|
WINDOW = 4
|
||||||
|
|
||||||
# Absolute minimum window size during transfer
|
# Absolute minimum window size during transfer
|
||||||
WINDOW_MIN = 1
|
WINDOW_MIN = 2
|
||||||
|
|
||||||
# The maximum window size for transfers on slow links
|
# The maximum window size for transfers on slow links
|
||||||
WINDOW_MAX_SLOW = 10
|
WINDOW_MAX_SLOW = 10
|
||||||
@@ -103,9 +105,10 @@ class Resource:
|
|||||||
|
|
||||||
PART_TIMEOUT_FACTOR = 4
|
PART_TIMEOUT_FACTOR = 4
|
||||||
PART_TIMEOUT_FACTOR_AFTER_RTT = 2
|
PART_TIMEOUT_FACTOR_AFTER_RTT = 2
|
||||||
MAX_RETRIES = 8
|
MAX_RETRIES = 16
|
||||||
MAX_ADV_RETRIES = 4
|
MAX_ADV_RETRIES = 4
|
||||||
SENDER_GRACE_TIME = 10
|
SENDER_GRACE_TIME = 10.0
|
||||||
|
PROCESSING_GRACE = 1.0
|
||||||
RETRY_GRACE_TIME = 0.25
|
RETRY_GRACE_TIME = 0.25
|
||||||
PER_RETRY_DELAY = 0.5
|
PER_RETRY_DELAY = 0.5
|
||||||
|
|
||||||
@@ -167,10 +170,8 @@ class Resource:
|
|||||||
resource.hashmap = [None] * resource.total_parts
|
resource.hashmap = [None] * resource.total_parts
|
||||||
resource.hashmap_height = 0
|
resource.hashmap_height = 0
|
||||||
resource.waiting_for_hmu = False
|
resource.waiting_for_hmu = False
|
||||||
|
|
||||||
resource.receiving_part = False
|
resource.receiving_part = False
|
||||||
|
resource.consecutive_completed_height = -1
|
||||||
resource.consecutive_completed_height = 0
|
|
||||||
|
|
||||||
if not resource.link.has_incoming_resource(resource):
|
if not resource.link.has_incoming_resource(resource):
|
||||||
resource.link.register_incoming_resource(resource)
|
resource.link.register_incoming_resource(resource)
|
||||||
@@ -204,9 +205,19 @@ class Resource:
|
|||||||
resource_data = None
|
resource_data = None
|
||||||
self.assembly_lock = False
|
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"):
|
if hasattr(data, "read"):
|
||||||
data_size = os.stat(data.name).st_size
|
if data_size == None:
|
||||||
self.total_size = data_size
|
data_size = os.stat(data.name).st_size
|
||||||
|
|
||||||
|
self.total_size = data_size
|
||||||
self.grand_total_parts = math.ceil(data_size/Resource.SDU)
|
self.grand_total_parts = math.ceil(data_size/Resource.SDU)
|
||||||
|
|
||||||
if data_size <= Resource.MAX_EFFICIENT_SIZE:
|
if data_size <= Resource.MAX_EFFICIENT_SIZE:
|
||||||
@@ -279,7 +290,7 @@ class Resource:
|
|||||||
self.uncompressed_data = data
|
self.uncompressed_data = data
|
||||||
|
|
||||||
compression_began = time.time()
|
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)
|
RNS.log("Compressing resource data...", RNS.LOG_DEBUG)
|
||||||
self.compressed_data = bz2.compress(self.uncompressed_data)
|
self.compressed_data = bz2.compress(self.uncompressed_data)
|
||||||
RNS.log("Compression completed in "+str(round(time.time()-compression_began, 3))+" seconds", RNS.LOG_DEBUG)
|
RNS.log("Compression completed in "+str(round(time.time()-compression_began, 3))+" seconds", RNS.LOG_DEBUG)
|
||||||
@@ -366,7 +377,8 @@ class Resource:
|
|||||||
if advertise:
|
if advertise:
|
||||||
self.advertise()
|
self.advertise()
|
||||||
else:
|
else:
|
||||||
pass
|
self.receive_lock = Lock()
|
||||||
|
|
||||||
|
|
||||||
def hashmap_update_packet(self, plaintext):
|
def hashmap_update_packet(self, plaintext):
|
||||||
if not self.status == Resource.FAILED:
|
if not self.status == Resource.FAILED:
|
||||||
@@ -440,7 +452,7 @@ class Resource:
|
|||||||
sleep_time = None
|
sleep_time = None
|
||||||
|
|
||||||
if self.status == Resource.ADVERTISED:
|
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 sleep_time < 0:
|
||||||
if self.retries_left <= 0:
|
if self.retries_left <= 0:
|
||||||
RNS.log("Resource transfer timeout after sending advertisement", RNS.LOG_DEBUG)
|
RNS.log("Resource transfer timeout after sending advertisement", RNS.LOG_DEBUG)
|
||||||
@@ -456,7 +468,7 @@ class Resource:
|
|||||||
self.adv_sent = self.last_activity
|
self.adv_sent = self.last_activity
|
||||||
sleep_time = 0.001
|
sleep_time = 0.001
|
||||||
except Exception as e:
|
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()
|
self.cancel()
|
||||||
|
|
||||||
|
|
||||||
@@ -612,10 +624,26 @@ class Resource:
|
|||||||
self.callback(self)
|
self.callback(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing resource concluded callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
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:
|
else:
|
||||||
# Otherwise we'll recursively create the
|
# Otherwise we'll recursively create the
|
||||||
# next segment of the resource
|
# 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:
|
else:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@@ -623,99 +651,99 @@ class Resource:
|
|||||||
|
|
||||||
|
|
||||||
def receive_part(self, packet):
|
def receive_part(self, packet):
|
||||||
while self.receiving_part:
|
with self.receive_lock:
|
||||||
sleep(0.001)
|
|
||||||
|
|
||||||
self.receiving_part = True
|
self.receiving_part = True
|
||||||
self.last_activity = time.time()
|
self.last_activity = time.time()
|
||||||
self.retries_left = self.max_retries
|
self.retries_left = self.max_retries
|
||||||
|
|
||||||
if self.req_resp == None:
|
if self.req_resp == None:
|
||||||
self.req_resp = self.last_activity
|
self.req_resp = self.last_activity
|
||||||
rtt = self.req_resp-self.req_sent
|
rtt = self.req_resp-self.req_sent
|
||||||
|
|
||||||
self.part_timeout_factor = Resource.PART_TIMEOUT_FACTOR_AFTER_RTT
|
self.part_timeout_factor = Resource.PART_TIMEOUT_FACTOR_AFTER_RTT
|
||||||
if self.rtt == None:
|
if self.rtt == None:
|
||||||
self.rtt = self.link.rtt
|
self.rtt = self.link.rtt
|
||||||
self.watchdog_job()
|
self.watchdog_job()
|
||||||
elif rtt < self.rtt:
|
elif rtt < self.rtt:
|
||||||
self.rtt = max(self.rtt - self.rtt*0.05, rtt)
|
self.rtt = max(self.rtt - self.rtt*0.05, rtt)
|
||||||
elif rtt > self.rtt:
|
elif rtt > self.rtt:
|
||||||
self.rtt = min(self.rtt + self.rtt*0.05, rtt)
|
self.rtt = min(self.rtt + self.rtt*0.05, rtt)
|
||||||
|
|
||||||
if rtt > 0:
|
if rtt > 0:
|
||||||
req_resp_cost = len(packet.raw)+self.req_sent_bytes
|
req_resp_cost = len(packet.raw)+self.req_sent_bytes
|
||||||
self.req_resp_rtt_rate = req_resp_cost / rtt
|
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:
|
if self.req_resp_rtt_rate > Resource.RATE_FAST and self.fast_rate_rounds < Resource.FAST_RATE_THRESHOLD:
|
||||||
self.fast_rate_rounds += 1
|
self.fast_rate_rounds += 1
|
||||||
|
|
||||||
if self.fast_rate_rounds == Resource.FAST_RATE_THRESHOLD:
|
if self.fast_rate_rounds == Resource.FAST_RATE_THRESHOLD:
|
||||||
self.window_max = Resource.WINDOW_MAX_FAST
|
self.window_max = Resource.WINDOW_MAX_FAST
|
||||||
|
|
||||||
if not self.status == Resource.FAILED:
|
if not self.status == Resource.FAILED:
|
||||||
self.status = Resource.TRANSFERRING
|
self.status = Resource.TRANSFERRING
|
||||||
part_data = packet.data
|
part_data = packet.data
|
||||||
part_hash = self.get_map_hash(part_data)
|
part_hash = self.get_map_hash(part_data)
|
||||||
|
|
||||||
i = self.consecutive_completed_height
|
consecutive_index = self.consecutive_completed_height if self.consecutive_completed_height >= 0 else 0
|
||||||
for map_hash in self.hashmap[self.consecutive_completed_height:self.consecutive_completed_height+self.window]:
|
i = consecutive_index
|
||||||
if map_hash == part_hash:
|
for map_hash in self.hashmap[consecutive_index:consecutive_index+self.window]:
|
||||||
if self.parts[i] == None:
|
if map_hash == part_hash:
|
||||||
|
if self.parts[i] == None:
|
||||||
|
|
||||||
# Insert data into parts list
|
# Insert data into parts list
|
||||||
self.parts[i] = part_data
|
self.parts[i] = part_data
|
||||||
self.rtt_rxd_bytes += len(part_data)
|
self.rtt_rxd_bytes += len(part_data)
|
||||||
self.received_count += 1
|
self.received_count += 1
|
||||||
self.outstanding_parts -= 1
|
self.outstanding_parts -= 1
|
||||||
|
|
||||||
# Update consecutive completed pointer
|
# Update consecutive completed pointer
|
||||||
if i == self.consecutive_completed_height + 1:
|
if i == self.consecutive_completed_height + 1:
|
||||||
self.consecutive_completed_height = i
|
self.consecutive_completed_height = i
|
||||||
|
|
||||||
cp = self.consecutive_completed_height + 1
|
cp = self.consecutive_completed_height + 1
|
||||||
while cp < len(self.parts) and self.parts[cp] != None:
|
while cp < len(self.parts) and self.parts[cp] != None:
|
||||||
self.consecutive_completed_height = cp
|
self.consecutive_completed_height = cp
|
||||||
cp += 1
|
cp += 1
|
||||||
|
|
||||||
if self.__progress_callback != None:
|
if self.__progress_callback != None:
|
||||||
try:
|
try:
|
||||||
self.__progress_callback(self)
|
self.__progress_callback(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while executing progress callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
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:
|
if self.received_count == self.total_parts and not self.assembly_lock:
|
||||||
self.assembly_lock = True
|
self.assembly_lock = True
|
||||||
self.assemble()
|
self.assemble()
|
||||||
elif self.outstanding_parts == 0:
|
elif self.outstanding_parts == 0:
|
||||||
# TODO: Figure out if there is a mathematically
|
# TODO: Figure out if there is a mathematically
|
||||||
# optimal way to adjust windows
|
# optimal way to adjust windows
|
||||||
if self.window < self.window_max:
|
if self.window < self.window_max:
|
||||||
self.window += 1
|
self.window += 1
|
||||||
if (self.window - self.window_min) > (self.window_flexibility-1):
|
if (self.window - self.window_min) > (self.window_flexibility-1):
|
||||||
self.window_min += 1
|
self.window_min += 1
|
||||||
|
|
||||||
if self.req_sent != 0:
|
if self.req_sent != 0:
|
||||||
rtt = time.time()-self.req_sent
|
rtt = time.time()-self.req_sent
|
||||||
req_transferred = self.rtt_rxd_bytes - self.rtt_rxd_bytes_at_part_req
|
req_transferred = self.rtt_rxd_bytes - self.rtt_rxd_bytes_at_part_req
|
||||||
|
|
||||||
if rtt != 0:
|
if rtt != 0:
|
||||||
self.req_data_rtt_rate = req_transferred/rtt
|
self.req_data_rtt_rate = req_transferred/rtt
|
||||||
self.rtt_rxd_bytes_at_part_req = self.rtt_rxd_bytes
|
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:
|
if self.req_data_rtt_rate > Resource.RATE_FAST and self.fast_rate_rounds < Resource.FAST_RATE_THRESHOLD:
|
||||||
self.fast_rate_rounds += 1
|
self.fast_rate_rounds += 1
|
||||||
|
|
||||||
if self.fast_rate_rounds == Resource.FAST_RATE_THRESHOLD:
|
if self.fast_rate_rounds == Resource.FAST_RATE_THRESHOLD:
|
||||||
self.window_max = Resource.WINDOW_MAX_FAST
|
self.window_max = Resource.WINDOW_MAX_FAST
|
||||||
|
|
||||||
self.request_next()
|
self.request_next()
|
||||||
else:
|
else:
|
||||||
self.receiving_part = False
|
self.receiving_part = False
|
||||||
|
|
||||||
# Called on incoming resource to send a request for more data
|
# Called on incoming resource to send a request for more data
|
||||||
def request_next(self):
|
def request_next(self):
|
||||||
@@ -728,11 +756,11 @@ class Resource:
|
|||||||
hashmap_exhausted = Resource.HASHMAP_IS_NOT_EXHAUSTED
|
hashmap_exhausted = Resource.HASHMAP_IS_NOT_EXHAUSTED
|
||||||
requested_hashes = b""
|
requested_hashes = b""
|
||||||
|
|
||||||
offset = (1 if self.consecutive_completed_height > 0 else 0)
|
i = 0; pn = self.consecutive_completed_height+1
|
||||||
i = 0; pn = self.consecutive_completed_height+offset
|
|
||||||
search_start = pn
|
search_start = pn
|
||||||
|
search_size = self.window
|
||||||
|
|
||||||
for part in self.parts[search_start:search_start+self.window]:
|
for part in self.parts[search_start:search_start+search_size]:
|
||||||
if part == None:
|
if part == None:
|
||||||
part_hash = self.hashmap[pn]
|
part_hash = self.hashmap[pn]
|
||||||
if part_hash != None:
|
if part_hash != None:
|
||||||
@@ -752,7 +780,6 @@ class Resource:
|
|||||||
hmu_part += last_map_hash
|
hmu_part += last_map_hash
|
||||||
self.waiting_for_hmu = True
|
self.waiting_for_hmu = True
|
||||||
|
|
||||||
requested_data = b""
|
|
||||||
request_data = hmu_part + self.hash + requested_hashes
|
request_data = hmu_part + self.hash + requested_hashes
|
||||||
request_packet = RNS.Packet(self.link, request_data, context = RNS.Packet.RESOURCE_REQ)
|
request_packet = RNS.Packet(self.link, request_data, context = RNS.Packet.RESOURCE_REQ)
|
||||||
|
|
||||||
@@ -908,8 +935,7 @@ class Resource:
|
|||||||
else:
|
else:
|
||||||
self.progress_total_parts = float(self.total_parts)
|
self.progress_total_parts = float(self.total_parts)
|
||||||
|
|
||||||
|
progress = min(1.0, self.processed_parts / self.progress_total_parts)
|
||||||
progress = self.processed_parts / self.progress_total_parts
|
|
||||||
return progress
|
return progress
|
||||||
|
|
||||||
def get_transfer_size(self):
|
def get_transfer_size(self):
|
||||||
|
|||||||
+35
-27
@@ -77,6 +77,8 @@ class Transport:
|
|||||||
DESTINATION_TIMEOUT = 60*60*24*7 # Destination table entries are removed if unused for one week
|
DESTINATION_TIMEOUT = 60*60*24*7 # Destination table entries are removed if unused for one week
|
||||||
MAX_RECEIPTS = 1024 # Maximum number of receipts to keep track of
|
MAX_RECEIPTS = 1024 # Maximum number of receipts to keep track of
|
||||||
MAX_RATE_TIMESTAMPS = 16 # Maximum number of announce timestamps to keep per destination
|
MAX_RATE_TIMESTAMPS = 16 # Maximum number of announce timestamps to keep per destination
|
||||||
|
PERSIST_RANDOM_BLOBS = 32 # Maximum number of random blobs per destination to persist to disk
|
||||||
|
MAX_RANDOM_BLOBS = 64 # Maximum number of random blobs per destination to keep in memory
|
||||||
|
|
||||||
interfaces = [] # All active interfaces
|
interfaces = [] # All active interfaces
|
||||||
destinations = [] # All active destinations
|
destinations = [] # All active destinations
|
||||||
@@ -334,7 +336,7 @@ class Transport:
|
|||||||
if time.time() - last_path_request > Transport.PATH_REQUEST_MI:
|
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)
|
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:
|
if not link.destination.hash in path_requests:
|
||||||
blocked_if = link_entry[4]
|
blocked_if = None
|
||||||
path_requests[link.destination.hash] = blocked_if
|
path_requests[link.destination.hash] = blocked_if
|
||||||
|
|
||||||
Transport.pending_links.remove(link)
|
Transport.pending_links.remove(link)
|
||||||
@@ -723,6 +725,29 @@ class Transport:
|
|||||||
sent = False
|
sent = False
|
||||||
outbound_time = time.time()
|
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
|
# 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:
|
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]
|
outbound_interface = Transport.destination_table[packet.destination_hash][5]
|
||||||
@@ -740,6 +765,7 @@ class Transport:
|
|||||||
new_raw += packet.raw[1:2]
|
new_raw += packet.raw[1:2]
|
||||||
new_raw += Transport.destination_table[packet.destination_hash][1]
|
new_raw += Transport.destination_table[packet.destination_hash][1]
|
||||||
new_raw += packet.raw[2:]
|
new_raw += packet.raw[2:]
|
||||||
|
packet_sent(packet)
|
||||||
Transport.transmit(outbound_interface, new_raw)
|
Transport.transmit(outbound_interface, new_raw)
|
||||||
Transport.destination_table[packet.destination_hash][0] = time.time()
|
Transport.destination_table[packet.destination_hash][0] = time.time()
|
||||||
sent = True
|
sent = True
|
||||||
@@ -759,6 +785,7 @@ class Transport:
|
|||||||
new_raw += packet.raw[1:2]
|
new_raw += packet.raw[1:2]
|
||||||
new_raw += Transport.destination_table[packet.destination_hash][1]
|
new_raw += Transport.destination_table[packet.destination_hash][1]
|
||||||
new_raw += packet.raw[2:]
|
new_raw += packet.raw[2:]
|
||||||
|
packet_sent(packet)
|
||||||
Transport.transmit(outbound_interface, new_raw)
|
Transport.transmit(outbound_interface, new_raw)
|
||||||
Transport.destination_table[packet.destination_hash][0] = time.time()
|
Transport.destination_table[packet.destination_hash][0] = time.time()
|
||||||
sent = True
|
sent = True
|
||||||
@@ -767,6 +794,7 @@ class Transport:
|
|||||||
# directly reachable, and also on which interface, so we
|
# directly reachable, and also on which interface, so we
|
||||||
# simply transmit the packet directly on that one.
|
# simply transmit the packet directly on that one.
|
||||||
else:
|
else:
|
||||||
|
packet_sent(packet)
|
||||||
Transport.transmit(outbound_interface, packet.raw)
|
Transport.transmit(outbound_interface, packet.raw)
|
||||||
sent = True
|
sent = True
|
||||||
|
|
||||||
@@ -850,7 +878,7 @@ class Transport:
|
|||||||
interface.announce_queue = []
|
interface.announce_queue = []
|
||||||
|
|
||||||
queued_announces = True if len(interface.announce_queue) > 0 else False
|
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
|
tx_time = (len(packet.raw)*8) / interface.bitrate
|
||||||
wait_time = (tx_time / interface.announce_cap)
|
wait_time = (tx_time / interface.announce_cap)
|
||||||
interface.announce_allowed_at = outbound_time + wait_time
|
interface.announce_allowed_at = outbound_time + wait_time
|
||||||
@@ -933,28 +961,9 @@ class Transport:
|
|||||||
Transport.transmit(interface, packet.raw)
|
Transport.transmit(interface, packet.raw)
|
||||||
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
||||||
interface.sent_announce()
|
interface.sent_announce()
|
||||||
|
packet_sent(packet)
|
||||||
sent = True
|
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
|
Transport.jobs_locked = False
|
||||||
return sent
|
return sent
|
||||||
|
|
||||||
@@ -1314,7 +1323,8 @@ class Transport:
|
|||||||
announce_entry[6] += 1
|
announce_entry[6] += 1
|
||||||
if announce_entry[6] >= Transport.LOCAL_REBROADCASTS_MAX:
|
if announce_entry[6] >= Transport.LOCAL_REBROADCASTS_MAX:
|
||||||
RNS.log("Max local rebroadcasts of announce for "+RNS.prettyhexrep(packet.destination_hash)+" reached, dropping announce from our table", RNS.LOG_DEBUG)
|
RNS.log("Max local rebroadcasts of announce for "+RNS.prettyhexrep(packet.destination_hash)+" reached, dropping announce from our table", RNS.LOG_DEBUG)
|
||||||
Transport.announce_table.pop(packet.destination_hash)
|
if packet.destination_hash in Transport.announce_table:
|
||||||
|
Transport.announce_table.pop(packet.destination_hash)
|
||||||
|
|
||||||
if packet.hops-1 == announce_entry[4]+1 and announce_entry[2] > 0:
|
if packet.hops-1 == announce_entry[4]+1 and announce_entry[2] > 0:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -1463,6 +1473,7 @@ class Transport:
|
|||||||
expires = now + Transport.PATHFINDER_E
|
expires = now + Transport.PATHFINDER_E
|
||||||
|
|
||||||
random_blobs.append(random_blob)
|
random_blobs.append(random_blob)
|
||||||
|
random_blobs = random_blobs[-Transport.MAX_RANDOM_BLOBS:]
|
||||||
|
|
||||||
if (RNS.Reticulum.transport_enabled() or Transport.from_local_client(packet)) and packet.context != RNS.Packet.PATH_RESPONSE:
|
if (RNS.Reticulum.transport_enabled() or Transport.from_local_client(packet)) and packet.context != RNS.Packet.PATH_RESPONSE:
|
||||||
# Insert announce into announce table for retransmission
|
# Insert announce into announce table for retransmission
|
||||||
@@ -1737,9 +1748,6 @@ class Transport:
|
|||||||
if receipt.hash == proof_hash:
|
if receipt.hash == proof_hash:
|
||||||
receipt_validated = receipt.validate_proof_packet(packet)
|
receipt_validated = receipt.validate_proof_packet(packet)
|
||||||
else:
|
else:
|
||||||
# TODO: This looks like it should actually
|
|
||||||
# be rewritten when implicit proofs are added.
|
|
||||||
|
|
||||||
# In case of an implicit proof, we have
|
# In case of an implicit proof, we have
|
||||||
# to check every single outstanding receipt
|
# to check every single outstanding receipt
|
||||||
receipt_validated = receipt.validate_proof_packet(packet)
|
receipt_validated = receipt.validate_proof_packet(packet)
|
||||||
@@ -2578,7 +2586,7 @@ class Transport:
|
|||||||
received_from = de[1]
|
received_from = de[1]
|
||||||
hops = de[2]
|
hops = de[2]
|
||||||
expires = de[3]
|
expires = de[3]
|
||||||
random_blobs = de[4]
|
random_blobs = de[4][-Transport.PERSIST_RANDOM_BLOBS:]
|
||||||
packet_hash = de[6].get_hash()
|
packet_hash = de[6].get_hash()
|
||||||
|
|
||||||
serialised_entry = [
|
serialised_entry = [
|
||||||
|
|||||||
+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("--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("-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("-v", "--verbose", action="count", default=0, help="increase verbosity")
|
||||||
parser.add_argument("-q", "--quiet", action="count", default=0, help="decrease 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("-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("-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("-e", "--encrypt", metavar="file", action="store", default=None, help="encrypt file")
|
||||||
parser.add_argument("-d", "--decrypt", metavar="path", action="store", default=None, help="decrypt 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("-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("-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("-r", "--read", metavar="file", 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("-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("-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("-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",
|
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-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("-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__))
|
parser.add_argument("--version", action="version", version="rnid {version}".format(version=__version__))
|
||||||
|
|
||||||
@@ -110,6 +114,59 @@ def main():
|
|||||||
args.read = args.sign
|
args.read = args.sign
|
||||||
|
|
||||||
identity_str = args.identity
|
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:
|
if not args.generate and not identity_str:
|
||||||
print("\nNo identity provided, cannot continue\n")
|
print("\nNo identity provided, cannot continue\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
@@ -246,14 +303,38 @@ def main():
|
|||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
if args.print_identity:
|
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 identity.prv:
|
||||||
if args.print_private:
|
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:
|
else:
|
||||||
RNS.log("Private Key : Hidden")
|
RNS.log("Private Key : Hidden")
|
||||||
exit(0)
|
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 args.validate:
|
||||||
if not args.read and args.validate.lower().endswith("."+SIG_EXT):
|
if not args.read and args.validate.lower().endswith("."+SIG_EXT):
|
||||||
args.read = str(args.validate).replace("."+SIG_EXT, "")
|
args.read = str(args.validate).replace("."+SIG_EXT, "")
|
||||||
|
|||||||
+249
-82
@@ -42,8 +42,8 @@ RNS.logtimefmt = "%H:%M:%S"
|
|||||||
RNS.compact_log_fmt = True
|
RNS.compact_log_fmt = True
|
||||||
|
|
||||||
program_version = "2.1.3"
|
program_version = "2.1.3"
|
||||||
eth_addr = "0x81F7B979fEa6134bA9FD5c701b3501A2e61E897a"
|
eth_addr = "0xFDabC71AC4c0C78C95aDDDe3B4FA19d6273c5E73"
|
||||||
btc_addr = "3CPmacGm34qYvR6XWLVEJmi2aNe3PZqUuq"
|
btc_addr = "35G9uWVzrpJJibzUwpNUQGQNFzLirhrYAH"
|
||||||
xmr_addr = "87HcDx6jRSkMQ9nPRd5K9hGGpZLn2s7vWETjMaVM5KfV4TD36NcYa8J8WSxhTSvBzzFpqDwp2fg5GX2moZ7VAP9QMZCZGET"
|
xmr_addr = "87HcDx6jRSkMQ9nPRd5K9hGGpZLn2s7vWETjMaVM5KfV4TD36NcYa8J8WSxhTSvBzzFpqDwp2fg5GX2moZ7VAP9QMZCZGET"
|
||||||
|
|
||||||
rnode = None
|
rnode = None
|
||||||
@@ -120,12 +120,16 @@ class KISS():
|
|||||||
class ROM():
|
class ROM():
|
||||||
PLATFORM_AVR = 0x90
|
PLATFORM_AVR = 0x90
|
||||||
PLATFORM_ESP32 = 0x80
|
PLATFORM_ESP32 = 0x80
|
||||||
|
PLATFORM_NRF52 = 0x70
|
||||||
|
|
||||||
MCU_1284P = 0x91
|
MCU_1284P = 0x91
|
||||||
MCU_2560 = 0x92
|
MCU_2560 = 0x92
|
||||||
MCU_ESP32 = 0x81
|
MCU_ESP32 = 0x81
|
||||||
|
MCU_NRF52 = 0x71
|
||||||
|
|
||||||
PRODUCT_RNODE = 0x03
|
PRODUCT_RNODE = 0x03
|
||||||
|
MODEL_A1 = 0xA1
|
||||||
|
MODEL_A6 = 0xA6
|
||||||
MODEL_A4 = 0xA4
|
MODEL_A4 = 0xA4
|
||||||
MODEL_A9 = 0xA9
|
MODEL_A9 = 0xA9
|
||||||
MODEL_A3 = 0xA3
|
MODEL_A3 = 0xA3
|
||||||
@@ -144,6 +148,8 @@ class ROM():
|
|||||||
PRODUCT_T32_21 = 0xB1
|
PRODUCT_T32_21 = 0xB1
|
||||||
MODEL_B4 = 0xB4
|
MODEL_B4 = 0xB4
|
||||||
MODEL_B9 = 0xB9
|
MODEL_B9 = 0xB9
|
||||||
|
MODEL_B4_TCXO = 0x04
|
||||||
|
MODEL_B9_TCXO = 0x09
|
||||||
|
|
||||||
PRODUCT_H32_V2 = 0xC0
|
PRODUCT_H32_V2 = 0xC0
|
||||||
MODEL_C4 = 0xC4
|
MODEL_C4 = 0xC4
|
||||||
@@ -152,6 +158,8 @@ class ROM():
|
|||||||
PRODUCT_TBEAM = 0xE0
|
PRODUCT_TBEAM = 0xE0
|
||||||
MODEL_E4 = 0xE4
|
MODEL_E4 = 0xE4
|
||||||
MODEL_E9 = 0xE9
|
MODEL_E9 = 0xE9
|
||||||
|
MODEL_E3 = 0xE3
|
||||||
|
MODEL_E8 = 0xE8
|
||||||
|
|
||||||
PRODUCT_HMBRW = 0xF0
|
PRODUCT_HMBRW = 0xF0
|
||||||
MODEL_FF = 0xFF
|
MODEL_FF = 0xFF
|
||||||
@@ -182,6 +190,7 @@ class ROM():
|
|||||||
BOARD_GENERIC_ESP32 = 0x35
|
BOARD_GENERIC_ESP32 = 0x35
|
||||||
BOARD_LORA32_V2_0 = 0x36
|
BOARD_LORA32_V2_0 = 0x36
|
||||||
BOARD_LORA32_V2_1 = 0x37
|
BOARD_LORA32_V2_1 = 0x37
|
||||||
|
BOARD_RAK4630 = 0x51
|
||||||
|
|
||||||
mapped_product = ROM.PRODUCT_RNODE
|
mapped_product = ROM.PRODUCT_RNODE
|
||||||
products = {
|
products = {
|
||||||
@@ -197,33 +206,41 @@ products = {
|
|||||||
platforms = {
|
platforms = {
|
||||||
ROM.PLATFORM_AVR: "AVR",
|
ROM.PLATFORM_AVR: "AVR",
|
||||||
ROM.PLATFORM_ESP32:"ESP32",
|
ROM.PLATFORM_ESP32:"ESP32",
|
||||||
|
ROM.PLATFORM_NRF52:"NRF52",
|
||||||
}
|
}
|
||||||
|
|
||||||
mcus = {
|
mcus = {
|
||||||
ROM.MCU_1284P: "ATmega1284P",
|
ROM.MCU_1284P: "ATmega1284P",
|
||||||
ROM.MCU_2560:"ATmega2560",
|
ROM.MCU_2560:"ATmega2560",
|
||||||
ROM.MCU_ESP32:"Espressif Systems ESP32",
|
ROM.MCU_ESP32:"Espressif Systems ESP32",
|
||||||
|
ROM.MCU_NRF52:"Nordic nRF52840",
|
||||||
}
|
}
|
||||||
|
|
||||||
models = {
|
models = {
|
||||||
0xA4: [410000000, 525000000, 14, "410 - 525 MHz", "rnode_firmware.hex"],
|
0xA4: [410000000, 525000000, 14, "410 - 525 MHz", "rnode_firmware.hex", "SX1278"],
|
||||||
0xA9: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware.hex"],
|
0xA9: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware.hex", "SX1276"],
|
||||||
0xA2: [410000000, 525000000, 17, "410 - 525 MHz", "rnode_firmware_ng21.zip"],
|
0xA1: [410000000, 525000000, 22, "410 - 525 MHz", "rnode_firmware_t3s3.zip", "SX1268"],
|
||||||
0xA7: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware_ng21.zip"],
|
0xA6: [820000000, 1020000000, 22, "820 - 960 MHz", "rnode_firmware_t3s3.zip", "SX1262"],
|
||||||
0xA3: [410000000, 525000000, 17, "410 - 525 MHz", "rnode_firmware_ng20.zip"],
|
0xA2: [410000000, 525000000, 17, "410 - 525 MHz", "rnode_firmware_ng21.zip", "SX1278"],
|
||||||
0xA8: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware_ng20.zip"],
|
0xA7: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware_ng21.zip", "SX1276"],
|
||||||
0xB3: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v20.zip"],
|
0xA3: [410000000, 525000000, 17, "410 - 525 MHz", "rnode_firmware_ng20.zip", "SX1278"],
|
||||||
0xB8: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v20.zip"],
|
0xA8: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware_ng20.zip", "SX1276"],
|
||||||
0xB4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v21.zip"],
|
0xB3: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v20.zip", "SX1278"],
|
||||||
0xB9: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v21.zip"],
|
0xB8: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v20.zip", "SX1276"],
|
||||||
0xBA: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v10.zip"],
|
0xB4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v21.zip", "SX1278"],
|
||||||
0xBB: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v10.zip"],
|
0xB9: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v21.zip", "SX1276"],
|
||||||
0xC4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_heltec32v2.zip"],
|
0x04: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v21_tcxo.zip", "SX1278"],
|
||||||
0xC9: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_heltec32v2.zip"],
|
0x09: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v21_tcxo.zip", "SX1276"],
|
||||||
0xE4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_tbeam.zip"],
|
0xBA: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_lora32v10.zip", "SX1278"],
|
||||||
0xE9: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_tbeam.zip"],
|
0xBB: [850000000, 950000000, 17, "850 - 950 MHz", "rnode_firmware_lora32v10.zip", "SX1276"],
|
||||||
0xFE: [100000000, 1100000000, 17, "(Band capabilities unknown)", None],
|
0xC4: [420000000, 520000000, 17, "420 - 520 MHz", "rnode_firmware_heltec32v2.zip", "SX1278"],
|
||||||
0xFF: [100000000, 1100000000, 14, "(Band capabilities unknown)", None],
|
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
|
CNF_DIR = None
|
||||||
@@ -516,7 +533,7 @@ class RNode():
|
|||||||
if (len(command_buffer) == 4):
|
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])
|
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):
|
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):
|
elif (command == KISS.CMD_STAT_SNR):
|
||||||
self.r_stat_snr = int.from_bytes(bytes([byte]), byteorder="big", signed=True) * 0.25
|
self.r_stat_snr = int.from_bytes(bytes([byte]), byteorder="big", signed=True) * 0.25
|
||||||
elif (command == KISS.CMD_RANDOM):
|
elif (command == KISS.CMD_RANDOM):
|
||||||
@@ -928,6 +945,7 @@ class RNode():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.provisioned = False
|
self.provisioned = False
|
||||||
RNS.log("Invalid EEPROM data, could not parse device EEPROM.")
|
RNS.log("Invalid EEPROM data, could not parse device EEPROM.")
|
||||||
|
RNS.log("The contained exception was: "+str(e))
|
||||||
|
|
||||||
|
|
||||||
def device_probe(self):
|
def device_probe(self):
|
||||||
@@ -1018,6 +1036,10 @@ def ensure_firmware_file(fw_filename):
|
|||||||
file = open(UPD_DIR+"/"+fw_filename+".version.latest", "rb")
|
file = open(UPD_DIR+"/"+fw_filename+".version.latest", "rb")
|
||||||
release_info = file.read().decode("utf-8").strip()
|
release_info = file.read().decode("utf-8").strip()
|
||||||
selected_version = release_info.split()[0]
|
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]
|
selected_hash = release_info.split()[1]
|
||||||
if not os.path.isdir(UPD_DIR+"/"+selected_version):
|
if not os.path.isdir(UPD_DIR+"/"+selected_version):
|
||||||
os.makedirs(UPD_DIR+"/"+selected_version)
|
os.makedirs(UPD_DIR+"/"+selected_version)
|
||||||
@@ -1169,15 +1191,15 @@ def main():
|
|||||||
|
|
||||||
parser.add_argument("--version", action="store_true", help="Print program version and exit")
|
parser.add_argument("--version", action="store_true", help="Print program version and exit")
|
||||||
|
|
||||||
parser.add_argument("-f", "--flash", action="store_true", help=argparse.SUPPRESS) # Flash firmware and bootstrap EEPROM
|
parser.add_argument("-f", "--flash", action="store_true", help="Flash firmware and bootstrap EEPROM")
|
||||||
parser.add_argument("-r", "--rom", action="store_true", help=argparse.SUPPRESS) # Bootstrap EEPROM without flashing firmware
|
parser.add_argument("-r", "--rom", action="store_true", help="Bootstrap EEPROM without flashing firmware")
|
||||||
parser.add_argument("-k", "--key", action="store_true", help=argparse.SUPPRESS) # Generate a new signing key and exit
|
parser.add_argument("-k", "--key", action="store_true", help="Generate a new signing key and exit") #
|
||||||
parser.add_argument("-S", "--sign", action="store_true", help=argparse.SUPPRESS) # Display public part of signing key
|
parser.add_argument("-S", "--sign", action="store_true", help="Display public part of signing key")
|
||||||
parser.add_argument("-H", "--firmware-hash", action="store", help=argparse.SUPPRESS) # Display public part of signing key
|
parser.add_argument("-H", "--firmware-hash", action="store", help="Display installed firmware hash")
|
||||||
parser.add_argument("--platform", action="store", metavar="platform", type=str, default=None, help=argparse.SUPPRESS) # Platform specification for device bootstrap
|
parser.add_argument("--platform", action="store", metavar="platform", type=str, default=None, help="Platform specification for device bootstrap")
|
||||||
parser.add_argument("--product", action="store", metavar="product", type=str, default=None, help=argparse.SUPPRESS) # Product specification for device bootstrap
|
parser.add_argument("--product", action="store", metavar="product", type=str, default=None, help="Product specification for device bootstrap") #
|
||||||
parser.add_argument("--model", action="store", metavar="model", type=str, default=None, help=argparse.SUPPRESS) # Model code for device bootstrap
|
parser.add_argument("--model", action="store", metavar="model", type=str, default=None, help="Model code for device bootstrap")
|
||||||
parser.add_argument("--hwrev", action="store", metavar="revision", type=int, default=None, help=argparse.SUPPRESS) # Hardware revision for device bootstrap
|
parser.add_argument("--hwrev", action="store", metavar="revision", type=int, default=None, help="Hardware revision for device bootstrap")
|
||||||
|
|
||||||
parser.add_argument("port", nargs="?", default=None, help="serial port where RNode is attached", type=str)
|
parser.add_argument("port", nargs="?", default=None, help="serial port where RNode is attached", type=str)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
@@ -1497,6 +1519,7 @@ def main():
|
|||||||
print("[5] LilyGO LoRa32 v1.0")
|
print("[5] LilyGO LoRa32 v1.0")
|
||||||
print("[6] LilyGO T-Beam")
|
print("[6] LilyGO T-Beam")
|
||||||
print("[7] Heltec LoRa32 v2")
|
print("[7] Heltec LoRa32 v2")
|
||||||
|
print("[8] LilyGO LoRa T3S3")
|
||||||
print(" .")
|
print(" .")
|
||||||
print(" / \\ Select one of these options if you want to easily turn")
|
print(" / \\ Select one of these options if you want to easily turn")
|
||||||
print(" | a supported development board into an RNode.")
|
print(" | a supported development board into an RNode.")
|
||||||
@@ -1507,7 +1530,8 @@ def main():
|
|||||||
selected_product = None
|
selected_product = None
|
||||||
try:
|
try:
|
||||||
c_dev = int(input())
|
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()
|
raise ValueError()
|
||||||
elif c_dev == 1:
|
elif c_dev == 1:
|
||||||
selected_product = ROM.PRODUCT_RNODE
|
selected_product = ROM.PRODUCT_RNODE
|
||||||
@@ -1536,8 +1560,7 @@ def main():
|
|||||||
print(" T-Beam RNode Installer")
|
print(" T-Beam RNode Installer")
|
||||||
print("")
|
print("")
|
||||||
print("The RNode firmware can currently be installed on T-Beam devices using the")
|
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("SX1276, SX1278, SX1262 and SX1268 transceiver chips.")
|
||||||
print("SX1262 and SX1268 chips is in development.")
|
|
||||||
print("")
|
print("")
|
||||||
print("Important! Using RNode firmware on T-Beam devices should currently be")
|
print("Important! Using RNode firmware on T-Beam devices should currently be")
|
||||||
print("considered experimental. It is not intended for production or critical use.")
|
print("considered experimental. It is not intended for production or critical use.")
|
||||||
@@ -1608,6 +1631,23 @@ def main():
|
|||||||
print("who would like to experiment with it. Hit enter to continue.")
|
print("who would like to experiment with it. Hit enter to continue.")
|
||||||
print("---------------------------------------------------------------------------")
|
print("---------------------------------------------------------------------------")
|
||||||
input()
|
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:
|
except Exception as e:
|
||||||
print("That device type does not exist, exiting now.")
|
print("That device type does not exist, exiting now.")
|
||||||
exit()
|
exit()
|
||||||
@@ -1660,53 +1700,86 @@ def main():
|
|||||||
|
|
||||||
|
|
||||||
elif selected_product == ROM.PRODUCT_RNODE:
|
elif selected_product == ROM.PRODUCT_RNODE:
|
||||||
selected_mcu = ROM.MCU_1284P
|
if not c_mod:
|
||||||
print("\nWhat model is this RNode?\n")
|
selected_mcu = ROM.MCU_1284P
|
||||||
print("[1] Handheld v2.x RNode, 410 - 525 MHz")
|
print("\nWhat model is this RNode?\n")
|
||||||
print("[2] Handheld v2.x RNode, 820 - 1020 MHz")
|
print("[1] Handheld v2.1 RNode, 410 - 525 MHz")
|
||||||
print("")
|
print("[2] Handheld v2.1 RNode, 820 - 1020 MHz")
|
||||||
print("[3] Original v1.x RNode, 410 - 525 MHz")
|
print("")
|
||||||
print("[4] Original v1.x RNode, 820 - 1020 MHz")
|
print("[3] Original v1.x RNode, 410 - 525 MHz")
|
||||||
# print("[5] Prototype v2 RNode, 410 - 525 MHz")
|
print("[4] Original v1.x RNode, 820 - 1020 MHz")
|
||||||
# print("[6] Prototype v2 RNode, 820 - 1020 MHz")
|
print("")
|
||||||
print("\n? ", end="")
|
print("[5] Prototype v2.2 RNode, 410 - 525 MHz")
|
||||||
try:
|
print("[6] Prototype v2.2 RNode, 820 - 1020 MHz")
|
||||||
c_model = int(input())
|
# print("[5] Prototype v2 RNode, 410 - 525 MHz")
|
||||||
if c_model < 1 or c_model > 6:
|
# print("[6] Prototype v2 RNode, 820 - 1020 MHz")
|
||||||
raise ValueError()
|
print("\n? ", end="")
|
||||||
elif c_model == 3:
|
try:
|
||||||
selected_model = ROM.MODEL_A4
|
c_model = int(input())
|
||||||
selected_platform = ROM.PLATFORM_AVR
|
if c_model < 1 or c_model > 6:
|
||||||
elif c_model == 4:
|
raise ValueError()
|
||||||
selected_model = ROM.MODEL_A9
|
elif c_model == 1:
|
||||||
selected_platform = ROM.PLATFORM_AVR
|
selected_model = ROM.MODEL_A2
|
||||||
elif c_model == 1:
|
selected_mcu = ROM.MCU_ESP32
|
||||||
selected_model = ROM.MODEL_A2
|
selected_platform = ROM.PLATFORM_ESP32
|
||||||
selected_mcu = ROM.MCU_ESP32
|
elif c_model == 2:
|
||||||
selected_platform = ROM.PLATFORM_ESP32
|
selected_model = ROM.MODEL_A7
|
||||||
elif c_model == 2:
|
selected_mcu = ROM.MCU_ESP32
|
||||||
selected_model = ROM.MODEL_A7
|
selected_platform = ROM.PLATFORM_ESP32
|
||||||
selected_mcu = ROM.MCU_ESP32
|
elif c_model == 3:
|
||||||
selected_platform = ROM.PLATFORM_ESP32
|
selected_model = ROM.MODEL_A4
|
||||||
# elif c_model == 5:
|
selected_platform = ROM.PLATFORM_AVR
|
||||||
# selected_model = ROM.MODEL_A3
|
elif c_model == 4:
|
||||||
# selected_mcu = ROM.MCU_ESP32
|
selected_model = ROM.MODEL_A9
|
||||||
# selected_platform = ROM.PLATFORM_ESP32
|
selected_platform = ROM.PLATFORM_AVR
|
||||||
# elif c_model == 6:
|
elif c_model == 5:
|
||||||
# selected_model = ROM.MODEL_A8
|
selected_model = ROM.MODEL_A1
|
||||||
# selected_mcu = ROM.MCU_ESP32
|
selected_mcu = ROM.MCU_ESP32
|
||||||
# selected_platform = ROM.PLATFORM_ESP32
|
selected_platform = ROM.PLATFORM_ESP32
|
||||||
except Exception as e:
|
elif c_model == 6:
|
||||||
print("That model does not exist, exiting now.")
|
selected_model = ROM.MODEL_A6
|
||||||
exit()
|
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:
|
elif selected_product == ROM.PRODUCT_TBEAM:
|
||||||
selected_mcu = ROM.MCU_ESP32
|
selected_mcu = ROM.MCU_ESP32
|
||||||
print("\nWhat band is this T-Beam for?\n")
|
print("\nWhat band is this T-Beam for?\n")
|
||||||
print("[1] 433 MHz")
|
print("[1] 433 MHz (with SX1278 chip)")
|
||||||
print("[2] 868 MHz")
|
print("[2] 868/915/923 MHz (with SX1276 chip)")
|
||||||
print("[3] 915 MHz")
|
print("");
|
||||||
print("[4] 923 MHz")
|
print("[3] 433 MHz (with SX1268 chip)")
|
||||||
|
print("[4] 868/915/923 MHz (with SX1262 chip)")
|
||||||
print("\n? ", end="")
|
print("\n? ", end="")
|
||||||
try:
|
try:
|
||||||
c_model = int(input())
|
c_model = int(input())
|
||||||
@@ -1715,9 +1788,15 @@ def main():
|
|||||||
elif c_model == 1:
|
elif c_model == 1:
|
||||||
selected_model = ROM.MODEL_E4
|
selected_model = ROM.MODEL_E4
|
||||||
selected_platform = ROM.PLATFORM_ESP32
|
selected_platform = ROM.PLATFORM_ESP32
|
||||||
elif c_model > 1:
|
elif c_model == 2:
|
||||||
selected_model = ROM.MODEL_E9
|
selected_model = ROM.MODEL_E9
|
||||||
selected_platform = ROM.PLATFORM_ESP32
|
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:
|
except Exception as e:
|
||||||
print("That band does not exist, exiting now.")
|
print("That band does not exist, exiting now.")
|
||||||
exit()
|
exit()
|
||||||
@@ -1770,9 +1849,9 @@ def main():
|
|||||||
selected_mcu = ROM.MCU_ESP32
|
selected_mcu = ROM.MCU_ESP32
|
||||||
print("\nWhat band is this LoRa32 for?\n")
|
print("\nWhat band is this LoRa32 for?\n")
|
||||||
print("[1] 433 MHz")
|
print("[1] 433 MHz")
|
||||||
print("[2] 868 MHz")
|
print("[2] 868/915/923 MHz")
|
||||||
print("[3] 915 MHz")
|
print("[3] 433 MHz, with TCXO")
|
||||||
print("[4] 923 MHz")
|
print("[4] 868/915/923 MHz, with TCXO")
|
||||||
print("\n? ", end="")
|
print("\n? ", end="")
|
||||||
try:
|
try:
|
||||||
c_model = int(input())
|
c_model = int(input())
|
||||||
@@ -1781,9 +1860,15 @@ def main():
|
|||||||
elif c_model == 1:
|
elif c_model == 1:
|
||||||
selected_model = ROM.MODEL_B4
|
selected_model = ROM.MODEL_B4
|
||||||
selected_platform = ROM.PLATFORM_ESP32
|
selected_platform = ROM.PLATFORM_ESP32
|
||||||
elif c_model > 1:
|
elif c_model == 2:
|
||||||
selected_model = ROM.MODEL_B9
|
selected_model = ROM.MODEL_B9
|
||||||
selected_platform = ROM.PLATFORM_ESP32
|
selected_platform = ROM.PLATFORM_ESP32
|
||||||
|
elif c_model == 3:
|
||||||
|
selected_model = ROM.MODEL_B4_TCXO
|
||||||
|
selected_platform = ROM.PLATFORM_ESP32
|
||||||
|
elif c_model == 4:
|
||||||
|
selected_model = ROM.MODEL_B9_TCXO
|
||||||
|
selected_platform = ROM.PLATFORM_ESP32
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("That band does not exist, exiting now.")
|
print("That band does not exist, exiting now.")
|
||||||
exit()
|
exit()
|
||||||
@@ -2098,6 +2183,42 @@ def main():
|
|||||||
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam.bin",
|
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam.bin",
|
||||||
"0x8000", UPD_DIR+"/"+selected_version+"/rnode_firmware_tbeam.partitions",
|
"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":
|
elif fw_filename == "rnode_firmware_lora32v10.zip":
|
||||||
if numeric_version >= 1.59:
|
if numeric_version >= 1.59:
|
||||||
return [
|
return [
|
||||||
@@ -2206,6 +2327,24 @@ def main():
|
|||||||
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_lora32v21.bin",
|
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_lora32v21.bin",
|
||||||
"0x8000", UPD_DIR+"/"+selected_version+"/rnode_firmware_lora32v21.partitions",
|
"0x8000", UPD_DIR+"/"+selected_version+"/rnode_firmware_lora32v21.partitions",
|
||||||
]
|
]
|
||||||
|
elif fw_filename == "rnode_firmware_lora32v21_tcxo.zip":
|
||||||
|
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_lora32v21_tcxo.boot_app0",
|
||||||
|
"0x1000", UPD_DIR+"/"+selected_version+"/rnode_firmware_lora32v21_tcxo.bootloader",
|
||||||
|
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_lora32v21_tcxo.bin",
|
||||||
|
"0x210000",UPD_DIR+"/"+selected_version+"/console_image.bin",
|
||||||
|
"0x8000", UPD_DIR+"/"+selected_version+"/rnode_firmware_lora32v21_tcxo.partitions",
|
||||||
|
]
|
||||||
elif fw_filename == "rnode_firmware_heltec32v2.zip":
|
elif fw_filename == "rnode_firmware_heltec32v2.zip":
|
||||||
if numeric_version >= 1.55:
|
if numeric_version >= 1.55:
|
||||||
return [
|
return [
|
||||||
@@ -2386,6 +2525,24 @@ def main():
|
|||||||
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_ng21.bin",
|
"0x10000", UPD_DIR+"/"+selected_version+"/rnode_firmware_ng21.bin",
|
||||||
"0x8000", UPD_DIR+"/"+selected_version+"/rnode_firmware_ng21.partitions",
|
"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":
|
elif fw_filename == "extracted_rnode_firmware.zip":
|
||||||
return [
|
return [
|
||||||
sys.executable, flasher,
|
sys.executable, flasher,
|
||||||
@@ -2770,6 +2927,7 @@ def main():
|
|||||||
RNS.log("\tFirmware version : "+rnode.version)
|
RNS.log("\tFirmware version : "+rnode.version)
|
||||||
RNS.log("\tHardware revision : "+str(int(rnode.hw_rev)))
|
RNS.log("\tHardware revision : "+str(int(rnode.hw_rev)))
|
||||||
RNS.log("\tSerial number : "+RNS.hexrep(rnode.serialno))
|
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("\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("\tMax TX power : "+str(rnode.max_output)+" dBm")
|
||||||
RNS.log("\tManufactured : "+timestring)
|
RNS.log("\tManufactured : "+timestring)
|
||||||
@@ -2851,12 +3009,21 @@ def main():
|
|||||||
mapped_product = ROM.PRODUCT_TBEAM
|
mapped_product = ROM.PRODUCT_TBEAM
|
||||||
|
|
||||||
if mapped_model != None:
|
if mapped_model != None:
|
||||||
model = mapped_model
|
if mapped_model == ROM.MODEL_B4_TCXO:
|
||||||
|
model = ROM.MODEL_B4
|
||||||
|
elif mapped_model == ROM.MODEL_B9_TCXO:
|
||||||
|
model = ROM.MODEL_B9
|
||||||
|
else:
|
||||||
|
model = mapped_model
|
||||||
else:
|
else:
|
||||||
if args.model == "a4":
|
if args.model == "a4":
|
||||||
model = ROM.MODEL_A4
|
model = ROM.MODEL_A4
|
||||||
elif args.model == "a9":
|
elif args.model == "a9":
|
||||||
model = ROM.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":
|
elif args.model == "e4":
|
||||||
model = ROM.MODEL_E4
|
model = ROM.MODEL_E4
|
||||||
elif args.model == "e9":
|
elif args.model == "e9":
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ from RNS._version import __version__
|
|||||||
DEFAULT_PROBE_SIZE = 16
|
DEFAULT_PROBE_SIZE = 16
|
||||||
DEFAULT_TIMEOUT = 12
|
DEFAULT_TIMEOUT = 12
|
||||||
|
|
||||||
def program_setup(configdir, destination_hexhash, size=None, full_name = None, verbosity = 0, timeout=None, probes=1):
|
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 size == None: size = DEFAULT_PROBE_SIZE
|
||||||
if full_name == None:
|
if full_name == None:
|
||||||
print("The full destination name including application name aspects must be specified for the destination")
|
print("The full destination name including application name aspects must be specified for the destination")
|
||||||
@@ -100,6 +100,9 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
|||||||
replies = 0
|
replies = 0
|
||||||
while probes:
|
while probes:
|
||||||
|
|
||||||
|
if sent > 0:
|
||||||
|
time.sleep(wait)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
probe = RNS.Packet(request_destination, os.urandom(size))
|
probe = RNS.Packet(request_destination, os.urandom(size))
|
||||||
probe.pack()
|
probe.pack()
|
||||||
@@ -129,7 +132,7 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
|||||||
i = (i+1)%len(syms)
|
i = (i+1)%len(syms)
|
||||||
|
|
||||||
if time.time() > _timeout:
|
if time.time() > _timeout:
|
||||||
print("\r \rProbe timed out")
|
print("\r \rProbe timed out")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("\b\b ")
|
print("\b\b ")
|
||||||
@@ -175,11 +178,11 @@ def program_setup(configdir, destination_hexhash, size=None, full_name = None, v
|
|||||||
reception_stats += " [SNR "+str(receipt.proof_packet.snr)+" dB]"
|
reception_stats += " [SNR "+str(receipt.proof_packet.snr)+" dB]"
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"Valid reply received from "+
|
"Valid reply from "+
|
||||||
RNS.prettyhexrep(receipt.destination.hash)+
|
RNS.prettyhexrep(receipt.destination.hash)+
|
||||||
"\nRound-trip time is "+rttstring+
|
"\nRound-trip time is "+rttstring+
|
||||||
" over "+str(hops)+" hop"+ms+
|
" over "+str(hops)+" hop"+ms+
|
||||||
reception_stats
|
reception_stats+"\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@@ -203,6 +206,7 @@ def main():
|
|||||||
parser.add_argument("-s", "--size", action="store", default=None, help="size of probe packet payload in bytes", type=int)
|
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("-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("-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("--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("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)
|
parser.add_argument("destination_hash", nargs="?", default=None, help="hexadecimal hash of the destination", type=str)
|
||||||
@@ -228,6 +232,8 @@ def main():
|
|||||||
full_name = args.full_name,
|
full_name = args.full_name,
|
||||||
verbosity = args.verbose,
|
verbosity = args.verbose,
|
||||||
probes = args.probes,
|
probes = args.probes,
|
||||||
|
wait = args.wait,
|
||||||
|
timeout = args.timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|||||||
@@ -144,6 +144,12 @@ def rand():
|
|||||||
result = instance_random.random()
|
result = instance_random.random()
|
||||||
return result
|
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):
|
def hexrep(data, delimit=True):
|
||||||
try:
|
try:
|
||||||
iter(data)
|
iter(data)
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
__version__ = "0.6.4"
|
__version__ = "0.7.2"
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
# Sphinx build info version 1
|
# Sphinx build info version 1
|
||||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||||
config: efbb3640be4dccd745e11c4ab0e199e2
|
config: 0f2f9f8af8c66687a92c6541875995ff
|
||||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||||
VERSION: '0.6.4 beta',
|
VERSION: '0.7.2 beta',
|
||||||
LANGUAGE: 'en',
|
LANGUAGE: 'en',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
BUILDER: 'html',
|
BUILDER: 'html',
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Support Reticulum" href="support.html" /><link rel="prev" title="Building Networks" href="networks.html" />
|
<link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="search.html" /><link rel="next" title="Support Reticulum" href="support.html" /><link rel="prev" title="Building Networks" href="networks.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>Code Examples - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>Code Examples - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -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"># And set up a small job to check for</span>
|
||||||
<span class="c1"># a potential timeout in receiving the</span>
|
<span class="c1"># a potential timeout in receiving the</span>
|
||||||
<span class="c1"># file list</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">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">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">start</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>
|
<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>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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="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"/>
|
<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.4 beta documentation</title>
|
<title>An Explanation of Reticulum for Human Beings - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -257,7 +257,7 @@
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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="viewport" content="width=device-width,initial-scale=1"/>
|
||||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="#" /><link rel="search" title="Search" href="search.html" />
|
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="#" /><link rel="search" title="Search" href="search.html" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/><title>Index - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/><title>Index - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -165,7 +165,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -530,6 +530,8 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul></td>
|
</ul></td>
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Link.no_data_for">no_data_for() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
<li><a href="reference.html#RNS.Link.no_inbound_for">no_inbound_for() (RNS.Link method)</a>
|
<li><a href="reference.html#RNS.Link.no_inbound_for">no_inbound_for() (RNS.Link method)</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="reference.html#RNS.Link.no_outbound_for">no_outbound_for() (RNS.Link method)</a>
|
<li><a href="reference.html#RNS.Link.no_outbound_for">no_outbound_for() (RNS.Link method)</a>
|
||||||
@@ -735,7 +737,7 @@
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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" />
|
<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"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>Getting Started Fast - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>Getting Started Fast - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -758,7 +758,7 @@ section of this manual.</p>
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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" />
|
<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"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>Communications Hardware - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>Communications Hardware - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -519,7 +519,7 @@ can be used with Reticulum. This includes virtual software modems such as
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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" />
|
<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"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="#"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="#"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -468,7 +468,7 @@ to participate in the development of Reticulum itself.</p>
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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" />
|
<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"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>Configuring Interfaces - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>Configuring Interfaces - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -1106,7 +1106,7 @@ to <code class="docutils literal notranslate"><span class="pre">30</span></code>
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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" />
|
<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"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>Building Networks - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>Building Networks - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -467,7 +467,7 @@ connected outliers are now an integral part of the network.</p>
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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" />
|
<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"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>API Reference - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>API Reference - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -1131,7 +1131,7 @@ statistics, you will be able to retrieve stats such as <em>RSSI</em>, <em>SNR</e
|
|||||||
<span class="sig-name descname"><span class="pre">no_inbound_for</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.no_inbound_for" title="Permalink to this definition">#</a></dt>
|
<span class="sig-name descname"><span class="pre">no_inbound_for</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.no_inbound_for" title="Permalink to this definition">#</a></dt>
|
||||||
<dd><dl class="field-list simple">
|
<dd><dl class="field-list simple">
|
||||||
<dt class="field-odd">Returns<span class="colon">:</span></dt>
|
<dt class="field-odd">Returns<span class="colon">:</span></dt>
|
||||||
<dd class="field-odd"><p>The time in seconds since last inbound packet on the link.</p>
|
<dd class="field-odd"><p>The time in seconds since last inbound packet on the link. This includes keepalive packets.</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
@@ -1141,7 +1141,17 @@ statistics, you will be able to retrieve stats such as <em>RSSI</em>, <em>SNR</e
|
|||||||
<span class="sig-name descname"><span class="pre">no_outbound_for</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.no_outbound_for" title="Permalink to this definition">#</a></dt>
|
<span class="sig-name descname"><span class="pre">no_outbound_for</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.no_outbound_for" title="Permalink to this definition">#</a></dt>
|
||||||
<dd><dl class="field-list simple">
|
<dd><dl class="field-list simple">
|
||||||
<dt class="field-odd">Returns<span class="colon">:</span></dt>
|
<dt class="field-odd">Returns<span class="colon">:</span></dt>
|
||||||
<dd class="field-odd"><p>The time in seconds since last outbound packet on the link.</p>
|
<dd class="field-odd"><p>The time in seconds since last outbound packet on the link. This includes keepalive packets.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="py method">
|
||||||
|
<dt class="sig sig-object py" id="RNS.Link.no_data_for">
|
||||||
|
<span class="sig-name descname"><span class="pre">no_data_for</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.no_data_for" title="Permalink to this definition">#</a></dt>
|
||||||
|
<dd><dl class="field-list simple">
|
||||||
|
<dt class="field-odd">Returns<span class="colon">:</span></dt>
|
||||||
|
<dd class="field-odd"><p>The time in seconds since payload data traversed the link. This excludes keepalive packets.</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
@@ -1151,7 +1161,7 @@ statistics, you will be able to retrieve stats such as <em>RSSI</em>, <em>SNR</e
|
|||||||
<span class="sig-name descname"><span class="pre">inactive_for</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.inactive_for" title="Permalink to this definition">#</a></dt>
|
<span class="sig-name descname"><span class="pre">inactive_for</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.inactive_for" title="Permalink to this definition">#</a></dt>
|
||||||
<dd><dl class="field-list simple">
|
<dd><dl class="field-list simple">
|
||||||
<dt class="field-odd">Returns<span class="colon">:</span></dt>
|
<dt class="field-odd">Returns<span class="colon">:</span></dt>
|
||||||
<dd class="field-odd"><p>The time in seconds since activity on the link.</p>
|
<dd class="field-odd"><p>The time in seconds since activity on the link. This includes keepalive packets.</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
@@ -1992,6 +2002,7 @@ will announce it.</p>
|
|||||||
<li><a class="reference internal" href="#RNS.Link.get_establishment_rate"><code class="docutils literal notranslate"><span class="pre">get_establishment_rate()</span></code></a></li>
|
<li><a class="reference internal" href="#RNS.Link.get_establishment_rate"><code class="docutils literal notranslate"><span class="pre">get_establishment_rate()</span></code></a></li>
|
||||||
<li><a class="reference internal" href="#RNS.Link.no_inbound_for"><code class="docutils literal notranslate"><span class="pre">no_inbound_for()</span></code></a></li>
|
<li><a class="reference internal" href="#RNS.Link.no_inbound_for"><code class="docutils literal notranslate"><span class="pre">no_inbound_for()</span></code></a></li>
|
||||||
<li><a class="reference internal" href="#RNS.Link.no_outbound_for"><code class="docutils literal notranslate"><span class="pre">no_outbound_for()</span></code></a></li>
|
<li><a class="reference internal" href="#RNS.Link.no_outbound_for"><code class="docutils literal notranslate"><span class="pre">no_outbound_for()</span></code></a></li>
|
||||||
|
<li><a class="reference internal" href="#RNS.Link.no_data_for"><code class="docutils literal notranslate"><span class="pre">no_data_for()</span></code></a></li>
|
||||||
<li><a class="reference internal" href="#RNS.Link.inactive_for"><code class="docutils literal notranslate"><span class="pre">inactive_for()</span></code></a></li>
|
<li><a class="reference internal" href="#RNS.Link.inactive_for"><code class="docutils literal notranslate"><span class="pre">inactive_for()</span></code></a></li>
|
||||||
<li><a class="reference internal" href="#RNS.Link.get_remote_identity"><code class="docutils literal notranslate"><span class="pre">get_remote_identity()</span></code></a></li>
|
<li><a class="reference internal" href="#RNS.Link.get_remote_identity"><code class="docutils literal notranslate"><span class="pre">get_remote_identity()</span></code></a></li>
|
||||||
<li><a class="reference internal" href="#RNS.Link.teardown"><code class="docutils literal notranslate"><span class="pre">teardown()</span></code></a></li>
|
<li><a class="reference internal" href="#RNS.Link.teardown"><code class="docutils literal notranslate"><span class="pre">teardown()</span></code></a></li>
|
||||||
@@ -2078,7 +2089,7 @@ will announce it.</p>
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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="viewport" content="width=device-width,initial-scale=1"/>
|
||||||
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="#" />
|
<meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="genindex.html" /><link rel="search" title="Search" href="#" />
|
||||||
|
|
||||||
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/><title>Search - Reticulum Network Stack 0.6.4 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.2 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/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/copybutton.css?v=76b2166b" />
|
||||||
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="#" role="search">
|
</a><form class="sidebar-search-container" method="get" action="#" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -262,7 +262,7 @@
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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" />
|
<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"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>Support Reticulum - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>Support Reticulum - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -330,7 +330,7 @@ report issues, suggest functionality and contribute code to Reticulum.</p>
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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" />
|
<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"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>Understanding Reticulum - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>Understanding Reticulum - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -1196,7 +1196,7 @@ those risks are acceptable to you.</p>
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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" />
|
<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"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>Using Reticulum on Your System - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>Using Reticulum on Your System - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -1057,7 +1057,7 @@ systemctl --user enable rnsd.service
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></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" />
|
<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"/>
|
<meta name="generator" content="sphinx-7.1.2, furo 2022.09.29.dev1"/>
|
||||||
<title>What is Reticulum? - Reticulum Network Stack 0.6.4 beta documentation</title>
|
<title>What is Reticulum? - Reticulum Network Stack 0.7.2 beta documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=a746c00c" />
|
<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/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/copybutton.css?v=76b2166b" />
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center">
|
<div class="header-center">
|
||||||
<a href="index.html"><div class="brand">Reticulum Network Stack 0.6.4 beta documentation</div></a>
|
<a href="index.html"><div class="brand">Reticulum Network Stack 0.7.2 beta documentation</div></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="theme-toggle-container theme-toggle-header">
|
<div class="theme-toggle-container theme-toggle-header">
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
<img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="sidebar-brand-text">Reticulum Network Stack 0.6.4 beta documentation</span>
|
<span class="sidebar-brand-text">Reticulum Network Stack 0.7.2 beta documentation</span>
|
||||||
|
|
||||||
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
</a><form class="sidebar-search-container" method="get" action="search.html" role="search">
|
||||||
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
<input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
|
||||||
@@ -434,7 +434,7 @@ want to help out with this, or can help sponsor an audit, please do get in touch
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=d9f3c795"></script>
|
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js?v=50521ac4"></script>
|
||||||
<script src="_static/doctools.js?v=888ff710"></script>
|
<script src="_static/doctools.js?v=888ff710"></script>
|
||||||
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
<script src="_static/sphinx_highlight.js?v=4825356b"></script>
|
||||||
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
<script src="_static/scripts/furo.js?v=2c7c1115"></script>
|
||||||
|
|||||||
+29
-4
@@ -140,6 +140,7 @@ class TestLink(unittest.TestCase):
|
|||||||
pstart = time.time()
|
pstart = time.time()
|
||||||
print("Sending "+str(num_packets)+" link packets of "+str(packet_size)+" bytes...")
|
print("Sending "+str(num_packets)+" link packets of "+str(packet_size)+" bytes...")
|
||||||
for i in range(0, num_packets):
|
for i in range(0, num_packets):
|
||||||
|
time.sleep(0.003)
|
||||||
b += packet_size
|
b += packet_size
|
||||||
data = os.urandom(packet_size)
|
data = os.urandom(packet_size)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
@@ -188,6 +189,9 @@ class TestLink(unittest.TestCase):
|
|||||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||||
self.assertEqual(id1.hash, bytes.fromhex(fixed_keys[0][1]))
|
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")
|
dest = RNS.Destination(id1, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, "link", "establish")
|
||||||
|
|
||||||
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||||
@@ -203,6 +207,7 @@ class TestLink(unittest.TestCase):
|
|||||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
|
# This is a hack, don't do it. Use the callbacks instead.
|
||||||
while resource.status < RNS.Resource.COMPLETE:
|
while resource.status < RNS.Resource.COMPLETE:
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
@@ -224,6 +229,9 @@ class TestLink(unittest.TestCase):
|
|||||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||||
self.assertEqual(id1.hash, bytes.fromhex(fixed_keys[0][1]))
|
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")
|
dest = RNS.Destination(id1, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, "link", "establish")
|
||||||
|
|
||||||
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||||
@@ -239,6 +247,7 @@ class TestLink(unittest.TestCase):
|
|||||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
|
# This is a hack, don't do it. Use the callbacks instead.
|
||||||
while resource.status < RNS.Resource.COMPLETE:
|
while resource.status < RNS.Resource.COMPLETE:
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
@@ -260,6 +269,9 @@ class TestLink(unittest.TestCase):
|
|||||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||||
self.assertEqual(id1.hash, bytes.fromhex(fixed_keys[0][1]))
|
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")
|
dest = RNS.Destination(id1, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, "link", "establish")
|
||||||
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||||
|
|
||||||
@@ -274,6 +286,7 @@ class TestLink(unittest.TestCase):
|
|||||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
|
# This is a hack, don't do it. Use the callbacks instead.
|
||||||
while resource.status < RNS.Resource.COMPLETE:
|
while resource.status < RNS.Resource.COMPLETE:
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
@@ -300,6 +313,9 @@ class TestLink(unittest.TestCase):
|
|||||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||||
self.assertEqual(id1.hash, bytes.fromhex(fixed_keys[0][1]))
|
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")
|
dest = RNS.Destination(id1, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, "link", "establish")
|
||||||
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||||
|
|
||||||
@@ -314,6 +330,7 @@ class TestLink(unittest.TestCase):
|
|||||||
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
resource = RNS.Resource(data, l1, timeout=resource_timeout)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
|
# This is a hack, don't do it. Use the callbacks instead.
|
||||||
while resource.status < RNS.Resource.COMPLETE:
|
while resource.status < RNS.Resource.COMPLETE:
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
@@ -325,6 +342,10 @@ class TestLink(unittest.TestCase):
|
|||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
self.assertEqual(l1.status, RNS.Link.CLOSED)
|
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")
|
@skipIf(os.getenv('SKIP_NORMAL_TESTS') != None, "Skipping")
|
||||||
def test_9_large_resource(self):
|
def test_9_large_resource(self):
|
||||||
if RNS.Cryptography.backend() == "internal":
|
if RNS.Cryptography.backend() == "internal":
|
||||||
@@ -339,6 +360,9 @@ class TestLink(unittest.TestCase):
|
|||||||
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
id1 = RNS.Identity.from_bytes(bytes.fromhex(fixed_keys[0][0]))
|
||||||
self.assertEqual(id1.hash, bytes.fromhex(fixed_keys[0][1]))
|
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")
|
dest = RNS.Destination(id1, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, "link", "establish")
|
||||||
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
self.assertEqual(dest.hash, bytes.fromhex("fb48da0e82e6e01ba0c014513f74540d"))
|
||||||
|
|
||||||
@@ -347,17 +371,18 @@ class TestLink(unittest.TestCase):
|
|||||||
self.assertEqual(l1.status, RNS.Link.ACTIVE)
|
self.assertEqual(l1.status, RNS.Link.ACTIVE)
|
||||||
|
|
||||||
resource_timeout = 120
|
resource_timeout = 120
|
||||||
resource_size = 35*1000*1000
|
resource_size = 50*1000*1000
|
||||||
data = os.urandom(resource_size)
|
data = os.urandom(resource_size)
|
||||||
print("Sending "+self.size_str(resource_size)+" resource...")
|
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()
|
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)
|
time.sleep(0.01)
|
||||||
|
|
||||||
t = time.time() - start
|
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")
|
print("Resource completed at "+self.size_str(resource_size/t, "b")+"ps")
|
||||||
|
|
||||||
l1.teardown()
|
l1.teardown()
|
||||||
|
|||||||
Reference in New Issue
Block a user