mirror of
https://github.com/markqvist/reticulum-cpp.git
synced 2024-10-01 02:55:46 -04:00
WIP: Added super basic UDP interface for testing
Basic UDP interface enabled testing with RNS reference implementation. Added to basic Transport implementation.
This commit is contained in:
parent
8d943318a6
commit
ea7b4603ed
50
src/Bytes.h
50
src/Bytes.h
@ -29,37 +29,37 @@ namespace RNS {
|
||||
|
||||
public:
|
||||
Bytes() {
|
||||
//extreme("Bytes object created from default, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
//mem("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((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
Bytes(const NoneConstructor none) {
|
||||
//mem("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");
|
||||
//mem("Bytes is using shared data");
|
||||
assign(bytes);
|
||||
//extreme("Bytes object copy created from bytes \"" + toString() + "\", this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
//mem("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) {
|
||||
Bytes(const uint8_t* chunk, size_t size) {
|
||||
assign(chunk, size);
|
||||
//extreme(std::string("Bytes object created from chunk \"") + toString() + "\", this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
//mem(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) {
|
||||
Bytes(const char* string) {
|
||||
assign(string);
|
||||
//extreme(std::string("Bytes object created from string \"") + toString() + "\", this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
//mem(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((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_data.get()));
|
||||
//mem(std::string("Bytes object created from std::string \"") + toString() + "\", this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((unsigned long)_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()));
|
||||
//mem(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) {
|
||||
inline const Bytes& operator = (const Bytes& bytes) {
|
||||
assign(bytes);
|
||||
return *this;
|
||||
}
|
||||
inline Bytes& operator += (const Bytes& bytes) {
|
||||
inline const Bytes& operator += (const Bytes& bytes) {
|
||||
append(bytes);
|
||||
return *this;
|
||||
}
|
||||
@ -87,12 +87,12 @@ namespace RNS {
|
||||
|
||||
private:
|
||||
inline SharedData shareData() const {
|
||||
//extreme("Bytes is sharing its own data");
|
||||
//mem("Bytes is sharing its own data");
|
||||
_owner = false;
|
||||
return _data;
|
||||
}
|
||||
inline void newData(size_t size = 0) {
|
||||
//extreme("Bytes is creating its own data");
|
||||
//mem("Bytes is creating its own data");
|
||||
if (size > 0) {
|
||||
_data = SharedData(new Data(size));
|
||||
}
|
||||
@ -124,7 +124,7 @@ namespace RNS {
|
||||
_data->insert(_data->begin(), bytes._data->begin(), bytes._data->end());
|
||||
#endif
|
||||
}
|
||||
inline void assign(const uint8_t *chunk, size_t size) {
|
||||
inline void assign(const uint8_t* chunk, size_t size) {
|
||||
// if assignment is empty then clear data and don't bother creating new
|
||||
if (chunk == nullptr || size <= 0) {
|
||||
_data = nullptr;
|
||||
@ -142,7 +142,7 @@ namespace RNS {
|
||||
return;
|
||||
}
|
||||
newData();
|
||||
_data->insert(_data->begin(), (uint8_t *)string, (uint8_t *)string + strlen(string));
|
||||
_data->insert(_data->begin(), (uint8_t* )string, (uint8_t* )string + strlen(string));
|
||||
}
|
||||
inline void assign(const std::string& string) { assign(string.c_str()); }
|
||||
void assignHex(const char* hex);
|
||||
@ -155,7 +155,7 @@ namespace RNS {
|
||||
ownData();
|
||||
_data->insert(_data->end(), bytes._data->begin(), bytes._data->end());
|
||||
}
|
||||
inline void append(const uint8_t *chunk, size_t size) {
|
||||
inline void append(const uint8_t* chunk, size_t size) {
|
||||
// if append is empty then do nothing
|
||||
if (chunk == nullptr || size <= 0) {
|
||||
return;
|
||||
@ -169,7 +169,7 @@ namespace RNS {
|
||||
return;
|
||||
}
|
||||
ownData();
|
||||
_data->insert(_data->end(), (uint8_t *)string, (uint8_t *)string + strlen(string));
|
||||
_data->insert(_data->end(), (uint8_t* )string, (uint8_t* )string + strlen(string));
|
||||
}
|
||||
inline void append(const std::string& string) { append(string.c_str()); }
|
||||
inline void append(uint8_t byte) {
|
||||
@ -187,7 +187,7 @@ namespace RNS {
|
||||
_data->resize(newsize);
|
||||
}
|
||||
|
||||
inline uint8_t *writable(size_t size) {
|
||||
inline uint8_t* writable(size_t size) {
|
||||
newData(size);
|
||||
return _data->data();
|
||||
}
|
||||
@ -197,7 +197,7 @@ namespace RNS {
|
||||
inline size_t size() const { if (!_data) return 0; return _data->size(); }
|
||||
inline bool empty() const { if (!_data) return true; return _data->empty(); }
|
||||
inline size_t capacity() const { if (!_data) return 0; return _data->capacity(); }
|
||||
inline const uint8_t *data() const { if (!_data) return nullptr; return _data->data(); }
|
||||
inline const uint8_t* data() const { if (!_data) return nullptr; return _data->data(); }
|
||||
|
||||
inline std::string toString() const { if (!_data) return ""; return {(const char*)data(), size()}; }
|
||||
std::string toHex(bool upper = true) const;
|
||||
@ -236,10 +236,10 @@ namespace RNS {
|
||||
|
||||
// following array function doesn't work without size since it's past as a pointer to the array sizeof() is of the pointer
|
||||
//inline Bytes bytesFromArray(const uint8_t arr[]) { return Bytes(arr, sizeof(arr)); }
|
||||
//inline Bytes bytesFromChunk(const uint8_t *ptr, size_t len) { return Bytes(ptr, len); }
|
||||
inline Bytes bytesFromChunk(const uint8_t *ptr, size_t len) { return {ptr, len}; }
|
||||
//inline Bytes bytesFromString(const char *str) { return Bytes((uint8_t*)str, strlen(str)); }
|
||||
inline Bytes bytesFromString(const char *str) { return {(uint8_t*)str, strlen(str)}; }
|
||||
//inline Bytes bytesFromChunk(const uint8_t* ptr, size_t len) { return Bytes(ptr, len); }
|
||||
inline Bytes bytesFromChunk(const uint8_t* ptr, size_t len) { return {ptr, len}; }
|
||||
//inline Bytes bytesFromString(const char* str) { return Bytes((uint8_t*)str, strlen(str)); }
|
||||
inline Bytes bytesFromString(const char* str) { return {(uint8_t*)str, strlen(str)}; }
|
||||
//z inline Bytes bytesFromInt(const int) { return {(uint8_t*)str, strlen(str)}; }
|
||||
|
||||
inline std::string stringFromBytes(const Bytes& bytes) { return bytes.toString(); }
|
||||
|
@ -64,7 +64,7 @@ size_t CBCCommon::ivSize() const
|
||||
return 16;
|
||||
}
|
||||
|
||||
bool CBCCommon::setKey(const uint8_t *key, size_t len)
|
||||
bool CBCCommon::setKey(const uint8_t* key, size_t len)
|
||||
{
|
||||
// Verify the cipher's block size, just in case.
|
||||
if (blockCipher->blockSize() != 16)
|
||||
@ -74,7 +74,7 @@ bool CBCCommon::setKey(const uint8_t *key, size_t len)
|
||||
return blockCipher->setKey(key, len);
|
||||
}
|
||||
|
||||
bool CBCCommon::setIV(const uint8_t *iv, size_t len)
|
||||
bool CBCCommon::setIV(const uint8_t* iv, size_t len)
|
||||
{
|
||||
if (len != 16)
|
||||
return false;
|
||||
@ -83,7 +83,7 @@ bool CBCCommon::setIV(const uint8_t *iv, size_t len)
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBCCommon::encrypt(uint8_t *output, const uint8_t *input, size_t len)
|
||||
void CBCCommon::encrypt(uint8_t* output, const uint8_t* input, size_t len)
|
||||
{
|
||||
uint8_t posn;
|
||||
while (len >= 16) {
|
||||
@ -96,7 +96,7 @@ void CBCCommon::encrypt(uint8_t *output, const uint8_t *input, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
void CBCCommon::decrypt(uint8_t *output, const uint8_t *input, size_t len)
|
||||
void CBCCommon::decrypt(uint8_t* output, const uint8_t* input, size_t len)
|
||||
{
|
||||
uint8_t posn;
|
||||
while (len >= 16) {
|
||||
|
@ -34,11 +34,11 @@ public:
|
||||
size_t keySize() const;
|
||||
size_t ivSize() const;
|
||||
|
||||
bool setKey(const uint8_t *key, size_t len);
|
||||
bool setIV(const uint8_t *iv, size_t len);
|
||||
bool setKey(const uint8_t* key, size_t len);
|
||||
bool setIV(const uint8_t* iv, size_t len);
|
||||
|
||||
void encrypt(uint8_t *output, const uint8_t *input, size_t len);
|
||||
void decrypt(uint8_t *output, const uint8_t *input, size_t len);
|
||||
void encrypt(uint8_t* output, const uint8_t* input, size_t len);
|
||||
void decrypt(uint8_t* output, const uint8_t* input, size_t len);
|
||||
|
||||
void clear();
|
||||
|
||||
|
@ -26,11 +26,11 @@ Fernet::Fernet(const Bytes& key) {
|
||||
//self._encryption_key = key[16:]
|
||||
_encryption_key = key.mid(16);
|
||||
|
||||
extreme("Fernet object created");
|
||||
mem("Fernet object created");
|
||||
}
|
||||
|
||||
Fernet::~Fernet() {
|
||||
extreme("Fernet object destroyed");
|
||||
mem("Fernet object destroyed");
|
||||
}
|
||||
|
||||
bool Fernet::verify_hmac(const Bytes& token) {
|
||||
|
@ -12,8 +12,9 @@
|
||||
using namespace RNS;
|
||||
using namespace RNS::Type::Destination;
|
||||
|
||||
Destination::Destination(const Identity& identity, const directions direction, const types type, const char* app_name, const char *aspects) : _object(new Object(identity)) {
|
||||
Destination::Destination(const Identity& identity, const directions direction, const types type, const char* app_name, const char* aspects) : _object(new Object(identity)) {
|
||||
assert(_object);
|
||||
mem("Destination object creating..., this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
|
||||
// Check input values and build name string
|
||||
if (strchr(app_name, '.') != nullptr) {
|
||||
@ -27,8 +28,8 @@ Destination::Destination(const Identity& identity, const directions direction, c
|
||||
if (!identity && direction == IN && _object->_type != PLAIN) {
|
||||
debug("Destination::Destination: identity not provided, creating new one");
|
||||
_object->_identity = Identity();
|
||||
// CBA TODO should following include a "." delimiter?
|
||||
fullaspects += _object->_identity.hexhash();
|
||||
// CBA TODO determine why identity.hexhash is added both here and by expand_name called below
|
||||
fullaspects += "." + _object->_identity.hexhash();
|
||||
}
|
||||
debug("Destination::Destination: full aspects: " + fullaspects);
|
||||
|
||||
@ -46,34 +47,53 @@ Destination::Destination(const Identity& identity, const directions direction, c
|
||||
debug("Destination::Destination: hash: " + _object->_hash.toHex());
|
||||
// CBA TEST CRASH
|
||||
debug("Destination::Destination: creating name hash...");
|
||||
_object->_name_hash = Identity::truncated_hash(expand_name({Type::NONE}, app_name, fullaspects.c_str()));
|
||||
//p self.name_hash = RNS.Identity.full_hash(self.expand_name(None, app_name, *aspects).encode("utf-8"))[:(RNS.Identity.NAME_HASH_LENGTH//8)]
|
||||
_object->_name_hash = name_hash(app_name, aspects);
|
||||
debug("Destination::Destination: name hash: " + _object->_name_hash.toHex());
|
||||
|
||||
debug("Destination::Destination: calling register_destination");
|
||||
Transport::register_destination(*this);
|
||||
|
||||
extreme("Destination object created");
|
||||
mem("Destination object created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
|
||||
/*virtual*/ Destination::~Destination() {
|
||||
mem("Destination object destroyed, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
if (_object && _object.use_count() == 1) {
|
||||
extreme("Destination object has last data reference");
|
||||
|
||||
// CBA Can't call deregister_destination here because it's possible (likely even) that Destination
|
||||
// is being destructed from that same collection which will result in a llop and memory errors.
|
||||
//debug("Destination::~Destination: calling deregister_destination");
|
||||
//Transport::deregister_destination(*this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
:returns: A destination name in adressable hash form, for an app_name and a number of aspects.
|
||||
*/
|
||||
/*static*/ Bytes Destination::hash(const Identity& identity, const char *app_name, const char *aspects) {
|
||||
//name_hash = Identity::full_hash(Destination.expand_name(None, app_name, *aspects).encode("utf-8"))[:(RNS.Identity.NAME_HASH_LENGTH//8)]
|
||||
//addr_hash_material = name_hash
|
||||
Bytes addr_hash_material = Identity::truncated_hash(expand_name({Type::NONE}, app_name, aspects));
|
||||
//if identity != None:
|
||||
// if isinstance(identity, RNS.Identity):
|
||||
// addr_hash_material += identity.hash
|
||||
// elif isinstance(identity, bytes) and len(identity) == RNS.Reticulum.TRUNCATED_HASHLENGTH//8:
|
||||
// addr_hash_material += identity
|
||||
// else:
|
||||
// raise TypeError("Invalid material supplied for destination hash calculation")
|
||||
addr_hash_material << identity.hash();
|
||||
/*static*/ Bytes Destination::hash(const Identity& identity, const char* app_name, const char* aspects) {
|
||||
//p name_hash = Identity::full_hash(Destination.expand_name(None, app_name, *aspects).encode("utf-8"))[:(RNS.Identity.NAME_HASH_LENGTH//8)]
|
||||
//p addr_hash_material = name_hash
|
||||
Bytes addr_hash_material = name_hash(app_name, aspects);
|
||||
if (identity) {
|
||||
addr_hash_material << identity.hash();
|
||||
}
|
||||
|
||||
//p return RNS.Identity.full_hash(addr_hash_material)[:RNS.Reticulum.TRUNCATED_HASHLENGTH//8]
|
||||
// CBA TODO valid alternative?
|
||||
//return Identity::full_hash(addr_hash_material).left(Type::Reticulum::TRUNCATED_HASHLENGTH/8);
|
||||
return Identity::truncated_hash(addr_hash_material);
|
||||
}
|
||||
|
||||
/*
|
||||
:returns: A name in hash form, for an app_name and a number of aspects.
|
||||
*/
|
||||
/*static*/ Bytes Destination::name_hash(const char* app_name, const char* aspects) {
|
||||
//p name_hash = Identity::full_hash(Destination.expand_name(None, app_name, *aspects).encode("utf-8"))[:(RNS.Identity.NAME_HASH_LENGTH//8)]
|
||||
return Identity::full_hash(expand_name({Type::NONE}, app_name, aspects)).left(Type::Identity::NAME_HASH_LENGTH/8);
|
||||
}
|
||||
|
||||
/*
|
||||
:returns: A tuple containing the app name and a list of aspects, for a full-name string.
|
||||
*/
|
||||
@ -97,7 +117,7 @@ Destination::Destination(const Identity& identity, const directions direction, c
|
||||
/*
|
||||
:returns: A string containing the full human-readable name of the destination, for an app_name and a number of aspects.
|
||||
*/
|
||||
/*static*/ std::string Destination::expand_name(const Identity& identity, const char *app_name, const char *aspects) {
|
||||
/*static*/ std::string Destination::expand_name(const Identity& identity, const char* app_name, const char* aspects) {
|
||||
|
||||
if (strchr(app_name, '.') != nullptr) {
|
||||
throw std::invalid_argument("Dots can't be used in app names");
|
||||
@ -194,8 +214,9 @@ Packet Destination::announce(const Bytes& app_data, bool path_response, const In
|
||||
}
|
||||
else {
|
||||
Bytes destination_hash = _object->_hash;
|
||||
//random_hash = Identity::get_random_hash()[0:5] << int(time.time()).to_bytes(5, "big")
|
||||
Bytes random_hash;
|
||||
//p random_hash = Identity::get_random_hash()[0:5] << int(time.time()).to_bytes(5, "big")
|
||||
// CBA TODO add in time to random hash
|
||||
Bytes random_hash = Cryptography::random(Type::Identity::RANDOM_HASH_LENGTH/8);
|
||||
|
||||
Bytes new_app_data(app_data);
|
||||
if (new_app_data.empty() && !_object->_default_app_data.empty()) {
|
||||
|
@ -40,7 +40,7 @@ namespace RNS {
|
||||
class Callbacks {
|
||||
public:
|
||||
using link_established = void(*)(const Link& link);
|
||||
//using packet = void(*)(uint8_t *data, uint16_t data_len, Packet *packet);
|
||||
//using packet = void(*)(uint8_t* data, uint16_t data_len, Packet *packet);
|
||||
using packet = void(*)(const Bytes& data, const Packet& packet);
|
||||
using proof_requested = bool(*)(const Packet& packet);
|
||||
public:
|
||||
@ -56,19 +56,23 @@ namespace RNS {
|
||||
|
||||
public:
|
||||
Destination(Type::NoneConstructor none) {
|
||||
extreme("Destination NONE object created");
|
||||
mem("Destination NONE object created, this: " + std::to_string((uintptr_t)this));
|
||||
}
|
||||
Destination(const Destination& destination) : _object(destination._object) {
|
||||
extreme("Destination object copy created");
|
||||
}
|
||||
Destination(const Identity& identity, const Type::Destination::directions direction, const Type::Destination::types type, const char* app_name, const char *aspects);
|
||||
virtual ~Destination() {
|
||||
extreme("Destination object destroyed");
|
||||
mem("Destination object copy created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
Destination(
|
||||
const Identity& identity,
|
||||
const Type::Destination::directions direction,
|
||||
const Type::Destination::types type,
|
||||
const char* app_name,
|
||||
const char* aspects
|
||||
);
|
||||
virtual ~Destination();
|
||||
|
||||
inline Destination& operator = (const Destination& destination) {
|
||||
_object = destination._object;
|
||||
extreme("Destination object copy created by assignment, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
mem("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 {
|
||||
@ -79,8 +83,9 @@ namespace RNS {
|
||||
}
|
||||
|
||||
public:
|
||||
static std::string expand_name(const Identity& identity, const char *app_name, const char *aspects);
|
||||
static Bytes hash(const Identity& identity, const char *app_name, const char *aspects);
|
||||
static std::string expand_name(const Identity& identity, const char* app_name, const char* aspects);
|
||||
static Bytes hash(const Identity& identity, const char* app_name, const char* aspects);
|
||||
static Bytes name_hash(const char* app_name, const char* aspects);
|
||||
static Bytes app_and_aspects_from_name(const char* full_name);
|
||||
static Bytes hash_from_name_and_identity(const char* full_name, const Identity& identity);
|
||||
|
||||
@ -168,8 +173,8 @@ namespace RNS {
|
||||
private:
|
||||
class Object {
|
||||
public:
|
||||
Object(const Identity& identity) : _identity(identity) {}
|
||||
virtual ~Object() {}
|
||||
Object(const Identity& identity) : _identity(identity) { mem("Destination::Data object created, this: " + std::to_string((uintptr_t)this)); }
|
||||
virtual ~Object() { mem("Destination::Data object destroyed, this: " + std::to_string((uintptr_t)this)); }
|
||||
private:
|
||||
bool _accept_link_requests = true;
|
||||
Callbacks _callbacks;
|
||||
|
261
src/Identity.cpp
261
src/Identity.cpp
@ -5,6 +5,7 @@
|
||||
#include "Packet.h"
|
||||
#include "Log.h"
|
||||
#include "Utilities/OS.h"
|
||||
#include "Cryptography/Ed25519.h"
|
||||
#include "Cryptography/X25519.h"
|
||||
#include "Cryptography/HKDF.h"
|
||||
#include "Cryptography/Fernet.h"
|
||||
@ -14,15 +15,17 @@
|
||||
|
||||
using namespace RNS;
|
||||
using namespace RNS::Type::Identity;
|
||||
using namespace RNS::Cryptography;
|
||||
using namespace RNS::Utilities;
|
||||
|
||||
/*static*/ std::map<Bytes, Identity::IdentityEntry> Identity::_known_destinations;
|
||||
/*static*/ bool Identity::_saving_known_destinations = false;
|
||||
|
||||
Identity::Identity(bool create_keys) : _object(new Object()) {
|
||||
Identity::Identity(bool create_keys /*= true*/) : _object(new Object()) {
|
||||
if (create_keys) {
|
||||
createKeys();
|
||||
}
|
||||
extreme("Identity object created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
mem("Identity object created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
|
||||
void Identity::createKeys() {
|
||||
@ -60,7 +63,6 @@ Load a private key into the instance.
|
||||
:returns: True if the key was loaded, otherwise False.
|
||||
*/
|
||||
bool Identity::load_private_key(const Bytes& prv_bytes) {
|
||||
/*
|
||||
assert(_object);
|
||||
try {
|
||||
//p self.prv_bytes = prv_bytes[:Identity.KEYSIZE//8//2]
|
||||
@ -70,11 +72,11 @@ bool Identity::load_private_key(const Bytes& prv_bytes) {
|
||||
_object->_sig_prv_bytes = prv_bytes.mid(Type::Identity::KEYSIZE/8/2);
|
||||
_object->_sig_prv = Ed25519PrivateKey::from_private_bytes(_object->_sig_prv_bytes);
|
||||
|
||||
_object->_pub = _object->_prv.public_key();
|
||||
_object->_pub_bytes = _object->_pub.public_bytes();
|
||||
_object->_pub = _object->_prv->public_key();
|
||||
_object->_pub_bytes = _object->_pub->public_bytes();
|
||||
|
||||
_object->_sig_pub = _object->_sig_prv.public_key();
|
||||
_object->_sig_pub_bytes = _object->_sig_pub.public_bytes();
|
||||
_object->_sig_pub = _object->_sig_prv->public_key();
|
||||
_object->_sig_pub_bytes = _object->_sig_pub->public_bytes();
|
||||
|
||||
update_hashes();
|
||||
|
||||
@ -82,13 +84,10 @@ bool Identity::load_private_key(const Bytes& prv_bytes) {
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
//p raise e
|
||||
error("Failed to load identity key";
|
||||
error("The contained exception was: " + e.what());
|
||||
error("Failed to load identity key");
|
||||
error("The contained exception was: " + std::string(e.what()));
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
// MOCK
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -98,7 +97,6 @@ Load a public key into the instance.
|
||||
:returns: True if the key was loaded, otherwise False.
|
||||
*/
|
||||
void Identity::load_public_key(const Bytes& pub_bytes) {
|
||||
/*
|
||||
assert(_object);
|
||||
try {
|
||||
//_pub_bytes = pub_bytes[:Identity.KEYSIZE//8//2]
|
||||
@ -106,15 +104,14 @@ void Identity::load_public_key(const Bytes& pub_bytes) {
|
||||
//_sig_pub_bytes = pub_bytes[Identity.KEYSIZE//8//2:]
|
||||
_object->_sig_pub_bytes = pub_bytes.mid(Type::Identity::KEYSIZE/8/2);
|
||||
|
||||
_object->_pub = X25519PublicKey::from_public_bytes(_object->_pub_bytes)
|
||||
_object->_sig_pub = Ed25519PublicKey::from_public_bytes(_object->_sig_pub_bytes)
|
||||
_object->_pub = X25519PublicKey::from_public_bytes(_object->_pub_bytes);
|
||||
_object->_sig_pub = Ed25519PublicKey::from_public_bytes(_object->_sig_pub_bytes);
|
||||
|
||||
update_hashes();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
error("Error while loading public key, the contained exception was: " + e.what());
|
||||
error("Error while loading public key, the contained exception was: " + std::string(e.what()));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool Identity::load(const char* path) {
|
||||
@ -150,8 +147,10 @@ Recall identity for a destination hash.
|
||||
:returns: An :ref:`RNS.Identity<api-identity>` instance that can be used to create an outgoing :ref:`RNS.Destination<api-destination>`, or *None* if the destination is unknown.
|
||||
*/
|
||||
/*static*/ Identity Identity::recall(const Bytes& destination_hash) {
|
||||
extreme("Identity::recall...");
|
||||
auto iter = _known_destinations.find(destination_hash);
|
||||
if (iter != _known_destinations.end()) {
|
||||
extreme("Identity::recall: Found identity entry for destination " + destination_hash.toHex());
|
||||
const IdentityEntry& identity_data = (*iter).second;
|
||||
Identity identity(false);
|
||||
identity.load_public_key(identity_data._public_key);
|
||||
@ -159,13 +158,16 @@ Recall identity for a destination hash.
|
||||
return identity;
|
||||
}
|
||||
else {
|
||||
extreme("Identity::recall: Unable to find identity entry for destination " + destination_hash.toHex() + ", performing destination lookup...");
|
||||
Destination registered_destination(Transport::find_destination_from_hash(destination_hash));
|
||||
if (registered_destination) {
|
||||
extreme("Identity::recall: Found destination " + destination_hash.toHex());
|
||||
Identity identity(false);
|
||||
identity.load_public_key(registered_destination.identity().get_public_key());
|
||||
identity.app_data({Bytes::NONE});
|
||||
return identity;
|
||||
}
|
||||
extreme("Identity::recall: Unable to find destination " + destination_hash.toHex());
|
||||
return {Type::NONE};
|
||||
}
|
||||
}
|
||||
@ -177,39 +179,46 @@ Recall last heard app_data for a destination hash.
|
||||
:returns: *Bytes* containing app_data, or *None* if the destination is unknown.
|
||||
*/
|
||||
/*static*/ Bytes Identity::recall_app_data(const Bytes& destination_hash) {
|
||||
extreme("Identity::recall_app_data...");
|
||||
auto iter = _known_destinations.find(destination_hash);
|
||||
if (iter != _known_destinations.end()) {
|
||||
extreme("Identity::recall_app_data: Found identity entry for destination " + destination_hash.toHex());
|
||||
const IdentityEntry& identity_data = (*iter).second;
|
||||
return identity_data._app_data;
|
||||
}
|
||||
else {
|
||||
extreme("Identity::recall_app_data: Unable to find identity entry for destination " + destination_hash.toHex());
|
||||
return {Bytes::NONE};
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void Identity::save_known_destinations() {
|
||||
/*
|
||||
/*static*/ bool Identity::save_known_destinations() {
|
||||
// TODO: Improve the storage method so we don't have to
|
||||
// deserialize and serialize the entire table on every
|
||||
// save, but the only changes. It might be possible to
|
||||
// simply overwrite on exit now that every local client
|
||||
// disconnect triggers a data persist.
|
||||
|
||||
try:
|
||||
if hasattr(Identity, "saving_known_destinations"):
|
||||
wait_interval = 0.2
|
||||
wait_timeout = 5
|
||||
wait_start = time.time()
|
||||
while Identity.saving_known_destinations:
|
||||
time.sleep(wait_interval)
|
||||
if time.time() > wait_start+wait_timeout:
|
||||
RNS.log("Could not save known destinations to storage, waiting for previous save operation timed out.", RNS.LOG_ERROR)
|
||||
return False
|
||||
try {
|
||||
if (_saving_known_destinations) {
|
||||
double wait_interval = 0.2;
|
||||
double wait_timeout = 5;
|
||||
double wait_start = OS::dtime();
|
||||
while (_saving_known_destinations) {
|
||||
OS::sleep(wait_interval);
|
||||
if (OS::dtime() > (wait_start + wait_timeout)) {
|
||||
error("Could not save known destinations to storage, waiting for previous save operation timed out.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Identity.saving_known_destinations = True
|
||||
save_start = time.time()
|
||||
_saving_known_destinations = true;
|
||||
double save_start = OS::dtime();
|
||||
|
||||
storage_known_destinations = {}
|
||||
std::map<Bytes, IdentityEntry> storage_known_destinations;
|
||||
// TODO
|
||||
/*
|
||||
if os.path.isfile(RNS.Reticulum.storagepath+"/known_destinations"):
|
||||
try:
|
||||
file = open(RNS.Reticulum.storagepath+"/known_destinations","rb")
|
||||
@ -217,32 +226,44 @@ Recall last heard app_data for a destination hash.
|
||||
file.close()
|
||||
except:
|
||||
pass
|
||||
*/
|
||||
|
||||
for destination_hash in storage_known_destinations:
|
||||
if not destination_hash in Identity.known_destinations:
|
||||
Identity.known_destinations[destination_hash] = storage_known_destinations[destination_hash]
|
||||
for (auto& [destination_hash, identity_entry] : storage_known_destinations) {
|
||||
if (_known_destinations.find(destination_hash) == _known_destinations.end()) {
|
||||
//_known_destinations[destination_hash] = storage_known_destinations[destination_hash];
|
||||
//_known_destinations[destination_hash] = identity_entry;
|
||||
_known_destinations.insert({destination_hash, identity_entry});
|
||||
}
|
||||
}
|
||||
|
||||
RNS.log("Saving "+str(len(Identity.known_destinations))+" known destinations to storage...", RNS.LOG_DEBUG)
|
||||
// TODO
|
||||
/*
|
||||
debug("Saving " + std::to_string(_known_destinations.size()) + " known destinations to storage...");
|
||||
file = open(RNS.Reticulum.storagepath+"/known_destinations","wb")
|
||||
umsgpack.dump(Identity.known_destinations, file)
|
||||
file.close()
|
||||
|
||||
save_time = time.time() - save_start
|
||||
if save_time < 1:
|
||||
time_str = str(round(save_time*1000,2))+"ms"
|
||||
else:
|
||||
time_str = str(round(save_time,2))+"s"
|
||||
|
||||
RNS.log("Saved known destinations to storage in "+time_str, RNS.LOG_DEBUG)
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Error while saving known destinations to disk, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
Identity.saving_known_destinations = False
|
||||
*/
|
||||
|
||||
std::string time_str;
|
||||
double save_time = OS::dtime() - save_start;
|
||||
if (save_time < 1) {
|
||||
time_str = std::to_string(OS::round(save_time*1000, 2)) + "ms";
|
||||
}
|
||||
else {
|
||||
time_str = std::to_string(OS::round(save_time, 2)) + "s";
|
||||
}
|
||||
|
||||
debug("Saved known destinations to storage in " + time_str);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
error("Error while saving known destinations to disk, the contained exception was: " + std::string(e.what()));
|
||||
}
|
||||
|
||||
_saving_known_destinations = false;
|
||||
}
|
||||
|
||||
/*static*/ void Identity::load_known_destinations() {
|
||||
// TODO
|
||||
/*
|
||||
if os.path.isfile(RNS.Reticulum.storagepath+"/known_destinations"):
|
||||
try:
|
||||
@ -264,44 +285,62 @@ Recall last heard app_data for a destination hash.
|
||||
}
|
||||
|
||||
/*static*/ bool Identity::validate_announce(const Packet& packet) {
|
||||
try {
|
||||
if (packet.packet_type() == Type::Packet::ANNOUNCE) {
|
||||
Bytes destination_hash = packet.destination_hash();
|
||||
extreme("Identity::validate_announce: destination_hash: " + packet.destination_hash().toHex());
|
||||
Bytes public_key = packet.data().left(KEYSIZE/8);
|
||||
extreme("Identity::validate_announce: public_key: " + public_key.toHex());
|
||||
Bytes name_hash = packet.data().mid(KEYSIZE/8, NAME_HASH_LENGTH/8);
|
||||
extreme("Identity::validate_announce: name_hash: " + name_hash.toHex());
|
||||
Bytes random_hash = packet.data().mid(KEYSIZE/8 + NAME_HASH_LENGTH/8, RANDOM_HASH_LENGTH/8);
|
||||
extreme("Identity::validate_announce: random_hash: " + random_hash.toHex());
|
||||
Bytes signature = packet.data().mid(KEYSIZE/8 + NAME_HASH_LENGTH/8 + RANDOM_HASH_LENGTH/8, SIGLENGTH/8);
|
||||
extreme("Identity::validate_announce: signature: " + signature.toHex());
|
||||
Bytes app_data;
|
||||
if (packet.data().size() > (KEYSIZE/8 + NAME_HASH_LENGTH/8 + RANDOM_HASH_LENGTH/8 + SIGLENGTH/8)) {
|
||||
app_data = packet.data().mid(KEYSIZE/8 + NAME_HASH_LENGTH/8 + RANDOM_HASH_LENGTH/8 + SIGLENGTH/8);
|
||||
}
|
||||
extreme("Identity::validate_announce: app_data: " + app_data.toHex());
|
||||
|
||||
Bytes signed_data;
|
||||
signed_data << packet.destination_hash() << public_key << name_hash << random_hash+app_data;
|
||||
extreme("Identity::validate_announce: signed_data: " + signed_data.toHex());
|
||||
|
||||
if (packet.data().size() <= KEYSIZE/8 + NAME_HASH_LENGTH/8 + RANDOM_HASH_LENGTH/8 + SIGLENGTH/8) {
|
||||
app_data.clear();
|
||||
}
|
||||
|
||||
Identity announced_identity(false);
|
||||
announced_identity.load_public_key(public_key);
|
||||
|
||||
if (announced_identity.pub() && announced_identity.validate(signature, signed_data)) {
|
||||
Bytes hash_material = name_hash << announced_identity.hash();
|
||||
Bytes expected_hash = full_hash(hash_material).left(Type::Reticulum::TRUNCATED_HASHLENGTH/8);
|
||||
extreme("Identity::validate_announce: destination_hash: " + packet.destination_hash().toHex());
|
||||
extreme("Identity::validate_announce: expected_hash: " + expected_hash.toHex());
|
||||
|
||||
if (packet.destination_hash() == expected_hash) {
|
||||
// Check if we already have a public key for this destination
|
||||
// and make sure the public key is not different.
|
||||
auto iter = _known_destinations.find(packet.destination_hash());
|
||||
if (iter != _known_destinations.end()) {
|
||||
IdentityEntry& identity_entry = (*iter).second;
|
||||
if (public_key != identity_entry._public_key) {
|
||||
// In reality, this should never occur, but in the odd case
|
||||
// that someone manages a hash collision, we reject the announce.
|
||||
critical("Received announce with valid signature and destination hash, but announced public key does not match already known public key.");
|
||||
critical("This may indicate an attempt to modify network paths, or a random hash collision. The announce was rejected.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
remember(packet.get_hash(), packet.destination_hash(), public_key, app_data);
|
||||
//p del announced_identity
|
||||
|
||||
std::string signal_str;
|
||||
// TODO
|
||||
/*
|
||||
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:
|
||||
@ -313,29 +352,34 @@ Recall last heard app_data for a destination hash.
|
||||
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;
|
||||
|
||||
if (packet.transport_id()) {
|
||||
extreme("Valid announce for " + packet.destination_hash().toHex() + " " + std::to_string(packet.hops()) + " hops away, received via " + packet.transport_id().toHex() + " on " + packet.receiving_interface().toString() + signal_str);
|
||||
}
|
||||
else {
|
||||
extreme("Valid announce for " + packet.destination_hash().toHex() + " " + std::to_string(packet.hops()) + " hops away, received on " + packet.receiving_interface().toString() + signal_str);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
debug("Received invalid announce for " + packet.destination_hash().toHex() + ": Destination mismatch.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Received invalid announce for " + packet.destination_hash().toHex() + ": Invalid signature.");
|
||||
//p del announced_identity
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
error("Error occurred while validating announce. The contained exception was: " + std::string(e.what()));
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -465,6 +509,7 @@ bool Identity::validate(const Bytes& signature, const Bytes& message) const {
|
||||
assert(_object);
|
||||
if (_object->_pub) {
|
||||
try {
|
||||
extreme("Identity::validate: Attempting to verify signature: " + signature.toHex() + " and message: " + message.toHex());
|
||||
_object->_sig_pub->verify(signature, message);
|
||||
return true;
|
||||
}
|
||||
|
@ -36,21 +36,25 @@ namespace RNS {
|
||||
Bytes _app_data;
|
||||
};
|
||||
|
||||
public:
|
||||
static std::map<Bytes, IdentityEntry> _known_destinations;
|
||||
static bool _saving_known_destinations;
|
||||
|
||||
public:
|
||||
Identity(Type::NoneConstructor none) {
|
||||
extreme("Identity NONE object created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
mem("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((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
mem("Identity object copy created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
Identity(bool create_keys = true);
|
||||
virtual ~Identity() {
|
||||
extreme("Identity object destroyed, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
mem("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((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
mem("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 {
|
||||
@ -102,7 +106,7 @@ namespace RNS {
|
||||
static void remember(const Bytes& packet_hash, const Bytes& destination_hash, const Bytes& public_key, const Bytes& app_data = {Bytes::NONE});
|
||||
static Identity recall(const Bytes& destination_hash);
|
||||
static Bytes recall_app_data(const Bytes& destination_hash);
|
||||
static void save_known_destinations();
|
||||
static bool save_known_destinations();
|
||||
static void load_known_destinations();
|
||||
/*
|
||||
Get a SHA-256 hash of passed data.
|
||||
@ -141,29 +145,31 @@ namespace RNS {
|
||||
inline const Bytes& encryptionPublicKey() const { assert(_object); return _object->_prv_bytes; }
|
||||
inline const Bytes& signingPublicKey() const { assert(_object); return _object->_sig_prv_bytes; }
|
||||
inline const Bytes& hash() const { assert(_object); return _object->_hash; }
|
||||
inline std::string hexhash() const { assert(_object); return _object->_hexhash; }
|
||||
inline const Bytes& app_data() const { assert(_object); return _object->_app_data; }
|
||||
inline void app_data(const Bytes& app_data) { assert(_object); _object->_app_data = app_data; }
|
||||
inline std::string hexhash() const { assert(_object); return _object->_hexhash; }
|
||||
//inline const Cryptography::X25519PrivateKey::Ptr prv() const { assert(_object); return _object->_prv; }
|
||||
inline const Cryptography::X25519PublicKey::Ptr pub() const { assert(_object); return _object->_pub; }
|
||||
|
||||
inline std::string toString() const { assert(_object); return "{Identity:" + _object->_hash.toHex() + "}"; }
|
||||
|
||||
private:
|
||||
class Object {
|
||||
public:
|
||||
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)); }
|
||||
Object() { mem("Identity::Data object created, this: " + std::to_string((uintptr_t)this)); }
|
||||
virtual ~Object() { mem("Identity::Data object destroyed, this: " + std::to_string((uintptr_t)this)); }
|
||||
private:
|
||||
|
||||
RNS::Cryptography::X25519PrivateKey::Ptr _prv;
|
||||
Cryptography::X25519PrivateKey::Ptr _prv;
|
||||
Bytes _prv_bytes;
|
||||
|
||||
RNS::Cryptography::Ed25519PrivateKey::Ptr _sig_prv;
|
||||
Cryptography::Ed25519PrivateKey::Ptr _sig_prv;
|
||||
Bytes _sig_prv_bytes;
|
||||
|
||||
RNS::Cryptography::X25519PublicKey::Ptr _pub;
|
||||
Cryptography::X25519PublicKey::Ptr _pub;
|
||||
Bytes _pub_bytes;
|
||||
|
||||
RNS::Cryptography::Ed25519PublicKey::Ptr _sig_pub;
|
||||
Cryptography::Ed25519PublicKey::Ptr _sig_pub;
|
||||
Bytes _sig_pub_bytes;
|
||||
|
||||
Bytes _hash;
|
||||
@ -175,8 +181,6 @@ namespace RNS {
|
||||
};
|
||||
std::shared_ptr<Object> _object;
|
||||
|
||||
static std::map<Bytes, IdentityEntry> _known_destinations;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -6,6 +6,8 @@
|
||||
using namespace RNS;
|
||||
using namespace RNS::Type::Interface;
|
||||
|
||||
/*static*/ uint8_t Interface::DISCOVER_PATHS_FOR = MODE_ACCESS_POINT | MODE_GATEWAY;
|
||||
|
||||
/*virtual*/ inline void Interface::processIncoming(const Bytes& data) {
|
||||
extreme("Interface::processIncoming: data: " + data.toHex());
|
||||
assert(_object);
|
||||
|
@ -30,31 +30,34 @@ namespace RNS {
|
||||
Bytes _raw;
|
||||
};
|
||||
|
||||
protected:
|
||||
using HInterface = std::shared_ptr<Interface>;
|
||||
|
||||
public:
|
||||
// Which interface modes a Transport Node
|
||||
// should actively discover paths for.
|
||||
uint8_t DISCOVER_PATHS_FOR = Type::Interface::MODE_ACCESS_POINT | Type::Interface::MODE_GATEWAY;
|
||||
static uint8_t DISCOVER_PATHS_FOR;
|
||||
|
||||
public:
|
||||
Interface(Type::NoneConstructor none) {
|
||||
extreme("Interface object NONE created");
|
||||
mem("Interface object NONE created");
|
||||
}
|
||||
Interface(const Interface& interface) : _object(interface._object) {
|
||||
extreme("Interface object copy created");
|
||||
mem("Interface object copy created");
|
||||
}
|
||||
Interface() : _object(new Object()) {
|
||||
extreme("Interface object created");
|
||||
mem("Interface object created");
|
||||
}
|
||||
Interface(const char *name) : _object(new Object(name)) {
|
||||
extreme("Interface object created");
|
||||
Interface(const char* name) : _object(new Object(name)) {
|
||||
mem("Interface object created");
|
||||
}
|
||||
virtual ~Interface() {
|
||||
extreme("Interface object destroyed");
|
||||
mem("Interface object destroyed");
|
||||
}
|
||||
|
||||
inline Interface& operator = (const Interface& interface) {
|
||||
_object = interface._object;
|
||||
extreme("Interface object copy created by assignment, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
mem("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 {
|
||||
@ -80,20 +83,26 @@ namespace RNS {
|
||||
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; }
|
||||
inline void name(const char* name) { assert(_object); _object->_name = name; }
|
||||
inline void bitrate(uint32_t bitrate) { assert(_object); _object->_bitrate = bitrate; }
|
||||
inline void online(bool online) { assert(_object); _object->_online = online; }
|
||||
inline void announce_allowed_at(uint64_t announce_allowed_at) { assert(_object); _object->_announce_allowed_at = announce_allowed_at; }
|
||||
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 bool online() const { assert(_object); return _object->_online; }
|
||||
inline std::string name() const { assert(_object); return _object->_name; }
|
||||
inline const Bytes& ifac_identity() const { assert(_object); return _object->_ifac_identity; }
|
||||
inline Type::Interface::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; }
|
||||
inline bool is_connected_to_shared_instance() const { assert(_object); return _object->_is_connected_to_shared_instance; }
|
||||
inline bool is_local_shared_instance() const { assert(_object); return _object->_is_local_shared_instance; }
|
||||
inline HInterface parent_interface() const { assert(_object); return _object->_parent_interface; }
|
||||
|
||||
virtual inline std::string toString() const { assert(_object); return "Interface[" + _object->_name + "]"; }
|
||||
|
||||
@ -101,7 +110,7 @@ namespace RNS {
|
||||
class Object {
|
||||
public:
|
||||
Object() {}
|
||||
Object(const char *name) : _name(name) {}
|
||||
Object(const char* name) : _name(name) {}
|
||||
virtual ~Object() {}
|
||||
private:
|
||||
bool _IN = false;
|
||||
@ -111,18 +120,22 @@ namespace RNS {
|
||||
std::string _name;
|
||||
size_t _rxb = 0;
|
||||
size_t _txb = 0;
|
||||
bool online = false;
|
||||
bool _online = false;
|
||||
Bytes _ifac_identity;
|
||||
Type::Interface::modes _mode = Type::Interface::MODE_NONE;
|
||||
uint32_t _bitrate = 0;
|
||||
uint64_t _announce_allowed_at = 0;
|
||||
float _announce_cap = 0.0;
|
||||
std::list<AnnounceEntry> _announce_queue;
|
||||
bool _is_connected_to_shared_instance = false;
|
||||
bool _is_local_shared_instance = false;
|
||||
HInterface _parent_interface;
|
||||
//Transport& _owner;
|
||||
friend class Interface;
|
||||
};
|
||||
std::shared_ptr<Object> _object;
|
||||
|
||||
friend class Transport;
|
||||
};
|
||||
|
||||
}
|
||||
|
134
src/Interfaces/UDPInterface.cpp
Normal file
134
src/Interfaces/UDPInterface.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
#include "UDPInterface.h"
|
||||
|
||||
#include "../Log.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace RNS;
|
||||
using namespace RNS::Interfaces;
|
||||
|
||||
/*
|
||||
@staticmethod
|
||||
def get_address_for_if(name):
|
||||
import RNS.vendor.ifaddr.niwrapper as netinfo
|
||||
ifaddr = netinfo.ifaddresses(name)
|
||||
return ifaddr[netinfo.AF_INET][0]["addr"]
|
||||
|
||||
@staticmethod
|
||||
def get_broadcast_for_if(name):
|
||||
import RNS.vendor.ifaddr.niwrapper as netinfo
|
||||
ifaddr = netinfo.ifaddresses(name)
|
||||
return ifaddr[netinfo.AF_INET][0]["broadcast"]
|
||||
*/
|
||||
|
||||
//p def __init__(self, owner, name, device=None, bindip=None, bindport=None, forwardip=None, forwardport=None):
|
||||
UDPInterface::UDPInterface(const char* name /*= "UDPInterface"*/) : Interface(name) {
|
||||
|
||||
IN(true);
|
||||
//OUT(false);
|
||||
OUT(true);
|
||||
bitrate(BITRATE_GUESS);
|
||||
|
||||
}
|
||||
|
||||
void UDPInterface::start() {
|
||||
|
||||
#ifdef ARDUINO
|
||||
// Connect to the WiFi network
|
||||
WiFi.begin(ssid, pwd);
|
||||
Serial.println("");
|
||||
|
||||
// Wait for WiFi network connection to complete
|
||||
Serial.print("Connecting to ");
|
||||
Serial.print(ssid);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("Connected to ");
|
||||
Serial.println(ssid);
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
// Listen for received UDP packets
|
||||
/*
|
||||
if (udp.listen(udpPort)) {
|
||||
Serial.print("UDP Listening on IP: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
udp.onPacket([](AsyncUDPPacket packet) {
|
||||
Serial.print("UDP Packet Type: ");
|
||||
Serial.print(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast");
|
||||
Serial.print(", From: ");
|
||||
Serial.print(packet.remoteIP());
|
||||
Serial.print(":");
|
||||
Serial.print(packet.remotePort());
|
||||
Serial.print(", To: ");
|
||||
Serial.print(packet.localIP());
|
||||
Serial.print(":");
|
||||
Serial.print(packet.localPort());
|
||||
Serial.print(", Length: ");
|
||||
Serial.print(packet.length()); //dlzka packetu
|
||||
Serial.print(", Data: ");
|
||||
Serial.write(packet.data(), packet.length());
|
||||
Serial.println();
|
||||
String myString = (const char*)packet.data();
|
||||
if (myString == "ZAP") {
|
||||
Serial.println("Zapinam rele");
|
||||
digitalWrite(rele, LOW);
|
||||
} else if (myString == "VYP") {
|
||||
Serial.println("Vypinam rele");
|
||||
digitalWrite(rele, HIGH);
|
||||
}
|
||||
packet.printf("Got %u bytes of data", packet.length());
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
// This initializes udp and transfer buffer
|
||||
udp.begin(udpPort);
|
||||
#endif
|
||||
|
||||
online(true);
|
||||
}
|
||||
|
||||
void UDPInterface::loop() {
|
||||
|
||||
if (online()) {
|
||||
// Check for incoming packet
|
||||
#ifdef ARDUINO
|
||||
udp.parsePacket();
|
||||
size_t len = udp.read(buffer.writable(Type::Reticulum::MTU), Type::Reticulum::MTU);
|
||||
if (len > 0) {
|
||||
buffer.resize(len);
|
||||
processIncoming(buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/ void UDPInterface::processIncoming(const Bytes& data) {
|
||||
debug("UDPInterface.processIncoming: data: " + data.toHex());
|
||||
//debug("UDPInterface.processIncoming: text: " + data.toString());
|
||||
Interface::processIncoming(data);
|
||||
}
|
||||
|
||||
/*virtual*/ void UDPInterface::processOutgoing(const Bytes& data) {
|
||||
debug("UDPInterface.processOutgoing: data: " + data.toHex());
|
||||
debug("UDPInterface.processOutgoing: text: " + data.toString());
|
||||
try {
|
||||
if (online()) {
|
||||
// Send packet
|
||||
#ifdef ARDUINO
|
||||
udp.beginPacket(udpAddress, udpPort);
|
||||
udp.write(data.data(), data.size());
|
||||
udp.endPacket();
|
||||
#endif
|
||||
}
|
||||
|
||||
Interface::processOutgoing(data);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
error("Could not transmit on " + toString() + ". The contained exception was: " + e.what());
|
||||
}
|
||||
}
|
61
src/Interfaces/UDPInterface.h
Normal file
61
src/Interfaces/UDPInterface.h
Normal file
@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Interface.h"
|
||||
#include "../Bytes.h"
|
||||
#include "../Type.h"
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include <WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
//#include <AsyncUDP.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace RNS { namespace Interfaces {
|
||||
|
||||
class UDPInterface : public Interface {
|
||||
|
||||
public:
|
||||
static const uint32_t BITRATE_GUESS = 10*1000*1000;
|
||||
|
||||
//z def get_address_for_if(name):
|
||||
//z def get_broadcast_for_if(name):
|
||||
|
||||
public:
|
||||
//p def __init__(self, owner, name, device=None, bindip=None, bindport=None, forwardip=None, forwardport=None):
|
||||
UDPInterface(const char* name = "UDPInterface");
|
||||
|
||||
void start();
|
||||
void loop();
|
||||
|
||||
virtual void processIncoming(const Bytes& data);
|
||||
virtual void processOutgoing(const Bytes& data);
|
||||
|
||||
//virtual inline std::string toString() const { return "UDPInterface[" + name() + "/" + bind_ip + ":" + bind_port + "]"; }
|
||||
virtual inline std::string toString() const { return "UDPInterface[" + name() + "]"; }
|
||||
|
||||
private:
|
||||
const uint16_t HW_MTU = 1064;
|
||||
//uint8_t buffer[Type::Reticulum::MTU] = {0};
|
||||
Bytes buffer;
|
||||
|
||||
// WiFi network name and password
|
||||
const char* ssid = "some-ssid";
|
||||
const char* pwd = "some-pass";
|
||||
|
||||
// IP address to send UDP data to.
|
||||
// it can be ip address of the server or
|
||||
// broadcast
|
||||
const char* udpAddress = "255.255.255.255";
|
||||
const int udpPort = 4242;
|
||||
|
||||
// create UDP instance
|
||||
#ifdef ARDUINO
|
||||
WiFiUDP udp;
|
||||
//AsyncUDP udp;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
} }
|
@ -9,7 +9,7 @@ using namespace RNS::Type::Link;
|
||||
Link::Link() : _object(new Object()) {
|
||||
assert(_object);
|
||||
|
||||
extreme("Link object created");
|
||||
mem("Link object created");
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,14 +20,14 @@ namespace RNS {
|
||||
|
||||
public:
|
||||
Link(Type::NoneConstructor none) {
|
||||
extreme("Link NONE object created");
|
||||
mem("Link NONE object created");
|
||||
}
|
||||
Link(const Link& link) : _object(link._object) {
|
||||
extreme("Link object copy created");
|
||||
mem("Link object copy created");
|
||||
}
|
||||
Link();
|
||||
virtual ~Link(){
|
||||
extreme("Link object destroyed");
|
||||
mem("Link object destroyed");
|
||||
}
|
||||
|
||||
inline Link& operator = (const Link& link) {
|
||||
|
13
src/Log.cpp
13
src/Log.cpp
@ -22,12 +22,15 @@ const char* getLevelName(LogLevel level) {
|
||||
return "DEBUG";
|
||||
case LOG_EXTREME:
|
||||
return "EXTRA";
|
||||
case LOG_MEM:
|
||||
return "MEM";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
LogLevel _level = LOG_VERBOSE;
|
||||
//LogLevel _level = LOG_VERBOSE;
|
||||
LogLevel _level = LOG_EXTREME;
|
||||
|
||||
void RNS::loglevel(LogLevel level) {
|
||||
_level = level;
|
||||
@ -37,11 +40,11 @@ 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;
|
||||
}
|
||||
#ifndef NATIVE
|
||||
#ifdef ARDUINO
|
||||
Serial.print(getLevelName(level));
|
||||
Serial.print(" ");
|
||||
Serial.println(msg);
|
||||
@ -51,11 +54,11 @@ void RNS::doLog(const char *msg, LogLevel level) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void RNS::head(const char *msg, LogLevel level) {
|
||||
void RNS::head(const char* msg, LogLevel level) {
|
||||
if (level > _level) {
|
||||
return;
|
||||
}
|
||||
#ifndef NATIVE
|
||||
#ifdef ARDUINO
|
||||
Serial.println("");
|
||||
#else
|
||||
printf("\n");
|
||||
|
30
src/Log.h
30
src/Log.h
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NATIVE
|
||||
#ifdef ARDUINO
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
@ -17,44 +17,48 @@ namespace RNS {
|
||||
LOG_VERBOSE = 5,
|
||||
LOG_DEBUG = 6,
|
||||
LOG_EXTREME = 7,
|
||||
LOG_MEM = 8,
|
||||
};
|
||||
|
||||
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); }
|
||||
#ifndef NATIVE
|
||||
inline void log(const char* msg, LogLevel level = LOG_NOTICE) { doLog(msg, level); }
|
||||
#ifdef ARDUINO
|
||||
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 critical(const char *msg) { doLog(msg, 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 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 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 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 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 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 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 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 mem(const char* msg) { doLog(msg, LOG_MEM); }
|
||||
inline void mem(const std::string& msg) { doLog(msg.c_str(), LOG_MEM); }
|
||||
|
||||
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); }
|
||||
|
||||
}
|
||||
|
@ -41,11 +41,11 @@ Packet::Packet(const Destination& destination, const Interface& attached_interfa
|
||||
_object->_fromPacked = true;
|
||||
_object->_create_receipt = false;
|
||||
}
|
||||
extreme("Packet object created");
|
||||
mem("Packet object created");
|
||||
}
|
||||
|
||||
Packet::~Packet() {
|
||||
extreme("Packet object destroyed");
|
||||
mem("Packet object destroyed");
|
||||
}
|
||||
|
||||
|
||||
@ -328,7 +328,7 @@ bool Packet::unpack() {
|
||||
throw std::length_error("Packet size of " + std::to_string(_object->_raw.size()) + " does not meet minimum header size of " + std::to_string(Type::Reticulum::HEADER_MINSIZE) +" bytes");
|
||||
}
|
||||
|
||||
const uint8_t *raw = _object->_raw.data();
|
||||
const uint8_t* raw = _object->_raw.data();
|
||||
|
||||
// read header
|
||||
_object->_flags = raw[0];
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Destination.h"
|
||||
#include "Link.h"
|
||||
#include "Interface.h"
|
||||
#include "Log.h"
|
||||
#include "Type.h"
|
||||
#include "Utilities/OS.h"
|
||||
|
||||
@ -124,10 +125,10 @@ namespace RNS {
|
||||
|
||||
public:
|
||||
Packet(Type::NoneConstructor none) {
|
||||
extreme("Packet NONE object created");
|
||||
mem("Packet NONE object created");
|
||||
}
|
||||
Packet(const Packet& packet) : _object(packet._object) {
|
||||
extreme("Packet object copy created");
|
||||
mem("Packet object copy created");
|
||||
}
|
||||
Packet(
|
||||
const Destination& destination,
|
||||
@ -154,7 +155,7 @@ namespace RNS {
|
||||
|
||||
inline Packet& operator = (const Packet& packet) {
|
||||
_object = packet._object;
|
||||
extreme("Packet object copy created by assignment, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
mem("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 {
|
||||
|
@ -5,6 +5,11 @@
|
||||
|
||||
#include <RNG.h>
|
||||
|
||||
#ifdef ARDUINO
|
||||
//#include <TransistorNoiseSource.h>
|
||||
//#include <Ethernet.h>
|
||||
#endif
|
||||
|
||||
using namespace RNS;
|
||||
using namespace RNS::Type::Reticulum;
|
||||
|
||||
@ -13,6 +18,11 @@ using namespace RNS::Type::Reticulum;
|
||||
/*static*/ bool Reticulum::__allow_probes = false;
|
||||
/*static*/ bool Reticulum::panic_on_interface_error = false;
|
||||
|
||||
#ifdef ARDUINO
|
||||
// Noise source to seed the random number generator.
|
||||
//TransistorNoiseSource noise(A1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
Initialises and starts a Reticulum instance. This must be
|
||||
done before any other operations, and Reticulum will not
|
||||
@ -22,10 +32,21 @@ pass any traffic before being instantiated.
|
||||
*/
|
||||
//def __init__(self,configdir=None, loglevel=None, logdest=None, verbosity=None):
|
||||
Reticulum::Reticulum() : _object(new Object()) {
|
||||
mem("Reticulum default object creating..., this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
|
||||
// Initialkize random number generator
|
||||
RNG.begin("Reticulum");
|
||||
//RNG.stir(mac_address, sizeof(mac_address));
|
||||
|
||||
#ifdef ARDUINO
|
||||
// Stir in the Ethernet MAC address.
|
||||
//byte mac[6];
|
||||
//Ethernet.begin(mac);
|
||||
// WiFi.macAddress(mac);
|
||||
//RNG.stir(mac, sizeof(mac));
|
||||
|
||||
// Add the noise source to the list of sources known to RNG.
|
||||
//RNG.addNoiseSource(noise);
|
||||
#endif
|
||||
|
||||
/*
|
||||
RNS.vendor.platformutils.platform_checks()
|
||||
@ -128,11 +149,7 @@ Reticulum::Reticulum() : _object(new Object()) {
|
||||
signal.signal(signal.SIGTERM, Reticulum.sigterm_handler)
|
||||
*/
|
||||
|
||||
extreme("Reticulum object created");
|
||||
}
|
||||
|
||||
Reticulum::~Reticulum() {
|
||||
extreme("Reticulum object destroyed");
|
||||
mem("Reticulum default object created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,17 +19,19 @@ namespace RNS {
|
||||
|
||||
public:
|
||||
Reticulum(Type::NoneConstructor none) {
|
||||
extreme("Reticulum NONE object created");
|
||||
mem("Reticulum NONE object created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
Reticulum(const Reticulum& reticulum) : _object(reticulum._object) {
|
||||
extreme("Reticulum object copy created");
|
||||
mem("Reticulum object copy created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
Reticulum();
|
||||
virtual ~Reticulum();
|
||||
virtual ~Reticulum() {
|
||||
mem("Reticulum object destroyed, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
|
||||
inline Reticulum& operator = (const Reticulum& reticulum) {
|
||||
_object = reticulum._object;
|
||||
extreme("Reticulum object copy created by assignment, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
mem("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 {
|
||||
@ -69,8 +71,12 @@ namespace RNS {
|
||||
private:
|
||||
class Object {
|
||||
public:
|
||||
Object() {}
|
||||
virtual ~Object() {}
|
||||
Object() {
|
||||
mem("Reticulum data object created, this: " + std::to_string((uintptr_t)this));
|
||||
}
|
||||
virtual ~Object() {
|
||||
mem("Reticulum data object destroyed, this: " + std::to_string((uintptr_t)this));
|
||||
}
|
||||
private:
|
||||
bool _is_connected_to_shared_instance = false;
|
||||
friend class Reticulum;
|
||||
|
@ -4,20 +4,9 @@
|
||||
|
||||
void test() {
|
||||
|
||||
//RNS::LogLevel loglevel = RNS::loglevel();
|
||||
//RNS::loglevel(RNS::LOG_WARNING);
|
||||
|
||||
testBytes();
|
||||
testCowBytes();
|
||||
testBytesConversion();
|
||||
testMap();
|
||||
|
||||
testCollections();
|
||||
testReference();
|
||||
|
||||
testCrypto();
|
||||
testHMAC();
|
||||
testPKCS7();
|
||||
|
||||
//RNS::loglevel(loglevel);
|
||||
|
||||
}
|
||||
|
@ -1,13 +1,7 @@
|
||||
|
||||
void test();
|
||||
|
||||
void testMap();
|
||||
void testBytes();
|
||||
void testCowBytes();
|
||||
void testBytesConversion();
|
||||
|
||||
void testCollections();
|
||||
void testReference();
|
||||
|
||||
void testCrypto();
|
||||
void testHMAC();
|
||||
void testPKCS7();
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include "Bytes.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <map>
|
||||
#include <assert.h>
|
||||
|
||||
//void testBytesDefault(const RNS::Bytes& bytes = {RNS::Bytes::NONE}) {
|
||||
@ -21,7 +20,7 @@ const RNS::Bytes& testBytesReference() {
|
||||
return ref;
|
||||
}
|
||||
|
||||
void testBytes() {
|
||||
void testBytesMain() {
|
||||
|
||||
RNS::Bytes bytes;
|
||||
assert(!bytes);
|
||||
@ -32,7 +31,7 @@ void testBytes() {
|
||||
const uint8_t prestr[] = "Hello";
|
||||
const uint8_t poststr[] = " World";
|
||||
|
||||
RNS::Bytes prebuf(prestr, 5);
|
||||
const RNS::Bytes prebuf(prestr, 5);
|
||||
assert(prebuf);
|
||||
assert(prebuf.size() == 5);
|
||||
assert(memcmp(prebuf.data(), "Hello", prebuf.size()) == 0);
|
||||
@ -40,7 +39,7 @@ void testBytes() {
|
||||
assert(bytes != prebuf);
|
||||
assert(bytes < prebuf);
|
||||
|
||||
RNS::Bytes postbuf(poststr, 6);
|
||||
const RNS::Bytes postbuf(poststr, 6);
|
||||
assert(postbuf);
|
||||
assert(postbuf.size() == 6);
|
||||
assert(memcmp(postbuf.data(), " World", postbuf.size()) == 0);
|
||||
@ -152,9 +151,9 @@ void testBytes() {
|
||||
{
|
||||
RNS::Bytes strmbuf;
|
||||
strmbuf << prebuf << postbuf;
|
||||
RNS::extreme("stream strmbuf: " + strmbuf.toString());
|
||||
RNS::extreme("stream prebuf: " + prebuf.toString());
|
||||
RNS::extreme("stream postbuf: " + postbuf.toString());
|
||||
RNS::extreme("stream strmbuf: " + strmbuf.toString());
|
||||
assert(strmbuf.size() == 11);
|
||||
assert(memcmp(strmbuf.data(), "Hello World", strmbuf.size()) == 0);
|
||||
assert(prebuf.size() == 5);
|
||||
@ -171,9 +170,9 @@ void testBytes() {
|
||||
assert(memcmp(strmbuf.data(), "Stream ", strmbuf.size()) == 0);
|
||||
|
||||
strmbuf << prebuf << postbuf;
|
||||
RNS::extreme("stream strmbuf: " + strmbuf.toString());
|
||||
RNS::extreme("stream prebuf: " + prebuf.toString());
|
||||
RNS::extreme("stream postbuf: " + postbuf.toString());
|
||||
RNS::extreme("stream strmbuf: " + strmbuf.toString());
|
||||
assert(strmbuf.size() == 18);
|
||||
assert(memcmp(strmbuf.data(), "Stream Hello World", strmbuf.size()) == 0);
|
||||
assert(prebuf.size() == 5);
|
||||
@ -183,18 +182,23 @@ void testBytes() {
|
||||
}
|
||||
|
||||
// stream with assignment
|
||||
// (this is a known and correct but perhaps unexpected and non-intuitive side-effect of assignment with stream)
|
||||
// (side effect of also updating pre - this is a known and correct but perhaps unexpected and non-intuitive side-effect of assignment with stream)
|
||||
{
|
||||
RNS::Bytes strmbuf = prebuf << postbuf;
|
||||
// NOTE pre must be volatile in order for below stream with assignment to work (since it gets modified)
|
||||
RNS::Bytes pre("Hello");
|
||||
assert(pre.size() == 5);
|
||||
const RNS::Bytes post(" World");
|
||||
assert(post.size() == 6);
|
||||
RNS::Bytes strmbuf = pre << post;
|
||||
RNS::extreme("stream pre: " + prebuf.toString());
|
||||
RNS::extreme("stream post: " + postbuf.toString());
|
||||
RNS::extreme("stream strmbuf: " + strmbuf.toString());
|
||||
RNS::extreme("stream prebuf: " + prebuf.toString());
|
||||
RNS::extreme("stream postbuf: " + postbuf.toString());
|
||||
assert(strmbuf.size() == 11);
|
||||
assert(memcmp(strmbuf.data(), "Hello World", strmbuf.size()) == 0);
|
||||
assert(prebuf.size() == 11);
|
||||
assert(memcmp(prebuf.data(), "Hello World", prebuf.size()) == 0);
|
||||
assert(postbuf.size() == 6);
|
||||
assert(memcmp(postbuf.data(), " World", postbuf.size()) == 0);
|
||||
assert(pre.size() == 11);
|
||||
assert(memcmp(pre.data(), "Hello World", pre.size()) == 0);
|
||||
assert(post.size() == 6);
|
||||
assert(memcmp(post.data(), " World", post.size()) == 0);
|
||||
}
|
||||
|
||||
// test creating bytes from default
|
||||
@ -230,11 +234,11 @@ void testBytes() {
|
||||
}
|
||||
|
||||
// function default argument
|
||||
RNS::head("TestBytes: function default argument", RNS::LOG_EXTREME);
|
||||
RNS::extreme("TestBytes: function default argument");
|
||||
testBytesDefault();
|
||||
|
||||
// function reference return
|
||||
RNS::head("TestBytes: function reference return", RNS::LOG_EXTREME);
|
||||
RNS::extreme("TestBytes: function reference return");
|
||||
{
|
||||
RNS::Bytes test = testBytesReference();
|
||||
RNS::extreme("returned");
|
||||
@ -336,52 +340,11 @@ void testBytesConversion() {
|
||||
|
||||
}
|
||||
|
||||
void testMap()
|
||||
{
|
||||
const uint8_t prestr[] = "Hello";
|
||||
const uint8_t poststr[] = "World";
|
||||
|
||||
RNS::Bytes prebuf(prestr, 5);
|
||||
assert(prebuf.size() == 5);
|
||||
assert(memcmp(prebuf.data(), "Hello", prebuf.size()) == 0);
|
||||
|
||||
RNS::Bytes postbuf(poststr, 5);
|
||||
assert(postbuf.size() == 5);
|
||||
assert(memcmp(postbuf.data(), "World", postbuf.size()) == 0);
|
||||
|
||||
std::map<RNS::Bytes, std::string> map;
|
||||
map.insert({prebuf, "hello"});
|
||||
map.insert({postbuf, "world"});
|
||||
assert(map.size() == 2);
|
||||
|
||||
auto preit = map.find(prebuf);
|
||||
assert(preit != map.end());
|
||||
assert((*preit).second.compare("hello") == 0);
|
||||
if (preit != map.end()) {
|
||||
RNS::extreme(std::string("found prebuf: ") + (*preit).second);
|
||||
}
|
||||
|
||||
auto postit = map.find(postbuf);
|
||||
assert(postit != map.end());
|
||||
assert((*postit).second.compare("world") == 0);
|
||||
if (postit != map.end()) {
|
||||
RNS::extreme(std::string("found postbuf: ") + (*postit).second);
|
||||
}
|
||||
|
||||
const uint8_t newstr[] = "World";
|
||||
RNS::Bytes newbuf(newstr, 5);
|
||||
assert(newbuf.size() == 5);
|
||||
assert(memcmp(newbuf.data(), "World", newbuf.size()) == 0);
|
||||
auto newit = map.find(newbuf);
|
||||
assert(newit != map.end());
|
||||
assert((*newit).second.compare("world") == 0);
|
||||
if (newit != map.end()) {
|
||||
RNS::extreme(std::string("found newbuf: ") + (*newit).second);
|
||||
}
|
||||
|
||||
std::string str = map["World"];
|
||||
assert(str.size() == 5);
|
||||
assert(str.compare("world") == 0);
|
||||
void testBytes() {
|
||||
RNS::head("Running testBytes...", RNS::LOG_EXTREME);
|
||||
testBytesMain();
|
||||
testCowBytes();
|
||||
testBytesConversion();
|
||||
}
|
||||
|
||||
/*
|
||||
|
136
src/Test/TestCollections.cpp
Normal file
136
src/Test/TestCollections.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
//#include <unity.h>
|
||||
|
||||
#include "Bytes.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
|
||||
void testBytesMap()
|
||||
{
|
||||
const uint8_t prestr[] = "Hello";
|
||||
const uint8_t poststr[] = "World";
|
||||
|
||||
RNS::Bytes prebuf(prestr, 5);
|
||||
assert(prebuf.size() == 5);
|
||||
assert(memcmp(prebuf.data(), "Hello", prebuf.size()) == 0);
|
||||
|
||||
RNS::Bytes postbuf(poststr, 5);
|
||||
assert(postbuf.size() == 5);
|
||||
assert(memcmp(postbuf.data(), "World", postbuf.size()) == 0);
|
||||
|
||||
std::map<RNS::Bytes, std::string> map;
|
||||
map.insert({prebuf, "hello"});
|
||||
map.insert({postbuf, "world"});
|
||||
assert(map.size() == 2);
|
||||
|
||||
auto preit = map.find(prebuf);
|
||||
assert(preit != map.end());
|
||||
assert((*preit).second.compare("hello") == 0);
|
||||
if (preit != map.end()) {
|
||||
RNS::extreme(std::string("found prebuf: ") + (*preit).second);
|
||||
}
|
||||
|
||||
auto postit = map.find(postbuf);
|
||||
assert(postit != map.end());
|
||||
assert((*postit).second.compare("world") == 0);
|
||||
if (postit != map.end()) {
|
||||
RNS::extreme(std::string("found postbuf: ") + (*postit).second);
|
||||
}
|
||||
|
||||
const uint8_t newstr[] = "World";
|
||||
RNS::Bytes newbuf(newstr, 5);
|
||||
assert(newbuf.size() == 5);
|
||||
assert(memcmp(newbuf.data(), "World", newbuf.size()) == 0);
|
||||
auto newit = map.find(newbuf);
|
||||
assert(newit != map.end());
|
||||
assert((*newit).second.compare("world") == 0);
|
||||
if (newit != map.end()) {
|
||||
RNS::extreme(std::string("found newbuf: ") + (*newit).second);
|
||||
}
|
||||
|
||||
std::string str = map["World"];
|
||||
assert(str.size() == 5);
|
||||
assert(str.compare("world") == 0);
|
||||
}
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
// CBA for some reason default constructor is required for map index reference/asign to work
|
||||
// ("error: no matching constructor for initialization of 'Entry'" results otherwise)
|
||||
Entry() { RNS::extreme("Entry: default constructor"); }
|
||||
Entry(const Entry& entry) : _hash(entry._hash) { RNS::extreme("Entry: copy constructor"); }
|
||||
Entry(const char* hash) : _hash(hash) { RNS::extreme("Entry: hash constructor"); }
|
||||
RNS::Bytes _hash;
|
||||
};
|
||||
|
||||
void testNewMap() {
|
||||
|
||||
std::map<RNS::Bytes, Entry> entries;
|
||||
std::map<RNS::Bytes, Entry> other_entries;
|
||||
|
||||
{
|
||||
Entry some_entry("some hash");
|
||||
entries.insert({some_entry._hash, some_entry});
|
||||
Entry some_other_entry("some other hash");
|
||||
other_entries.insert({some_entry._hash, some_entry});
|
||||
other_entries.insert({some_other_entry._hash, some_other_entry});
|
||||
}
|
||||
|
||||
assert(entries.size() == 1);
|
||||
assert(other_entries.size() == 2);
|
||||
for (auto& [hash, entry] : other_entries) {
|
||||
if (entries.find(hash) == entries.end()) {
|
||||
entries[hash] = other_entries[hash];
|
||||
}
|
||||
}
|
||||
for (auto& [hash, entry] : entries) {
|
||||
RNS::extreme("entries: " + entry._hash.toString());
|
||||
}
|
||||
assert(entries.size() == 2);
|
||||
assert(other_entries.size() == 2);
|
||||
|
||||
}
|
||||
|
||||
void testCollections() {
|
||||
RNS::head("Running testCollections...", RNS::LOG_EXTREME);
|
||||
testBytesMap();
|
||||
testNewMap();
|
||||
}
|
||||
|
||||
/*
|
||||
void setUp(void) {
|
||||
// set stuff up here
|
||||
}
|
||||
|
||||
void tearDown(void) {
|
||||
// clean stuff up here
|
||||
}
|
||||
|
||||
int runUnityTests(void) {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(testCollections);
|
||||
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();
|
||||
}
|
||||
*/
|
@ -12,11 +12,13 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
void testCrypto() {
|
||||
void testCryptoMain() {
|
||||
|
||||
RNS::Reticulum reticulum;
|
||||
RNS::Reticulum reticulum_crypto;
|
||||
assert(reticulum_crypto);
|
||||
|
||||
RNS::Identity identity;
|
||||
assert(identity);
|
||||
|
||||
RNS::Destination destination(identity, RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "appname", "aspects");
|
||||
//assert(encryptionPrivateKey().toHex().compare("") == );
|
||||
@ -126,6 +128,13 @@ void testPKCS7() {
|
||||
}
|
||||
}
|
||||
|
||||
void testCrypto() {
|
||||
RNS::head("Running testCrypto...", RNS::LOG_EXTREME);
|
||||
testCryptoMain();
|
||||
testHMAC();
|
||||
testPKCS7();
|
||||
}
|
||||
|
||||
/*
|
||||
int main(void)
|
||||
{
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
void testReference() {
|
||||
RNS::head("Running testReference...", RNS::LOG_EXTREME);
|
||||
|
||||
RNS::Reticulum reticulum_default;
|
||||
assert(reticulum_default);
|
||||
@ -19,6 +20,101 @@ void testReference() {
|
||||
RNS::Reticulum reticulum_none_copy(reticulum_none);
|
||||
assert(!reticulum_none_copy);
|
||||
|
||||
/*
|
||||
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;
|
||||
*/
|
||||
/*
|
||||
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;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -39,10 +39,12 @@ using namespace RNS::Utilities;
|
||||
/*static*/ std::map<Bytes, Transport::DestinationEntry> Transport::_destination_table;
|
||||
/*static*/ std::map<Bytes, Transport::ReverseEntry> Transport::_reverse_table;
|
||||
/*static*/ std::map<Bytes, Transport::LinkEntry> Transport::_link_table;
|
||||
/*static*/ std::map<Bytes, Transport::AnnounceEntry> Transport::_held_announces;
|
||||
/*static*/ std::set<HAnnounceHandler> Transport::_announce_handlers;
|
||||
/*static*/ std::set<Bytes> Transport::_path_requests;
|
||||
/*static*/ std::map<Bytes, uint64_t> Transport::_path_requests;
|
||||
|
||||
/*static*/ std::map<Bytes, Transport::PathRequestEntry> Transport::_discovery_path_requests;
|
||||
/*static*/ std::set<Bytes> Transport::_discovery_pr_tags;
|
||||
/*static*/ uint16_t Transport::_max_pr_taXgxs = 32000;
|
||||
|
||||
/*static*/ std::set<Destination> Transport::_control_destinations;
|
||||
@ -73,6 +75,7 @@ using namespace RNS::Utilities;
|
||||
/*static*/ Identity Transport::_identity({Type::NONE});
|
||||
|
||||
/*static*/ void Transport::start(const Reticulum& reticulum_instance) {
|
||||
info("Transport starting...");
|
||||
_jobs_running = true;
|
||||
_owner = reticulum_instance;
|
||||
|
||||
@ -92,6 +95,7 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
/*
|
||||
packet_hashlist_path = Reticulum::storagepath + "/packet_hashlist";
|
||||
if (!owner.is_connected_to_shared_instance()) {
|
||||
@ -106,21 +110,24 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Create transport-specific destinations
|
||||
Transport.path_request_destination = RNS.Destination(None, RNS.Destination.IN, RNS.Destination.PLAIN, Transport.APP_NAME, "path", "request")
|
||||
Transport.path_request_destination.set_packet_callback(Transport.path_request_handler)
|
||||
Transport.control_destinations.append(Transport.path_request_destination)
|
||||
Transport.control_hashes.append(Transport.path_request_destination.hash)
|
||||
Destination path_request_destination({Type::NONE}, Type::Destination::IN, Type::Destination::PLAIN, APP_NAME, "path.request");
|
||||
path_request_destination.set_packet_callback(path_request_handler);
|
||||
_control_destinations.insert(path_request_destination);
|
||||
_control_hashes.insert(path_request_destination.hash());
|
||||
|
||||
Transport.tunnel_synthesize_destination = RNS.Destination(None, RNS.Destination.IN, RNS.Destination.PLAIN, Transport.APP_NAME, "tunnel", "synthesize")
|
||||
Transport.tunnel_synthesize_destination.set_packet_callback(Transport.tunnel_synthesize_handler)
|
||||
Transport.control_destinations.append(Transport.tunnel_synthesize_handler)
|
||||
Transport.control_hashes.append(Transport.tunnel_synthesize_destination.hash)
|
||||
*/
|
||||
Destination tunnel_synthesize_destination({Type::NONE}, Type::Destination::IN, Type::Destination::PLAIN, APP_NAME, "tunnel.synthesize");
|
||||
tunnel_synthesize_destination.set_packet_callback(tunnel_synthesize_handler);
|
||||
// CBA BUG?
|
||||
//p Transport.control_destinations.append(Transport.tunnel_synthesize_handler)
|
||||
_control_destinations.insert(tunnel_synthesize_destination);
|
||||
_control_hashes.insert(tunnel_synthesize_destination.hash());
|
||||
|
||||
_jobs_running = false;
|
||||
|
||||
// TODO
|
||||
/*
|
||||
thread = threading.Thread(target=Transport.jobloop, daemon=True)
|
||||
thread.start()
|
||||
@ -256,6 +263,7 @@ using namespace RNS::Utilities;
|
||||
_jobs_running = true;
|
||||
|
||||
try {
|
||||
// TODO
|
||||
/*
|
||||
if (!Transport.jobs_locked) {
|
||||
|
||||
@ -586,6 +594,7 @@ using namespace RNS::Utilities;
|
||||
try {
|
||||
//if hasattr(interface, "ifac_identity") and interface.ifac_identity != None:
|
||||
if (interface.ifac_identity()) {
|
||||
// TODO
|
||||
/*
|
||||
// Calculate packet access code
|
||||
ifac = interface.ifac_identity.sign(raw)[-interface.ifac_size:]
|
||||
@ -816,7 +825,7 @@ using namespace RNS::Utilities;
|
||||
// list comprehension: [x for x in xyz if x in a]
|
||||
// CBA TODO confirm that above pattern just selects the first matching destination
|
||||
#if defined(DESTINATIONS_SET)
|
||||
//Destination local_destination({Typeestination::NONE});
|
||||
//Destination local_destination({Type::Destination::NONE});
|
||||
bool found_local = false;
|
||||
for (auto& destination : _destinations) {
|
||||
if (destination.hash() == packet.destination_hash()) {
|
||||
@ -859,6 +868,7 @@ using namespace RNS::Utilities;
|
||||
// TODO: Rethink whether this is actually optimal.
|
||||
if (packet.hops() > 0) {
|
||||
|
||||
// TODO
|
||||
/*
|
||||
if not hasattr(interface, "announce_cap"):
|
||||
interface.announce_cap = RNS.Reticulum.ANNOUNCE_CAP
|
||||
@ -1089,6 +1099,7 @@ using namespace RNS::Utilities;
|
||||
|
||||
/*static*/ void Transport::inbound(const Bytes& raw, const Interface& interface /*= {Type::NONE}*/) {
|
||||
extreme("Transport::inbound()");
|
||||
// TODO
|
||||
/*
|
||||
// If interface access codes are enabled,
|
||||
// we must authenticate each packet.
|
||||
@ -1179,6 +1190,7 @@ using namespace RNS::Utilities;
|
||||
packet.receiving_interface(interface);
|
||||
packet.hops(packet.hops() + 1);
|
||||
|
||||
// TODO
|
||||
/*
|
||||
if (interface) {
|
||||
if hasattr(interface, "r_stat_rssi"):
|
||||
@ -1517,6 +1529,7 @@ using namespace RNS::Utilities;
|
||||
|
||||
// First, check that the announce is not for a destination
|
||||
// local to this system, and that hops are less than the max
|
||||
// CBA TODO determine why packet desitnation hash is being searched in destinations again since we entered this logic becuase it did not exist above
|
||||
//if (not any(packet.destination_hash == d.hash for d in Transport.destinations) and packet.hops < Transport.PATHFINDER_M+1):
|
||||
#if defined(DESTINATIONS_SET)
|
||||
bool found_local = false;
|
||||
@ -1531,11 +1544,10 @@ using namespace RNS::Utilities;
|
||||
auto iter = _destinations.find(packet.destination_hash());
|
||||
if (iter == _destinations.end() && packet.hops() < (PATHFINDER_M+1)) {
|
||||
#endif
|
||||
extreme("Transport::inbound: Packet is announce for non-local destination, processing...");
|
||||
uint64_t announce_emitted = Transport::announce_emitted(packet);
|
||||
|
||||
//p random_blob = packet.data[RNS.Identity.KEYSIZE//8+RNS.Identity.NAME_HASH_LENGTH//8:RNS.Identity.KEYSIZE//8+RNS.Identity.NAME_HASH_LENGTH//8+10]
|
||||
Bytes random_blob = packet.data().mid(Type::Identity::KEYSIZE/8 + Type::Identity::NAME_HASH_LENGTH/8, 10);
|
||||
Bytes random_blob = packet.data().mid(Type::Identity::KEYSIZE/8 + Type::Identity::NAME_HASH_LENGTH/8, Type::Identity::RANDOM_HASH_LENGTH/8);
|
||||
//p random_blobs = []
|
||||
std::set<Bytes> empty_random_blobs;
|
||||
std::set<Bytes>& random_blobs = empty_random_blobs;
|
||||
@ -1573,6 +1585,7 @@ using namespace RNS::Utilities;
|
||||
uint64_t path_announce_emitted = 0;
|
||||
for (const Bytes& path_random_blob : random_blobs) {
|
||||
//p path_announce_emitted = max(path_announce_emitted, int.from_bytes(path_random_blob[5:10], "big"))
|
||||
// CBA TODO
|
||||
//z path_announce_emitted = std::max(path_announce_emitted, int.from_bytes(path_random_blob[5:10], "big"));
|
||||
if (path_announce_emitted >= announce_emitted) {
|
||||
break;
|
||||
@ -1617,6 +1630,7 @@ using namespace RNS::Utilities;
|
||||
|
||||
bool rate_blocked = false;
|
||||
|
||||
// TODO
|
||||
/*
|
||||
if packet.context != RNS.Packet.PATH_RESPONSE and packet.receiving_interface.announce_rate_target != None:
|
||||
if not packet.destination_hash in Transport.announce_rate_table:
|
||||
@ -1658,7 +1672,7 @@ using namespace RNS::Utilities;
|
||||
bool block_rebroadcasts = false;
|
||||
Interface attached_interface = {Type::NONE};
|
||||
|
||||
uint64_t retransmit_timeout = now + (RNS::Cryptography::random() * PATHFINDER_RW);
|
||||
uint64_t retransmit_timeout = now + (Cryptography::random() * PATHFINDER_RW);
|
||||
|
||||
uint64_t expires;
|
||||
if (packet.receiving_interface().mode() == Type::Interface::MODE_ACCESS_POINT) {
|
||||
@ -1823,7 +1837,10 @@ using namespace RNS::Utilities;
|
||||
_destination_table.insert({packet.destination_hash(), destination_table_entry});
|
||||
|
||||
debug("Destination " + packet.destination_hash().toHex() + " is now " + std::to_string(announce_hops) + " hops away via " + received_from.toHex() + " on " + packet.receiving_interface().toString());
|
||||
extreme("Transport::inbound: Destination " + packet.destination_hash().toHex() + " has data: " + packet.data().toHex());
|
||||
//extreme("Transport::inbound: Destination " + packet.destination_hash().toHex() + " has text: " + packet.data().toString());
|
||||
|
||||
// TODO
|
||||
/*
|
||||
// If the receiving interface is a tunnel, we add the
|
||||
// announce to the tunnels table
|
||||
@ -1840,7 +1857,9 @@ using namespace RNS::Utilities;
|
||||
// Call externally registered callbacks from apps
|
||||
// wanting to know when an announce arrives
|
||||
if (packet.context() != Type::Packet::PATH_RESPONSE) {
|
||||
extreme("Transport::inbound: Not path response, sending to announce handler...");
|
||||
for (auto& handler : _announce_handlers) {
|
||||
extreme("Transport::inbound: Checking filter of announce handler...");
|
||||
try {
|
||||
// Check that the announced destination matches
|
||||
// the handlers aspect filter
|
||||
@ -1912,6 +1931,7 @@ using namespace RNS::Utilities;
|
||||
else if (packet.packet_type() == Type::Packet::DATA) {
|
||||
extreme("Transport::inbound: Packet is DATA");
|
||||
if (packet.destination_type() == Type::Destination::LINK) {
|
||||
extreme("Transport::inbound: Packet is for LINK");
|
||||
for (auto& link : _active_links) {
|
||||
if (link.link_id() == packet.destination_hash()) {
|
||||
packet.link(link);
|
||||
@ -1926,8 +1946,10 @@ using namespace RNS::Utilities;
|
||||
#elif defined(DESTINATIONS_MAP)
|
||||
auto iter = _destinations.find(packet.destination_hash());
|
||||
if (iter != _destinations.end()) {
|
||||
debug("Transport::inbound: Packet destination " + packet.destination_hash().toHex() + " found");
|
||||
auto& destination = (*iter).second;
|
||||
if (destination.type() == packet.destination_type()) {
|
||||
debug("Transport::inbound: Packet destination type " + std::to_string(packet.destination_type()) + " matched, processing");
|
||||
#endif
|
||||
packet.destination(destination);
|
||||
#if defined(DESTINATIONS_SET)
|
||||
@ -1952,6 +1974,12 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Transport::inbound: Packet destination type " + std::to_string(packet.destination_type()) + " mismatch, ignoring");
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Transport::inbound: Packet destination " + packet.destination_hash().toHex() + " not found, ignoring");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1959,6 +1987,7 @@ using namespace RNS::Utilities;
|
||||
// Handling for proofs and link-request proofs
|
||||
else if (packet.packet_type() == Type::Packet::PROOF) {
|
||||
extreme("Transport::inbound: Packet is PROOF");
|
||||
// TODO
|
||||
/*
|
||||
if packet.context == RNS.Packet.LRPROOF:
|
||||
// This is a link request proof, check if it
|
||||
@ -2050,6 +2079,7 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
|
||||
/*static*/ void Transport::synthesize_tunnel(const Interface& interface) {
|
||||
// TODO
|
||||
/*
|
||||
Bytes interface_hash = interface.get_hash();
|
||||
Bytes public_key = _identity.get_public_key();
|
||||
@ -2073,6 +2103,7 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
|
||||
/*static*/ void Transport::tunnel_synthesize_handler(const Bytes& data, const Packet& packet) {
|
||||
// TODO
|
||||
/*
|
||||
try:
|
||||
expected_length = RNS.Identity.KEYSIZE//8+RNS.Identity.HASHLENGTH//8+RNS.Reticulum.TRUNCATED_HASHLENGTH//8+RNS.Identity.SIGLENGTH//8
|
||||
@ -2099,6 +2130,7 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
|
||||
/*static*/ void Transport::handle_tunnel(const Bytes& tunnel_id, const Interface& interface) {
|
||||
// TODO
|
||||
/*
|
||||
expires = time.time() + Transport.DESTINATION_TIMEOUT
|
||||
if not tunnel_id in Transport.tunnels:
|
||||
@ -2191,20 +2223,21 @@ using namespace RNS::Utilities;
|
||||
#elif defined(INTERFACES_MAP)
|
||||
auto iter = _interfaces.find(interface.get_hash());
|
||||
if (iter != _interfaces.end()) {
|
||||
extreme("Transport::deregister_interface: Found and removing interface " + (*iter).second.toString());
|
||||
extreme("Transport::deregister_interface: Found and removed interface " + (*iter).second.toString());
|
||||
_interfaces.erase(iter);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/ void Transport::register_destination(Destination& destination) {
|
||||
extreme("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
extreme("Transport: Registering destination " + destination.toString());
|
||||
destination.mtu(Type::Reticulum::MTU);
|
||||
if (destination.direction() == Type::Destination::IN) {
|
||||
#if defined(DESTINATIONS_SET)
|
||||
for (auto& registered_destination : _destinations) {
|
||||
if (destination.hash() == registered_destination.hash()) {
|
||||
//raise KeyError("Attempt to register an already registered destination.")
|
||||
//p raise KeyError("Attempt to register an already registered destination.")
|
||||
throw std::runtime_error("Attempt to register an already registered destination.");
|
||||
}
|
||||
}
|
||||
@ -2213,19 +2246,29 @@ using namespace RNS::Utilities;
|
||||
#elif defined(DESTINATIONS_MAP)
|
||||
auto iter = _destinations.find(destination.hash());
|
||||
if (iter != _destinations.end()) {
|
||||
//raise KeyError("Attempt to register an already registered destination.")
|
||||
//p raise KeyError("Attempt to register an already registered destination.")
|
||||
throw std::runtime_error("Attempt to register an already registered destination.");
|
||||
}
|
||||
|
||||
_destinations.insert({destination.hash(), destination});
|
||||
#endif
|
||||
|
||||
if (_owner.is_connected_to_shared_instance()) {
|
||||
if (_owner && _owner.is_connected_to_shared_instance()) {
|
||||
if (destination.type() == Type::Destination::SINGLE) {
|
||||
extreme("Transport:register_destination: Announcing destination " + destination.toString());
|
||||
destination.announce({}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DESTINATIONS_SET)
|
||||
for (const Destination& destination : _destinations) {
|
||||
#elif defined(DESTINATIONS_MAP)
|
||||
for (auto& [hash, destination] : _destinations) {
|
||||
#endif
|
||||
extreme("Transport::register_destination: Listed destination " + destination.toString());
|
||||
}
|
||||
extreme("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
}
|
||||
|
||||
/*static*/ void Transport::deregister_destination(const Destination& destination) {
|
||||
@ -2233,16 +2276,19 @@ using namespace RNS::Utilities;
|
||||
#if defined(DESTINATIONS_SET)
|
||||
if (_destinations.find(destination) != _destinations.end()) {
|
||||
_destinations.erase(destination);
|
||||
extreme("Transport::deregister_destination: Found and removed destination " + destination.toString());
|
||||
}
|
||||
#elif defined(DESTINATIONS_MAP)
|
||||
auto iter = _destinations.find(destination.hash());
|
||||
if (iter != _destinations.end()) {
|
||||
_destinations.erase(iter);
|
||||
extreme("Transport::deregister_destination: Found and removed destination " + (*iter).second.toString());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/ void Transport::register_link(const Link& link) {
|
||||
// TODO
|
||||
/*
|
||||
extreme("Transport: Registering link " + link.toString());
|
||||
if (link.initiator()) {
|
||||
@ -2255,6 +2301,7 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
|
||||
/*static*/ void Transport::activate_link(Link& link) {
|
||||
// TODO
|
||||
/*
|
||||
extreme("Transport: Activating link " + link.toString());
|
||||
if (_pending_links.find(link) != _pending_links.end()) {
|
||||
@ -2298,18 +2345,21 @@ Deregisters an announce handler.
|
||||
#if defined(INTERFACES_SET)
|
||||
for (const Interface& interface : _interfaces) {
|
||||
if (interface.get_hash() == interface_hash) {
|
||||
extreme("Transport::find_interface_from_hash: Found interface " + interface.toString());
|
||||
return interface;
|
||||
}
|
||||
}
|
||||
#elif defined(INTERFACES_LIST)
|
||||
for (Interface& interface : _interfaces) {
|
||||
if (interface.get_hash() == interface_hash) {
|
||||
extreme("Transport::find_interface_from_hash: Found interface " + interface.toString());
|
||||
return interface;
|
||||
}
|
||||
}
|
||||
#elif defined(INTERFACES_MAP)
|
||||
auto iter = _interfaces.find(interface_hash);
|
||||
if (iter != _interfaces.end()) {
|
||||
extreme("Transport::find_interface_from_hash: Found interface " + (*iter).second.toString());
|
||||
return (*iter).second;
|
||||
}
|
||||
#endif
|
||||
@ -2333,6 +2383,7 @@ Deregisters an announce handler.
|
||||
// increased yet! Take note of this when reading from
|
||||
// the packet cache.
|
||||
/*static*/ void Transport::cache(const Packet& packet, bool force_cache /*= false*/) {
|
||||
// TODO
|
||||
/*
|
||||
if (should_cache(packet) || force_cache) {
|
||||
try {
|
||||
@ -2356,6 +2407,7 @@ Deregisters an announce handler.
|
||||
}
|
||||
|
||||
/*static*/ Packet Transport::get_cached_packet(const Bytes& packet_hash) {
|
||||
// TODO
|
||||
/*
|
||||
try {
|
||||
//packet_hash = RNS.hexrep(packet_hash, delimit=False)
|
||||
@ -2504,21 +2556,28 @@ will announce it.
|
||||
*/
|
||||
///*static*/ void Transport::request_path(const Bytes& destination_hash, const Interface& on_interface /*= {Type::NONE}*/, const Bytes& tag /*= {}*/, bool recursive /*= false*/) {
|
||||
/*static*/ void Transport::request_path(const Bytes& destination_hash, const Interface& on_interface, const Bytes& tag /*= {}*/, bool recursive /*= false*/) {
|
||||
Bytes request_tag;
|
||||
if (tag) {
|
||||
request_tag = Identity::get_random_hash();
|
||||
}
|
||||
else {
|
||||
request_tag = tag;
|
||||
}
|
||||
|
||||
Bytes path_request_data;
|
||||
if (Reticulum::transport_enabled()) {
|
||||
path_request_data = destination_hash + _identity.hash() + request_tag;
|
||||
}
|
||||
else {
|
||||
path_request_data = destination_hash + request_tag;
|
||||
}
|
||||
|
||||
Destination path_request_dst({Type::NONE}, Type::Destination::OUT, Type::Destination::PLAIN, Type::Transport::APP_NAME, "path.request");
|
||||
Packet packet(path_request_dst, on_interface, path_request_data, Type::Packet::DATA, Type::Packet::CONTEXT_NONE, Type::Transport::BROADCAST, Type::Packet::HEADER_1);
|
||||
|
||||
if (on_interface && recursive) {
|
||||
// TODO
|
||||
/*
|
||||
if tag == None:
|
||||
request_tag = RNS.Identity.get_random_hash()
|
||||
else:
|
||||
request_tag = tag
|
||||
|
||||
if RNS.Reticulum.transport_enabled():
|
||||
path_request_data = destination_hash+Transport.identity.hash+request_tag
|
||||
else:
|
||||
path_request_data = destination_hash+request_tag
|
||||
|
||||
path_request_dst = RNS.Destination(None, RNS.Destination.OUT, RNS.Destination.PLAIN, Transport.APP_NAME, "path", "request")
|
||||
packet = RNS.Packet(path_request_dst, path_request_data, packet_type = RNS.Packet.DATA, transport_type = RNS.Transport.BROADCAST, header_type = RNS.Packet.HEADER_1, attached_interface = on_interface)
|
||||
|
||||
if on_interface != None and recursive:
|
||||
if not hasattr(on_interface, "announce_cap"):
|
||||
on_interface.announce_cap = RNS.Reticulum.ANNOUNCE_CAP
|
||||
|
||||
@ -2527,24 +2586,30 @@ will announce it.
|
||||
|
||||
if not hasattr(on_interface, "announce_queue"):
|
||||
on_interface.announce_queue = []
|
||||
|
||||
queued_announces = True if len(on_interface.announce_queue) > 0 else False
|
||||
if queued_announces:
|
||||
RNS.log("Blocking recursive path request on "+str(on_interface)+" due to queued announces", RNS.LOG_EXTREME)
|
||||
return
|
||||
else:
|
||||
now = time.time()
|
||||
if now < on_interface.announce_allowed_at:
|
||||
RNS.log("Blocking recursive path request on "+str(on_interface)+" due to active announce cap", RNS.LOG_EXTREME)
|
||||
return
|
||||
else:
|
||||
tx_time = ((len(path_request_data)+RNS.Reticulum.HEADER_MINSIZE)*8) / on_interface.bitrate
|
||||
wait_time = (tx_time / on_interface.announce_cap)
|
||||
on_interface.announce_allowed_at = now + wait_time
|
||||
|
||||
packet.send()
|
||||
Transport.path_requests[destination_hash] = time.time()
|
||||
*/
|
||||
|
||||
bool queued_announces = (on_interface.announce_queue().size() > 0);
|
||||
if (queued_announces) {
|
||||
extreme("Blocking recursive path request on " + on_interface.toString() + " due to queued announces");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
uint64_t now = OS::time();
|
||||
if (now < on_interface.announce_allowed_at()) {
|
||||
extreme("Blocking recursive path request on " + on_interface.toString() + " due to active announce cap");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
//p tx_time = ((len(path_request_data)+RNS.Reticulum.HEADER_MINSIZE)*8) / on_interface.bitrate
|
||||
uint32_t tx_time = ((path_request_data.size() + Type::Reticulum::HEADER_MINSIZE)*8) / on_interface.bitrate();
|
||||
uint32_t wait_time = (tx_time / on_interface.announce_cap());
|
||||
const_cast<Interface&>(on_interface).announce_allowed_at(now + wait_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
packet.send();
|
||||
_path_requests[destination_hash] = OS::time();
|
||||
}
|
||||
|
||||
/*static*/ void Transport::request_path(const Bytes& destination_hash) {
|
||||
@ -2552,80 +2617,98 @@ will announce it.
|
||||
}
|
||||
|
||||
/*static*/ void Transport::path_request_handler(const Bytes& data, const Packet& packet) {
|
||||
/*
|
||||
try:
|
||||
extreme("Transport::path_request_handler");
|
||||
try {
|
||||
// If there is at least bytes enough for a destination
|
||||
// hash in the packet, we assume those bytes are the
|
||||
// destination being requested.
|
||||
if len(data) >= RNS.Identity.TRUNCATED_HASHLENGTH//8:
|
||||
destination_hash = data[:RNS.Identity.TRUNCATED_HASHLENGTH//8]
|
||||
if (data.size() >= Type::Identity::TRUNCATED_HASHLENGTH/8) {
|
||||
Bytes destination_hash = data.left(Type::Identity::TRUNCATED_HASHLENGTH/8);
|
||||
extreme("Transport::path_request_handler: destination_hash: " + destination_hash.toHex());
|
||||
// If there is also enough bytes for a transport
|
||||
// instance ID and at least one tag byte, we
|
||||
// assume the next bytes to be the trasport ID
|
||||
// of the requesting transport instance.
|
||||
if len(data) > (RNS.Identity.TRUNCATED_HASHLENGTH//8)*2:
|
||||
requesting_transport_instance = data[RNS.Identity.TRUNCATED_HASHLENGTH//8:(RNS.Identity.TRUNCATED_HASHLENGTH//8)*2]
|
||||
else:
|
||||
requesting_transport_instance = None
|
||||
Bytes requesting_transport_instance;
|
||||
if (data.size() > (Type::Identity::TRUNCATED_HASHLENGTH/8)*2) {
|
||||
requesting_transport_instance = data.mid(Type::Identity::TRUNCATED_HASHLENGTH/8, Type::Identity::TRUNCATED_HASHLENGTH/8);
|
||||
extreme("Transport::path_request_handler: requesting_transport_instance: " + requesting_transport_instance.toHex());
|
||||
}
|
||||
|
||||
tag_bytes = None
|
||||
if len(data) > (RNS.Identity.TRUNCATED_HASHLENGTH//8)*2:
|
||||
tag_bytes = data[RNS.Identity.TRUNCATED_HASHLENGTH//8*2:]
|
||||
Bytes tag_bytes;
|
||||
if (data.size() > Type::Identity::TRUNCATED_HASHLENGTH/8*2) {
|
||||
tag_bytes = data.mid(Type::Identity::TRUNCATED_HASHLENGTH/8*2);
|
||||
}
|
||||
else if (data.size() > Type::Identity::TRUNCATED_HASHLENGTH/8) {
|
||||
tag_bytes = data.mid(Type::Identity::TRUNCATED_HASHLENGTH/8);
|
||||
}
|
||||
|
||||
elif len(data) > (RNS.Identity.TRUNCATED_HASHLENGTH//8):
|
||||
tag_bytes = data[RNS.Identity.TRUNCATED_HASHLENGTH//8:]
|
||||
if (tag_bytes) {
|
||||
extreme("Transport::path_request_handler: tag_bytes: " + tag_bytes.toHex());
|
||||
if (tag_bytes.size() > Type::Identity::TRUNCATED_HASHLENGTH/8) {
|
||||
tag_bytes = tag_bytes.left(Type::Identity::TRUNCATED_HASHLENGTH/8);
|
||||
}
|
||||
|
||||
if tag_bytes != None:
|
||||
if len(tag_bytes) > RNS.Identity.TRUNCATED_HASHLENGTH//8:
|
||||
tag_bytes = tag_bytes[:RNS.Identity.TRUNCATED_HASHLENGTH//8]
|
||||
Bytes unique_tag = destination_hash + tag_bytes;
|
||||
extreme("Transport::path_request_handler: unique_tag: " + unique_tag.toHex());
|
||||
|
||||
unique_tag = destination_hash+tag_bytes
|
||||
if (_discovery_pr_tags.find(unique_tag) == _discovery_pr_tags.end()) {
|
||||
_discovery_pr_tags.insert(unique_tag);
|
||||
|
||||
if not unique_tag in Transport.discovery_pr_tags:
|
||||
Transport.discovery_pr_tags.append(unique_tag)
|
||||
|
||||
Transport.path_request(
|
||||
path_request(
|
||||
destination_hash,
|
||||
Transport.from_local_client(packet),
|
||||
packet.receiving_interface,
|
||||
requestor_transport_id = requesting_transport_instance,
|
||||
tag=tag_bytes
|
||||
)
|
||||
|
||||
else:
|
||||
RNS.log("Ignoring duplicate path request for "+RNS.prettyhexrep(destination_hash)+" with tag "+RNS.prettyhexrep(unique_tag), RNS.LOG_DEBUG)
|
||||
|
||||
else:
|
||||
RNS.log("Ignoring tagless path request for "+RNS.prettyhexrep(destination_hash), RNS.LOG_DEBUG)
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Error while handling path request. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
*/
|
||||
from_local_client(packet),
|
||||
packet.receiving_interface(),
|
||||
requesting_transport_instance,
|
||||
tag_bytes
|
||||
);
|
||||
}
|
||||
else {
|
||||
debug("Ignoring duplicate path request for " + destination_hash.toHex() + " with tag " + unique_tag.toHex());
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Ignoring tagless path request for " + destination_hash.toHex());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
error("Error while handling path request. The contained exception was: " + std::string(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void Transport::path_request(const Bytes& destination_hash, bool is_from_local_client, const Interface& attached_interface, const Bytes& requestor_transport_id /*= {}*/, const Bytes& tag /*= {}*/) {
|
||||
/*
|
||||
should_search_for_unknown = False
|
||||
extreme("Transport::path_request");
|
||||
bool should_search_for_unknown = false;
|
||||
std::string interface_str;
|
||||
|
||||
if attached_interface != None:
|
||||
if RNS.Reticulum.transport_enabled() and attached_interface.mode in RNS.Interfaces.Interface.Interface.DISCOVER_PATHS_FOR:
|
||||
should_search_for_unknown = True
|
||||
if (attached_interface) {
|
||||
if (Reticulum::transport_enabled() && (attached_interface.mode() & Interface::DISCOVER_PATHS_FOR) > 0) {
|
||||
should_search_for_unknown = true;
|
||||
}
|
||||
|
||||
interface_str = " on "+str(attached_interface)
|
||||
else:
|
||||
interface_str = ""
|
||||
interface_str = " on " + attached_interface.toString();
|
||||
}
|
||||
|
||||
RNS.log("Path request for "+RNS.prettyhexrep(destination_hash)+interface_str, RNS.LOG_DEBUG)
|
||||
debug("Path request for destination " + destination_hash.toHex() + interface_str);
|
||||
|
||||
destination_exists_on_local_client = False
|
||||
if len(Transport.local_client_interfaces) > 0:
|
||||
if destination_hash in Transport.destination_table:
|
||||
destination_interface = Transport.destination_table[destination_hash][5]
|
||||
|
||||
if Transport.is_local_client_interface(destination_interface):
|
||||
destination_exists_on_local_client = True
|
||||
Transport.pending_local_path_requests[destination_hash] = attached_interface
|
||||
|
||||
bool destination_exists_on_local_client = false;
|
||||
if (_local_client_interfaces.size() > 0) {
|
||||
auto iter = _destination_table.find(destination_hash);
|
||||
if (iter != _destination_table.end()) {
|
||||
extreme("Transport::path_request_handler: entry found for destination " + destination_hash.toHex());
|
||||
DestinationEntry& destination_entry = (*iter).second;
|
||||
if (is_local_client_interface(destination_entry._receiving_interface)) {
|
||||
destination_exists_on_local_client = true;
|
||||
_pending_local_path_requests.insert({destination_hash, attached_interface});
|
||||
}
|
||||
}
|
||||
else {
|
||||
extreme("Transport::path_request_handler: entry not found for destination " + destination_hash.toHex());
|
||||
}
|
||||
}
|
||||
|
||||
auto destination_iter = _destination_table.find(destination_hash);
|
||||
//local_destination = next((d for d in Transport.destinations if d.hash == destination_hash), None)
|
||||
#if defined(DESTINATIONS_SET)
|
||||
Destination local_destination({Type::NONE});
|
||||
@ -2642,40 +2725,46 @@ will announce it.
|
||||
if (iter != _destinations.end()) {
|
||||
auto& local_destination = (*iter).second;
|
||||
#endif
|
||||
local_destination.announce(path_response=True, tag=tag, attached_interface=attached_interface);
|
||||
debug("Answering path request for " + destination_hash.toHex() + interface_str + ", destination is local to this system");
|
||||
local_destination.announce({Bytes::NONE}, true, attached_interface, tag);
|
||||
debug("Answering path request for destination " + destination_hash.toHex() + interface_str + ", destination is local to this system");
|
||||
}
|
||||
else if ((RNS.Reticulum.transport_enabled() || is_from_local_client) && destination_table.find(destination_hash) != _destination_table.ends()) {
|
||||
packet = Transport.destination_table[destination_hash][6]
|
||||
next_hop = Transport.destination_table[destination_hash][1]
|
||||
received_from = Transport.destination_table[destination_hash][5]
|
||||
//p elif (RNS.Reticulum.transport_enabled() or is_from_local_client) and (destination_hash in Transport.destination_table):
|
||||
else if ((Reticulum::transport_enabled() || is_from_local_client) && destination_iter != _destination_table.end()) {
|
||||
DestinationEntry& destination_entry = (*destination_iter).second;
|
||||
const Packet& packet = destination_entry._announce_packet;
|
||||
const Bytes& next_hop = destination_entry._received_from;
|
||||
const Interface& received_from = destination_entry._receiving_interface;
|
||||
|
||||
if attached_interface.mode == RNS.Interfaces.Interface.Interface.MODE_ROAMING and attached_interface == received_from:
|
||||
RNS.log("Not answering path request on roaming-mode interface, since next hop is on same roaming-mode interface", RNS.LOG_DEBUG)
|
||||
|
||||
else:
|
||||
if requestor_transport_id != None and next_hop == requestor_transport_id:
|
||||
if (attached_interface.mode() == Type::Interface::MODE_ROAMING && attached_interface == destination_entry._receiving_interface) {
|
||||
debug("Not answering path request on roaming-mode interface, since next hop is on same roaming-mode interface");
|
||||
}
|
||||
else {
|
||||
if (requestor_transport_id && destination_entry._received_from == requestor_transport_id) {
|
||||
// TODO: Find a bandwidth efficient way to invalidate our
|
||||
// known path on this signal. The obvious way of signing
|
||||
// path requests with transport instance keys is quite
|
||||
// inefficient. There is probably a better way. Doing
|
||||
// path invalidation here would decrease the network
|
||||
// convergence time. Maybe just drop it?
|
||||
RNS.log("Not answering path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", since next hop is the requestor", RNS.LOG_DEBUG)
|
||||
else:
|
||||
RNS.log("Answering path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", path is known", RNS.LOG_DEBUG)
|
||||
debug("Not answering path request for destination " + destination_hash.toHex() + interface_str + ", since next hop is the requestor");
|
||||
}
|
||||
else {
|
||||
debug("Answering path request for destination " + destination_hash.toHex() + interface_str + ", path is known");
|
||||
|
||||
now = time.time()
|
||||
retries = Transport.PATHFINDER_R
|
||||
local_rebroadcasts = 0
|
||||
block_rebroadcasts = True
|
||||
announce_hops = packet.hops
|
||||
uint64_t now = OS::time();
|
||||
uint8_t retries = Type::Transport::PATHFINDER_R;
|
||||
uint8_t local_rebroadcasts = 0;
|
||||
bool block_rebroadcasts = true;
|
||||
uint8_t announce_hops = destination_entry._announce_packet.hops();
|
||||
|
||||
if is_from_local_client:
|
||||
retransmit_timeout = now
|
||||
else:
|
||||
uint64_t retransmit_timeout = 0;
|
||||
if (is_from_local_client) {
|
||||
retransmit_timeout = now;
|
||||
}
|
||||
else {
|
||||
// TODO: Look at this timing
|
||||
retransmit_timeout = now + Transport.PATH_REQUEST_GRACE // + (RNS.rand() * Transport.PATHFINDER_RW)
|
||||
retransmit_timeout = now + Type::Transport::PATH_REQUEST_GRACE /*+ (RNS.rand() * Transport.PATHFINDER_RW)*/;
|
||||
}
|
||||
|
||||
// This handles an edge case where a peer sends a past
|
||||
// request for a destination just after an announce for
|
||||
@ -2683,86 +2772,123 @@ will announce it.
|
||||
// rebroadcast locally. In such a case the actual announce
|
||||
// is temporarily held, and then reinserted when the path
|
||||
// request has been served to the peer.
|
||||
if packet.destination_hash in Transport.announce_table:
|
||||
held_entry = Transport.announce_table[packet.destination_hash]
|
||||
Transport.held_announces[packet.destination_hash] = held_entry
|
||||
auto announce_iter = _announce_table.find(destination_entry._announce_packet.destination_hash());
|
||||
if (announce_iter != _announce_table.end()) {
|
||||
AnnounceEntry& held_entry = (*announce_iter).second;
|
||||
_held_announces.insert({destination_entry._announce_packet.destination_hash(), held_entry});
|
||||
}
|
||||
|
||||
Transport.announce_table[packet.destination_hash] = [now, retransmit_timeout, retries, received_from, announce_hops, packet, local_rebroadcasts, block_rebroadcasts, attached_interface]
|
||||
|
||||
elif is_from_local_client:
|
||||
_announce_table.insert({destination_entry._announce_packet.destination_hash(), {
|
||||
now,
|
||||
retransmit_timeout,
|
||||
retries,
|
||||
// BUG?
|
||||
//destination_entry.receiving_interface,
|
||||
destination_entry._received_from,
|
||||
announce_hops,
|
||||
destination_entry._announce_packet,
|
||||
local_rebroadcasts,
|
||||
block_rebroadcasts,
|
||||
attached_interface
|
||||
}});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_from_local_client) {
|
||||
// Forward path request on all interfaces
|
||||
// except the local client
|
||||
RNS.log("Forwarding path request from local client for "+RNS.prettyhexrep(destination_hash)+interface_str+" to all other interfaces", RNS.LOG_DEBUG)
|
||||
request_tag = RNS.Identity.get_random_hash()
|
||||
for interface in Transport.interfaces:
|
||||
if not interface == attached_interface:
|
||||
Transport.request_path(destination_hash, interface, tag = request_tag)
|
||||
|
||||
elif should_search_for_unknown:
|
||||
if destination_hash in Transport.discovery_path_requests:
|
||||
RNS.log("There is already a waiting path request for "+RNS.prettyhexrep(destination_hash)+" on behalf of path request"+interface_str, RNS.LOG_DEBUG)
|
||||
else:
|
||||
debug("Forwarding path request from local client for destination " + destination_hash.toHex() + interface_str + " to all other interfaces");
|
||||
Bytes request_tag = Identity::get_random_hash();
|
||||
#if defined(INTERFACES_SET)
|
||||
for (const Interface& interface : _interfaces) {
|
||||
#elif defined(INTERFACES_LIST)
|
||||
for (Interface& interface : _interfaces) {
|
||||
#elif defined(INTERFACES_MAP)
|
||||
for (auto& [hash, interface] : _interfaces) {
|
||||
#endif
|
||||
if (interface != attached_interface) {
|
||||
request_path(destination_hash, interface, request_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (should_search_for_unknown) {
|
||||
if (_discovery_path_requests.find(destination_hash) != _discovery_path_requests.end()) {
|
||||
debug("There is already a waiting path request for destination " + destination_hash.toHex() + " on behalf of path request " + interface_str);
|
||||
}
|
||||
else {
|
||||
// Forward path request on all interfaces
|
||||
// except the requestor interface
|
||||
RNS.log("Attempting to discover unknown path to "+RNS.prettyhexrep(destination_hash)+" on behalf of path request"+interface_str, RNS.LOG_DEBUG)
|
||||
pr_entry = { "destination_hash": destination_hash, "timeout": time.time()+Transport.PATH_REQUEST_TIMEOUT, "requesting_interface": attached_interface }
|
||||
Transport.discovery_path_requests[destination_hash] = pr_entry
|
||||
debug("Attempting to discover unknown path to destination " + destination_hash.toHex() + " on behalf of path request " + interface_str);
|
||||
//p pr_entry = { "destination_hash": destination_hash, "timeout": time.time()+Transport.PATH_REQUEST_TIMEOUT, "requesting_interface": attached_interface }
|
||||
//p _discovery_path_requests[destination_hash] = pr_entry;
|
||||
_discovery_path_requests.insert({destination_hash, {
|
||||
destination_hash,
|
||||
OS::time() + Type::Transport::PATH_REQUEST_TIMEOUT,
|
||||
attached_interface
|
||||
}});
|
||||
|
||||
for interface in Transport.interfaces:
|
||||
if not interface == attached_interface:
|
||||
#if defined(INTERFACES_SET)
|
||||
for (const Interface& interface : _interfaces) {
|
||||
#elif defined(INTERFACES_LIST)
|
||||
for (Interface& interface : _interfaces) {
|
||||
#elif defined(INTERFACES_MAP)
|
||||
for (auto& [hash, interface] : _interfaces) {
|
||||
#endif
|
||||
if (interface != attached_interface) {
|
||||
// Use the previously extracted tag from this path request
|
||||
// on the new path requests as well, to avoid potential loops
|
||||
Transport.request_path(destination_hash, on_interface=interface, tag=tag, recursive=True)
|
||||
|
||||
elif not is_from_local_client and len(Transport.local_client_interfaces) > 0:
|
||||
request_path(destination_hash, interface, tag, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!is_from_local_client && _local_client_interfaces.size() > 0) {
|
||||
// Forward the path request on all local
|
||||
// client interfaces
|
||||
RNS.log("Forwarding path request for "+RNS.prettyhexrep(destination_hash)+interface_str+" to local clients", RNS.LOG_DEBUG)
|
||||
for interface in Transport.local_client_interfaces:
|
||||
Transport.request_path(destination_hash, on_interface=interface)
|
||||
|
||||
else:
|
||||
RNS.log("Ignoring path request for "+RNS.prettyhexrep(destination_hash)+interface_str+", no path known", RNS.LOG_DEBUG)
|
||||
*/
|
||||
debug("Forwarding path request for destination " + destination_hash.toHex() + interface_str + " to local clients");
|
||||
for (const Interface& interface : _local_client_interfaces) {
|
||||
request_path(destination_hash, interface);
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Ignoring path request for destination " + destination_hash.toHex() + interface_str + ", no path known");
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ bool Transport::from_local_client(const Packet& packet) {
|
||||
/*
|
||||
if hasattr(packet.receiving_interface, "parent_interface"):
|
||||
return Transport.is_local_client_interface(packet.receiving_interface)
|
||||
else:
|
||||
return False
|
||||
*/
|
||||
// MOCK
|
||||
return false;
|
||||
if (packet.receiving_interface().parent_interface()) {
|
||||
return is_local_client_interface(packet.receiving_interface());
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ bool Transport::is_local_client_interface(const Interface& interface) {
|
||||
/*
|
||||
if hasattr(interface, "parent_interface"):
|
||||
if hasattr(interface.parent_interface, "is_local_shared_instance"):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
*/
|
||||
// MOCK
|
||||
return false;
|
||||
if (interface.parent_interface()) {
|
||||
if (interface.parent_interface()->is_local_shared_instance()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ bool Transport::interface_to_shared_instance(const Interface& interface) {
|
||||
/*
|
||||
if hasattr(interface, "is_connected_to_shared_instance"):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
*/
|
||||
// MOCK
|
||||
return false;
|
||||
if (interface.is_connected_to_shared_instance()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void Transport::detach_interfaces() {
|
||||
// TODO
|
||||
/*
|
||||
detachable_interfaces = []
|
||||
|
||||
@ -2790,6 +2916,7 @@ will announce it.
|
||||
}
|
||||
|
||||
/*static*/ void Transport::shared_connection_disappeared() {
|
||||
// TODO
|
||||
/*
|
||||
for link in Transport.active_links:
|
||||
link.teardown()
|
||||
@ -2808,6 +2935,7 @@ will announce it.
|
||||
}
|
||||
|
||||
/*static*/ void Transport::shared_connection_reappeared() {
|
||||
// TODO
|
||||
/*
|
||||
if Transport.owner.is_connected_to_shared_instance:
|
||||
for registered_destination in Transport.destinations:
|
||||
@ -2817,6 +2945,7 @@ will announce it.
|
||||
}
|
||||
|
||||
/*static*/ void Transport::drop_announce_queues() {
|
||||
// TODO
|
||||
/*
|
||||
for interface in Transport.interfaces:
|
||||
if hasattr(interface, "announce_queue") and interface.announce_queue != None:
|
||||
@ -2833,6 +2962,7 @@ will announce it.
|
||||
}
|
||||
|
||||
/*static*/ bool Transport::announce_emitted(const Packet& packet) {
|
||||
// TODO
|
||||
/*
|
||||
random_blob = packet.data[RNS.Identity.KEYSIZE//8+RNS.Identity.NAME_HASH_LENGTH//8:RNS.Identity.KEYSIZE//8+RNS.Identity.NAME_HASH_LENGTH//8+10]
|
||||
announce_emitted = int.from_bytes(random_blob[5:10], "big")
|
||||
@ -2844,6 +2974,7 @@ will announce it.
|
||||
}
|
||||
|
||||
/*static*/ void Transport::save_packet_hashlist() {
|
||||
// TODO
|
||||
/*
|
||||
if not Transport.owner.is_connected_to_shared_instance:
|
||||
if hasattr(Transport, "saving_packet_hashlist"):
|
||||
@ -2885,6 +3016,7 @@ will announce it.
|
||||
}
|
||||
|
||||
/*static*/ void Transport::save_path_table() {
|
||||
// TODO
|
||||
/*
|
||||
if not Transport.owner.is_connected_to_shared_instance:
|
||||
if hasattr(Transport, "saving_path_table"):
|
||||
@ -2956,6 +3088,7 @@ will announce it.
|
||||
}
|
||||
|
||||
/*static*/ void Transport::save_tunnel_table() {
|
||||
// TODO
|
||||
/*
|
||||
if not Transport.owner.is_connected_to_shared_instance:
|
||||
if hasattr(Transport, "saving_tunnel_table"):
|
||||
@ -3047,15 +3180,18 @@ will announce it.
|
||||
}
|
||||
|
||||
/*static*/ Destination Transport::find_destination_from_hash(const Bytes& destination_hash) {
|
||||
extreme("Transport: Searching for destination " + destination_hash.toHex());
|
||||
#if defined(DESTINATIONS_SET)
|
||||
for (const Destination& destination : _destinations) {
|
||||
if (destination.get_hash() == destination_hash) {
|
||||
extreme("Transport::find_destination_from_hash: Found destination " + destination.toString());
|
||||
return destination;
|
||||
}
|
||||
}
|
||||
#elif defined(DESTINATIONS_MAP)
|
||||
auto iter = _destinations.find(destination_hash);
|
||||
if (iter != _destinations.end()) {
|
||||
extreme("Transport::find_destination_from_hash: Found destination " + (*iter).second.toString());
|
||||
return (*iter).second;
|
||||
}
|
||||
#endif
|
||||
|
@ -35,7 +35,7 @@ namespace RNS {
|
||||
// None, all announces will be passed to the instance.
|
||||
// If only some announces are wanted, it can be set to
|
||||
// an aspect string.
|
||||
AnnounceHandler(const char* aspect_filter) { _aspect_filter = aspect_filter; }
|
||||
AnnounceHandler(const char* aspect_filter = nullptr) { if (aspect_filter != nullptr) _aspect_filter = aspect_filter; }
|
||||
// This method will be called by Reticulums Transport
|
||||
// system when an announce arrives that matches the
|
||||
// configured aspect filter. Filters must be specific,
|
||||
@ -65,7 +65,7 @@ namespace RNS {
|
||||
_expires(expires),
|
||||
_random_blobs(random_blobs),
|
||||
_receiving_interface(receiving_interface),
|
||||
_packet(packet)
|
||||
_announce_packet(packet)
|
||||
{
|
||||
}
|
||||
public:
|
||||
@ -75,14 +75,14 @@ namespace RNS {
|
||||
uint64_t _expires = 0;
|
||||
std::set<Bytes> _random_blobs;
|
||||
Interface& _receiving_interface;
|
||||
const Packet& _packet;
|
||||
const Packet& _announce_packet;
|
||||
};
|
||||
|
||||
// CBA TODO Analyze safety of using Inrerface references here
|
||||
// CBA TODO Analyze safety of using Packet references here
|
||||
class AnnounceEntry {
|
||||
public:
|
||||
AnnounceEntry(uint64_t timestamp, uint16_t retransmit_timeout, uint8_t retries, const Bytes& received_from, uint8_t hops, const Packet& packet, uint8_t local_rebroadcasts, bool block_rebroadcasts, const Interface& attached_interface) :
|
||||
AnnounceEntry(uint64_t timestamp, uint64_t retransmit_timeout, uint8_t retries, const 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),
|
||||
@ -96,7 +96,7 @@ namespace RNS {
|
||||
}
|
||||
public:
|
||||
uint64_t _timestamp = 0;
|
||||
uint16_t _retransmit_timeout = 0;
|
||||
uint64_t _retransmit_timeout = 0;
|
||||
uint8_t _retries = 0;
|
||||
Bytes _received_from;
|
||||
uint8_t _hops = 0;
|
||||
@ -251,10 +251,10 @@ namespace RNS {
|
||||
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
|
||||
static std::map<Bytes, uint64_t> _path_requests; // A table for storing path request timestamps
|
||||
|
||||
static std::map<Bytes, PathRequestEntry> _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 std::set<Bytes> _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
|
||||
|
@ -95,6 +95,7 @@ namespace RNS { namespace Type {
|
||||
static const uint16_t SIGLENGTH = KEYSIZE; // In bits
|
||||
|
||||
static const uint8_t NAME_HASH_LENGTH = 80;
|
||||
static const uint8_t RANDOM_HASH_LENGTH = 80;
|
||||
static const uint16_t TRUNCATED_HASHLENGTH = Reticulum::TRUNCATED_HASHLENGTH; // In bits
|
||||
// Constant specifying the truncated hash length (in bits) used by Reticulum
|
||||
// for addressable hashes and other purposes. Non-configurable.
|
||||
|
@ -14,9 +14,16 @@ namespace RNS { namespace Utilities {
|
||||
// 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; }
|
||||
|
||||
// return current time in float seconds since 00:00:00, January 1, 1970 (Unix Epoch)
|
||||
static double dtime() { timeval time; ::gettimeofday(&time, NULL); return (double)time.tv_sec + ((double)time.tv_usec / 1000000); }
|
||||
|
||||
// round decimal number to specified precision
|
||||
//static inline float round(float value, uint8_t precision) { return std::round(value / precision) * precision; }
|
||||
static inline double round(double value, uint8_t precision) { return std::round(value / precision) * precision; }
|
||||
|
||||
};
|
||||
|
||||
|
243
src/main.cpp
243
src/main.cpp
@ -8,10 +8,13 @@
|
||||
#include "Packet.h"
|
||||
#include "Transport.h"
|
||||
#include "Interface.h"
|
||||
#include "Log.h"
|
||||
#include "Bytes.h"
|
||||
#include "Type.h"
|
||||
#include "Interfaces/UDPInterface.h"
|
||||
#include "Utilities/OS.h"
|
||||
|
||||
#ifndef NATIVE
|
||||
#ifdef ARDUINO
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
@ -23,6 +26,13 @@
|
||||
#include <functional>
|
||||
//#include <sstream>
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
//#define RUN_TESTS
|
||||
#endif
|
||||
#define RUN_RETICULUM
|
||||
//#define RETICULUM_PACKET_TEST
|
||||
|
||||
// Let's define an app name. We'll use this for all
|
||||
// destinations we create. Since this basic example
|
||||
// is part of a range of example utilities, we'll put
|
||||
@ -39,7 +49,7 @@ public:
|
||||
IN(true);
|
||||
OUT(true);
|
||||
}
|
||||
TestInterface(const char *name) : RNS::Interface(name) {
|
||||
TestInterface(const char* name) : RNS::Interface(name) {
|
||||
IN(true);
|
||||
OUT(true);
|
||||
}
|
||||
@ -61,7 +71,7 @@ public:
|
||||
IN(true);
|
||||
OUT(true);
|
||||
}
|
||||
TestLoopbackInterface(RNS::Interface& loopback_interface, const char *name) : RNS::Interface(name), _loopback_interface(loopback_interface) {
|
||||
TestLoopbackInterface(RNS::Interface& loopback_interface, const char* name) : RNS::Interface(name), _loopback_interface(loopback_interface) {
|
||||
IN(true);
|
||||
OUT(true);
|
||||
}
|
||||
@ -87,7 +97,7 @@ public:
|
||||
OUT(true);
|
||||
IN(false);
|
||||
}
|
||||
TestOutInterface(const char *name) : RNS::Interface(name) {
|
||||
TestOutInterface(const char* name) : RNS::Interface(name) {
|
||||
OUT(true);
|
||||
IN(false);
|
||||
}
|
||||
@ -107,7 +117,7 @@ public:
|
||||
OUT(false);
|
||||
IN(true);
|
||||
}
|
||||
TestInInterface(const char *name) : RNS::Interface(name) {
|
||||
TestInInterface(const char* name) : RNS::Interface(name) {
|
||||
OUT(false);
|
||||
IN(true);
|
||||
}
|
||||
@ -124,105 +134,111 @@ public:
|
||||
// Test AnnounceHandler
|
||||
class ExampleAnnounceHandler : public RNS::AnnounceHandler {
|
||||
public:
|
||||
ExampleAnnounceHandler(const char* aspect_filter) : AnnounceHandler(aspect_filter) {}
|
||||
ExampleAnnounceHandler(const char* aspect_filter = nullptr) : AnnounceHandler(aspect_filter) {}
|
||||
virtual ~ExampleAnnounceHandler() {}
|
||||
virtual void received_announce(const RNS::Bytes& destination_hash, const RNS::Identity& announced_identity, const RNS::Bytes& app_data) {
|
||||
RNS::info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
RNS::info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
RNS::info("ExampleAnnounceHandler: destination hash: " + destination_hash.toHex());
|
||||
RNS::info("ExampleAnnounceHandler: destination hash: " + destination_hash.toHex());
|
||||
if (app_data) {
|
||||
RNS::info("ExampleAnnounceHandler: app data: " + app_data.toString());
|
||||
if (announced_identity) {
|
||||
RNS::info("ExampleAnnounceHandler: announced identity hash: " + announced_identity.hash().toHex());
|
||||
RNS::info("ExampleAnnounceHandler: announced identity app data: " + announced_identity.app_data().toHex());
|
||||
}
|
||||
RNS::info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
if (app_data) {
|
||||
RNS::info("ExampleAnnounceHandler: app data text: \"" + app_data.toString() + "\"");
|
||||
}
|
||||
RNS::info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
}
|
||||
};
|
||||
|
||||
// Test packet receive callback
|
||||
void onPacket(const RNS::Bytes& data, const RNS::Packet& packet) {
|
||||
RNS::info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
RNS::info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
RNS::head("onPacket: data: " + data.toHex(), RNS::LOG_INFO);
|
||||
RNS::head("onPacket: data string: \"" + data.toString() + "\"", RNS::LOG_INFO);
|
||||
//RNS::head("onPacket: " + packet.debugString(), RNS::LOG_EXTREME);
|
||||
RNS::info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
}
|
||||
|
||||
void setup() {
|
||||
|
||||
#ifndef NATIVE
|
||||
Serial.begin(115200);
|
||||
Serial.print("Hello from T-Beam on PlatformIO!\n");
|
||||
#if defined(RUN_RETICULUM)
|
||||
RNS::Reticulum reticulum({RNS::Type::NONE});
|
||||
|
||||
//TestInterface interface;
|
||||
TestOutInterface outinterface;
|
||||
TestInInterface ininterface;
|
||||
TestLoopbackInterface loopinterface(ininterface);
|
||||
RNS::Interfaces::UDPInterface udpinterface;
|
||||
|
||||
//ExampleAnnounceHandler announce_handler((const char*)"example_utilities.announcesample.fruits");
|
||||
//RNS::HAnnounceHandler announce_handler(new ExampleAnnounceHandler("example_utilities.announcesample.fruits"));
|
||||
RNS::HAnnounceHandler announce_handler(new ExampleAnnounceHandler());
|
||||
#endif
|
||||
|
||||
#if defined(RUN_TESTS)
|
||||
void run_tests() {
|
||||
|
||||
try {
|
||||
|
||||
#ifndef NDEBUG
|
||||
RNS::loglevel(RNS::LOG_WARNING);
|
||||
//RNS::loglevel(RNS::LOG_EXTREME);
|
||||
RNS::extreme("Running tests...");
|
||||
RNS::LogLevel loglevel = RNS::loglevel();
|
||||
//RNS::loglevel(RNS::LOG_WARNING);
|
||||
RNS::loglevel(RNS::LOG_EXTREME);
|
||||
test();
|
||||
//testReference();
|
||||
//testCrypto();
|
||||
RNS::loglevel(loglevel);
|
||||
RNS::extreme("Finished running tests");
|
||||
//return;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
RNS::error(std::string("!!! Exception in test: ") + e.what() + " !!!");
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RUN_RETICULUM)
|
||||
void setup_reticulum() {
|
||||
RNS::info("Setting up Reticulum...");
|
||||
|
||||
try {
|
||||
|
||||
//std::stringstream test;
|
||||
// !!! just adding this single stringstream alone (not even using it) adds a whopping 17.1% !!!
|
||||
// !!! JUST SAY NO TO STRINGSTREAM !!!
|
||||
|
||||
RNS::loglevel(RNS::LOG_EXTREME);
|
||||
|
||||
// 18.5% completely empty program
|
||||
|
||||
// 21.8% baseline here with serial
|
||||
|
||||
RNS::head("Creating Reticulum instance...", RNS::LOG_EXTREME);
|
||||
RNS::Reticulum reticulum;
|
||||
//RNS::Reticulum reticulum;
|
||||
reticulum = RNS::Reticulum();
|
||||
//return;
|
||||
// 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::Transport::register_interface(udpinterface);
|
||||
|
||||
RNS::head("Starting UDPInterface...", RNS::LOG_EXTREME);
|
||||
udpinterface.start();
|
||||
|
||||
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::Type::Destination::IN, RNS::Type::Destination::SINGLE, "test", "context");
|
||||
RNS::Destination destination(identity, RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "app", "aspects");
|
||||
// 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::Type::Destination::PROVE_ALL);
|
||||
|
||||
RNS::head("Registering announce handler with Transport...", RNS::LOG_EXTREME);
|
||||
RNS::HAnnounceHandler announce_handler(new ExampleAnnounceHandler("example_utilities.announcesample.fruits"));
|
||||
//ExampleAnnounceHandler announce_handler((const char*)"example_utilities.announcesample.fruits");
|
||||
RNS::Transport::register_announce_handler(announce_handler);
|
||||
|
||||
RNS::head("Announcing destination...", RNS::LOG_EXTREME);
|
||||
@ -233,7 +249,7 @@ void setup() {
|
||||
destination.announce(RNS::bytesFromString(fruits[rand() % 7]));
|
||||
// 23.9% (+0.8%)
|
||||
|
||||
/*
|
||||
#if defined (RETICULUM_PACKET_TEST)
|
||||
// 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");
|
||||
@ -253,12 +269,24 @@ void setup() {
|
||||
|
||||
RNS::head("Spoofing recv packet to destination...", RNS::LOG_EXTREME);
|
||||
destination.receive(recv_packet);
|
||||
*/
|
||||
#endif
|
||||
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
RNS::error(std::string("!!! Exception in setup_reticulum: ") + e.what() + " !!!");
|
||||
}
|
||||
}
|
||||
|
||||
void teardown_reticulum() {
|
||||
RNS::info("Tearing down Reticulum...");
|
||||
|
||||
try {
|
||||
|
||||
RNS::head("Deregistering announce handler with Transport...", RNS::LOG_EXTREME);
|
||||
RNS::Transport::deregister_announce_handler(announce_handler);
|
||||
|
||||
RNS::head("Deregistering Interface instances with Transport...", RNS::LOG_EXTREME);
|
||||
RNS::Transport::deregister_interface(udpinterface);
|
||||
RNS::Transport::deregister_interface(loopinterface);
|
||||
RNS::Transport::deregister_interface(ininterface);
|
||||
RNS::Transport::deregister_interface(outinterface);
|
||||
@ -266,97 +294,52 @@ void setup() {
|
||||
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
RNS::error(std::string("!!! Exception in main: ") + e.what() + " !!!");
|
||||
RNS::error(std::string("!!! Exception in teardown_reticulum: ") + e.what() + " !!!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NATIVE
|
||||
void setup() {
|
||||
|
||||
#ifdef ARDUINO
|
||||
Serial.begin(115200);
|
||||
Serial.print("Hello from T-Beam on PlatformIO!\n");
|
||||
#endif
|
||||
|
||||
RNS::loglevel(RNS::LOG_EXTREME);
|
||||
|
||||
/*
|
||||
{
|
||||
//RNS::Reticulum reticulum_test;
|
||||
RNS::Destination destination_test({RNS::Type::NONE}, RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "test", "test");
|
||||
}
|
||||
*/
|
||||
|
||||
#if defined(RUN_TESTS)
|
||||
run_tests();
|
||||
#endif
|
||||
|
||||
#if defined(RUN_RETICULUM)
|
||||
setup_reticulum();
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO
|
||||
Serial.print("Goodbye from T-Beam on PlatformIO!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
#if defined(RUN_RETICULUM)
|
||||
reticulum.loop();
|
||||
udpinterface.loop();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
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