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