mirror of
https://github.com/markqvist/reticulum-cpp.git
synced 2024-10-01 02:55:46 -04:00
WIP update
Minimal transport implementation.
This commit is contained in:
parent
18ed42b40f
commit
a2e956eced
@ -11,16 +11,10 @@
|
||||
[platformio]
|
||||
;default_envs = native
|
||||
|
||||
[env:avr-test]
|
||||
platform = atmelavr
|
||||
board = megaatmega2560
|
||||
framework = arduino
|
||||
debug_tool = simavr
|
||||
|
||||
[env:native]
|
||||
platform = native
|
||||
build_flags =
|
||||
-std=c++11
|
||||
-std=c++11
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wno-missing-field-initializers
|
||||
@ -28,7 +22,7 @@ build_flags =
|
||||
-Isrc
|
||||
-DNATIVE
|
||||
lib_deps =
|
||||
; rweather/Crypto@^0.4.0
|
||||
rweather/Crypto@^0.4.0
|
||||
lib_compat_mode = off
|
||||
|
||||
[env:ttgo-t-beam]
|
||||
|
38
src/Bytes.h
38
src/Bytes.h
@ -29,30 +29,30 @@ namespace RNS {
|
||||
|
||||
public:
|
||||
Bytes() {
|
||||
//extreme("Bytes object created from default, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_data.get()));
|
||||
//extreme("Bytes object created from default, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
}
|
||||
Bytes(NoneConstructor none) {
|
||||
//extreme("Bytes object created from NONE, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_data.get()));
|
||||
//extreme("Bytes object created from NONE, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
}
|
||||
Bytes(const Bytes &bytes) {
|
||||
//extreme("Bytes is using shared data");
|
||||
assign(bytes);
|
||||
//extreme("Bytes object copy created from bytes \"" + toString() + "\", this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_data.get()));
|
||||
//extreme("Bytes object copy created from bytes \"" + toString() + "\", this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
}
|
||||
Bytes(const uint8_t *chunk, size_t size) {
|
||||
assign(chunk, size);
|
||||
//extreme(std::string("Bytes object created from chunk \"") + toString() + "\", this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_data.get()));
|
||||
//extreme(std::string("Bytes object created from chunk \"") + toString() + "\", this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
}
|
||||
Bytes(const char *string) {
|
||||
assign(string);
|
||||
//extreme(std::string("Bytes object created from string \"") + toString() + "\", this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_data.get()));
|
||||
//extreme(std::string("Bytes object created from string \"") + toString() + "\", this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
}
|
||||
Bytes(const std::string &string) {
|
||||
assign(string);
|
||||
//extreme(std::string("Bytes object created from std::string \"") + toString() + "\", this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_data.get()));
|
||||
//extreme(std::string("Bytes object created from std::string \"") + toString() + "\", this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
}
|
||||
~Bytes() {
|
||||
//extreme(std::string("Bytes object destroyed \"") + toString() + "\", this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_data.get()));
|
||||
virtual ~Bytes() {
|
||||
//extreme(std::string("Bytes object destroyed \"") + toString() + "\", this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
}
|
||||
|
||||
inline Bytes& operator = (const Bytes &bytes) {
|
||||
@ -206,6 +206,28 @@ namespace RNS {
|
||||
inline Bytes left(size_t len) const { if (!_data) return NONE; if (len > size()) len = size(); return {data(), len}; }
|
||||
inline Bytes right(size_t len) const { if (!_data) return NONE; if (len > size()) len = size(); return {data() + (size() - len), len}; }
|
||||
|
||||
// Python array indexing
|
||||
// [8:16]
|
||||
// pos 8 to pos 16
|
||||
// mid(8, 8)
|
||||
// [:16]
|
||||
// start to pos 16 (same as first 16)
|
||||
// left(16)
|
||||
// [16:]
|
||||
// pos 16 to end
|
||||
// mid(16)
|
||||
// [-16:]
|
||||
// last 16
|
||||
// right(16)
|
||||
// [:-16]
|
||||
// all except the last 16
|
||||
// left(size()-16)
|
||||
// mid(0, size()-16)
|
||||
// [-1]
|
||||
// last element
|
||||
// [-2]
|
||||
// second to last element
|
||||
|
||||
private:
|
||||
SharedData _data;
|
||||
mutable bool _owner = true;
|
||||
|
@ -21,28 +21,6 @@ Fernet::Fernet(const Bytes &key) {
|
||||
throw std::invalid_argument("Fernet key must be 32 bytes, not " + std::to_string(key.size()));
|
||||
}
|
||||
|
||||
// Python array indexing
|
||||
// [8:16]
|
||||
// pos 8 to pos 16
|
||||
// mid(8, 8)
|
||||
// [:16]
|
||||
// start to pos 16 (same as first 16)
|
||||
// left(16)
|
||||
// [16:]
|
||||
// pos 16 to end
|
||||
// mid(16)
|
||||
// [-16:]
|
||||
// last 16
|
||||
// right(16)
|
||||
// [:-16]
|
||||
// all except the last 16
|
||||
// left(size()-16)
|
||||
// mid(0, size()-16)
|
||||
// [-1]
|
||||
// last element
|
||||
// [-2]
|
||||
// seocnd to last element
|
||||
|
||||
//self._signing_key = key[:16]
|
||||
_signing_key = key.left(16);
|
||||
//self._encryption_key = key[16:]
|
||||
|
@ -31,11 +31,15 @@ namespace RNS { namespace Cryptography {
|
||||
//debug("PKCS7::pad: len: " + std::to_string(len));
|
||||
size_t padlen = bs - (len % bs);
|
||||
//debug("PKCS7::pad: pad len: " + std::to_string(padlen));
|
||||
// create byte array of size n?
|
||||
//v = bytes([padlen])
|
||||
uint8_t pad[padlen] = {0};
|
||||
// create zero-filled byte padding array of size padlen
|
||||
//p v = bytes([padlen])
|
||||
//uint8_t pad[padlen] = {0};
|
||||
uint8_t pad[padlen];
|
||||
memset(pad, 0, padlen);
|
||||
// set last byte of padding array to size of padding
|
||||
pad[padlen-1] = (uint8_t)padlen;
|
||||
//return data+v*padlen
|
||||
// concatenate data with padding
|
||||
//p return data+v*padlen
|
||||
data.append(pad, padlen);
|
||||
//debug("PKCS7::pad: data size: " + std::to_string(data.size()));
|
||||
}
|
||||
@ -44,13 +48,14 @@ namespace RNS { namespace Cryptography {
|
||||
static inline void inplace_unpad(Bytes &data, size_t bs = BLOCKSIZE) {
|
||||
size_t len = data.size();
|
||||
//debug("PKCS7::unpad: len: " + std::to_string(len));
|
||||
// last byte is pad length
|
||||
// read last byte which is pad length
|
||||
//pad = data[-1]
|
||||
size_t padlen = (size_t)data.data()[data.size()-1];
|
||||
//debug("PKCS7::unpad: pad len: " + std::to_string(padlen));
|
||||
if (padlen > bs) {
|
||||
throw std::runtime_error("Cannot unpad, invalid padding length of " + std::to_string(padlen) + " bytes");
|
||||
}
|
||||
// truncate data to strip padding
|
||||
//return data[:len-padlen]
|
||||
data.resize(len - padlen);
|
||||
//debug("PKCS7::unpad: data size: " + std::to_string(data.size()));
|
||||
|
@ -7,10 +7,32 @@
|
||||
|
||||
namespace RNS { namespace Cryptography {
|
||||
|
||||
// return vector specified length of random bytes
|
||||
inline Bytes random(size_t length) {
|
||||
Bytes rand;
|
||||
RNG.rand(rand.writable(length), length);
|
||||
return rand;
|
||||
}
|
||||
|
||||
// return 32 bit random unigned int
|
||||
inline uint32_t randomnum() {
|
||||
Bytes rand;
|
||||
RNG.rand(rand.writable(4), 4);
|
||||
uint32_t randnum = uint32_t((unsigned char)(rand.data()[0]) << 24 |
|
||||
(unsigned char)(rand.data()[0]) << 16 |
|
||||
(unsigned char)(rand.data()[0]) << 8 |
|
||||
(unsigned char)(rand.data()[0]));
|
||||
return randnum;
|
||||
}
|
||||
|
||||
// return 32 bit random unigned int between 0 and specified value
|
||||
inline uint32_t randomnum(uint32_t max) {
|
||||
return randomnum() % max;
|
||||
}
|
||||
|
||||
// return random float value from 0 to 1
|
||||
inline float random() {
|
||||
return (float)(randomnum() / (float)0xffffffff);
|
||||
}
|
||||
|
||||
} }
|
||||
|
@ -55,8 +55,8 @@ namespace RNS { namespace Cryptography {
|
||||
class X25519PrivateKey {
|
||||
|
||||
public:
|
||||
const float MIN_EXEC_TIME = 0.002;
|
||||
const float MAX_EXEC_TIME = 0.5;
|
||||
const float MIN_EXEC_TIME = 2; // in milliseconds
|
||||
const float MAX_EXEC_TIME = 500; // in milliseconds
|
||||
const uint8_t DELAY_WINDOW = 10;
|
||||
|
||||
//zT_CLEAR = None
|
||||
@ -134,11 +134,11 @@ namespace RNS { namespace Cryptography {
|
||||
if isinstance(peer_public_key, bytes):
|
||||
peer_public_key = X25519PublicKey.from_public_bytes(peer_public_key)
|
||||
|
||||
start = time.time()
|
||||
start = OS::time()
|
||||
|
||||
shared = _pack_number(_raw_curve25519(peer_public_key.x, _a))
|
||||
|
||||
end = time.time()
|
||||
end = OS::time()
|
||||
duration = end-start
|
||||
|
||||
if X25519PrivateKey.T_CLEAR == None:
|
||||
@ -158,7 +158,7 @@ namespace RNS { namespace Cryptography {
|
||||
target = start+X25519PrivateKey.MIN_EXEC_TIME
|
||||
|
||||
try:
|
||||
time.sleep(target-time.time())
|
||||
OS::sleep(target-OS::time())
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
|
@ -54,10 +54,6 @@ Destination::Destination(const Identity &identity, const directions direction, c
|
||||
extreme("Destination object created");
|
||||
}
|
||||
|
||||
Destination::~Destination() {
|
||||
extreme("Destination object destroyed");
|
||||
}
|
||||
|
||||
/*
|
||||
:returns: A destination name in adressable hash form, for an app_name and a number of aspects.
|
||||
*/
|
||||
@ -124,7 +120,7 @@ Packet Destination::announce(const Bytes &app_data, bool path_response, Interfac
|
||||
// vector
|
||||
//Response &entry = *it;
|
||||
// map
|
||||
Response &entry = (*it).second;
|
||||
PathResponse &entry = (*it).second;
|
||||
if (now > (entry.first + Destination::PR_TAG_WINDOW)) {
|
||||
it = _object->_path_responses.erase(it);
|
||||
}
|
||||
@ -218,6 +214,7 @@ Packet Destination::announce(const Bytes &app_data, bool path_response, Interfac
|
||||
Packet announce_packet(*this, announce_data, Packet::ANNOUNCE, announce_context, Transport::BROADCAST, Packet::HEADER_1, nullptr, attached_interface);
|
||||
|
||||
if (send) {
|
||||
debug("Destination::announce: sending announce packet...");
|
||||
announce_packet.send();
|
||||
return Packet::NONE;
|
||||
}
|
||||
|
@ -1,15 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "Reticulum.h"
|
||||
#include "Link.h"
|
||||
#include "Identity.h"
|
||||
#include "Bytes.h"
|
||||
#include "None.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace RNS {
|
||||
@ -17,6 +18,7 @@ namespace RNS {
|
||||
class Interface;
|
||||
class Packet;
|
||||
class Link;
|
||||
class Identity;
|
||||
|
||||
/**
|
||||
* @brief A class used to describe endpoints in a Reticulum Network. Destination
|
||||
@ -40,7 +42,7 @@ namespace RNS {
|
||||
using link_established = void(*)(const Link &link);
|
||||
//using packet = void(*)(uint8_t *data, uint16_t data_len, Packet *packet);
|
||||
using packet = void(*)(const Bytes &data, const Packet &packet);
|
||||
using proof_requested = void(*)(const Packet &packet);
|
||||
using proof_requested = bool(*)(const Packet &packet);
|
||||
public:
|
||||
link_established _link_established = nullptr;
|
||||
packet _packet = nullptr;
|
||||
@ -49,8 +51,8 @@ namespace RNS {
|
||||
};
|
||||
|
||||
//typedef std::pair<time_t, std::string> Response;
|
||||
using Response = std::pair<time_t, Bytes>;
|
||||
//using Response = std::pair<time_t, std::vector<uint8_t>>;
|
||||
using PathResponse = std::pair<time_t, Bytes>;
|
||||
//using PathResponse = std::pair<time_t, std::vector<uint8_t>>;
|
||||
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
@ -87,20 +89,28 @@ namespace RNS {
|
||||
Destination(NoneConstructor none) {
|
||||
extreme("Destination NONE object created");
|
||||
}
|
||||
Destination(RNS::NoneConstructor none) {
|
||||
extreme("Destination NONE object created");
|
||||
}
|
||||
Destination(const Destination &destination) : _object(destination._object) {
|
||||
extreme("Destination object copy created");
|
||||
}
|
||||
Destination(const Identity &identity, const directions direction, const types type, const char* app_name, const char *aspects);
|
||||
~Destination();
|
||||
virtual ~Destination() {
|
||||
extreme("Destination object destroyed");
|
||||
}
|
||||
|
||||
inline Destination& operator = (const Destination &destination) {
|
||||
_object = destination._object;
|
||||
extreme("Destination object copy created by assignment, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((uint32_t)_object.get()));
|
||||
extreme("Destination object copy created by assignment, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
return *this;
|
||||
}
|
||||
inline operator bool() const {
|
||||
return _object.get() != nullptr;
|
||||
}
|
||||
inline bool operator < (const Destination &destination) const {
|
||||
return _object.get() < destination._object.get();
|
||||
}
|
||||
|
||||
public:
|
||||
static Bytes hash(const Identity &identity, const char *app_name, const char *aspects);
|
||||
@ -172,12 +182,15 @@ namespace RNS {
|
||||
|
||||
// getters/setters
|
||||
inline types type() const { assert(_object); return _object->_type; }
|
||||
inline directions _direction() const { assert(_object); return _object->_direction; }
|
||||
inline proof_strategies _proof_strategy() const { assert(_object); return _object->_proof_strategy; }
|
||||
inline directions direction() const { assert(_object); return _object->_direction; }
|
||||
inline proof_strategies proof_strategy() const { assert(_object); return _object->_proof_strategy; }
|
||||
inline Bytes hash() const { assert(_object); return _object->_hash; }
|
||||
inline Bytes link_id() const { assert(_object); return _object->_link_id; }
|
||||
inline uint16_t mtu() const { assert(_object); return _object->_mtu; }
|
||||
inline void mtu(uint16_t mtu) { assert(_object); _object->_mtu = mtu; }
|
||||
inline Link::status status() const { assert(_object); return _object->_status; }
|
||||
inline const Callbacks &callbacks() const { assert(_object); return _object->_callbacks; }
|
||||
inline const Identity &identity() const { assert(_object); return _object->_identity; }
|
||||
|
||||
inline std::string toString() const { assert(_object); return "{Destination:" + _object->_hash.toHex() + "}"; }
|
||||
|
||||
@ -185,6 +198,7 @@ namespace RNS {
|
||||
class Object {
|
||||
public:
|
||||
Object(const Identity &identity) : _identity(identity) {}
|
||||
virtual ~Object() {}
|
||||
private:
|
||||
bool _accept_link_requests = true;
|
||||
Callbacks _callbacks;
|
||||
@ -194,8 +208,8 @@ namespace RNS {
|
||||
proof_strategies _proof_strategy = PROVE_NONE;
|
||||
uint16_t _mtu = 0;
|
||||
|
||||
//std::vector<Response> _path_responses;
|
||||
std::map<Bytes, Response> _path_responses;
|
||||
//std::vector<PathResponse> _path_responses;
|
||||
std::map<Bytes, PathResponse> _path_responses;
|
||||
//z_links = []
|
||||
|
||||
Identity _identity;
|
||||
@ -214,6 +228,9 @@ namespace RNS {
|
||||
// CBA _link_id is expected by packet but only present in Link
|
||||
// CBA TODO determine if Link needs to inherit from Destination or vice-versa
|
||||
Bytes _link_id;
|
||||
|
||||
Link::status _status;
|
||||
|
||||
friend class Destination;
|
||||
};
|
||||
std::shared_ptr<Object> _object;
|
||||
|
@ -16,7 +16,7 @@ Identity::Identity(bool create_keys) : _object(new Object()) {
|
||||
if (create_keys) {
|
||||
createKeys();
|
||||
}
|
||||
extreme("Identity object created, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_object.get()));
|
||||
extreme("Identity object created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
|
||||
|
||||
@ -49,6 +49,81 @@ void Identity::createKeys() {
|
||||
}
|
||||
|
||||
|
||||
/*static*/ bool Identity::validate_announce(const Packet &packet) {
|
||||
/*
|
||||
try:
|
||||
if packet.packet_type == RNS.Packet.ANNOUNCE:
|
||||
destination_hash = packet.destination_hash
|
||||
public_key = packet.data[:Identity.KEYSIZE//8]
|
||||
name_hash = packet.data[Identity.KEYSIZE//8:Identity.KEYSIZE//8+Identity.NAME_HASH_LENGTH//8]
|
||||
random_hash = packet.data[Identity.KEYSIZE//8+Identity.NAME_HASH_LENGTH//8:Identity.KEYSIZE//8+Identity.NAME_HASH_LENGTH//8+10]
|
||||
signature = packet.data[Identity.KEYSIZE//8+Identity.NAME_HASH_LENGTH//8+10:Identity.KEYSIZE//8+Identity.NAME_HASH_LENGTH//8+10+Identity.SIGLENGTH//8]
|
||||
app_data = b""
|
||||
if len(packet.data) > Identity.KEYSIZE//8+Identity.NAME_HASH_LENGTH//8+10+Identity.SIGLENGTH//8:
|
||||
app_data = packet.data[Identity.KEYSIZE//8+Identity.NAME_HASH_LENGTH//8+10+Identity.SIGLENGTH//8:]
|
||||
|
||||
signed_data = destination_hash+public_key+name_hash+random_hash+app_data
|
||||
|
||||
if not len(packet.data) > Identity.KEYSIZE//8+Identity.NAME_HASH_LENGTH//8+10+Identity.SIGLENGTH//8:
|
||||
app_data = None
|
||||
|
||||
announced_identity = Identity(create_keys=False)
|
||||
announced_identity.load_public_key(public_key)
|
||||
|
||||
if announced_identity.pub != None and announced_identity.validate(signature, signed_data):
|
||||
hash_material = name_hash+announced_identity.hash
|
||||
expected_hash = RNS.Identity.full_hash(hash_material)[:RNS.Reticulum.TRUNCATED_HASHLENGTH//8]
|
||||
|
||||
if destination_hash == expected_hash:
|
||||
# Check if we already have a public key for this destination
|
||||
# and make sure the public key is not different.
|
||||
if destination_hash in Identity.known_destinations:
|
||||
if public_key != Identity.known_destinations[destination_hash][2]:
|
||||
# In reality, this should never occur, but in the odd case
|
||||
# that someone manages a hash collision, we reject the announce.
|
||||
RNS.log("Received announce with valid signature and destination hash, but announced public key does not match already known public key.", RNS.LOG_CRITICAL)
|
||||
RNS.log("This may indicate an attempt to modify network paths, or a random hash collision. The announce was rejected.", RNS.LOG_CRITICAL)
|
||||
return False
|
||||
|
||||
RNS.Identity.remember(packet.get_hash(), destination_hash, public_key, app_data)
|
||||
del announced_identity
|
||||
|
||||
if packet.rssi != None or packet.snr != None:
|
||||
signal_str = " ["
|
||||
if packet.rssi != None:
|
||||
signal_str += "RSSI "+str(packet.rssi)+"dBm"
|
||||
if packet.snr != None:
|
||||
signal_str += ", "
|
||||
if packet.snr != None:
|
||||
signal_str += "SNR "+str(packet.snr)+"dB"
|
||||
signal_str += "]"
|
||||
else:
|
||||
signal_str = ""
|
||||
|
||||
if hasattr(packet, "transport_id") and packet.transport_id != None:
|
||||
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" "+str(packet.hops)+" hops away, received via "+RNS.prettyhexrep(packet.transport_id)+" on "+str(packet.receiving_interface)+signal_str, RNS.LOG_EXTREME)
|
||||
else:
|
||||
RNS.log("Valid announce for "+RNS.prettyhexrep(destination_hash)+" "+str(packet.hops)+" hops away, received on "+str(packet.receiving_interface)+signal_str, RNS.LOG_EXTREME)
|
||||
|
||||
return True
|
||||
|
||||
else:
|
||||
RNS.log("Received invalid announce for "+RNS.prettyhexrep(destination_hash)+": Destination mismatch.", RNS.LOG_DEBUG)
|
||||
return False
|
||||
|
||||
else:
|
||||
RNS.log("Received invalid announce for "+RNS.prettyhexrep(destination_hash)+": Invalid signature.", RNS.LOG_DEBUG)
|
||||
del announced_identity
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Error occurred while validating announce. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
return False
|
||||
*/
|
||||
// MOCK
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Encrypts information for the identity.
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
//#include "Destination.h"
|
||||
#include "Log.h"
|
||||
#include "Bytes.h"
|
||||
#include "None.h"
|
||||
#include "Cryptography/Hashes.h"
|
||||
#include "Cryptography/Ed25519.h"
|
||||
#include "Cryptography/X25519.h"
|
||||
@ -46,24 +47,30 @@ namespace RNS {
|
||||
|
||||
public:
|
||||
Identity(NoneConstructor none) {
|
||||
extreme("Identity NONE object created, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_object.get()));
|
||||
extreme("Identity NONE object created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
Identity(RNS::NoneConstructor none) {
|
||||
extreme("Identity NONE object created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
Identity(const Identity &identity) : _object(identity._object) {
|
||||
extreme("Identity object copy created, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_object.get()));
|
||||
extreme("Identity object copy created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
Identity(bool create_keys = true);
|
||||
~Identity() {
|
||||
extreme("Identity object destroyed, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((ulong)_object.get()));
|
||||
virtual ~Identity() {
|
||||
extreme("Identity object destroyed, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
|
||||
inline Identity& operator = (const Identity &identity) {
|
||||
_object = identity._object;
|
||||
extreme("Identity object copy created by assignment, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((uint32_t)_object.get()));
|
||||
extreme("Identity object copy created by assignment, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
return *this;
|
||||
}
|
||||
inline operator bool() const {
|
||||
return _object.get() != nullptr;
|
||||
}
|
||||
inline bool operator < (const Identity &identity) const {
|
||||
return _object.get() < identity._object.get();
|
||||
}
|
||||
|
||||
public:
|
||||
void createKeys();
|
||||
@ -110,6 +117,8 @@ namespace RNS {
|
||||
return truncated_hash(Cryptography::random(Identity::TRUNCATED_HASHLENGTH/8));
|
||||
}
|
||||
|
||||
static bool validate_announce(const Packet &packet);
|
||||
|
||||
inline Bytes get_salt() { assert(_object); return _object->_hash; }
|
||||
inline Bytes get_context() { return Bytes::NONE; }
|
||||
|
||||
@ -133,8 +142,8 @@ namespace RNS {
|
||||
private:
|
||||
class Object {
|
||||
public:
|
||||
Object() { extreme("Identity::Data object created, this: " + std::to_string((ulong)this)); }
|
||||
~Object() { extreme("Identity::Data object destroyed, this: " + std::to_string((ulong)this)); }
|
||||
Object() { extreme("Identity::Data object created, this: " + std::to_string((uintptr_t)this)); }
|
||||
virtual ~Object() { extreme("Identity::Data object destroyed, this: " + std::to_string((uintptr_t)this)); }
|
||||
private:
|
||||
|
||||
RNS::Cryptography::X25519PrivateKey::Ptr _prv;
|
||||
|
@ -1,14 +1,65 @@
|
||||
#include "Interface.h"
|
||||
|
||||
#include "Log.h"
|
||||
#include "../Transport.h"
|
||||
|
||||
using namespace RNS;
|
||||
|
||||
Interface::Interface() {
|
||||
extreme("Interface object created");
|
||||
|
||||
/*virtual*/ inline void Interface::processIncoming(const Bytes &data) {
|
||||
extreme("Interface::processIncoming: data: " + data.toHex());
|
||||
assert(_object);
|
||||
_object->_rxb += data.size();
|
||||
// CBA TODO implement concept of owner or a callback mechanism for incoming data
|
||||
//_object->_owner.inbound(data, *this);
|
||||
Transport::inbound(data, *this);
|
||||
}
|
||||
|
||||
Interface::~Interface() {
|
||||
extreme("Interface object destroyed");
|
||||
/*virtual*/ inline void Interface::processOutgoing(const Bytes &data) {
|
||||
extreme("Interface::processOutgoing: data: " + data.toHex());
|
||||
assert(_object);
|
||||
_object->_txb += data.size();
|
||||
}
|
||||
|
||||
void Interface::process_announce_queue() {
|
||||
/*
|
||||
if not hasattr(self, "announce_cap"):
|
||||
self.announce_cap = RNS.Reticulum.ANNOUNCE_CAP
|
||||
|
||||
if hasattr(self, "announce_queue"):
|
||||
try:
|
||||
now = time.time()
|
||||
stale = []
|
||||
for a in self.announce_queue:
|
||||
if now > a["time"]+RNS.Reticulum.QUEUED_ANNOUNCE_LIFE:
|
||||
stale.append(a)
|
||||
|
||||
for s in stale:
|
||||
if s in self.announce_queue:
|
||||
self.announce_queue.remove(s)
|
||||
|
||||
if len(self.announce_queue) > 0:
|
||||
min_hops = min(entry["hops"] for entry in self.announce_queue)
|
||||
entries = list(filter(lambda e: e["hops"] == min_hops, self.announce_queue))
|
||||
entries.sort(key=lambda e: e["time"])
|
||||
selected = entries[0]
|
||||
|
||||
now = time.time()
|
||||
tx_time = (len(selected["raw"])*8) / self.bitrate
|
||||
wait_time = (tx_time / self.announce_cap)
|
||||
self.announce_allowed_at = now + wait_time
|
||||
|
||||
self.processOutgoing(selected["raw"])
|
||||
|
||||
if selected in self.announce_queue:
|
||||
self.announce_queue.remove(selected)
|
||||
|
||||
if len(self.announce_queue) > 0:
|
||||
timer = threading.Timer(wait_time, self.process_announce_queue)
|
||||
timer.start()
|
||||
|
||||
except Exception as e:
|
||||
self.announce_queue = []
|
||||
RNS.log("Error while processing announce queue on "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
RNS.log("The announce queue for this interface has been cleared.", RNS.LOG_ERROR)
|
||||
*/
|
||||
}
|
||||
|
@ -1,13 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Log.h"
|
||||
#include "../Bytes.h"
|
||||
#include "../None.h"
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace RNS {
|
||||
|
||||
class Interface {
|
||||
|
||||
public:
|
||||
class AnnounceEntry {
|
||||
public:
|
||||
AnnounceEntry() {}
|
||||
AnnounceEntry(const Bytes &destination, uint64_t time, uint8_t hops, uint64_t emitted, const Bytes &raw) :
|
||||
_destination(destination),
|
||||
_time(time),
|
||||
_hops(hops),
|
||||
_emitted(emitted),
|
||||
_raw(raw) {}
|
||||
public:
|
||||
Bytes _destination;
|
||||
uint64_t _time = 0;
|
||||
uint8_t _hops = 0;
|
||||
uint64_t _emitted = 0;
|
||||
Bytes _raw;
|
||||
};
|
||||
|
||||
public:
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
@ -16,42 +38,106 @@ namespace RNS {
|
||||
public:
|
||||
// Interface mode definitions
|
||||
enum modes {
|
||||
MODE_FULL = 0x01,
|
||||
MODE_POINT_TO_POINT = 0x02,
|
||||
MODE_ACCESS_POINT = 0x03,
|
||||
MODE_ROAMING = 0x04,
|
||||
MODE_BOUNDARY = 0x05,
|
||||
MODE_GATEWAY = 0x06,
|
||||
MODE_NONE = 0x00,
|
||||
MODE_FULL = 0x01,
|
||||
MODE_POINT_TO_POINT = 0x04,
|
||||
MODE_ACCESS_POINT = 0x08,
|
||||
MODE_ROAMING = 0x10,
|
||||
MODE_BOUNDARY = 0x20,
|
||||
MODE_GATEWAY = 0x40,
|
||||
};
|
||||
|
||||
// Which interface modes a Transport Node
|
||||
// should actively discover paths for.
|
||||
//zDISCOVER_PATHS_FOR = [MODE_ACCESS_POINT, MODE_GATEWAY]
|
||||
uint8_t DISCOVER_PATHS_FOR = MODE_ACCESS_POINT | MODE_GATEWAY;
|
||||
|
||||
public:
|
||||
public:
|
||||
Interface(NoneConstructor none) {
|
||||
extreme("Interface object NONE created");
|
||||
}
|
||||
Interface(RNS::NoneConstructor none) {
|
||||
extreme("Interface object NONE created");
|
||||
}
|
||||
Interface(const Interface &interface) : _object(interface._object) {
|
||||
extreme("Interface object copy created");
|
||||
}
|
||||
Interface();
|
||||
~Interface();
|
||||
Interface() : _object(new Object()) {
|
||||
extreme("Interface object created");
|
||||
}
|
||||
Interface(const char *name) : _object(new Object(name)) {
|
||||
extreme("Interface object created");
|
||||
}
|
||||
virtual ~Interface() {
|
||||
extreme("Interface object destroyed");
|
||||
}
|
||||
|
||||
inline Interface& operator = (const Interface &interface) {
|
||||
_object = interface._object;
|
||||
extreme("Interface object copy created by assignment, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((uint32_t)_object.get()));
|
||||
extreme("Interface object copy created by assignment, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
return *this;
|
||||
}
|
||||
inline operator bool() const {
|
||||
return _object.get() != nullptr;
|
||||
}
|
||||
inline bool operator < (const Interface &interface) const {
|
||||
return _object.get() < interface._object.get();
|
||||
}
|
||||
|
||||
public:
|
||||
inline Bytes get_hash() const { /*return Identity::full_hash();*/ return {}; }
|
||||
void process_announce_queue();
|
||||
inline void detach() {}
|
||||
|
||||
virtual void processIncoming(const Bytes &data);
|
||||
virtual void processOutgoing(const Bytes &data);
|
||||
|
||||
inline void add_announce(AnnounceEntry &entry) { assert(_object); _object->_announce_queue.push_back(entry); }
|
||||
|
||||
// getters/setters
|
||||
protected:
|
||||
inline void IN(bool IN) { assert(_object); _object->_IN = IN; }
|
||||
inline void OUT(bool OUT) { assert(_object); _object->_OUT = OUT; }
|
||||
inline void FWD(bool FWD) { assert(_object); _object->_FWD = FWD; }
|
||||
inline void RPT(bool RPT) { assert(_object); _object->_RPT = RPT; }
|
||||
inline void name(const char *name) { assert(_object); _object->_name = name; }
|
||||
public:
|
||||
inline bool IN() const { assert(_object); return _object->_IN; }
|
||||
inline bool OUT() const { assert(_object); return _object->_OUT; }
|
||||
inline bool FWD() const { assert(_object); return _object->_FWD; }
|
||||
inline bool RPT() const { assert(_object); return _object->_RPT; }
|
||||
inline std::string name() const { assert(_object); return _object->_name; }
|
||||
inline Bytes ifac_identity() const { assert(_object); return _object->_ifac_identity; }
|
||||
inline modes mode() const { assert(_object); return _object->_mode; }
|
||||
inline uint32_t bitrate() const { assert(_object); return _object->_bitrate; }
|
||||
inline uint64_t announce_allowed_at() const { assert(_object); return _object->_announce_allowed_at; }
|
||||
inline void announce_allowed_at(uint64_t announce_allowed_at) { assert(_object); _object->_announce_allowed_at = announce_allowed_at; }
|
||||
inline float announce_cap() const { assert(_object); return _object->_announce_cap; }
|
||||
inline std::list<AnnounceEntry> announce_queue() const { assert(_object); return _object->_announce_queue; }
|
||||
|
||||
virtual inline std::string toString() const { assert(_object); return "Interface[" + _object->_name + "]"; }
|
||||
|
||||
private:
|
||||
class Object {
|
||||
public:
|
||||
Object() {}
|
||||
Object(const char *name) : _name(name) {}
|
||||
virtual ~Object() {}
|
||||
private:
|
||||
|
||||
|
||||
bool _IN = false;
|
||||
bool _OUT = false;
|
||||
bool _FWD = false;
|
||||
bool _RPT = false;
|
||||
std::string _name;
|
||||
size_t _rxb = 0;
|
||||
size_t _txb = 0;
|
||||
bool online = false;
|
||||
Bytes _ifac_identity;
|
||||
modes _mode = MODE_NONE;
|
||||
uint32_t _bitrate = 0;
|
||||
uint64_t _announce_allowed_at = 0;
|
||||
float _announce_cap = 0.0;
|
||||
std::list<AnnounceEntry> _announce_queue;
|
||||
//Transport &_owner;
|
||||
friend class Interface;
|
||||
};
|
||||
std::shared_ptr<Object> _object;
|
||||
|
16
src/Link.cpp
16
src/Link.cpp
@ -1,14 +1,22 @@
|
||||
#include "Link.h"
|
||||
|
||||
#include "Packet.h"
|
||||
#include "Log.h"
|
||||
|
||||
using namespace RNS;
|
||||
|
||||
Link::Link() {
|
||||
log("Link object created", LOG_EXTREME);
|
||||
Link::Link() : _object(new Object()) {
|
||||
assert(_object);
|
||||
|
||||
extreme("Link object created");
|
||||
}
|
||||
|
||||
Link::~Link() {
|
||||
log("Link object destroyed", LOG_EXTREME);
|
||||
|
||||
void Link::set_link_id(const Packet &packet) {
|
||||
assert(_object);
|
||||
_object->_link_id = packet.getTruncatedHash();
|
||||
_object->_hash = _object->_link_id;
|
||||
}
|
||||
|
||||
void Link::receive(const Packet &packet) {
|
||||
}
|
||||
|
68
src/Link.h
68
src/Link.h
@ -2,6 +2,12 @@
|
||||
|
||||
#include "Reticulum.h"
|
||||
#include "Identity.h"
|
||||
// CBA TODO resolve circular dependency with following header file
|
||||
//#include "Packet.h"
|
||||
#include "Bytes.h"
|
||||
#include "None.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace RNS {
|
||||
|
||||
@ -14,6 +20,10 @@ namespace RNS {
|
||||
typedef void (*closed)(Link *link);
|
||||
};
|
||||
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
static constexpr const char* CURVE = Identity::CURVE;
|
||||
// The curve used for Elliptic Curve DH key exchanges
|
||||
|
||||
@ -51,20 +61,64 @@ namespace RNS {
|
||||
};
|
||||
|
||||
enum teardown_reasons {
|
||||
TIMEOUT = 0x01,
|
||||
INITIATOR_CLOSED = 0x02,
|
||||
DESTINATION_CLOSED = 0x03,
|
||||
TIMEOUT = 0x01,
|
||||
INITIATOR_CLOSED = 0x02,
|
||||
DESTINATION_CLOSED = 0x03,
|
||||
};
|
||||
|
||||
enum resource_strategies {
|
||||
ACCEPT_NONE = 0x00,
|
||||
ACCEPT_APP = 0x01,
|
||||
ACCEPT_ALL = 0x02,
|
||||
ACCEPT_NONE = 0x00,
|
||||
ACCEPT_APP = 0x01,
|
||||
ACCEPT_ALL = 0x02,
|
||||
};
|
||||
|
||||
public:
|
||||
Link(NoneConstructor none) {
|
||||
extreme("Link NONE object created");
|
||||
}
|
||||
Link(RNS::NoneConstructor none) {
|
||||
extreme("Link NONE object created");
|
||||
}
|
||||
Link(const Link &link) : _object(link._object) {
|
||||
extreme("Link object copy created");
|
||||
}
|
||||
Link();
|
||||
~Link();
|
||||
virtual ~Link(){
|
||||
extreme("Link object destroyed");
|
||||
}
|
||||
|
||||
inline Link& operator = (const Link &link) {
|
||||
_object = link._object;
|
||||
return *this;
|
||||
}
|
||||
inline operator bool() const {
|
||||
return _object.get() != nullptr;
|
||||
}
|
||||
inline bool operator < (const Link &link) const {
|
||||
return _object.get() < link._object.get();
|
||||
}
|
||||
|
||||
public:
|
||||
void set_link_id(const Packet &packet);
|
||||
void receive(const Packet &packet);
|
||||
|
||||
// getters/setters
|
||||
inline const Bytes &link_id() const { assert(_object); return _object->_link_id; }
|
||||
inline const Bytes &hash() const { assert(_object); return _object->_hash; }
|
||||
|
||||
inline std::string toString() const { assert(_object); return "{Link: unknown}"; }
|
||||
|
||||
private:
|
||||
class Object {
|
||||
public:
|
||||
Object() {}
|
||||
virtual ~Object() {}
|
||||
private:
|
||||
Bytes _link_id;
|
||||
Bytes _hash;
|
||||
friend class Link;
|
||||
};
|
||||
std::shared_ptr<Object> _object;
|
||||
|
||||
};
|
||||
|
||||
|
14
src/Log.cpp
14
src/Log.cpp
@ -37,7 +37,7 @@ LogLevel RNS::loglevel() {
|
||||
return _level;
|
||||
}
|
||||
|
||||
void RNS::doLog(const char* msg, LogLevel level) {
|
||||
void RNS::doLog(const char *msg, LogLevel level) {
|
||||
if (level > _level) {
|
||||
return;
|
||||
}
|
||||
@ -50,3 +50,15 @@ void RNS::doLog(const char* msg, LogLevel level) {
|
||||
printf("%s: %s\n", getLevelName(level), msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RNS::head(const char *msg, LogLevel level) {
|
||||
if (level > _level) {
|
||||
return;
|
||||
}
|
||||
#ifndef NATIVE
|
||||
Serial.println("");
|
||||
#else
|
||||
printf("\n");
|
||||
#endif
|
||||
doLog(msg, level);
|
||||
}
|
||||
|
41
src/Log.h
41
src/Log.h
@ -22,36 +22,39 @@ namespace RNS {
|
||||
void loglevel(LogLevel level);
|
||||
LogLevel loglevel();
|
||||
|
||||
void doLog(const char* msg, LogLevel level);
|
||||
void doLog(const char *msg, LogLevel level);
|
||||
|
||||
inline void log(const char* msg, LogLevel level = LOG_NOTICE) { doLog(msg, level); }
|
||||
inline void log(const char *msg, LogLevel level = LOG_NOTICE) { doLog(msg, level); }
|
||||
#ifndef NATIVE
|
||||
inline void log(const String msg, LogLevel level = LOG_NOTICE) { doLog(msg.c_str(), level); }
|
||||
#endif
|
||||
inline void log(const std::string& msg, LogLevel level = LOG_NOTICE) { doLog(msg.c_str(), level); }
|
||||
inline void log(const std::string &msg, LogLevel level = LOG_NOTICE) { doLog(msg.c_str(), level); }
|
||||
|
||||
inline void critical(const char* msg) { doLog(msg, LOG_CRITICAL); }
|
||||
inline void critical(const std::string& msg) { doLog(msg.c_str(), LOG_CRITICAL); }
|
||||
inline void critical(const char *msg) { doLog(msg, LOG_CRITICAL); }
|
||||
inline void critical(const std::string &msg) { doLog(msg.c_str(), LOG_CRITICAL); }
|
||||
|
||||
inline void error(const char* msg) { doLog(msg, LOG_ERROR); }
|
||||
inline void error(const std::string& msg) { doLog(msg.c_str(), LOG_ERROR); }
|
||||
inline void error(const char *msg) { doLog(msg, LOG_ERROR); }
|
||||
inline void error(const std::string &msg) { doLog(msg.c_str(), LOG_ERROR); }
|
||||
|
||||
inline void warning(const char* msg) { doLog(msg, LOG_WARNING); }
|
||||
inline void warning(const std::string& msg) { doLog(msg.c_str(), LOG_WARNING); }
|
||||
inline void warning(const char *msg) { doLog(msg, LOG_WARNING); }
|
||||
inline void warning(const std::string &msg) { doLog(msg.c_str(), LOG_WARNING); }
|
||||
|
||||
inline void notice(const char* msg) { doLog(msg, LOG_NOTICE); }
|
||||
inline void notice(const std::string& msg) { doLog(msg.c_str(), LOG_NOTICE); }
|
||||
inline void notice(const char *msg) { doLog(msg, LOG_NOTICE); }
|
||||
inline void notice(const std::string &msg) { doLog(msg.c_str(), LOG_NOTICE); }
|
||||
|
||||
inline void info(const char* msg) { doLog(msg, LOG_INFO); }
|
||||
inline void info(const std::string& msg) { doLog(msg.c_str(), LOG_INFO); }
|
||||
inline void info(const char *msg) { doLog(msg, LOG_INFO); }
|
||||
inline void info(const std::string &msg) { doLog(msg.c_str(), LOG_INFO); }
|
||||
|
||||
inline void verbose(const char* msg) { doLog(msg, LOG_VERBOSE); }
|
||||
inline void verbose(const std::string& msg) { doLog(msg.c_str(), LOG_VERBOSE); }
|
||||
inline void verbose(const char *msg) { doLog(msg, LOG_VERBOSE); }
|
||||
inline void verbose(const std::string &msg) { doLog(msg.c_str(), LOG_VERBOSE); }
|
||||
|
||||
inline void debug(const char* msg) { doLog(msg, LOG_DEBUG); }
|
||||
inline void debug(const std::string& msg) { doLog(msg.c_str(), LOG_DEBUG); }
|
||||
inline void debug(const char *msg) { doLog(msg, LOG_DEBUG); }
|
||||
inline void debug(const std::string &msg) { doLog(msg.c_str(), LOG_DEBUG); }
|
||||
|
||||
inline void extreme(const char* msg) { doLog(msg, LOG_EXTREME); }
|
||||
inline void extreme(const std::string& msg) { doLog(msg.c_str(), LOG_EXTREME); }
|
||||
inline void extreme(const char *msg) { doLog(msg, LOG_EXTREME); }
|
||||
inline void extreme(const std::string &msg) { doLog(msg.c_str(), LOG_EXTREME); }
|
||||
|
||||
void head(const char *msg, LogLevel level = LOG_NOTICE);
|
||||
inline void head(const std::string &msg, LogLevel level = LOG_NOTICE) { head(msg.c_str(), level); }
|
||||
|
||||
}
|
||||
|
10
src/None.h
Normal file
10
src/None.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace RNS {
|
||||
|
||||
// generic empty object constructor type
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
}
|
@ -11,7 +11,7 @@ using namespace RNS;
|
||||
Packet::Packet(const Destination &destination, const Interface &attached_interface, const Bytes &data, types packet_type /*= DATA*/, context_types context /*= CONTEXT_NONE*/, Transport::types transport_type /*= Transport::BROADCAST*/, header_types header_type /*= HEADER_1*/, const Bytes &transport_id /*= Bytes::NONE*/, bool create_receipt /*= true*/) : _object(new Object(destination, attached_interface)) {
|
||||
|
||||
if (_object->_destination) {
|
||||
extreme("Creating packet with detination...");
|
||||
extreme("Creating packet with destination...");
|
||||
// CBA TODO handle NONE
|
||||
if (transport_type == -1) {
|
||||
transport_type = Transport::BROADCAST;
|
||||
@ -32,7 +32,7 @@ Packet::Packet(const Destination &destination, const Interface &attached_interfa
|
||||
_object->_create_receipt = create_receipt;
|
||||
}
|
||||
else {
|
||||
extreme("Creating packet without detination...");
|
||||
extreme("Creating packet without destination...");
|
||||
_object->_raw = data;
|
||||
_object->_packed = true;
|
||||
_object->_fromPacked = true;
|
||||
@ -399,8 +399,8 @@ bool Packet::send() {
|
||||
}
|
||||
|
||||
if (RNS::Transport::outbound(*this)) {
|
||||
//zreturn self.receipt
|
||||
debug("Packet::send: successfully sent packet!!!");
|
||||
//zreturn self.receipt
|
||||
// MOCK
|
||||
return true;
|
||||
}
|
||||
@ -428,8 +428,8 @@ bool Packet::resend() {
|
||||
pack();
|
||||
|
||||
if (RNS::Transport::outbound(*this)) {
|
||||
//zreturn self.receipt
|
||||
debug("Packet::resend: successfully sent packet!!!");
|
||||
//zreturn self.receipt
|
||||
// MOCK
|
||||
return true;
|
||||
}
|
||||
@ -441,24 +441,41 @@ bool Packet::resend() {
|
||||
}
|
||||
}
|
||||
|
||||
void Packet::prove(const Destination &destination /*= {Destination::NONE}*/) {
|
||||
/*
|
||||
assert(_object);
|
||||
if (_object->_fromPacked && _object->_destination) {
|
||||
if (_object->_destination.identity() && _object->_destination.identity().prv()) {
|
||||
_object->_destination.identity().prove(*this, _object->_destination);
|
||||
}
|
||||
}
|
||||
else if (_object->_fromPacked && _object->_link) {
|
||||
_object->_link.prove_packet(*this);
|
||||
}
|
||||
else {
|
||||
error("Could not prove packet associated with neither a destination nor a link");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Packet::update_hash() {
|
||||
assert(_object);
|
||||
_object->_packet_hash = get_hash();
|
||||
}
|
||||
|
||||
Bytes Packet::get_hash() {
|
||||
const Bytes Packet::get_hash() const {
|
||||
assert(_object);
|
||||
Bytes hashable_part = get_hashable_part();
|
||||
return Identity::full_hash(hashable_part);
|
||||
}
|
||||
|
||||
Bytes Packet::getTruncatedHash() {
|
||||
const Bytes Packet::getTruncatedHash() const {
|
||||
assert(_object);
|
||||
Bytes hashable_part = get_hashable_part();
|
||||
return Identity::truncated_hash(hashable_part);
|
||||
}
|
||||
|
||||
Bytes Packet::get_hashable_part() {
|
||||
const Bytes Packet::get_hashable_part() const {
|
||||
assert(_object);
|
||||
Bytes hashable_part;
|
||||
hashable_part << (uint8_t)(_object->_raw.data()[0] & 0b00001111);
|
||||
@ -480,7 +497,7 @@ Bytes Packet::get_hashable_part() {
|
||||
//}
|
||||
|
||||
|
||||
std::string Packet::debugString() {
|
||||
std::string Packet::debugString() const {
|
||||
if (_object->_packed) {
|
||||
//unpack();
|
||||
}
|
||||
@ -495,15 +512,16 @@ std::string Packet::debugString() {
|
||||
dump += "transport: " + _object->_transport_id.toHex() + "\n";
|
||||
dump += "destination: " + _object->_destination_hash.toHex() + "\n";
|
||||
dump += "context_type: " + std::to_string(_object->_header_type) + "\n";
|
||||
dump += "data: " + _object->_data.toHex() + "\n";
|
||||
dump += " length: " + std::to_string(_object->_data.size()) + "\n";
|
||||
dump += "raw: " + _object->_raw.toHex() + "\n";
|
||||
dump += " length: " + std::to_string(_object->_raw.size()) + "\n";
|
||||
dump += "data: " + _object->_data.toHex() + "\n";
|
||||
dump += " length: " + std::to_string(_object->_data.size()) + "\n";
|
||||
if (_object->_encrypted && _object->_raw.size() > 0) {
|
||||
size_t header_len = Reticulum::HEADER_MINSIZE;
|
||||
if (_object->_header_type == HEADER_2) {
|
||||
header_len = Reticulum::HEADER_MAXSIZE;
|
||||
}
|
||||
dump += "encrypted:\n";
|
||||
dump += " header: " + _object->_raw.left(header_len).toHex() + "\n";
|
||||
dump += " key: " + _object->_raw.mid(header_len, Identity::KEYSIZE/8/2).toHex() + "\n";
|
||||
Bytes ciphertext(_object->_raw.mid(header_len+Identity::KEYSIZE/8/2));
|
||||
@ -517,3 +535,23 @@ std::string Packet::debugString() {
|
||||
dump += "--------------------\n";
|
||||
return dump;
|
||||
}
|
||||
|
||||
void PacketReceipt::check_timeout() {
|
||||
assert(_object);
|
||||
if (_object->_status == SENT && is_timed_out()) {
|
||||
if (_object->_timeout == -1) {
|
||||
_object->_status = CULLED;
|
||||
}
|
||||
else {
|
||||
_object->_status = FAILED;
|
||||
}
|
||||
|
||||
_object->_concluded_at = Utilities::OS::time();
|
||||
|
||||
if (_object->_callbacks._timeout) {
|
||||
//zthread = threading.Thread(target=self.callbacks.timeout, args=(self,))
|
||||
//zthread.daemon = True
|
||||
//zthread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
202
src/Packet.h
202
src/Packet.h
@ -1,10 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "Reticulum.h"
|
||||
#include "Identity.h"
|
||||
#include "Transport.h"
|
||||
#include "Reticulum.h"
|
||||
#include "Link.h"
|
||||
#include "Identity.h"
|
||||
#include "Destination.h"
|
||||
#include "None.h"
|
||||
#include "Interfaces/Interface.h"
|
||||
#include "Utilities/OS.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
@ -12,11 +15,125 @@
|
||||
|
||||
namespace RNS {
|
||||
|
||||
class Packet;
|
||||
class PacketProof;
|
||||
class ProofDestination;
|
||||
class PacketReceipt;
|
||||
class PacketReceiptCallbacks;
|
||||
class Packet;
|
||||
|
||||
|
||||
class ProofDestination {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
The PacketReceipt class is used to receive notifications about
|
||||
:ref:`RNS.Packet<api-packet>` instances sent over the network. Instances
|
||||
of this class are never created manually, but always returned from
|
||||
the *send()* method of a :ref:`RNS.Packet<api-packet>` instance.
|
||||
*/
|
||||
class PacketReceipt {
|
||||
|
||||
public:
|
||||
class Callbacks {
|
||||
public:
|
||||
using delivery = void(*)(const PacketReceipt &packet_receipt);
|
||||
using timeout = void(*)(const PacketReceipt &packet_receipt);
|
||||
public:
|
||||
delivery _delivery = nullptr;
|
||||
timeout _timeout = nullptr;
|
||||
friend class PacketReceipt;
|
||||
};
|
||||
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
// Receipt status constants
|
||||
enum Status {
|
||||
FAILED = 0x00,
|
||||
SENT = 0x01,
|
||||
DELIVERED = 0x02,
|
||||
CULLED = 0xFF
|
||||
};
|
||||
|
||||
static const uint16_t EXPL_LENGTH = Identity::HASHLENGTH / 8 + Identity::SIGLENGTH / 8;
|
||||
static const uint16_t IMPL_LENGTH = Identity::SIGLENGTH / 8;
|
||||
|
||||
public:
|
||||
PacketReceipt(NoneConstructor none) {}
|
||||
PacketReceipt(const PacketReceipt &packet_receipt) : _object(packet_receipt._object) {}
|
||||
PacketReceipt() : _object(new Object()) {}
|
||||
PacketReceipt(const Packet &packet) {}
|
||||
|
||||
inline PacketReceipt& operator = (const PacketReceipt &packet_receipt) {
|
||||
_object = packet_receipt._object;
|
||||
return *this;
|
||||
}
|
||||
inline operator bool() const {
|
||||
return _object.get() != nullptr;
|
||||
}
|
||||
inline bool operator < (const PacketReceipt &packet_receipt) const {
|
||||
return _object.get() < packet_receipt._object.get();
|
||||
}
|
||||
|
||||
public:
|
||||
inline bool is_timed_out() {
|
||||
assert(_object);
|
||||
return ((_object->_sent_at + _object->_timeout) < Utilities::OS::time());
|
||||
}
|
||||
|
||||
void check_timeout();
|
||||
|
||||
/*
|
||||
Sets a timeout in seconds
|
||||
|
||||
:param timeout: The timeout in seconds.
|
||||
*/
|
||||
inline void set_timeout(int16_t timeout) {
|
||||
assert(_object);
|
||||
_object->_timeout = timeout;
|
||||
}
|
||||
|
||||
/*
|
||||
Sets a function that gets called if a successfull delivery has been proven.
|
||||
|
||||
:param callback: A *callable* with the signature *callback(packet_receipt)*
|
||||
*/
|
||||
inline void set_delivery_callback(Callbacks::delivery callback) {
|
||||
assert(_object);
|
||||
_object->_callbacks._delivery = callback;
|
||||
}
|
||||
|
||||
/*
|
||||
Sets a function that gets called if the delivery times out.
|
||||
|
||||
:param callback: A *callable* with the signature *callback(packet_receipt)*
|
||||
*/
|
||||
inline void set_timeout_callback(Callbacks::timeout callback) {
|
||||
assert(_object);
|
||||
_object->_callbacks._timeout = callback;
|
||||
}
|
||||
|
||||
private:
|
||||
class Object {
|
||||
public:
|
||||
Object() {}
|
||||
virtual ~Object() {}
|
||||
private:
|
||||
bool _sent = true;
|
||||
uint64_t _sent_at = Utilities::OS::time();
|
||||
bool _proved = false;
|
||||
Status _status = SENT;
|
||||
Destination _destination = Destination::NONE;
|
||||
Callbacks _callbacks;
|
||||
uint64_t _concluded_at = 0;
|
||||
//zPacket _proof_packet;
|
||||
int16_t _timeout = 0;
|
||||
friend class PacketReceipt;
|
||||
};
|
||||
std::shared_ptr<Object> _object;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Packet {
|
||||
|
||||
@ -85,25 +202,30 @@ namespace RNS {
|
||||
uint8_t EMPTY_DESTINATION[Reticulum::DESTINATION_LENGTH] = {0};
|
||||
|
||||
public:
|
||||
Packet(const Destination &destination, const Interface &attached_interface, const Bytes &data, types packet_type = DATA, context_types context = CONTEXT_NONE, Transport::types transport_type = Transport::BROADCAST, header_types header_type = HEADER_1, const Bytes &transport_id = Bytes::NONE, bool create_receipt = true);
|
||||
Packet(const Destination &destination, const Bytes &data, types packet_type = DATA, context_types context = CONTEXT_NONE, Transport::types transport_type = Transport::BROADCAST, header_types header_type = HEADER_1, const Bytes &transport_id = Bytes::NONE, bool create_receipt = true) : Packet(destination, Interface::NONE, data, packet_type, context, transport_type, header_type, transport_id, create_receipt) {
|
||||
}
|
||||
Packet(NoneConstructor none) {
|
||||
extreme("Packet NONE object created");
|
||||
}
|
||||
Packet(RNS::NoneConstructor none) {
|
||||
extreme("Packet NONE object created");
|
||||
}
|
||||
Packet(const Packet &packet) : _object(packet._object) {
|
||||
extreme("Packet object copy created");
|
||||
}
|
||||
~Packet();
|
||||
Packet(const Destination &destination, const Interface &attached_interface, const Bytes &data, types packet_type = DATA, context_types context = CONTEXT_NONE, Transport::types transport_type = Transport::BROADCAST, header_types header_type = HEADER_1, const Bytes &transport_id = Bytes::NONE, bool create_receipt = true);
|
||||
Packet(const Destination &destination, const Bytes &data, types packet_type = DATA, context_types context = CONTEXT_NONE, Transport::types transport_type = Transport::BROADCAST, header_types header_type = HEADER_1, const Bytes &transport_id = Bytes::NONE, bool create_receipt = true) : Packet(destination, Interface::NONE, data, packet_type, context, transport_type, header_type, transport_id, create_receipt) {}
|
||||
virtual ~Packet();
|
||||
|
||||
inline Packet& operator = (const Packet &packet) {
|
||||
_object = packet._object;
|
||||
extreme("Packet object copy created by assignment, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((uint32_t)_object.get()));
|
||||
extreme("Packet object copy created by assignment, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
return *this;
|
||||
}
|
||||
inline operator bool() const {
|
||||
return _object.get() != nullptr;
|
||||
}
|
||||
inline bool operator < (const Packet &packet) const {
|
||||
return _object.get() < packet._object.get();
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
@ -120,37 +242,59 @@ namespace RNS {
|
||||
bool unpack();
|
||||
bool send();
|
||||
bool resend();
|
||||
void prove(const Destination &destination = Destination::NONE);
|
||||
void update_hash();
|
||||
Bytes get_hash();
|
||||
Bytes getTruncatedHash();
|
||||
Bytes get_hashable_part();
|
||||
const Bytes get_hash() const;
|
||||
const Bytes getTruncatedHash() const;
|
||||
const Bytes get_hashable_part() const;
|
||||
//zProofDestination &generate_proof_destination();
|
||||
|
||||
// getters/setters
|
||||
inline const Destination &destination() const { assert(_object); return _object->_destination; }
|
||||
inline void destination(const Destination &destination) { assert(_object); _object->_destination = destination; }
|
||||
inline const Link &link() const { assert(_object); return _object->_link; }
|
||||
inline void link(const Link &link) { assert(_object); _object->_link = link; }
|
||||
inline const Interface &attached_interface() const { assert(_object); return _object->_attached_interface; }
|
||||
inline const Interface &receiving_interface() const { assert(_object); return _object->_receiving_interface; }
|
||||
inline void receiving_interface(const Interface &receiving_interface) { assert(_object); _object->_receiving_interface = receiving_interface; }
|
||||
inline header_types header_type() const { assert(_object); return _object->_header_type; }
|
||||
inline Transport::types transport_type() const { assert(_object); return _object->_transport_type; }
|
||||
inline Destination::types destination_type() const { assert(_object); return _object->_destination_type; }
|
||||
inline types packet_type() const { assert(_object); return _object->_packet_type; }
|
||||
inline context_types context() const { assert(_object); return _object->_context; }
|
||||
inline const Bytes &data() const { assert(_object); return _object->_data; }
|
||||
inline const Bytes &raw() const { assert(_object); return _object->_raw; }
|
||||
inline bool sent() const { assert(_object); return _object->_sent; }
|
||||
inline void sent(bool sent) { assert(_object); _object->_sent = sent; }
|
||||
inline time_t sent_at() const { assert(_object); return _object->_sent_at; }
|
||||
inline void sent_at(time_t sent_at) { assert(_object); _object->_sent_at = sent_at; }
|
||||
inline bool create_receipt() const { assert(_object); return _object->_create_receipt; }
|
||||
inline const PacketReceipt &receipt() const { assert(_object); return _object->_receipt; }
|
||||
inline void receipt(const PacketReceipt &receipt) { assert(_object); _object->_receipt = receipt; }
|
||||
inline uint8_t flags() const { assert(_object); return _object->_flags; }
|
||||
inline uint8_t hops() const { assert(_object); return _object->_hops; }
|
||||
inline void hops(uint8_t hops) { assert(_object); _object->_hops = hops; }
|
||||
inline Bytes packet_hash() const { assert(_object); return _object->_packet_hash; }
|
||||
inline Bytes destination_hash() const { assert(_object); return _object->_destination_hash; }
|
||||
inline Bytes transport_id() const { assert(_object); return _object->_transport_id; }
|
||||
inline void transport_id(const Bytes &transport_id) { assert(_object); _object->_transport_id = transport_id; }
|
||||
inline const Bytes &raw() const { assert(_object); return _object->_raw; }
|
||||
inline const Bytes &data() const { assert(_object); return _object->_data; }
|
||||
|
||||
inline std::string toString() const { assert(_object); return "{Packet:" + _object->_packet_hash.toHex() + "}"; }
|
||||
|
||||
std::string debugString();
|
||||
std::string debugString() const;
|
||||
|
||||
private:
|
||||
class Object {
|
||||
public:
|
||||
Object(const Destination &destination, const Interface &attached_interface) : _destination(destination), _attached_interface(attached_interface) {}
|
||||
virtual ~Object() {}
|
||||
private:
|
||||
Destination _destination;
|
||||
Destination _destination = {Destination::NONE};
|
||||
Link _link = {Link::NONE};
|
||||
|
||||
Interface _attached_interface = {Interface::NONE};
|
||||
Interface _receiving_interface = {Interface::NONE};
|
||||
|
||||
Interface _attached_interface;
|
||||
Interface _receiving_interface;
|
||||
|
||||
header_types _header_type = HEADER_1;
|
||||
Transport::types _transport_type = Transport::BROADCAST;
|
||||
Destination::types _destination_type = Destination::SINGLE;
|
||||
@ -166,7 +310,7 @@ namespace RNS {
|
||||
bool _fromPacked = false;
|
||||
bool _truncated = false; // whether data was truncated
|
||||
bool _encrypted = false; // whether data is encrytpted
|
||||
//z_receipt = nullptr;
|
||||
PacketReceipt _receipt;
|
||||
|
||||
uint16_t _mtu = Reticulum::MTU;
|
||||
time_t _sent_at = 0;
|
||||
@ -186,20 +330,4 @@ namespace RNS {
|
||||
std::shared_ptr<Object> _object;
|
||||
};
|
||||
|
||||
|
||||
class ProofDestination {
|
||||
};
|
||||
|
||||
|
||||
class PacketReceipt {
|
||||
|
||||
public:
|
||||
class Callbacks {
|
||||
public:
|
||||
typedef void (*delivery)(PacketReceipt *packet_receipt);
|
||||
typedef void (*timeout)(PacketReceipt *packet_receipt);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,31 +1,134 @@
|
||||
#include "Reticulum.h"
|
||||
|
||||
#include "Transport.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <RNG.h>
|
||||
|
||||
using namespace RNS;
|
||||
|
||||
/*
|
||||
Initialises and starts a Reticulum instance. This must be
|
||||
done before any other operations, and Reticulum will not
|
||||
pass any traffic before being instantiated.
|
||||
|
||||
:param configdir: Full path to a Reticulum configuration directory.
|
||||
*/
|
||||
//def __init__(self,configdir=None, loglevel=None, logdest=None, verbosity=None):
|
||||
Reticulum::Reticulum() : _object(new Object()) {
|
||||
extreme("Reticulum object created");
|
||||
|
||||
// Initialkize random number generator
|
||||
RNG.begin("Reticulum");
|
||||
//RNG.stir(mac_address, sizeof(mac_address));
|
||||
|
||||
/*
|
||||
RNS.vendor.platformutils.platform_checks()
|
||||
|
||||
if configdir != None:
|
||||
Reticulum.configdir = configdir
|
||||
else:
|
||||
if os.path.isdir("/etc/reticulum") and os.path.isfile("/etc/reticulum/config"):
|
||||
Reticulum.configdir = "/etc/reticulum"
|
||||
elif os.path.isdir(Reticulum.userdir+"/.config/reticulum") and os.path.isfile(Reticulum.userdir+"/.config/reticulum/config"):
|
||||
Reticulum.configdir = Reticulum.userdir+"/.config/reticulum"
|
||||
else:
|
||||
Reticulum.configdir = Reticulum.userdir+"/.reticulum"
|
||||
|
||||
if logdest == RNS.LOG_FILE:
|
||||
RNS.logdest = RNS.LOG_FILE
|
||||
RNS.logfile = Reticulum.configdir+"/logfile"
|
||||
|
||||
Reticulum.configpath = Reticulum.configdir+"/config"
|
||||
Reticulum.storagepath = Reticulum.configdir+"/storage"
|
||||
Reticulum.cachepath = Reticulum.configdir+"/storage/cache"
|
||||
Reticulum.resourcepath = Reticulum.configdir+"/storage/resources"
|
||||
Reticulum.identitypath = Reticulum.configdir+"/storage/identities"
|
||||
|
||||
Reticulum.__transport_enabled = False
|
||||
Reticulum.__use_implicit_proof = True
|
||||
Reticulum.__allow_probes = False
|
||||
|
||||
Reticulum.panic_on_interface_error = False
|
||||
|
||||
self.local_interface_port = 37428
|
||||
self.local_control_port = 37429
|
||||
self.share_instance = True
|
||||
self.rpc_listener = None
|
||||
|
||||
self.ifac_salt = Reticulum.IFAC_SALT
|
||||
|
||||
self.requested_loglevel = loglevel
|
||||
self.requested_verbosity = verbosity
|
||||
if self.requested_loglevel != None:
|
||||
if self.requested_loglevel > RNS.LOG_EXTREME:
|
||||
self.requested_loglevel = RNS.LOG_EXTREME
|
||||
if self.requested_loglevel < RNS.LOG_CRITICAL:
|
||||
self.requested_loglevel = RNS.LOG_CRITICAL
|
||||
|
||||
RNS.loglevel = self.requested_loglevel
|
||||
|
||||
self.is_shared_instance = False
|
||||
self.is_connected_to_shared_instance = False
|
||||
self.is_standalone_instance = False
|
||||
self.jobs_thread = None
|
||||
self.last_data_persist = time.time()
|
||||
self.last_cache_clean = 0
|
||||
|
||||
if not os.path.isdir(Reticulum.storagepath):
|
||||
os.makedirs(Reticulum.storagepath)
|
||||
|
||||
if not os.path.isdir(Reticulum.cachepath):
|
||||
os.makedirs(Reticulum.cachepath)
|
||||
|
||||
if not os.path.isdir(Reticulum.resourcepath):
|
||||
os.makedirs(Reticulum.resourcepath)
|
||||
|
||||
if not os.path.isdir(Reticulum.identitypath):
|
||||
os.makedirs(Reticulum.identitypath)
|
||||
|
||||
if os.path.isfile(self.configpath):
|
||||
try:
|
||||
self.config = ConfigObj(self.configpath)
|
||||
except Exception as e:
|
||||
RNS.log("Could not parse the configuration at "+self.configpath, RNS.LOG_ERROR)
|
||||
RNS.log("Check your configuration file for errors!", RNS.LOG_ERROR)
|
||||
RNS.panic()
|
||||
else:
|
||||
RNS.log("Could not load config file, creating default configuration file...")
|
||||
self.__create_default_config()
|
||||
RNS.log("Default config file created. Make any necessary changes in "+Reticulum.configdir+"/config and restart Reticulum if needed.")
|
||||
time.sleep(1.5)
|
||||
|
||||
self.__apply_config()
|
||||
RNS.log("Configuration loaded from "+self.configpath, RNS.LOG_VERBOSE)
|
||||
|
||||
RNS.Identity.load_known_destinations()
|
||||
*/
|
||||
|
||||
Transport::start(*this);
|
||||
|
||||
/*
|
||||
self.rpc_addr = ("127.0.0.1", self.local_control_port)
|
||||
self.rpc_key = RNS.Identity.full_hash(RNS.Transport.identity.get_private_key())
|
||||
|
||||
if self.is_shared_instance:
|
||||
self.rpc_listener = multiprocessing.connection.Listener(self.rpc_addr, authkey=self.rpc_key)
|
||||
thread = threading.Thread(target=self.rpc_loop)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
atexit.register(Reticulum.exit_handler)
|
||||
signal.signal(signal.SIGINT, Reticulum.sigint_handler)
|
||||
signal.signal(signal.SIGTERM, Reticulum.sigterm_handler)
|
||||
*/
|
||||
|
||||
extreme("Reticulum object created");
|
||||
}
|
||||
|
||||
Reticulum::~Reticulum() {
|
||||
extreme("Reticulum object destroyed");
|
||||
}
|
||||
|
||||
/*
|
||||
Returns whether proofs sent are explicit or implicit.
|
||||
|
||||
:returns: True if the current running configuration specifies to use implicit proofs. False if not.
|
||||
*/
|
||||
/*static*/ bool Reticulum::should_use_implicit_proof() {
|
||||
return __use_implicit_proof;
|
||||
}
|
||||
|
||||
void Reticulum::loop() {
|
||||
// Perform random number gnerator housekeeping
|
||||
|
@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "Log.h"
|
||||
#include "None.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
namespace RNS {
|
||||
|
||||
@ -86,31 +87,64 @@ namespace RNS {
|
||||
static const bool panic_on_interface_error = false;
|
||||
|
||||
public:
|
||||
Reticulum();
|
||||
Reticulum(NoneConstructor none) {
|
||||
extreme("Reticulum NONE object created");
|
||||
}
|
||||
Reticulum(RNS::NoneConstructor none) {
|
||||
extreme("Reticulum NONE object created");
|
||||
}
|
||||
Reticulum(const Reticulum &reticulum) : _object(reticulum._object) {
|
||||
extreme("Reticulum object copy created");
|
||||
}
|
||||
~Reticulum();
|
||||
Reticulum();
|
||||
virtual ~Reticulum();
|
||||
|
||||
inline Reticulum& operator = (const Reticulum &reticulum) {
|
||||
_object = reticulum._object;
|
||||
extreme("Reticulum object copy created by assignment, this: " + std::to_string((ulong)this) + ", data: " + std::to_string((uint32_t)_object.get()));
|
||||
extreme("Reticulum object copy created by assignment, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
return *this;
|
||||
}
|
||||
inline operator bool() const {
|
||||
return _object.get() != nullptr;
|
||||
}
|
||||
inline bool operator < (const Reticulum &reticulum) const {
|
||||
return _object.get() < reticulum._object.get();
|
||||
}
|
||||
|
||||
public:
|
||||
static bool should_use_implicit_proof();
|
||||
void loop();
|
||||
|
||||
/*
|
||||
Returns whether proofs sent are explicit or implicit.
|
||||
|
||||
:returns: True if the current running configuration specifies to use implicit proofs. False if not.
|
||||
*/
|
||||
inline static bool should_use_implicit_proof() { return __use_implicit_proof; }
|
||||
|
||||
/*
|
||||
Returns whether Transport is enabled for the running
|
||||
instance.
|
||||
|
||||
When Transport is enabled, Reticulum will
|
||||
route traffic for other peers, respond to path requests
|
||||
and pass announces over the network.
|
||||
|
||||
:returns: True if Transport is enabled, False if not.
|
||||
*/
|
||||
inline static bool transport_enabled() { return __transport_enabled; }
|
||||
|
||||
inline static bool probe_destination_enabled() { return __allow_probes; }
|
||||
|
||||
// getters/setters
|
||||
inline bool is_connected_to_shared_instance() const { assert(_object); return _object->_is_connected_to_shared_instance; }
|
||||
|
||||
private:
|
||||
class Object {
|
||||
public:
|
||||
Object() {}
|
||||
virtual ~Object() {}
|
||||
private:
|
||||
bool _is_connected_to_shared_instance = false;
|
||||
friend class Reticulum;
|
||||
};
|
||||
std::shared_ptr<Object> _object;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <unity.h>
|
||||
//#include <unity.h>
|
||||
|
||||
#include "Bytes.h"
|
||||
#include "Log.h"
|
||||
@ -209,9 +209,9 @@ void testCowBytes() {
|
||||
assert(memcmp(bytes3.data(), "1", bytes3.size()) == 0);
|
||||
assert(bytes3.data() == bytes2.data());
|
||||
|
||||
RNS::extreme("pre bytes1 ptr: " + std::to_string((uint32_t)bytes1.data()) + " data: " + bytes1.toString());
|
||||
RNS::extreme("pre bytes2 ptr: " + std::to_string((uint32_t)bytes2.data()) + " data: " + bytes2.toString());
|
||||
RNS::extreme("pre bytes3 ptr: " + std::to_string((uint32_t)bytes3.data()) + " data: " + bytes3.toString());
|
||||
RNS::extreme("pre bytes1 ptr: " + std::to_string((uintptr_t)bytes1.data()) + " data: " + bytes1.toString());
|
||||
RNS::extreme("pre bytes2 ptr: " + std::to_string((uintptr_t)bytes2.data()) + " data: " + bytes2.toString());
|
||||
RNS::extreme("pre bytes3 ptr: " + std::to_string((uintptr_t)bytes3.data()) + " data: " + bytes3.toString());
|
||||
|
||||
//bytes1.append("mississippi");
|
||||
//assert(bytes1.size() == 12);
|
||||
@ -228,9 +228,9 @@ void testCowBytes() {
|
||||
assert(memcmp(bytes3.data(), "mississippi", bytes3.size()) == 0);
|
||||
assert(bytes3.data() != bytes2.data());
|
||||
|
||||
RNS::extreme("post bytes1 ptr: " + std::to_string((uint32_t)bytes1.data()) + " data: " + bytes1.toString());
|
||||
RNS::extreme("post bytes2 ptr: " + std::to_string((uint32_t)bytes2.data()) + " data: " + bytes2.toString());
|
||||
RNS::extreme("post bytes3 ptr: " + std::to_string((uint32_t)bytes3.data()) + " data: " + bytes3.toString());
|
||||
RNS::extreme("post bytes1 ptr: " + std::to_string((uintptr_t)bytes1.data()) + " data: " + bytes1.toString());
|
||||
RNS::extreme("post bytes2 ptr: " + std::to_string((uintptr_t)bytes2.data()) + " data: " + bytes2.toString());
|
||||
RNS::extreme("post bytes3 ptr: " + std::to_string((uintptr_t)bytes3.data()) + " data: " + bytes3.toString());
|
||||
}
|
||||
|
||||
void testBytesConversion() {
|
||||
@ -331,8 +331,15 @@ void testMap()
|
||||
}
|
||||
|
||||
/*
|
||||
int main(void)
|
||||
{
|
||||
void setUp(void) {
|
||||
// set stuff up here
|
||||
}
|
||||
|
||||
void tearDown(void) {
|
||||
// clean stuff up here
|
||||
}
|
||||
|
||||
int runUnityTests(void) {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(testBytes);
|
||||
RUN_TEST(testCowBytes);
|
||||
@ -340,4 +347,24 @@ int main(void)
|
||||
RUN_TEST(testMap);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
// For native dev-platform or for some embedded frameworks
|
||||
int main(void) {
|
||||
return runUnityTests();
|
||||
}
|
||||
|
||||
// For Arduino framework
|
||||
void setup() {
|
||||
// Wait ~2 seconds before the Unity test runner
|
||||
// establishes connection with a board Serial interface
|
||||
delay(2000);
|
||||
|
||||
runUnityTests();
|
||||
}
|
||||
void loop() {}
|
||||
|
||||
// For ESP-IDF framework
|
||||
void app_main() {
|
||||
runUnityTests();
|
||||
}
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <unity.h>
|
||||
//#include <unity.h>
|
||||
|
||||
#include "Reticulum.h"
|
||||
#include "Identity.h"
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <unity.h>
|
||||
//#include <unity.h>
|
||||
|
||||
#include "Reticulum.h"
|
||||
#include "Bytes.h"
|
||||
|
2878
src/Transport.cpp
2878
src/Transport.cpp
File diff suppressed because it is too large
Load Diff
246
src/Transport.h
246
src/Transport.h
@ -1,29 +1,150 @@
|
||||
#pragma once
|
||||
|
||||
#include "Reticulum.h"
|
||||
#include "Link.h"
|
||||
// CBA TODO resolve circular dependency with following header file
|
||||
//#include "Packet.h"
|
||||
#include "Bytes.h"
|
||||
#include "None.h"
|
||||
#include "Interfaces/Interface.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace RNS {
|
||||
|
||||
class Packet;
|
||||
class PacketReceipt;
|
||||
class Destination;
|
||||
class Interface;
|
||||
class Link;
|
||||
class Identity;
|
||||
|
||||
class AnnounceHandler {
|
||||
public:
|
||||
AnnounceHandler(const std::string &aspect_filter) {
|
||||
_aspect_filter = aspect_filter;
|
||||
}
|
||||
virtual void received_announce(const Bytes &destination_hash, const Identity &announced_identity, const Bytes &app_data) = 0;
|
||||
private:
|
||||
std::string _aspect_filter;
|
||||
};
|
||||
using HAnnounceHandler = std::shared_ptr<AnnounceHandler>;
|
||||
|
||||
/*
|
||||
Through static methods of this class you can interact with the
|
||||
Transport system of Reticulum.
|
||||
*/
|
||||
class Transport {
|
||||
|
||||
private:
|
||||
class DestinationEntry {
|
||||
public:
|
||||
DestinationEntry(uint64_t time, Bytes received_from, uint8_t announce_hops, uint64_t expires, std::set<Bytes> random_blobs, Interface &receiving_interface, const Packet &packet) :
|
||||
_timestamp(time),
|
||||
_received_from(received_from),
|
||||
_hops(announce_hops),
|
||||
_expires(expires),
|
||||
_random_blobs(random_blobs),
|
||||
_receiving_interface(receiving_interface),
|
||||
_packet(packet)
|
||||
{
|
||||
}
|
||||
public:
|
||||
uint64_t _timestamp = 0;
|
||||
Bytes _received_from;
|
||||
uint8_t _hops = 0;
|
||||
uint64_t _expires = 0;
|
||||
std::set<Bytes> _random_blobs;
|
||||
Interface &_receiving_interface;
|
||||
const Packet &_packet;
|
||||
};
|
||||
|
||||
class AnnounceEntry {
|
||||
public:
|
||||
AnnounceEntry(uint64_t timestamp, uint16_t retransmit_timeout, uint8_t retries, Bytes received_from, uint8_t hops, const Packet &packet, uint8_t local_rebroadcasts, bool block_rebroadcasts, const Interface &attached_interface) :
|
||||
_timestamp(timestamp),
|
||||
_retransmit_timeout(retransmit_timeout),
|
||||
_retries(retries),
|
||||
_received_from(received_from),
|
||||
_hops(hops),
|
||||
_packet(packet),
|
||||
_local_rebroadcasts(local_rebroadcasts),
|
||||
_block_rebroadcasts(block_rebroadcasts),
|
||||
_attached_interface(attached_interface)
|
||||
{
|
||||
}
|
||||
public:
|
||||
uint64_t _timestamp = 0;
|
||||
uint16_t _retransmit_timeout = 0;
|
||||
uint8_t _retries = 0;
|
||||
Bytes _received_from;
|
||||
uint8_t _hops = 0;
|
||||
const Packet &_packet;
|
||||
uint8_t _local_rebroadcasts = 0;
|
||||
bool _block_rebroadcasts = false;
|
||||
const Interface &_attached_interface;
|
||||
};
|
||||
|
||||
class LinkEntry {
|
||||
public:
|
||||
LinkEntry(uint64_t timestamp, const Bytes &next_hop, const Interface &outbound_interface, uint8_t remaining_hops, const Interface &receiving_interface, uint8_t hops, const Bytes &destination_hash, bool validated, uint64_t proof_timeout) :
|
||||
_timestamp(timestamp),
|
||||
_next_hop(next_hop),
|
||||
_outbound_interface(outbound_interface),
|
||||
_remaining_hops(remaining_hops),
|
||||
_receiving_interface(receiving_interface),
|
||||
_hops(hops),
|
||||
_destination_hash(destination_hash),
|
||||
_validated(validated),
|
||||
_proof_timeout(proof_timeout)
|
||||
{
|
||||
}
|
||||
public:
|
||||
uint64_t _timestamp = 0;
|
||||
Bytes _next_hop;
|
||||
const Interface &_outbound_interface;
|
||||
uint8_t _remaining_hops = 0;
|
||||
const Interface &_receiving_interface;
|
||||
uint8_t _hops = 0;
|
||||
Bytes _destination_hash;
|
||||
bool _validated = false;
|
||||
uint64_t _proof_timeout = 0;
|
||||
};
|
||||
|
||||
class ReverseEntry {
|
||||
public:
|
||||
ReverseEntry(const Interface &receiving_interface, const Interface &outbound_interface, uint64_t timestamp) :
|
||||
_receiving_interface(receiving_interface),
|
||||
_outbound_interface(outbound_interface),
|
||||
_timestamp(timestamp)
|
||||
{
|
||||
}
|
||||
public:
|
||||
const Interface &_receiving_interface;
|
||||
const Interface &_outbound_interface;
|
||||
uint64_t _timestamp = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
// Constants
|
||||
enum types {
|
||||
BROADCAST = 0x00,
|
||||
TRANSPORT = 0x01,
|
||||
RELAY = 0x02,
|
||||
TUNNEL = 0x03,
|
||||
NONE = 0xFF,
|
||||
BROADCAST = 0x00,
|
||||
TRANSPORT = 0x01,
|
||||
RELAY = 0x02,
|
||||
TUNNEL = 0x03,
|
||||
NONE = 0xFF,
|
||||
};
|
||||
|
||||
enum reachabilities {
|
||||
REACHABILITY_UNREACHABLE = 0x00,
|
||||
REACHABILITY_DIRECT = 0x01,
|
||||
REACHABILITY_TRANSPORT = 0x02,
|
||||
REACHABILITY_UNREACHABLE = 0x00,
|
||||
REACHABILITY_DIRECT = 0x01,
|
||||
REACHABILITY_TRANSPORT = 0x02,
|
||||
};
|
||||
|
||||
static constexpr const char* APP_NAME = "rnstransport";
|
||||
@ -54,13 +175,112 @@ namespace RNS {
|
||||
static const uint8_t MAX_RATE_TIMESTAMPS = 16; // Maximum number of announce timestamps to keep per destination
|
||||
|
||||
public:
|
||||
Transport();
|
||||
~Transport();
|
||||
|
||||
public:
|
||||
static void start(const Reticulum &reticulum_instance);
|
||||
static void jobloop();
|
||||
static void jobs();
|
||||
static void transmit(Interface &interface, const Bytes &raw);
|
||||
static bool outbound(Packet &packet);
|
||||
static bool packet_filter(const Packet &packet);
|
||||
static void inbound(const Bytes &raw, const Interface &interface = Interface::NONE);
|
||||
static void synthesize_tunnel(const Interface &interface);
|
||||
static void tunnel_synthesize_handler(const Bytes &data, const Packet &packet);
|
||||
static void handle_tunnel(const Bytes &tunnel_id, const Interface &interface);
|
||||
static void register_interface(Interface &interface);
|
||||
static void deregister_interface(const Interface &interface);
|
||||
static void register_destination(Destination &destination);
|
||||
static bool outbound(const Packet &packet);
|
||||
static void deregister_destination(const Destination &destination);
|
||||
static void register_link(const Link &link);
|
||||
static void activate_link(Link &link);
|
||||
static void register_announce_handler(HAnnounceHandler handler);
|
||||
static void deregister_announce_handler(HAnnounceHandler handler);
|
||||
static Interface find_interface_from_hash(const Bytes &interface_hash);
|
||||
static bool should_cache(const Packet &packet);
|
||||
static void cache(const Packet &packet, bool force_cache = false);
|
||||
static Packet get_cached_packet(const Bytes &packet_hash);
|
||||
static bool cache_request_packet(const Packet &packet);
|
||||
static void cache_request(const Bytes &packet_hash, const Destination &destination);
|
||||
static bool has_path(const Bytes &destination_hash);
|
||||
static uint8_t hops_to(const Bytes &destination_hash);
|
||||
static Bytes next_hop(const Bytes &destination_hash);
|
||||
static Interface next_hop_interface(const Bytes &destination_hash);
|
||||
static bool expire_path(const Bytes &destination_hash);
|
||||
static void request_path(const Bytes &destination_hash, const Interface &on_interface = {Interface::NONE}, const Bytes &tag = {}, bool recursive = false);
|
||||
static void path_request_handler(const Bytes &data, const Packet &packet);
|
||||
static void path_request(const Bytes &destination_hash, bool is_from_local_client, const Interface &attached_interface, const Bytes &requestor_transport_id = {}, const Bytes &tag = {});
|
||||
static bool from_local_client(const Packet &packet);
|
||||
static bool is_local_client_interface(const Interface &interface);
|
||||
static bool interface_to_shared_instance(const Interface &interface);
|
||||
static void detach_interfaces();
|
||||
static void shared_connection_disappeared();
|
||||
static void shared_connection_reappeared();
|
||||
static void drop_announce_queues();
|
||||
static bool announce_emitted(const Packet &packet);
|
||||
static void save_packet_hashlist();
|
||||
static void save_path_table();
|
||||
static void save_tunnel_table();
|
||||
static void persist_data();
|
||||
static void exit_handler();
|
||||
|
||||
private:
|
||||
//static std::set<std::reference_wrapper<const Interface>, std::less<const Interface>> _interfaces; // All active interfaces
|
||||
static std::list<std::reference_wrapper<Interface>> _interfaces; // All active interfaces
|
||||
static std::set<Destination> _destinations; // All active destinations
|
||||
//static std::map<Bytes, Destination> _destinations; // All active destinations
|
||||
static std::set<Link> _pending_links; // Links that are being established
|
||||
static std::set<Link> _active_links; // Links that are active
|
||||
static std::set<Bytes> _packet_hashlist; // A list of packet hashes for duplicate detection
|
||||
static std::set<PacketReceipt> _receipts; // Receipts of all outgoing packets for proof processing
|
||||
|
||||
// TODO: "destination_table" should really be renamed to "path_table"
|
||||
// Notes on memory usage: 1 megabyte of memory can store approximately
|
||||
// 55.100 path table entries or approximately 22.300 link table entries.
|
||||
|
||||
static std::map<Bytes, AnnounceEntry> _announce_table; // A table for storing announces currently waiting to be retransmitted
|
||||
static std::map<Bytes, DestinationEntry> _destination_table; // A lookup table containing the next hop to a given destination
|
||||
static std::map<Bytes, ReverseEntry> _reverse_table; // A lookup table for storing packet hashes used to return proofs and replies
|
||||
static std::map<Bytes, LinkEntry> _link_table; // A lookup table containing hops for links
|
||||
static std::map<Bytes, AnnounceEntry> _held_announces; // A table containing temporarily held announce-table entries
|
||||
static std::set<HAnnounceHandler> _announce_handlers; // A table storing externally registered announce handlers
|
||||
//z_tunnels = {} // A table storing tunnels to other transport instances
|
||||
//z_announce_rate_table = {} // A table for keeping track of announce rates
|
||||
static std::set<Bytes> _path_requests; // A table for storing path request timestamps
|
||||
|
||||
//z_discovery_path_requests = {} // A table for keeping track of path requests on behalf of other nodes
|
||||
//z_discovery_pr_tags = [] // A table for keeping track of tagged path requests
|
||||
static uint16_t _max_pr_taXgxs; // Maximum amount of unique path request tags to remember
|
||||
|
||||
// Transport control destinations are used
|
||||
// for control purposes like path requests
|
||||
static std::set<Destination> _control_destinations;
|
||||
static std::set<Bytes> _control_hashes;
|
||||
|
||||
// Interfaces for communicating with
|
||||
// local clients connected to a shared
|
||||
// Reticulum instance
|
||||
static std::set<Interface> _local_client_interfaces;
|
||||
|
||||
//z_local_client_rssi_cache = []
|
||||
//z_local_client_snr_cache = []
|
||||
static uint16_t _LOCAL_CLIENT_CACHE_MAXSIZE;
|
||||
|
||||
std::map<Bytes, Interface> _pending_local_path_requests;
|
||||
|
||||
static uint64_t _start_time;
|
||||
static bool _jobs_locked;
|
||||
static bool _jobs_running;
|
||||
static uint32_t _job_interval;
|
||||
static uint64_t _links_last_checked;
|
||||
static uint32_t _links_check_interval;
|
||||
static uint64_t _receipts_last_checked;
|
||||
static uint32_t _receipts_check_interval;
|
||||
static uint64_t _announces_last_checked;
|
||||
static uint32_t _announces_check_interval;
|
||||
static uint32_t _hashlist_maxsize;
|
||||
static uint64_t _tables_last_culled;
|
||||
static uint32_t _tables_cull_interval;
|
||||
|
||||
static Reticulum _owner;
|
||||
static Identity _identity;
|
||||
};
|
||||
|
||||
}
|
23
src/Utilities/OS.h
Normal file
23
src/Utilities/OS.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
namespace RNS { namespace Utilities {
|
||||
|
||||
class OS {
|
||||
|
||||
public:
|
||||
// sleep for specified milliseconds
|
||||
static inline void sleep(float seconds) { ::sleep(seconds); }
|
||||
//static inline void sleep(uint32_t milliseconds) { ::sleep((float)milliseconds / 1000.0); }
|
||||
// return current time in milliseconds since 00:00:00, January 1, 1970 (Unix Epoch)
|
||||
static uint64_t time() { timeval time; ::gettimeofday(&time, NULL); return (uint64_t)(time.tv_sec * 1000) + (uint64_t)(time.tv_usec / 1000); }
|
||||
static inline float round(float value, uint8_t precision) { return std::round(value / precision) * precision; }
|
||||
|
||||
};
|
||||
|
||||
} }
|
226
src/main.cpp
226
src/main.cpp
@ -6,6 +6,7 @@
|
||||
#include "Identity.h"
|
||||
#include "Destination.h"
|
||||
#include "Packet.h"
|
||||
#include "Interfaces/Interface.h"
|
||||
#include "Bytes.h"
|
||||
|
||||
#ifndef NATIVE
|
||||
@ -17,6 +18,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
//#include <sstream>
|
||||
|
||||
// Let's define an app name. We'll use this for all
|
||||
@ -29,9 +31,98 @@ const char* APP_NAME = "example_utilities";
|
||||
const char* fruits[] = {"Peach", "Quince", "Date", "Tangerine", "Pomelo", "Carambola", "Grape"};
|
||||
const char* noble_gases[] = {"Helium", "Neon", "Argon", "Krypton", "Xenon", "Radon", "Oganesson"};
|
||||
|
||||
class TestInterface : public RNS::Interface {
|
||||
public:
|
||||
TestInterface() : RNS::Interface("TestInterface") {
|
||||
IN(true);
|
||||
OUT(true);
|
||||
}
|
||||
TestInterface(const char *name) : RNS::Interface(name) {
|
||||
IN(true);
|
||||
OUT(true);
|
||||
}
|
||||
virtual ~TestInterface() {
|
||||
name("deleted");
|
||||
}
|
||||
virtual void processIncoming(const RNS::Bytes &data) {
|
||||
RNS::extreme("TestInterface.processIncoming: data: " + data.toHex());
|
||||
}
|
||||
virtual void processOutgoing(const RNS::Bytes &data) {
|
||||
RNS::extreme("TestInterface.processOutgoing: data: " + data.toHex());
|
||||
}
|
||||
virtual inline std::string toString() const { return "TestInterface[" + name() + "]"; }
|
||||
};
|
||||
|
||||
class TestLoopbackInterface : public RNS::Interface {
|
||||
public:
|
||||
TestLoopbackInterface(RNS::Interface &loopback_interface) : RNS::Interface("TestLoopbackInterface"), _loopback_interface(loopback_interface) {
|
||||
IN(true);
|
||||
OUT(true);
|
||||
}
|
||||
TestLoopbackInterface(RNS::Interface &loopback_interface, const char *name) : RNS::Interface(name), _loopback_interface(loopback_interface) {
|
||||
IN(true);
|
||||
OUT(true);
|
||||
}
|
||||
virtual ~TestLoopbackInterface() {
|
||||
name("deleted");
|
||||
}
|
||||
virtual void processIncoming(const RNS::Bytes &data) {
|
||||
RNS::extreme("TestLoopbackInterface.processIncoming: data: " + data.toHex());
|
||||
_loopback_interface.processOutgoing(data);
|
||||
}
|
||||
virtual void processOutgoing(const RNS::Bytes &data) {
|
||||
RNS::extreme("TestLoopbackInterface.processOutgoing: data: " + data.toHex());
|
||||
_loopback_interface.processIncoming(data);
|
||||
}
|
||||
virtual inline std::string toString() const { return "TestLoopbackInterface[" + name() + "]"; }
|
||||
private:
|
||||
RNS::Interface &_loopback_interface;
|
||||
};
|
||||
|
||||
class TestOutInterface : public RNS::Interface {
|
||||
public:
|
||||
TestOutInterface() : RNS::Interface("TestOutInterface") {
|
||||
OUT(true);
|
||||
IN(false);
|
||||
}
|
||||
TestOutInterface(const char *name) : RNS::Interface(name) {
|
||||
OUT(true);
|
||||
IN(false);
|
||||
}
|
||||
virtual ~TestOutInterface() {
|
||||
name("(deleted)");
|
||||
}
|
||||
virtual void processOutgoing(const RNS::Bytes &data) {
|
||||
RNS::head("TestOutInterface.processOutgoing: data: " + data.toHex(), RNS::LOG_EXTREME);
|
||||
RNS::Interface::processOutgoing(data);
|
||||
}
|
||||
virtual inline std::string toString() const { return "TestOutInterface[" + name() + "]"; }
|
||||
};
|
||||
|
||||
class TestInInterface : public RNS::Interface {
|
||||
public:
|
||||
TestInInterface() : RNS::Interface("TestInInterface") {
|
||||
OUT(false);
|
||||
IN(true);
|
||||
}
|
||||
TestInInterface(const char *name) : RNS::Interface(name) {
|
||||
OUT(false);
|
||||
IN(true);
|
||||
}
|
||||
virtual ~TestInInterface() {
|
||||
name("(deleted)");
|
||||
}
|
||||
virtual void processIncoming(const RNS::Bytes &data) {
|
||||
RNS::head("TestInInterface.processIncoming: data: " + data.toHex(), RNS::LOG_EXTREME);
|
||||
RNS::Interface::processIncoming(data);
|
||||
}
|
||||
virtual inline std::string toString() const { return "TestInInterface[" + name() + "]"; }
|
||||
};
|
||||
|
||||
void onPacket(const RNS::Bytes &data, const RNS::Packet &packet) {
|
||||
RNS::extreme("onPacket: data: " + data.toHex());
|
||||
RNS::extreme("onPacket: data string: \"" + data.toString() + "\"");
|
||||
RNS::head("onPacket: data: " + data.toHex(), RNS::LOG_EXTREME);
|
||||
RNS::head("onPacket: data string: \"" + data.toString() + "\"", RNS::LOG_EXTREME);
|
||||
//RNS::head("onPacket: " + packet.debugString(), RNS::LOG_EXTREME);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
@ -46,7 +137,11 @@ void setup() {
|
||||
#ifndef NDEBUG
|
||||
RNS::loglevel(RNS::LOG_WARNING);
|
||||
//RNS::loglevel(RNS::LOG_EXTREME);
|
||||
RNS::extreme("Running tests...");
|
||||
test();
|
||||
//testReference();
|
||||
//testCrypto();
|
||||
RNS::extreme("Finished running tests");
|
||||
#endif
|
||||
|
||||
//std::stringstream test;
|
||||
@ -59,22 +154,58 @@ void setup() {
|
||||
|
||||
// 21.8% baseline here with serial
|
||||
|
||||
RNS::head("Creating Reticulum instance...", RNS::LOG_EXTREME);
|
||||
RNS::Reticulum reticulum;
|
||||
// 21.9% (+0.1%)
|
||||
|
||||
RNS::head("Creating Interface instances...", RNS::LOG_EXTREME);
|
||||
//TestInterface interface;
|
||||
TestOutInterface outinterface;
|
||||
TestInInterface ininterface;
|
||||
TestLoopbackInterface loopinterface(ininterface);
|
||||
|
||||
RNS::head("Registering Interface instances with Transport...", RNS::LOG_EXTREME);
|
||||
//RNS::Transport::register_interface(interface);
|
||||
RNS::Transport::register_interface(outinterface);
|
||||
RNS::Transport::register_interface(ininterface);
|
||||
RNS::Transport::register_interface(loopinterface);
|
||||
|
||||
RNS::head("Creating Identity instance...", RNS::LOG_EXTREME);
|
||||
RNS::Identity identity;
|
||||
// 22.6% (+0.7%)
|
||||
|
||||
RNS::head("Creating Destination instance...", RNS::LOG_EXTREME);
|
||||
RNS::Destination destination(identity, RNS::Destination::IN, RNS::Destination::SINGLE, "test", "context");
|
||||
// 23.0% (+0.4%)
|
||||
|
||||
/*
|
||||
RNS::head("Testing map...", RNS::LOG_EXTREME);
|
||||
{
|
||||
std::map<RNS::Bytes, RNS::Destination&> destinations;
|
||||
destinations.insert({destination.hash(), destination});
|
||||
//for (RNS::Destination &destination : destinations) {
|
||||
for (auto &[hash, destination] : destinations) {
|
||||
RNS::extreme("Iterated destination: " + destination.toString());
|
||||
}
|
||||
RNS::Bytes hash = destination.hash();
|
||||
auto iter = destinations.find(hash);
|
||||
if (iter != destinations.end()) {
|
||||
RNS::Destination &destination = (*iter).second;
|
||||
RNS::extreme("Found destination: " + destination.toString());
|
||||
}
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
destination.set_proof_strategy(RNS::Destination::PROVE_ALL);
|
||||
|
||||
//zRNS::head("Registering announce handler with Transport...", RNS::LOG_EXTREME);
|
||||
//zannounce_handler = ExampleAnnounceHandler(
|
||||
//z aspect_filter="example_utilities.announcesample.fruits";
|
||||
//z)
|
||||
//zRNS::Transport.register_announce_handler(announce_handler);
|
||||
|
||||
RNS::head("Announcing destination...", RNS::LOG_EXTREME);
|
||||
//destination.announce(RNS::bytesFromString(fruits[rand() % 7]));
|
||||
// test path
|
||||
//destination.announce(RNS::bytesFromString(fruits[rand() % 7]), true, nullptr, RNS::bytesFromString("test_tag"));
|
||||
@ -82,17 +213,27 @@ void setup() {
|
||||
destination.announce(RNS::bytesFromString(fruits[rand() % 7]));
|
||||
// 23.9% (+0.8%)
|
||||
|
||||
/*
|
||||
// test data send packet
|
||||
RNS::head("Creating send packet...", RNS::LOG_EXTREME);
|
||||
RNS::Packet send_packet(destination, "The quick brown fox jumps over the lazy dog");
|
||||
|
||||
RNS::head("Sending send packet...", RNS::LOG_EXTREME);
|
||||
send_packet.pack();
|
||||
RNS::extreme("Test send_packet packet: " + send_packet.debugString());
|
||||
RNS::extreme("Test send_packet: " + send_packet.debugString());
|
||||
|
||||
// test data receive packet
|
||||
RNS::head("Registering packet callback with Destination...", RNS::LOG_EXTREME);
|
||||
destination.set_packet_callback(onPacket);
|
||||
|
||||
RNS::head("Creating recv packet...", RNS::LOG_EXTREME);
|
||||
RNS::Packet recv_packet(RNS::Destination::NONE, send_packet.raw());
|
||||
recv_packet.unpack();
|
||||
RNS::extreme("Test recv_packet packet: " + recv_packet.debugString());
|
||||
RNS::extreme("Test recv_packet: " + recv_packet.debugString());
|
||||
|
||||
RNS::head("Spoofing recv packet to destination...", RNS::LOG_EXTREME);
|
||||
destination.receive(recv_packet);
|
||||
*/
|
||||
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
@ -110,6 +251,83 @@ void loop() {
|
||||
int main(void) {
|
||||
printf("Hello from Native on PlatformIO!\n");
|
||||
|
||||
/*
|
||||
RNS::loglevel(RNS::LOG_EXTREME);
|
||||
TestInterface testinterface;
|
||||
|
||||
std::set<std::reference_wrapper<RNS::Interface>, std::less<RNS::Interface>> interfaces;
|
||||
interfaces.insert(testinterface);
|
||||
for (auto iter = interfaces.begin(); iter != interfaces.end(); ++iter) {
|
||||
RNS::Interface &interface = (*iter);
|
||||
RNS::extreme("Found interface: " + interface.toString());
|
||||
RNS::Bytes data;
|
||||
const_cast<RNS::Interface&>(interface).processOutgoing(data);
|
||||
}
|
||||
return 0;
|
||||
*/
|
||||
/*
|
||||
RNS::loglevel(RNS::LOG_EXTREME);
|
||||
TestInterface testinterface;
|
||||
|
||||
std::set<std::reference_wrapper<RNS::Interface>, std::less<RNS::Interface>> interfaces;
|
||||
interfaces.insert(testinterface);
|
||||
for (auto &interface : interfaces) {
|
||||
RNS::extreme("Found interface: " + interface.toString());
|
||||
RNS::Bytes data;
|
||||
const_cast<RNS::Interface&>(interface).processOutgoing(data);
|
||||
}
|
||||
return 0;
|
||||
*/
|
||||
/*
|
||||
RNS::loglevel(RNS::LOG_EXTREME);
|
||||
TestInterface testinterface;
|
||||
|
||||
std::list<std::reference_wrapper<RNS::Interface>> interfaces;
|
||||
interfaces.push_back(testinterface);
|
||||
for (auto iter = interfaces.begin(); iter != interfaces.end(); ++iter) {
|
||||
RNS::Interface &interface = (*iter);
|
||||
RNS::extreme("Found interface: " + interface.toString());
|
||||
RNS::Bytes data;
|
||||
const_cast<RNS::Interface&>(interface).processOutgoing(data);
|
||||
}
|
||||
return 0;
|
||||
*/
|
||||
/*
|
||||
RNS::loglevel(RNS::LOG_EXTREME);
|
||||
TestInterface testinterface;
|
||||
|
||||
std::list<std::reference_wrapper<RNS::Interface>> interfaces;
|
||||
interfaces.push_back(testinterface);
|
||||
//for (auto &interface : interfaces) {
|
||||
for (RNS::Interface &interface : interfaces) {
|
||||
RNS::extreme("Found interface: " + interface.toString());
|
||||
RNS::Bytes data;
|
||||
const_cast<RNS::Interface&>(interface).processOutgoing(data);
|
||||
}
|
||||
return 0;
|
||||
*/
|
||||
/*
|
||||
std::list<std::reference_wrapper<RNS::Interface>> interfaces;
|
||||
{
|
||||
RNS::loglevel(RNS::LOG_EXTREME);
|
||||
TestInterface testinterface;
|
||||
interfaces.push_back(testinterface);
|
||||
for (auto iter = interfaces.begin(); iter != interfaces.end(); ++iter) {
|
||||
RNS::Interface &interface = (*iter);
|
||||
RNS::extreme("1 Found interface: " + interface.toString());
|
||||
RNS::Bytes data;
|
||||
const_cast<RNS::Interface&>(interface).processOutgoing(data);
|
||||
}
|
||||
}
|
||||
for (auto iter = interfaces.begin(); iter != interfaces.end(); ++iter) {
|
||||
RNS::Interface &interface = (*iter);
|
||||
RNS::extreme("2 Found interface: " + interface.toString());
|
||||
RNS::Bytes data;
|
||||
const_cast<RNS::Interface&>(interface).processOutgoing(data);
|
||||
}
|
||||
return 0;
|
||||
*/
|
||||
|
||||
setup();
|
||||
|
||||
//while (true) {
|
||||
|
Loading…
Reference in New Issue
Block a user