mirror of
https://github.com/markqvist/reticulum-cpp.git
synced 2024-10-01 02:55:46 -04:00
WIP: Refactored to minimize circular dependenies
Moved core class constants and enums into single header Types.h. Switched form class-specific NoneContructor to single Type::NoneConstructor.
This commit is contained in:
parent
a2e956eced
commit
33fda8a7f9
@ -19,6 +19,7 @@ build_flags =
|
||||
-Wextra
|
||||
-Wno-missing-field-initializers
|
||||
-Wno-format
|
||||
-Wno-unused-parameter
|
||||
-Isrc
|
||||
-DNATIVE
|
||||
lib_deps =
|
||||
|
@ -65,6 +65,8 @@ namespace RNS { namespace Cryptography {
|
||||
public:
|
||||
// creates a new instance with a random seed
|
||||
static inline Ptr generate() {
|
||||
// CBA TODO determine why below is confused with (implicit) copy constructor
|
||||
//return Ptr(new Ed25519PrivateKey({Bytes::NONE}));
|
||||
return Ptr(new Ed25519PrivateKey(Bytes::NONE));
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
using namespace RNS;
|
||||
|
||||
Bytes RNS::Cryptography::hkdf(size_t length, const Bytes &derive_from, const Bytes &salt /*= Bytes::NONE*/, const Bytes &context /*= Bytes::NONE*/) {
|
||||
Bytes RNS::Cryptography::hkdf(size_t length, const Bytes &derive_from, const Bytes &salt /*= {Bytes::NONE}*/, const Bytes &context /*= {Bytes::NONE}*/) {
|
||||
|
||||
if (length <= 0) {
|
||||
throw std::invalid_argument("Invalid output key length");
|
||||
|
@ -4,6 +4,6 @@
|
||||
|
||||
namespace RNS { namespace Cryptography {
|
||||
|
||||
Bytes hkdf(size_t length, const Bytes &derive_from, const Bytes &salt = Bytes::NONE, const Bytes &context = Bytes::NONE);
|
||||
Bytes hkdf(size_t length, const Bytes &derive_from, const Bytes &salt = {Bytes::NONE}, const Bytes &context = {Bytes::NONE});
|
||||
|
||||
} }
|
||||
|
@ -28,7 +28,7 @@ namespace RNS { namespace Cryptography {
|
||||
msg: bytes or buffer, Initial input for the hash or None.
|
||||
digest: The underlying hash algorithm to use
|
||||
*/
|
||||
HMAC(const Bytes &key, const Bytes &msg = Bytes::NONE, Digest digest = DIGEST_SHA256) {
|
||||
HMAC(const Bytes &key, const Bytes &msg = {Bytes::NONE}, Digest digest = DIGEST_SHA256) {
|
||||
|
||||
if (digest == DIGEST_NONE) {
|
||||
throw std::invalid_argument("Cannot derive key from empty input material");
|
||||
@ -83,7 +83,7 @@ namespace RNS { namespace Cryptography {
|
||||
method, and can ask for the hash value at any time by calling its digest()
|
||||
method.
|
||||
*/
|
||||
static inline Ptr generate(const Bytes &key, const Bytes &msg = Bytes::NONE, Digest digest = DIGEST_SHA256) {
|
||||
static inline Ptr generate(const Bytes &key, const Bytes &msg = {Bytes::NONE}, Digest digest = DIGEST_SHA256) {
|
||||
return Ptr(new HMAC(key, msg, digest));
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ namespace RNS { namespace Cryptography {
|
||||
}
|
||||
*/
|
||||
static inline Ptr generate() {
|
||||
return from_private_bytes(Bytes::NONE);
|
||||
return from_private_bytes({Bytes::NONE});
|
||||
}
|
||||
|
||||
// creates a new instance with specified seed
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <vector>
|
||||
|
||||
using namespace RNS;
|
||||
using namespace RNS::Type::Destination;
|
||||
|
||||
Destination::Destination(const Identity &identity, const directions direction, const types type, const char* app_name, const char *aspects) : _object(new Object(identity)) {
|
||||
assert(_object);
|
||||
@ -23,7 +24,7 @@ Destination::Destination(const Identity &identity, const directions direction, c
|
||||
_object->_direction = direction;
|
||||
|
||||
std::string fullaspects(aspects);
|
||||
if (!identity && direction == Destination::IN && _object->_type != Destination::PLAIN) {
|
||||
if (!identity && direction == IN && _object->_type != PLAIN) {
|
||||
debug("Destination::Destination: identity not provided, creating new one");
|
||||
_object->_identity = Identity();
|
||||
// CBA TODO should following include a "." delimiter?
|
||||
@ -31,7 +32,7 @@ Destination::Destination(const Identity &identity, const directions direction, c
|
||||
}
|
||||
debug("Destination::Destination: full aspects: " + fullaspects);
|
||||
|
||||
if (_object->_identity && _object->_type == Destination::PLAIN) {
|
||||
if (_object->_identity && _object->_type == PLAIN) {
|
||||
throw std::invalid_argument("Selected destination type PLAIN cannot hold an identity");
|
||||
}
|
||||
|
||||
@ -45,7 +46,7 @@ Destination::Destination(const Identity &identity, const directions direction, c
|
||||
debug("Destination::Destination: hash: " + _object->_hash.toHex());
|
||||
// CBA TEST CRASH
|
||||
debug("Destination::Destination: creating name hash...");
|
||||
_object->_name_hash = Identity::truncated_hash(expand_name(Identity::NONE, app_name, fullaspects.c_str()));
|
||||
_object->_name_hash = Identity::truncated_hash(expand_name({Type::NONE}, app_name, fullaspects.c_str()));
|
||||
debug("Destination::Destination: name hash: " + _object->_name_hash.toHex());
|
||||
|
||||
debug("Destination::Destination: calling register_destination");
|
||||
@ -60,7 +61,7 @@ Destination::Destination(const Identity &identity, const directions direction, c
|
||||
/*static*/ Bytes Destination::hash(const Identity &identity, const char *app_name, const char *aspects) {
|
||||
//name_hash = Identity::full_hash(Destination.expand_name(None, app_name, *aspects).encode("utf-8"))[:(RNS.Identity.NAME_HASH_LENGTH//8)]
|
||||
//addr_hash_material = name_hash
|
||||
Bytes addr_hash_material = Identity::truncated_hash(expand_name(Identity::NONE, app_name, aspects));
|
||||
Bytes addr_hash_material = Identity::truncated_hash(expand_name({Type::NONE}, app_name, aspects));
|
||||
//if identity != None:
|
||||
// if isinstance(identity, RNS.Identity):
|
||||
// addr_hash_material += identity.hash
|
||||
@ -121,7 +122,7 @@ Packet Destination::announce(const Bytes &app_data, bool path_response, Interfac
|
||||
//Response &entry = *it;
|
||||
// map
|
||||
PathResponse &entry = (*it).second;
|
||||
if (now > (entry.first + Destination::PR_TAG_WINDOW)) {
|
||||
if (now > (entry.first + PR_TAG_WINDOW)) {
|
||||
it = _object->_path_responses.erase(it);
|
||||
}
|
||||
else {
|
||||
@ -205,18 +206,18 @@ Packet Destination::announce(const Bytes &app_data, bool path_response, Interfac
|
||||
}
|
||||
debug("Destination::announce: announce_data:" + announce_data.toHex());
|
||||
|
||||
Packet::context_types announce_context = Packet::CONTEXT_NONE;
|
||||
Type::Packet::context_types announce_context = Type::Packet::CONTEXT_NONE;
|
||||
if (path_response) {
|
||||
announce_context = Packet::PATH_RESPONSE;
|
||||
announce_context = Type::Packet::PATH_RESPONSE;
|
||||
}
|
||||
|
||||
debug("Destination::announce: creating announce packet...");
|
||||
Packet announce_packet(*this, announce_data, Packet::ANNOUNCE, announce_context, Transport::BROADCAST, Packet::HEADER_1, nullptr, attached_interface);
|
||||
Packet announce_packet(*this, announce_data, Type::Packet::ANNOUNCE, announce_context, Type::Transport::BROADCAST, Type::Packet::HEADER_1, nullptr, attached_interface);
|
||||
|
||||
if (send) {
|
||||
debug("Destination::announce: sending announce packet...");
|
||||
announce_packet.send();
|
||||
return Packet::NONE;
|
||||
return {Type::NONE};
|
||||
}
|
||||
else {
|
||||
return announce_packet;
|
||||
@ -267,7 +268,7 @@ bool Destination::deregister_request_handler(const Bytes &path) {
|
||||
|
||||
void Destination::receive(const Packet &packet) {
|
||||
assert(_object);
|
||||
if (packet.packet_type() == Packet::LINKREQUEST) {
|
||||
if (packet.packet_type() == Type::Packet::LINKREQUEST) {
|
||||
Bytes plaintext(packet.data());
|
||||
incoming_link_request(plaintext, packet);
|
||||
}
|
||||
@ -276,7 +277,7 @@ void Destination::receive(const Packet &packet) {
|
||||
Bytes plaintext(decrypt(packet.data()));
|
||||
extreme("Destination::receive: decrypted data: " + plaintext.toHex());
|
||||
if (plaintext) {
|
||||
if (packet.packet_type() == RNS::Packet::DATA) {
|
||||
if (packet.packet_type() == Type::Packet::DATA) {
|
||||
if (_object->_callbacks._packet) {
|
||||
try {
|
||||
_object->_callbacks._packet(plaintext, packet);
|
||||
@ -293,10 +294,10 @@ void Destination::receive(const Packet &packet) {
|
||||
void Destination::incoming_link_request(const Bytes &data, const Packet &packet) {
|
||||
assert(_object);
|
||||
if (_object->_accept_link_requests) {
|
||||
//zlink = RNS::Link::validate_request(data, packet);
|
||||
//zif (link) {
|
||||
//z link = Link::validate_request(data, packet);
|
||||
//z if (link) {
|
||||
//z _links.append(link);
|
||||
//z}
|
||||
//z }
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,16 +311,16 @@ Bytes Destination::encrypt(const Bytes &data) {
|
||||
assert(_object);
|
||||
debug("Destination::encrypt: encrypting data...");
|
||||
|
||||
if (_object->_type == Destination::PLAIN) {
|
||||
if (_object->_type == PLAIN) {
|
||||
return data;
|
||||
}
|
||||
|
||||
if (_object->_type == Destination::SINGLE && _object->_identity) {
|
||||
if (_object->_type == SINGLE && _object->_identity) {
|
||||
return _object->_identity.encrypt(data);
|
||||
}
|
||||
|
||||
/*
|
||||
if (_object->_type == Destination::GROUP {
|
||||
if (_object->_type == GROUP {
|
||||
if hasattr(self, "prv") and self.prv != None:
|
||||
try:
|
||||
return self.prv.encrypt(plaintext)
|
||||
@ -331,7 +332,7 @@ Bytes Destination::encrypt(const Bytes &data) {
|
||||
}
|
||||
*/
|
||||
// MOCK
|
||||
return Bytes::NONE;
|
||||
return {Bytes::NONE};
|
||||
}
|
||||
|
||||
/*
|
||||
@ -344,16 +345,16 @@ Bytes Destination::decrypt(const Bytes &data) {
|
||||
assert(_object);
|
||||
debug("Destination::decrypt: decrypting data...");
|
||||
|
||||
if (_object->_type == Destination::PLAIN) {
|
||||
if (_object->_type == PLAIN) {
|
||||
return data;
|
||||
}
|
||||
|
||||
if (_object->_type == Destination::SINGLE && _object->_identity) {
|
||||
if (_object->_type == SINGLE && _object->_identity) {
|
||||
return _object->_identity.decrypt(data);
|
||||
}
|
||||
|
||||
/*
|
||||
if (_object->_type == Destination::GROUP) {
|
||||
if (_object->_type == GROUP) {
|
||||
if hasattr(self, "prv") and self.prv != None:
|
||||
try:
|
||||
return self.prv.decrypt(ciphertext)
|
||||
@ -365,7 +366,7 @@ Bytes Destination::decrypt(const Bytes &data) {
|
||||
}
|
||||
*/
|
||||
// MOCK
|
||||
return Bytes::NONE;
|
||||
return {Bytes::NONE};
|
||||
}
|
||||
|
||||
/*
|
||||
@ -376,8 +377,8 @@ Signs information for ``RNS.Destination.SINGLE`` type destination.
|
||||
*/
|
||||
Bytes Destination::sign(const Bytes &message) {
|
||||
assert(_object);
|
||||
if (_object->_type == Destination::SINGLE && _object->_identity) {
|
||||
if (_object->_type == SINGLE && _object->_identity) {
|
||||
return _object->_identity.sign(message);
|
||||
}
|
||||
return Bytes::NONE;
|
||||
return {Bytes::NONE};
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "Link.h"
|
||||
#include "Identity.h"
|
||||
#include "Bytes.h"
|
||||
#include "None.h"
|
||||
#include "Type.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -54,48 +54,14 @@ namespace RNS {
|
||||
using PathResponse = std::pair<time_t, Bytes>;
|
||||
//using PathResponse = std::pair<time_t, std::vector<uint8_t>>;
|
||||
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
// Constants
|
||||
enum types {
|
||||
SINGLE = 0x00,
|
||||
GROUP = 0x01,
|
||||
PLAIN = 0x02,
|
||||
LINK = 0x03,
|
||||
};
|
||||
|
||||
enum proof_strategies {
|
||||
PROVE_NONE = 0x21,
|
||||
PROVE_APP = 0x22,
|
||||
PROVE_ALL = 0x23,
|
||||
};
|
||||
|
||||
enum request_policies {
|
||||
ALLOW_NONE = 0x00,
|
||||
ALLOW_ALL = 0x01,
|
||||
ALLOW_LIST = 0x02,
|
||||
};
|
||||
|
||||
enum directions {
|
||||
IN = 0x11,
|
||||
OUT = 0x12,
|
||||
};
|
||||
|
||||
const uint8_t PR_TAG_WINDOW = 30;
|
||||
|
||||
public:
|
||||
Destination(NoneConstructor none) {
|
||||
extreme("Destination NONE object created");
|
||||
}
|
||||
Destination(RNS::NoneConstructor none) {
|
||||
Destination(Type::NoneConstructor none) {
|
||||
extreme("Destination NONE object created");
|
||||
}
|
||||
Destination(const Destination &destination) : _object(destination._object) {
|
||||
extreme("Destination object copy created");
|
||||
}
|
||||
Destination(const Identity &identity, const directions direction, const types type, const char* app_name, const char *aspects);
|
||||
Destination(const Identity &identity, const Type::Destination::directions direction, const Type::Destination::types type, const char* app_name, const char *aspects);
|
||||
virtual ~Destination() {
|
||||
extreme("Destination object destroyed");
|
||||
}
|
||||
@ -165,7 +131,7 @@ namespace RNS {
|
||||
|
||||
:param proof_strategy: One of ``RNS.Destination.PROVE_NONE``, ``RNS.Destination.PROVE_ALL`` or ``RNS.Destination.PROVE_APP``. If ``RNS.Destination.PROVE_APP`` is set, the `proof_requested_callback` will be called to determine whether a proof should be sent or not.
|
||||
*/
|
||||
inline void set_proof_strategy(proof_strategies proof_strategy) {
|
||||
inline void set_proof_strategy(Type::Destination::proof_strategies proof_strategy) {
|
||||
assert(_object);
|
||||
//if (proof_strategy <= PROOF_NONE) {
|
||||
// throw throw std::invalid_argument("Unsupported proof strategy");
|
||||
@ -181,14 +147,14 @@ namespace RNS {
|
||||
Bytes sign(const Bytes &message);
|
||||
|
||||
// getters/setters
|
||||
inline types type() const { assert(_object); return _object->_type; }
|
||||
inline directions direction() const { assert(_object); return _object->_direction; }
|
||||
inline proof_strategies proof_strategy() const { assert(_object); return _object->_proof_strategy; }
|
||||
inline Type::Destination::types type() const { assert(_object); return _object->_type; }
|
||||
inline Type::Destination::directions direction() const { assert(_object); return _object->_direction; }
|
||||
inline Type::Destination::proof_strategies proof_strategy() const { assert(_object); return _object->_proof_strategy; }
|
||||
inline Bytes hash() const { assert(_object); return _object->_hash; }
|
||||
inline Bytes link_id() const { assert(_object); return _object->_link_id; }
|
||||
inline uint16_t mtu() const { assert(_object); return _object->_mtu; }
|
||||
inline void mtu(uint16_t mtu) { assert(_object); _object->_mtu = mtu; }
|
||||
inline Link::status status() const { assert(_object); return _object->_status; }
|
||||
inline Type::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; }
|
||||
|
||||
@ -203,9 +169,9 @@ namespace RNS {
|
||||
bool _accept_link_requests = true;
|
||||
Callbacks _callbacks;
|
||||
//z_request_handlers = {}
|
||||
types _type;
|
||||
directions _direction;
|
||||
proof_strategies _proof_strategy = PROVE_NONE;
|
||||
Type::Destination::types _type;
|
||||
Type::Destination::directions _direction;
|
||||
Type::Destination::proof_strategies _proof_strategy = Type::Destination::PROVE_NONE;
|
||||
uint16_t _mtu = 0;
|
||||
|
||||
//std::vector<PathResponse> _path_responses;
|
||||
@ -229,7 +195,7 @@ namespace RNS {
|
||||
// CBA TODO determine if Link needs to inherit from Destination or vice-versa
|
||||
Bytes _link_id;
|
||||
|
||||
Link::status _status;
|
||||
Type::Link::status _status;
|
||||
|
||||
friend class Destination;
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <string.h>
|
||||
|
||||
using namespace RNS;
|
||||
using namespace RNS::Type::Identity;
|
||||
|
||||
Identity::Identity(bool create_keys) : _object(new Object()) {
|
||||
if (create_keys) {
|
||||
@ -177,14 +178,14 @@ Bytes Identity::decrypt(const Bytes &ciphertext_token) {
|
||||
if (!_object->_prv) {
|
||||
throw std::runtime_error("Decryption failed because identity does not hold a private key");
|
||||
}
|
||||
if (ciphertext_token.size() <= Identity::KEYSIZE/8/2) {
|
||||
if (ciphertext_token.size() <= Type::Identity::KEYSIZE/8/2) {
|
||||
debug("Decryption failed because the token size " + std::to_string(ciphertext_token.size()) + " was invalid.");
|
||||
return Bytes::NONE;
|
||||
return {Bytes::NONE};
|
||||
}
|
||||
Bytes plaintext;
|
||||
try {
|
||||
//peer_pub_bytes = ciphertext_token[:Identity.KEYSIZE//8//2]
|
||||
Bytes peer_pub_bytes = ciphertext_token.left(Identity::KEYSIZE/8/2);
|
||||
Bytes peer_pub_bytes = ciphertext_token.left(Type::Identity::KEYSIZE/8/2);
|
||||
//peer_pub = X25519PublicKey.from_public_bytes(peer_pub_bytes)
|
||||
//Cryptography::X25519PublicKey::Ptr peer_pub = Cryptography::X25519PublicKey::from_public_bytes(peer_pub_bytes);
|
||||
debug("Identity::decrypt: peer public key: " + peer_pub_bytes.toHex());
|
||||
@ -204,7 +205,7 @@ Bytes Identity::decrypt(const Bytes &ciphertext_token) {
|
||||
|
||||
Cryptography::Fernet fernet(derived_key);
|
||||
//ciphertext = ciphertext_token[Identity.KEYSIZE//8//2:]
|
||||
Bytes ciphertext(ciphertext_token.mid(Identity::KEYSIZE/8/2));
|
||||
Bytes ciphertext(ciphertext_token.mid(Type::Identity::KEYSIZE/8/2));
|
||||
debug("Identity::decrypt: Fernet decrypting data of length " + std::to_string(ciphertext.size()));
|
||||
extreme("Identity::decrypt: ciphertext: " + ciphertext.toHex());
|
||||
plaintext = fernet.decrypt(ciphertext);
|
||||
@ -263,7 +264,7 @@ bool Identity::validate(const Bytes &signature, const Bytes &message) {
|
||||
}
|
||||
}
|
||||
|
||||
void Identity::prove(const Packet &packet, const Destination &destination /*= Destination::NONE*/) {
|
||||
void Identity::prove(const Packet &packet, const Destination &destination /*= {Destination::NONE}*/) {
|
||||
assert(_object);
|
||||
Bytes signature(sign(packet.packet_hash()));
|
||||
Bytes proof_data;
|
||||
@ -278,6 +279,6 @@ void Identity::prove(const Packet &packet, const Destination &destination /*= De
|
||||
//z destination = packet.generate_proof_destination();
|
||||
//z}
|
||||
|
||||
Packet proof(destination, packet.receiving_interface(), proof_data, RNS::Packet::PROOF);
|
||||
Packet proof(destination, packet.receiving_interface(), proof_data, Type::Packet::PROOF);
|
||||
proof.send();
|
||||
}
|
||||
|
@ -1,15 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Reticulum.h"
|
||||
// CBA TODO determine why including Destination.h here causes build errors
|
||||
//#include "Destination.h"
|
||||
#include "Log.h"
|
||||
#include "Bytes.h"
|
||||
#include "None.h"
|
||||
#include "Cryptography/Hashes.h"
|
||||
#include "Cryptography/Ed25519.h"
|
||||
#include "Cryptography/X25519.h"
|
||||
#include "Cryptography/Fernet.h"
|
||||
#include "Type.h"
|
||||
|
||||
|
||||
#include <memory>
|
||||
@ -23,33 +22,7 @@ namespace RNS {
|
||||
class Identity {
|
||||
|
||||
public:
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
//static const char CURVE[] = "Curve25519";
|
||||
static constexpr const char* CURVE = "Curve25519";
|
||||
// The curve used for Elliptic Curve DH key exchanges
|
||||
|
||||
static const uint16_t KEYSIZE = 256*2;
|
||||
// X25519 key size in bits. A complete key is the concatenation of a 256 bit encryption key, and a 256 bit signing key.
|
||||
|
||||
// Non-configurable constants
|
||||
static const uint8_t FERNET_OVERHEAD = RNS::Cryptography::Fernet::FERNET_OVERHEAD;
|
||||
static const uint8_t AES128_BLOCKSIZE = 16; // In bytes
|
||||
static const uint16_t HASHLENGTH = Reticulum::HASHLENGTH; // In bits
|
||||
static const uint16_t SIGLENGTH = KEYSIZE; // In bits
|
||||
|
||||
static const uint8_t NAME_HASH_LENGTH = 80;
|
||||
static const uint16_t TRUNCATED_HASHLENGTH = Reticulum::TRUNCATED_HASHLENGTH; // In bits
|
||||
// Constant specifying the truncated hash length (in bits) used by Reticulum
|
||||
// for addressable hashes and other purposes. Non-configurable.
|
||||
|
||||
public:
|
||||
Identity(NoneConstructor none) {
|
||||
extreme("Identity NONE object created, this: " + std::to_string((uintptr_t)this) + ", data: " + std::to_string((uintptr_t)_object.get()));
|
||||
}
|
||||
Identity(RNS::NoneConstructor none) {
|
||||
Identity(Type::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) {
|
||||
@ -105,7 +78,7 @@ namespace RNS {
|
||||
*/
|
||||
static inline Bytes truncated_hash(const Bytes &data) {
|
||||
//return Identity.full_hash(data)[:(Identity.TRUNCATED_HASHLENGTH//8)]
|
||||
return full_hash(data).left(TRUNCATED_HASHLENGTH/8);
|
||||
return full_hash(data).left(Type::Identity::TRUNCATED_HASHLENGTH/8);
|
||||
}
|
||||
/*
|
||||
Get a random SHA-256 hash.
|
||||
@ -114,19 +87,19 @@ namespace RNS {
|
||||
:returns: Truncated SHA-256 hash of random data as *bytes*
|
||||
*/
|
||||
static inline Bytes get_random_hash() {
|
||||
return truncated_hash(Cryptography::random(Identity::TRUNCATED_HASHLENGTH/8));
|
||||
return truncated_hash(Cryptography::random(Type::Identity::TRUNCATED_HASHLENGTH/8));
|
||||
}
|
||||
|
||||
static bool validate_announce(const Packet &packet);
|
||||
|
||||
inline Bytes get_salt() { assert(_object); return _object->_hash; }
|
||||
inline Bytes get_context() { return Bytes::NONE; }
|
||||
inline Bytes get_context() { return {Bytes::NONE}; }
|
||||
|
||||
Bytes encrypt(const Bytes &plaintext);
|
||||
Bytes decrypt(const Bytes &ciphertext_token);
|
||||
Bytes sign(const Bytes &message);
|
||||
bool validate(const Bytes &signature, const Bytes &message);
|
||||
//void prove(const Packet &packet, const Destination &destination = Destination::NONE);
|
||||
//void prove(const Packet &packet, const Destination &destination = {Destination::NONE});
|
||||
void prove(const Packet &packet, const Destination &destination);
|
||||
|
||||
// getters/setters
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "../Transport.h"
|
||||
|
||||
using namespace RNS;
|
||||
|
||||
using namespace RNS::Type::Interface;
|
||||
|
||||
/*virtual*/ inline void Interface::processIncoming(const Bytes &data) {
|
||||
extreme("Interface::processIncoming: data: " + data.toHex());
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "../Log.h"
|
||||
#include "../Bytes.h"
|
||||
#include "../None.h"
|
||||
#include "../Type.h"
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
@ -31,31 +31,12 @@ namespace RNS {
|
||||
};
|
||||
|
||||
public:
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
public:
|
||||
// Interface mode definitions
|
||||
enum modes {
|
||||
MODE_NONE = 0x00,
|
||||
MODE_FULL = 0x01,
|
||||
MODE_POINT_TO_POINT = 0x04,
|
||||
MODE_ACCESS_POINT = 0x08,
|
||||
MODE_ROAMING = 0x10,
|
||||
MODE_BOUNDARY = 0x20,
|
||||
MODE_GATEWAY = 0x40,
|
||||
};
|
||||
|
||||
// Which interface modes a Transport Node
|
||||
// should actively discover paths for.
|
||||
uint8_t DISCOVER_PATHS_FOR = MODE_ACCESS_POINT | MODE_GATEWAY;
|
||||
uint8_t DISCOVER_PATHS_FOR = Type::Interface::MODE_ACCESS_POINT | Type::Interface::MODE_GATEWAY;
|
||||
|
||||
public:
|
||||
Interface(NoneConstructor none) {
|
||||
extreme("Interface object NONE created");
|
||||
}
|
||||
Interface(RNS::NoneConstructor none) {
|
||||
Interface(Type::NoneConstructor none) {
|
||||
extreme("Interface object NONE created");
|
||||
}
|
||||
Interface(const Interface &interface) : _object(interface._object) {
|
||||
@ -107,7 +88,7 @@ namespace RNS {
|
||||
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 Type::Interface::modes mode() const { assert(_object); return _object->_mode; }
|
||||
inline uint32_t bitrate() const { assert(_object); return _object->_bitrate; }
|
||||
inline uint64_t announce_allowed_at() const { assert(_object); return _object->_announce_allowed_at; }
|
||||
inline void announce_allowed_at(uint64_t announce_allowed_at) { assert(_object); _object->_announce_allowed_at = announce_allowed_at; }
|
||||
@ -132,7 +113,7 @@ namespace RNS {
|
||||
size_t _txb = 0;
|
||||
bool online = false;
|
||||
Bytes _ifac_identity;
|
||||
modes _mode = MODE_NONE;
|
||||
Type::Interface::modes _mode = Type::Interface::MODE_NONE;
|
||||
uint32_t _bitrate = 0;
|
||||
uint64_t _announce_allowed_at = 0;
|
||||
float _announce_cap = 0.0;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "Log.h"
|
||||
|
||||
using namespace RNS;
|
||||
using namespace RNS::Type::Link;
|
||||
|
||||
Link::Link() : _object(new Object()) {
|
||||
assert(_object);
|
||||
|
59
src/Link.h
59
src/Link.h
@ -5,7 +5,7 @@
|
||||
// CBA TODO resolve circular dependency with following header file
|
||||
//#include "Packet.h"
|
||||
#include "Bytes.h"
|
||||
#include "None.h"
|
||||
#include "Type.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@ -20,63 +20,8 @@ namespace RNS {
|
||||
typedef void (*closed)(Link *link);
|
||||
};
|
||||
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
static constexpr const char* CURVE = Identity::CURVE;
|
||||
// The curve used for Elliptic Curve DH key exchanges
|
||||
|
||||
static const uint16_t ECPUBSIZE = 32+32;
|
||||
static const uint8_t KEYSIZE = 32;
|
||||
|
||||
//static const uint16_t MDU = floor((Reticulum::MTU-Reticulum::IFAC_MIN_SIZE-Reticulum::HEADER_MINSIZE-Identity::FERNET_OVERHEAD)/Identity::AES128_BLOCKSIZE)*Identity::AES128_BLOCKSIZE - 1;
|
||||
static const uint16_t MDU = ((Reticulum::MTU-Reticulum::IFAC_MIN_SIZE-Reticulum::HEADER_MINSIZE-Identity::FERNET_OVERHEAD)/Identity::AES128_BLOCKSIZE)*Identity::AES128_BLOCKSIZE - 1;
|
||||
|
||||
static const uint8_t ESTABLISHMENT_TIMEOUT_PER_HOP = Reticulum::DEFAULT_PER_HOP_TIMEOUT;
|
||||
// Timeout for link establishment in seconds per hop to destination.
|
||||
|
||||
static const uint16_t TRAFFIC_TIMEOUT_FACTOR = 6;
|
||||
static const uint16_t KEEPALIVE_TIMEOUT_FACTOR = 4;
|
||||
// RTT timeout factor used in link timeout calculation.
|
||||
static const uint8_t STALE_GRACE = 2;
|
||||
// Grace period in seconds used in link timeout calculation.
|
||||
static const uint16_t KEEPALIVE = 360;
|
||||
// Interval for sending keep-alive packets on established links in seconds.
|
||||
static const uint16_t STALE_TIME = 2*KEEPALIVE;
|
||||
/*
|
||||
If no traffic or keep-alive packets are received within this period, the
|
||||
link will be marked as stale, and a final keep-alive packet will be sent.
|
||||
If after this no traffic or keep-alive packets are received within ``RTT`` *
|
||||
``KEEPALIVE_TIMEOUT_FACTOR`` + ``STALE_GRACE``, the link is considered timed out,
|
||||
and will be torn down.
|
||||
*/
|
||||
|
||||
enum status {
|
||||
PENDING = 0x00,
|
||||
HANDSHAKE = 0x01,
|
||||
ACTIVE = 0x02,
|
||||
STALE = 0x03,
|
||||
CLOSED = 0x04
|
||||
};
|
||||
|
||||
enum teardown_reasons {
|
||||
TIMEOUT = 0x01,
|
||||
INITIATOR_CLOSED = 0x02,
|
||||
DESTINATION_CLOSED = 0x03,
|
||||
};
|
||||
|
||||
enum resource_strategies {
|
||||
ACCEPT_NONE = 0x00,
|
||||
ACCEPT_APP = 0x01,
|
||||
ACCEPT_ALL = 0x02,
|
||||
};
|
||||
|
||||
public:
|
||||
Link(NoneConstructor none) {
|
||||
extreme("Link NONE object created");
|
||||
}
|
||||
Link(RNS::NoneConstructor none) {
|
||||
Link(Type::NoneConstructor none) {
|
||||
extreme("Link NONE object created");
|
||||
}
|
||||
Link(const Link &link) : _object(link._object) {
|
||||
|
10
src/None.h
10
src/None.h
@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace RNS {
|
||||
|
||||
// generic empty object constructor type
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
}
|
@ -7,14 +7,16 @@
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace RNS;
|
||||
using namespace RNS::Type::PacketReceipt;
|
||||
using namespace RNS::Type::Packet;
|
||||
|
||||
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*/, Type::Transport::types transport_type /*= Type::Transport::BROADCAST*/, header_types header_type /*= HEADER_1*/, const Bytes &transport_id /*= {Bytes::NONE}*/, bool create_receipt /*= true*/) : _object(new Object(destination, attached_interface)) {
|
||||
|
||||
if (_object->_destination) {
|
||||
extreme("Creating packet with destination...");
|
||||
// CBA TODO handle NONE
|
||||
if (transport_type == -1) {
|
||||
transport_type = Transport::BROADCAST;
|
||||
transport_type = Type::Transport::BROADCAST;
|
||||
}
|
||||
// following moved to object constructor to avoid extra NONE object
|
||||
//_destination = destination;
|
||||
@ -50,7 +52,7 @@ uint8_t Packet::get_packed_flags() {
|
||||
assert(_object);
|
||||
uint8_t packed_flags = 0;
|
||||
if (_object->_context == LRPROOF) {
|
||||
packed_flags = (_object->_header_type << 6) | (_object->_transport_type << 4) | (Destination::LINK << 2) | _object->_packet_type;
|
||||
packed_flags = (_object->_header_type << 6) | (_object->_transport_type << 4) | (Type::Destination::LINK << 2) | _object->_packet_type;
|
||||
}
|
||||
else {
|
||||
packed_flags = (_object->_header_type << 6) | (_object->_transport_type << 4) | (_object->_destination.type() << 2) | _object->_packet_type;
|
||||
@ -61,8 +63,8 @@ uint8_t Packet::get_packed_flags() {
|
||||
void Packet::unpack_flags(uint8_t flags) {
|
||||
assert(_object);
|
||||
_object->_header_type = static_cast<header_types>((flags & 0b01000000) >> 6);
|
||||
_object->_transport_type = static_cast<Transport::types>((flags & 0b00110000) >> 4);
|
||||
_object->_destination_type = static_cast<Destination::types>((flags & 0b00001100) >> 2);
|
||||
_object->_transport_type = static_cast<Type::Transport::types>((flags & 0b00110000) >> 4);
|
||||
_object->_destination_type = static_cast<Type::Destination::types>((flags & 0b00001100) >> 2);
|
||||
_object->_packet_type = static_cast<types>(flags & 0b00000011);
|
||||
}
|
||||
|
||||
@ -267,7 +269,7 @@ void Packet::pack() {
|
||||
// Resource proofs are not encrypted
|
||||
_object->_raw << _object->_data;
|
||||
}
|
||||
else if (_object->_packet_type == PROOF && _object->_destination.type() == Destination::LINK) {
|
||||
else if (_object->_packet_type == PROOF && _object->_destination.type() == Type::Destination::LINK) {
|
||||
// Packet proofs over links are not encrypted
|
||||
_object->_raw << _object->_data;
|
||||
}
|
||||
@ -321,8 +323,8 @@ bool Packet::unpack() {
|
||||
assert(_object);
|
||||
debug("Packet::unpack: unpacking packet...");
|
||||
try {
|
||||
if (_object->_raw.size() < Reticulum::HEADER_MINSIZE) {
|
||||
throw std::length_error("Packet size of " + std::to_string(_object->_raw.size()) + " does not meet minimum header size of " + std::to_string(Reticulum::HEADER_MINSIZE) +" bytes");
|
||||
if (_object->_raw.size() < Type::Reticulum::HEADER_MINSIZE) {
|
||||
throw std::length_error("Packet size of " + std::to_string(_object->_raw.size()) + " does not meet minimum header size of " + std::to_string(Type::Reticulum::HEADER_MINSIZE) +" bytes");
|
||||
}
|
||||
|
||||
const uint8_t *raw = _object->_raw.data();
|
||||
@ -340,21 +342,21 @@ bool Packet::unpack() {
|
||||
}
|
||||
|
||||
if (_object->_header_type == HEADER_2) {
|
||||
if (_object->_raw.size() < Reticulum::HEADER_MAXSIZE) {
|
||||
throw std::length_error("Packet size of " + std::to_string(_object->_raw.size()) + " does not meet minimum header size of " + std::to_string(Reticulum::HEADER_MAXSIZE) +" bytes");
|
||||
if (_object->_raw.size() < Type::Reticulum::HEADER_MAXSIZE) {
|
||||
throw std::length_error("Packet size of " + std::to_string(_object->_raw.size()) + " does not meet minimum header size of " + std::to_string(Type::Reticulum::HEADER_MAXSIZE) +" bytes");
|
||||
}
|
||||
_object->_transport_id.assign(raw+2, Reticulum::DESTINATION_LENGTH);
|
||||
_object->_destination_hash.assign(raw+Reticulum::DESTINATION_LENGTH+2, Reticulum::DESTINATION_LENGTH);
|
||||
_object->_context = static_cast<context_types>(raw[2*Reticulum::DESTINATION_LENGTH+2]);
|
||||
_object->_data.assign(raw+2*Reticulum::DESTINATION_LENGTH+3, _object->_raw.size()-(2*Reticulum::DESTINATION_LENGTH+3));
|
||||
_object->_transport_id.assign(raw+2, Type::Reticulum::DESTINATION_LENGTH);
|
||||
_object->_destination_hash.assign(raw+Type::Reticulum::DESTINATION_LENGTH+2, Type::Reticulum::DESTINATION_LENGTH);
|
||||
_object->_context = static_cast<context_types>(raw[2*Type::Reticulum::DESTINATION_LENGTH+2]);
|
||||
_object->_data.assign(raw+2*Type::Reticulum::DESTINATION_LENGTH+3, _object->_raw.size()-(2*Type::Reticulum::DESTINATION_LENGTH+3));
|
||||
// uknown at this point whether data is encrypted or not
|
||||
_object->_encrypted = true;
|
||||
}
|
||||
else {
|
||||
_object->_transport_id.clear();
|
||||
_object->_destination_hash.assign(raw+2, Reticulum::DESTINATION_LENGTH);
|
||||
_object->_context = static_cast<context_types>(raw[Reticulum::DESTINATION_LENGTH+2]);
|
||||
_object->_data.assign(raw+Reticulum::DESTINATION_LENGTH+3, _object->_raw.size()-(Reticulum::DESTINATION_LENGTH+3));
|
||||
_object->_destination_hash.assign(raw+2, Type::Reticulum::DESTINATION_LENGTH);
|
||||
_object->_context = static_cast<context_types>(raw[Type::Reticulum::DESTINATION_LENGTH+2]);
|
||||
_object->_data.assign(raw+Type::Reticulum::DESTINATION_LENGTH+3, _object->_raw.size()-(Type::Reticulum::DESTINATION_LENGTH+3));
|
||||
// uknown at this point whether data is encrypted or not
|
||||
_object->_encrypted = true;
|
||||
}
|
||||
@ -383,7 +385,7 @@ bool Packet::send() {
|
||||
}
|
||||
/*
|
||||
if (_destination->type == RNS::Destination::LINK) {
|
||||
if (_destination->status == RNS::Link::CLOSED) {
|
||||
if (_destination->status == Type::Link::CLOSED) {
|
||||
throw std::runtime_error("Attempt to transmit over a closed link");
|
||||
}
|
||||
else {
|
||||
@ -398,7 +400,7 @@ bool Packet::send() {
|
||||
pack();
|
||||
}
|
||||
|
||||
if (RNS::Transport::outbound(*this)) {
|
||||
if (Transport::outbound(*this)) {
|
||||
debug("Packet::send: successfully sent packet!!!");
|
||||
//zreturn self.receipt
|
||||
// MOCK
|
||||
@ -427,7 +429,7 @@ bool Packet::resend() {
|
||||
// encrypted destinations
|
||||
pack();
|
||||
|
||||
if (RNS::Transport::outbound(*this)) {
|
||||
if (Transport::outbound(*this)) {
|
||||
debug("Packet::resend: successfully sent packet!!!");
|
||||
//zreturn self.receipt
|
||||
// MOCK
|
||||
@ -441,7 +443,7 @@ bool Packet::resend() {
|
||||
}
|
||||
}
|
||||
|
||||
void Packet::prove(const Destination &destination /*= {Destination::NONE}*/) {
|
||||
void Packet::prove(const Destination &destination /*= {Type::NONE}*/) {
|
||||
/*
|
||||
assert(_object);
|
||||
if (_object->_fromPacked && _object->_destination) {
|
||||
@ -479,9 +481,9 @@ const Bytes Packet::get_hashable_part() const {
|
||||
assert(_object);
|
||||
Bytes hashable_part;
|
||||
hashable_part << (uint8_t)(_object->_raw.data()[0] & 0b00001111);
|
||||
if (_object->_header_type == Packet::HEADER_2) {
|
||||
if (_object->_header_type == HEADER_2) {
|
||||
//hashable_part += self.raw[(RNS.Identity.TRUNCATED_HASHLENGTH//8)+2:]
|
||||
hashable_part << _object->_raw.mid((Identity::TRUNCATED_HASHLENGTH/8)+2);
|
||||
hashable_part << _object->_raw.mid((Type::Identity::TRUNCATED_HASHLENGTH/8)+2);
|
||||
}
|
||||
else {
|
||||
//hashable_part += self.raw[2:];
|
||||
@ -517,14 +519,14 @@ std::string Packet::debugString() const {
|
||||
dump += "data: " + _object->_data.toHex() + "\n";
|
||||
dump += " length: " + std::to_string(_object->_data.size()) + "\n";
|
||||
if (_object->_encrypted && _object->_raw.size() > 0) {
|
||||
size_t header_len = Reticulum::HEADER_MINSIZE;
|
||||
size_t header_len = Type::Reticulum::HEADER_MINSIZE;
|
||||
if (_object->_header_type == HEADER_2) {
|
||||
header_len = Reticulum::HEADER_MAXSIZE;
|
||||
header_len = Type::Reticulum::HEADER_MAXSIZE;
|
||||
}
|
||||
dump += "encrypted:\n";
|
||||
dump += " header: " + _object->_raw.left(header_len).toHex() + "\n";
|
||||
dump += " key: " + _object->_raw.mid(header_len, Identity::KEYSIZE/8/2).toHex() + "\n";
|
||||
Bytes ciphertext(_object->_raw.mid(header_len+Identity::KEYSIZE/8/2));
|
||||
dump += " key: " + _object->_raw.mid(header_len, Type::Identity::KEYSIZE/8/2).toHex() + "\n";
|
||||
Bytes ciphertext(_object->_raw.mid(header_len+Type::Identity::KEYSIZE/8/2));
|
||||
dump += " ciphertext: " + ciphertext.toHex() + "\n";
|
||||
dump += " length: " + std::to_string(ciphertext.size()) + "\n";
|
||||
dump += " iv: " + ciphertext.left(16).toHex() + "\n";
|
||||
|
140
src/Packet.h
140
src/Packet.h
@ -2,12 +2,12 @@
|
||||
|
||||
#include "Transport.h"
|
||||
#include "Reticulum.h"
|
||||
#include "Link.h"
|
||||
//#include "Link.h"
|
||||
#include "Identity.h"
|
||||
#include "Destination.h"
|
||||
#include "None.h"
|
||||
#include "Interfaces/Interface.h"
|
||||
#include "Utilities/OS.h"
|
||||
#include "Type.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
@ -43,23 +43,8 @@ namespace RNS {
|
||||
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(Type::NoneConstructor none) {}
|
||||
PacketReceipt(const PacketReceipt &packet_receipt) : _object(packet_receipt._object) {}
|
||||
PacketReceipt() : _object(new Object()) {}
|
||||
PacketReceipt(const Packet &packet) {}
|
||||
@ -119,14 +104,14 @@ namespace RNS {
|
||||
Object() {}
|
||||
virtual ~Object() {}
|
||||
private:
|
||||
bool _sent = true;
|
||||
uint64_t _sent_at = Utilities::OS::time();
|
||||
bool _proved = false;
|
||||
Status _status = SENT;
|
||||
Destination _destination = Destination::NONE;
|
||||
bool _sent = true;
|
||||
uint64_t _sent_at = Utilities::OS::time();
|
||||
bool _proved = false;
|
||||
Type::PacketReceipt::Status _status = Type::PacketReceipt::SENT;
|
||||
Destination _destination = {Type::NONE};
|
||||
Callbacks _callbacks;
|
||||
uint64_t _concluded_at = 0;
|
||||
//zPacket _proof_packet;
|
||||
uint64_t _concluded_at = 0;
|
||||
//z Packet _proof_packet;
|
||||
int16_t _timeout = 0;
|
||||
friend class PacketReceipt;
|
||||
};
|
||||
@ -138,81 +123,18 @@ namespace RNS {
|
||||
class Packet {
|
||||
|
||||
public:
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
// Packet types
|
||||
enum types {
|
||||
DATA = 0x00, // Data packets
|
||||
ANNOUNCE = 0x01, // Announces
|
||||
LINKREQUEST = 0x02, // Link requests
|
||||
PROOF = 0x03, // Proofs
|
||||
};
|
||||
|
||||
// Header types
|
||||
enum header_types {
|
||||
HEADER_1 = 0x00, // Normal header format
|
||||
HEADER_2 = 0x01, // Header format used for packets in transport
|
||||
};
|
||||
|
||||
// Packet context types
|
||||
enum context_types {
|
||||
CONTEXT_NONE = 0x00, // Generic data packet
|
||||
RESOURCE = 0x01, // Packet is part of a resource
|
||||
RESOURCE_ADV = 0x02, // Packet is a resource advertisement
|
||||
RESOURCE_REQ = 0x03, // Packet is a resource part request
|
||||
RESOURCE_HMU = 0x04, // Packet is a resource hashmap update
|
||||
RESOURCE_PRF = 0x05, // Packet is a resource proof
|
||||
RESOURCE_ICL = 0x06, // Packet is a resource initiator cancel message
|
||||
RESOURCE_RCL = 0x07, // Packet is a resource receiver cancel message
|
||||
CACHE_REQUEST = 0x08, // Packet is a cache request
|
||||
REQUEST = 0x09, // Packet is a request
|
||||
RESPONSE = 0x0A, // Packet is a response to a request
|
||||
PATH_RESPONSE = 0x0B, // Packet is a response to a path request
|
||||
COMMAND = 0x0C, // Packet is a command
|
||||
COMMAND_STATUS = 0x0D, // Packet is a status of an executed command
|
||||
CHANNEL = 0x0E, // Packet contains link channel data
|
||||
KEEPALIVE = 0xFA, // Packet is a keepalive packet
|
||||
LINKIDENTIFY = 0xFB, // Packet is a link peer identification proof
|
||||
LINKCLOSE = 0xFC, // Packet is a link close message
|
||||
LINKPROOF = 0xFD, // Packet is a link packet proof
|
||||
LRRTT = 0xFE, // Packet is a link request round-trip time measurement
|
||||
LRPROOF = 0xFF, // Packet is a link request proof
|
||||
};
|
||||
|
||||
// This is used to calculate allowable
|
||||
// payload sizes
|
||||
static const uint16_t HEADER_MAXSIZE = Reticulum::HEADER_MAXSIZE;
|
||||
static const uint16_t MDU = Reticulum::MDU;
|
||||
|
||||
// With an MTU of 500, the maximum of data we can
|
||||
// send in a single encrypted packet is given by
|
||||
// the below calculation; 383 bytes.
|
||||
//static const uint16_t ENCRYPTED_MDU = floor((Reticulum::MDU-Identity::FERNET_OVERHEAD-Identity::KEYSIZE/16)/Identity::AES128_BLOCKSIZE)*Identity::AES128_BLOCKSIZE - 1;
|
||||
//static const uint16_t ENCRYPTED_MDU;
|
||||
static const uint16_t ENCRYPTED_MDU = ((Reticulum::MDU-Identity::FERNET_OVERHEAD-Identity::KEYSIZE/16)/Identity::AES128_BLOCKSIZE)*Identity::AES128_BLOCKSIZE - 1;
|
||||
// The maximum size of the payload data in a single encrypted packet
|
||||
static const uint16_t PLAIN_MDU = MDU;
|
||||
// The maximum size of the payload data in a single unencrypted packet
|
||||
|
||||
static const uint8_t TIMEOUT_PER_HOP = Reticulum::DEFAULT_PER_HOP_TIMEOUT;
|
||||
|
||||
//static constexpr const uint8_t EMPTY_DESTINATION[Reticulum::DESTINATION_LENGTH] = {0};
|
||||
uint8_t EMPTY_DESTINATION[Reticulum::DESTINATION_LENGTH] = {0};
|
||||
//static constexpr const uint8_t EMPTY_DESTINATION[Type::Reticulum::DESTINATION_LENGTH] = {0};
|
||||
uint8_t EMPTY_DESTINATION[Type::Reticulum::DESTINATION_LENGTH] = {0};
|
||||
|
||||
public:
|
||||
Packet(NoneConstructor none) {
|
||||
extreme("Packet NONE object created");
|
||||
}
|
||||
Packet(RNS::NoneConstructor none) {
|
||||
Packet(Type::NoneConstructor none) {
|
||||
extreme("Packet NONE object created");
|
||||
}
|
||||
Packet(const Packet &packet) : _object(packet._object) {
|
||||
extreme("Packet object copy created");
|
||||
}
|
||||
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(const Destination &destination, const Interface &attached_interface, const Bytes &data, Type::Packet::types packet_type = Type::Packet::DATA, Type::Packet::context_types context = Type::Packet::CONTEXT_NONE, Type::Transport::types transport_type = Type::Transport::BROADCAST, Type::Packet::header_types header_type = Type::Packet::HEADER_1, const Bytes &transport_id = {Bytes::NONE}, bool create_receipt = true);
|
||||
Packet(const Destination &destination, const Bytes &data, Type::Packet::types packet_type = Type::Packet::DATA, Type::Packet::context_types context = Type::Packet::CONTEXT_NONE, Type::Transport::types transport_type = Type::Transport::BROADCAST, Type::Packet::header_types header_type = Type::Packet::HEADER_1, const Bytes &transport_id = {Bytes::NONE}, bool create_receipt = true) : Packet(destination, {Type::NONE}, data, packet_type, context, transport_type, header_type, transport_id, create_receipt) {}
|
||||
virtual ~Packet();
|
||||
|
||||
inline Packet& operator = (const Packet &packet) {
|
||||
@ -242,7 +164,7 @@ namespace RNS {
|
||||
bool unpack();
|
||||
bool send();
|
||||
bool resend();
|
||||
void prove(const Destination &destination = Destination::NONE);
|
||||
void prove(const Destination &destination = {Type::NONE});
|
||||
void update_hash();
|
||||
const Bytes get_hash() const;
|
||||
const Bytes getTruncatedHash() const;
|
||||
@ -257,11 +179,11 @@ namespace RNS {
|
||||
inline const Interface &attached_interface() const { assert(_object); return _object->_attached_interface; }
|
||||
inline const Interface &receiving_interface() const { assert(_object); return _object->_receiving_interface; }
|
||||
inline void receiving_interface(const Interface &receiving_interface) { assert(_object); _object->_receiving_interface = receiving_interface; }
|
||||
inline header_types header_type() const { assert(_object); return _object->_header_type; }
|
||||
inline Transport::types transport_type() const { assert(_object); return _object->_transport_type; }
|
||||
inline Destination::types destination_type() const { assert(_object); return _object->_destination_type; }
|
||||
inline types packet_type() const { assert(_object); return _object->_packet_type; }
|
||||
inline context_types context() const { assert(_object); return _object->_context; }
|
||||
inline Type::Packet::header_types header_type() const { assert(_object); return _object->_header_type; }
|
||||
inline Type::Transport::types transport_type() const { assert(_object); return _object->_transport_type; }
|
||||
inline Type::Destination::types destination_type() const { assert(_object); return _object->_destination_type; }
|
||||
inline Type::Packet::types packet_type() const { assert(_object); return _object->_packet_type; }
|
||||
inline Type::Packet::context_types context() const { assert(_object); return _object->_context; }
|
||||
inline bool sent() const { assert(_object); return _object->_sent; }
|
||||
inline void sent(bool sent) { assert(_object); _object->_sent = sent; }
|
||||
inline time_t sent_at() const { assert(_object); return _object->_sent_at; }
|
||||
@ -289,17 +211,17 @@ namespace RNS {
|
||||
Object(const Destination &destination, const Interface &attached_interface) : _destination(destination), _attached_interface(attached_interface) {}
|
||||
virtual ~Object() {}
|
||||
private:
|
||||
Destination _destination = {Destination::NONE};
|
||||
Link _link = {Link::NONE};
|
||||
Destination _destination = {Type::NONE};
|
||||
Link _link = {Type::NONE};
|
||||
|
||||
Interface _attached_interface = {Interface::NONE};
|
||||
Interface _receiving_interface = {Interface::NONE};
|
||||
Interface _attached_interface = {Type::NONE};
|
||||
Interface _receiving_interface = {Type::NONE};
|
||||
|
||||
header_types _header_type = HEADER_1;
|
||||
Transport::types _transport_type = Transport::BROADCAST;
|
||||
Destination::types _destination_type = Destination::SINGLE;
|
||||
types _packet_type = DATA;
|
||||
context_types _context = CONTEXT_NONE;
|
||||
Type::Packet::header_types _header_type = Type::Packet::HEADER_1;
|
||||
Type::Transport::types _transport_type = Type::Transport::BROADCAST;
|
||||
Type::Destination::types _destination_type = Type::Destination::SINGLE;
|
||||
Type::Packet::types _packet_type = Type::Packet::DATA;
|
||||
Type::Packet::context_types _context = Type::Packet::CONTEXT_NONE;
|
||||
|
||||
uint8_t _flags = 0;
|
||||
uint8_t _hops = 0;
|
||||
@ -312,7 +234,7 @@ namespace RNS {
|
||||
bool _encrypted = false; // whether data is encrytpted
|
||||
PacketReceipt _receipt;
|
||||
|
||||
uint16_t _mtu = Reticulum::MTU;
|
||||
uint16_t _mtu = Type::Reticulum::MTU;
|
||||
time_t _sent_at = 0;
|
||||
|
||||
float _rssi = 0.0;
|
||||
|
@ -6,6 +6,12 @@
|
||||
#include <RNG.h>
|
||||
|
||||
using namespace RNS;
|
||||
using namespace RNS::Type::Reticulum;
|
||||
|
||||
/*static*/ bool Reticulum::__transport_enabled = false;
|
||||
/*static*/ bool Reticulum::__use_implicit_proof = true;
|
||||
/*static*/ bool Reticulum::__allow_probes = false;
|
||||
/*static*/ bool Reticulum::panic_on_interface_error = false;
|
||||
|
||||
/*
|
||||
Initialises and starts a Reticulum instance. This must be
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Log.h"
|
||||
#include "None.h"
|
||||
#include "Type.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
@ -12,85 +12,13 @@ namespace RNS {
|
||||
class Reticulum {
|
||||
|
||||
public:
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
// Future minimum will probably be locked in at 251 bytes to support
|
||||
// networks with segments of different MTUs. Absolute minimum is 219.
|
||||
static const uint16_t MTU = 500;
|
||||
/*
|
||||
The MTU that Reticulum adheres to, and will expect other peers to
|
||||
adhere to. By default, the MTU is 507 bytes. In custom RNS network
|
||||
implementations, it is possible to change this value, but doing so will
|
||||
completely break compatibility with all other RNS networks. An identical
|
||||
MTU is a prerequisite for peers to communicate in the same network.
|
||||
|
||||
Unless you really know what you are doing, the MTU should be left at
|
||||
the default value.
|
||||
*/
|
||||
|
||||
static const uint16_t MAX_QUEUED_ANNOUNCES = 16384;
|
||||
static const uint32_t QUEUED_ANNOUNCE_LIFE = 60*60*24;
|
||||
|
||||
static const uint8_t ANNOUNCE_CAP = 2;
|
||||
/*
|
||||
The maximum percentage of interface bandwidth that, at any given time,
|
||||
may be used to propagate announces. If an announce was scheduled for
|
||||
broadcasting on an interface, but doing so would exceed the allowed
|
||||
bandwidth allocation, the announce will be queued for transmission
|
||||
when there is bandwidth available.
|
||||
|
||||
Reticulum will always prioritise propagating announces with fewer
|
||||
hops, ensuring that distant, large networks with many peers on fast
|
||||
links don't overwhelm the capacity of smaller networks on slower
|
||||
mediums. If an announce remains queued for an extended amount of time,
|
||||
it will eventually be dropped.
|
||||
|
||||
This value will be applied by default to all created interfaces,
|
||||
but it can be configured individually on a per-interface basis.
|
||||
*/
|
||||
|
||||
static const uint16_t MINIMUM_BITRATE = 500;
|
||||
|
||||
// TODO: To reach the 300bps level without unreasonably impacting
|
||||
// performance on faster links, we need a mechanism for setting
|
||||
// this value more intelligently. One option could be inferring it
|
||||
// from interface speed, but a better general approach would most
|
||||
// probably be to let Reticulum somehow continously build a map of
|
||||
// per-hop latencies and use this map for the timeout calculation.
|
||||
static const uint8_t DEFAULT_PER_HOP_TIMEOUT = 6;
|
||||
|
||||
static const uint16_t HASHLENGTH = 256; // In bits
|
||||
// Length of truncated hashes in bits.
|
||||
static const uint16_t TRUNCATED_HASHLENGTH = 128; // In bits
|
||||
|
||||
static const uint16_t HEADER_MINSIZE = 2+1+(TRUNCATED_HASHLENGTH/8)*1; // In bytes
|
||||
static const uint16_t HEADER_MAXSIZE = 2+1+(TRUNCATED_HASHLENGTH/8)*2; // In bytes
|
||||
static const uint16_t IFAC_MIN_SIZE = 1;
|
||||
//zIFAC_SALT = bytes.fromhex("adf54d882c9a9b80771eb4995d702d4a3e733391b2a0f53f416d9f907e55cff8")
|
||||
|
||||
static const uint16_t MDU = MTU - HEADER_MAXSIZE - IFAC_MIN_SIZE;
|
||||
|
||||
static const uint32_t RESOURCE_CACHE = 24*60*60;
|
||||
static const uint16_t JOB_INTERVAL = 5*60;
|
||||
static const uint16_t CLEAN_INTERVAL = 15*60;
|
||||
static const uint16_t PERSIST_INTERVAL = 60*60*12;
|
||||
static const uint16_t GRACIOUS_PERSIST_INTERVAL = 60*5;
|
||||
|
||||
static const uint8_t DESTINATION_LENGTH = TRUNCATED_HASHLENGTH/8; // In bytes
|
||||
|
||||
static const bool __transport_enabled = false;
|
||||
static const bool __use_implicit_proof = true;
|
||||
static const bool __allow_probes = false;
|
||||
|
||||
static const bool panic_on_interface_error = false;
|
||||
static bool __transport_enabled;
|
||||
static bool __use_implicit_proof;
|
||||
static bool __allow_probes;
|
||||
static bool panic_on_interface_error;
|
||||
|
||||
public:
|
||||
Reticulum(NoneConstructor none) {
|
||||
extreme("Reticulum NONE object created");
|
||||
}
|
||||
Reticulum(RNS::NoneConstructor none) {
|
||||
Reticulum(Type::NoneConstructor none) {
|
||||
extreme("Reticulum NONE object created");
|
||||
}
|
||||
Reticulum(const Reticulum &reticulum) : _object(reticulum._object) {
|
||||
|
@ -183,7 +183,7 @@ void testBytes() {
|
||||
|
||||
// test creating bytes from NONE
|
||||
{
|
||||
RNS::Bytes bytes(RNS::Bytes::NONE);
|
||||
RNS::Bytes bytes({RNS::Bytes::NONE});
|
||||
assert(!bytes);
|
||||
assert(bytes.size() == 0);
|
||||
assert(bytes.data() == nullptr);
|
||||
|
@ -18,7 +18,7 @@ void testCrypto() {
|
||||
|
||||
RNS::Identity identity;
|
||||
|
||||
RNS::Destination destination(identity, RNS::Destination::IN, RNS::Destination::SINGLE, "appname", "aspects");
|
||||
RNS::Destination destination(identity, RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "appname", "aspects");
|
||||
//assert(encryptionPrivateKey().toHex().compare("") == );
|
||||
//assert(signingPrivateKey().toHex().compare("") == );
|
||||
//assert(encryptionPublicKey().toHex().compare("") == );
|
||||
|
@ -10,7 +10,7 @@ void testReference() {
|
||||
RNS::Reticulum reticulum_default;
|
||||
assert(reticulum_default);
|
||||
|
||||
RNS::Reticulum reticulum_none(RNS::Reticulum::NONE);
|
||||
RNS::Reticulum reticulum_none({RNS::Type::NONE});
|
||||
assert(!reticulum_none);
|
||||
|
||||
RNS::Reticulum reticulum_default_copy(reticulum_default);
|
||||
|
@ -54,8 +54,8 @@ using namespace RNS::Utilities;
|
||||
/*static*/ uint64_t Transport::_tables_last_culled = 0;
|
||||
/*static*/ uint32_t Transport::_tables_cull_interval = 5000;
|
||||
|
||||
/*static*/ Reticulum Transport::_owner(Reticulum::NONE);
|
||||
/*static*/ Identity Transport::_identity(Identity::NONE);
|
||||
/*static*/ Reticulum Transport::_owner({Type::NONE});
|
||||
/*static*/ Identity Transport::_identity({Type::NONE});
|
||||
|
||||
/*static*/ void Transport::start(const Reticulum &reticulum_instance) {
|
||||
_jobs_running = true;
|
||||
@ -634,7 +634,7 @@ using namespace RNS::Utilities;
|
||||
|
||||
// Check if we have a known path for the destination in the path table
|
||||
//if packet.packet_type != RNS.Packet.ANNOUNCE and packet.destination.type != RNS.Destination.PLAIN and packet.destination.type != RNS.Destination.GROUP and packet.destination_hash in Transport.destination_table:
|
||||
if (packet.packet_type() != Packet::ANNOUNCE && packet.destination().type() != Destination::PLAIN && packet.destination().type() != Destination::GROUP && _destination_table.find(packet.destination_hash()) != _destination_table.end()) {
|
||||
if (packet.packet_type() != Type::Packet::ANNOUNCE && packet.destination().type() != Type::Destination::PLAIN && packet.destination().type() != Type::Destination::GROUP && _destination_table.find(packet.destination_hash()) != _destination_table.end()) {
|
||||
extreme("Transport::outbound: Path to destination is known");
|
||||
//outbound_interface = Transport.destination_table[packet.destination_hash][5]
|
||||
DestinationEntry destination_entry = (*_destination_table.find(packet.destination_hash())).second;
|
||||
@ -648,10 +648,10 @@ using namespace RNS::Utilities;
|
||||
//if Transport.destination_table[packet.destination_hash][2] > 1:
|
||||
if (destination_entry._hops > 1) {
|
||||
extreme("Forwarding packet to next closest interface...");
|
||||
if (packet.header_type() == Packet::HEADER_1) {
|
||||
if (packet.header_type() == Type::Packet::HEADER_1) {
|
||||
// Insert packet into transport
|
||||
//new_flags = (RNS.Packet.HEADER_2) << 6 | (Transport.TRANSPORT) << 4 | (packet.flags & 0b00001111)
|
||||
uint8_t new_flags = (Packet::HEADER_2) << 6 | (Transport::TRANSPORT) << 4 | (packet.flags() & 0b00001111);
|
||||
uint8_t new_flags = (Type::Packet::HEADER_2) << 6 | (Type::Transport::TRANSPORT) << 4 | (packet.flags() & 0b00001111);
|
||||
Bytes new_raw;
|
||||
//new_raw = struct.pack("!B", new_flags)
|
||||
new_raw << new_flags;
|
||||
@ -678,10 +678,10 @@ using namespace RNS::Utilities;
|
||||
//elif Transport.destination_table[packet.destination_hash][2] == 1 and Transport.owner.is_connected_to_shared_instance:
|
||||
else if (destination_entry._hops == 1 && _owner.is_connected_to_shared_instance()) {
|
||||
extreme("Transport::outbound: Sending packet for directly connected interface to shared instance...");
|
||||
if (packet.header_type() == Packet::HEADER_1) {
|
||||
if (packet.header_type() == Type::Packet::HEADER_1) {
|
||||
// Insert packet into transport
|
||||
//new_flags = (RNS.Packet.HEADER_2) << 6 | (Transport.TRANSPORT) << 4 | (packet.flags & 0b00001111)
|
||||
uint8_t new_flags = (Packet::HEADER_2) << 6 | (Transport::TRANSPORT) << 4 | (packet.flags() & 0b00001111);
|
||||
uint8_t new_flags = (Type::Packet::HEADER_2) << 6 | (Type::Transport::TRANSPORT) << 4 | (packet.flags() & 0b00001111);
|
||||
Bytes new_raw;
|
||||
//new_raw = struct.pack("!B", new_flags)
|
||||
new_raw << new_flags;
|
||||
@ -719,8 +719,8 @@ using namespace RNS::Utilities;
|
||||
if (interface.OUT()) {
|
||||
bool should_transmit = true;
|
||||
|
||||
if (packet.destination().type() == Destination::LINK) {
|
||||
if (packet.destination().status() == Link::CLOSED) {
|
||||
if (packet.destination().type() == Type::Destination::LINK) {
|
||||
if (packet.destination().status() == Type::Link::CLOSED) {
|
||||
should_transmit = false;
|
||||
}
|
||||
// CBA Destination has no member attached_interface
|
||||
@ -733,16 +733,16 @@ using namespace RNS::Utilities;
|
||||
should_transmit = false;
|
||||
}
|
||||
|
||||
if (packet.packet_type() == Packet::ANNOUNCE) {
|
||||
if (packet.packet_type() == Type::Packet::ANNOUNCE) {
|
||||
if (!packet.attached_interface()) {
|
||||
extreme("Transport::outbound: Packet has no attached interface");
|
||||
if (interface.mode() == Interface::MODE_ACCESS_POINT) {
|
||||
if (interface.mode() == Type::Interface::MODE_ACCESS_POINT) {
|
||||
extreme("Blocking announce broadcast on " + interface.toString() + " due to AP mode");
|
||||
should_transmit = false;
|
||||
}
|
||||
else if (interface.mode() == Interface::MODE_ROAMING) {
|
||||
else if (interface.mode() == Type::Interface::MODE_ROAMING) {
|
||||
//local_destination = next((d for d in Transport.destinations if d.hash == packet.destination_hash), None)
|
||||
//Destination local_destination(Destination::NONE);
|
||||
//Destination local_destination({Type::NONE});
|
||||
bool found_local = false;
|
||||
for (auto &destination : _destinations) {
|
||||
if (destination.hash() == packet.destination_hash()) {
|
||||
@ -759,34 +759,34 @@ using namespace RNS::Utilities;
|
||||
else {
|
||||
const Interface &from_interface = next_hop_interface(packet.destination_hash());
|
||||
//if from_interface == None or not hasattr(from_interface, "mode"):
|
||||
if (!from_interface || from_interface.mode() == Interface::MODE_NONE) {
|
||||
if (!from_interface || from_interface.mode() == Type::Interface::MODE_NONE) {
|
||||
should_transmit = false;
|
||||
if (!from_interface) {
|
||||
extreme("Blocking announce broadcast on " + interface.toString() + " since next hop interface doesn't exist");
|
||||
}
|
||||
else if (from_interface.mode() == Interface::MODE_NONE) {
|
||||
else if (from_interface.mode() == Type::Interface::MODE_NONE) {
|
||||
extreme("Blocking announce broadcast on " + interface.toString() + " since next hop interface has no mode configured");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (from_interface.mode() == Interface::MODE_ROAMING) {
|
||||
if (from_interface.mode() == Type::Interface::MODE_ROAMING) {
|
||||
extreme("Blocking announce broadcast on " + interface.toString() + " due to roaming-mode next-hop interface");
|
||||
should_transmit = false;
|
||||
}
|
||||
else if (from_interface.mode() == Interface::MODE_BOUNDARY) {
|
||||
else if (from_interface.mode() == Type::Interface::MODE_BOUNDARY) {
|
||||
extreme("Blocking announce broadcast on " + interface.toString() + " due to boundary-mode next-hop interface");
|
||||
should_transmit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (interface.mode() == Interface::MODE_BOUNDARY) {
|
||||
else if (interface.mode() == Type::Interface::MODE_BOUNDARY) {
|
||||
//local_destination = next((d for d in Transport.destinations if d.hash == packet.destination_hash), None)
|
||||
// next and filter pattern?
|
||||
// next(iterable, default)
|
||||
// list comprehension: [x for x in xyz if x in a]
|
||||
// CBA TODO confirm that above pattern just selects the first matching destination
|
||||
//Destination local_destination(Destination::NONE);
|
||||
//Destination local_destination({Typeestination::NONE});
|
||||
bool found_local = false;
|
||||
for (auto &destination : _destinations) {
|
||||
if (destination.hash() == packet.destination_hash()) {
|
||||
@ -802,17 +802,17 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
else {
|
||||
const Interface &from_interface = next_hop_interface(packet.destination_hash());
|
||||
if (!from_interface || from_interface.mode() == Interface::MODE_NONE) {
|
||||
if (!from_interface || from_interface.mode() == Type::Interface::MODE_NONE) {
|
||||
should_transmit = false;
|
||||
if (!from_interface) {
|
||||
extreme("Blocking announce broadcast on " + interface.toString() + " since next hop interface doesn't exist");
|
||||
}
|
||||
else if (from_interface.mode() == Interface::MODE_NONE) {
|
||||
else if (from_interface.mode() == Type::Interface::MODE_NONE) {
|
||||
extreme("Blocking announce broadcast on " + interface.toString() + " since next hop interface has no mode configured");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (from_interface.mode() == Interface::MODE_ROAMING) {
|
||||
if (from_interface.mode() == Type::Interface::MODE_ROAMING) {
|
||||
extreme("Blocking announce broadcast on " + interface.toString() + " due to roaming-mode next-hop interface");
|
||||
should_transmit = false;
|
||||
}
|
||||
@ -844,7 +844,7 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
else {
|
||||
should_transmit = false;
|
||||
if (interface.announce_queue().size() < Reticulum::MAX_QUEUED_ANNOUNCES) {
|
||||
if (interface.announce_queue().size() < Type::Reticulum::MAX_QUEUED_ANNOUNCES) {
|
||||
bool should_queue = true;
|
||||
for (auto &entry : interface.announce_queue()) {
|
||||
if (entry._destination == packet.destination_hash()) {
|
||||
@ -947,13 +947,13 @@ using namespace RNS::Utilities;
|
||||
// Don't generate receipt if it has been explicitly disabled
|
||||
if (packet.create_receipt() &&
|
||||
// Only generate receipts for DATA packets
|
||||
packet.packet_type() == Packet::DATA &&
|
||||
packet.packet_type() == Type::Packet::DATA &&
|
||||
// Don't generate receipts for PLAIN destinations
|
||||
packet.destination().type() != Destination::PLAIN &&
|
||||
packet.destination().type() != Type::Destination::PLAIN &&
|
||||
// Don't generate receipts for link-related packets
|
||||
!(packet.context() >= Packet::KEEPALIVE && packet.context() <= Packet::LRPROOF) &&
|
||||
!(packet.context() >= Type::Packet::KEEPALIVE && packet.context() <= Type::Packet::LRPROOF) &&
|
||||
// Don't generate receipts for resource packets
|
||||
!(packet.context() >= Packet::RESOURCE && packet.context() <= Packet::RESOURCE_RCL)) {
|
||||
!(packet.context() >= Type::Packet::RESOURCE && packet.context() <= Type::Packet::RESOURCE_RCL)) {
|
||||
|
||||
PacketReceipt receipt(packet);
|
||||
packet.receipt(receipt);
|
||||
@ -971,27 +971,27 @@ using namespace RNS::Utilities;
|
||||
// TODO: Think long and hard about this.
|
||||
// Is it even strictly necessary with the current
|
||||
// transport rules?
|
||||
if (packet.context() == Packet::KEEPALIVE) {
|
||||
if (packet.context() == Type::Packet::KEEPALIVE) {
|
||||
return true;
|
||||
}
|
||||
if (packet.context() == Packet::RESOURCE_REQ) {
|
||||
if (packet.context() == Type::Packet::RESOURCE_REQ) {
|
||||
return true;
|
||||
}
|
||||
if (packet.context() == Packet::RESOURCE_PRF) {
|
||||
if (packet.context() == Type::Packet::RESOURCE_PRF) {
|
||||
return true;
|
||||
}
|
||||
if (packet.context() == Packet::RESOURCE) {
|
||||
if (packet.context() == Type::Packet::RESOURCE) {
|
||||
return true;
|
||||
}
|
||||
if (packet.context() == Packet::CACHE_REQUEST) {
|
||||
if (packet.context() == Type::Packet::CACHE_REQUEST) {
|
||||
return true;
|
||||
}
|
||||
if (packet.context() == Packet::CHANNEL) {
|
||||
if (packet.context() == Type::Packet::CHANNEL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (packet.destination_type() == Destination::PLAIN) {
|
||||
if (packet.packet_type() != Packet::ANNOUNCE) {
|
||||
if (packet.destination_type() == Type::Destination::PLAIN) {
|
||||
if (packet.packet_type() != Type::Packet::ANNOUNCE) {
|
||||
if (packet.hops() > 1) {
|
||||
debug("Dropped PLAIN packet " + packet.packet_hash().toHex() + " with " + std::to_string(packet.hops()) + " hops");
|
||||
return false;
|
||||
@ -1006,8 +1006,8 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
}
|
||||
|
||||
if (packet.destination_type() == Destination::GROUP) {
|
||||
if (packet.packet_type() != Packet::ANNOUNCE) {
|
||||
if (packet.destination_type() == Type::Destination::GROUP) {
|
||||
if (packet.packet_type() != Type::Packet::ANNOUNCE) {
|
||||
if (packet.hops() > 1) {
|
||||
debug("Dropped GROUP packet " + packet.packet_hash().toHex() + " with " + std::to_string(packet.hops()) + " hops");
|
||||
return false;
|
||||
@ -1026,8 +1026,8 @@ using namespace RNS::Utilities;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (packet.packet_type() == Packet::ANNOUNCE) {
|
||||
if (packet.destination_type() == Destination::SINGLE) {
|
||||
if (packet.packet_type() == Type::Packet::ANNOUNCE) {
|
||||
if (packet.destination_type() == Type::Destination::SINGLE) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@ -1041,7 +1041,7 @@ using namespace RNS::Utilities;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*static*/ void Transport::inbound(const Bytes &raw, const Interface &interface /*= Interface::NONE*/) {
|
||||
/*static*/ void Transport::inbound(const Bytes &raw, const Interface &interface /*= {Type::NONE}*/) {
|
||||
extreme("Transport::inbound()");
|
||||
/*
|
||||
// If interface access codes are enabled,
|
||||
@ -1122,7 +1122,7 @@ using namespace RNS::Utilities;
|
||||
|
||||
_jobs_locked = true;
|
||||
|
||||
Packet packet(Destination::NONE, raw);
|
||||
Packet packet({Type::NONE}, raw);
|
||||
if (!packet.unpack()) {
|
||||
warning("Transport::inbound: Pscket unpack failed!");
|
||||
return;
|
||||
@ -1178,7 +1178,7 @@ using namespace RNS::Utilities;
|
||||
//for_local_client_link |= (packet.packet_type != RNS.Packet.ANNOUNCE) and (packet.destination_hash in Transport.link_table and Transport.link_table[packet.destination_hash][2] in Transport.local_client_interfaces)
|
||||
bool for_local_client = false;
|
||||
bool for_local_client_link = false;
|
||||
if (packet.packet_type() != Packet::ANNOUNCE) {
|
||||
if (packet.packet_type() != Type::Packet::ANNOUNCE) {
|
||||
auto destination_iter = _destination_table.find(packet.destination_hash());
|
||||
if (destination_iter != _destination_table.end()) {
|
||||
DestinationEntry destination_entry = (*destination_iter).second;
|
||||
@ -1211,7 +1211,7 @@ using namespace RNS::Utilities;
|
||||
// directly on all attached interfaces, since they are
|
||||
// never injected into transport.
|
||||
if (_control_hashes.find(packet.destination_hash()) == _control_hashes.end()) {
|
||||
if (packet.destination_type() == Destination::PLAIN && packet.transport_type() == Transport::BROADCAST) {
|
||||
if (packet.destination_type() == Type::Destination::PLAIN && packet.transport_type() == Type::Transport::BROADCAST) {
|
||||
// Send to all interfaces except the originator
|
||||
if (from_local_client) {
|
||||
for (const Interface &interface : _interfaces) {
|
||||
@ -1252,7 +1252,7 @@ using namespace RNS::Utilities;
|
||||
// If this is a cache request, and we can fullfill
|
||||
// it, do so and stop processing. Otherwise resume
|
||||
// normal processing.
|
||||
if (packet.context() == Packet::CACHE_REQUEST) {
|
||||
if (packet.context() == Type::Packet::CACHE_REQUEST) {
|
||||
if (cache_request_packet(packet)) {
|
||||
extreme("Transport::inbound: Cached packet");
|
||||
return;
|
||||
@ -1262,7 +1262,7 @@ using namespace RNS::Utilities;
|
||||
// If the packet is in transport, check whether we
|
||||
// are the designated next hop, and process it
|
||||
// accordingly if we are.
|
||||
if (packet.transport_id() && packet.packet_type() != Packet::ANNOUNCE) {
|
||||
if (packet.transport_id() && packet.packet_type() != Type::Packet::ANNOUNCE) {
|
||||
if (packet.transport_id() == _identity.hash()) {
|
||||
auto destination_iter = _destination_table.find(packet.destination_hash());
|
||||
if (destination_iter != _destination_table.end()) {
|
||||
@ -1280,18 +1280,18 @@ using namespace RNS::Utilities;
|
||||
//new_raw += next_hop
|
||||
new_raw << next_hop;
|
||||
//new_raw += packet.raw[(RNS.Identity.TRUNCATED_HASHLENGTH//8)+2:]
|
||||
new_raw << packet.raw().mid((Identity::TRUNCATED_HASHLENGTH/8)+2);
|
||||
new_raw << packet.raw().mid((Type::Identity::TRUNCATED_HASHLENGTH/8)+2);
|
||||
}
|
||||
else if (remaining_hops == 1) {
|
||||
// Strip transport headers and transmit
|
||||
//new_flags = (RNS.Packet.HEADER_1) << 6 | (Transport.BROADCAST) << 4 | (packet.flags & 0b00001111)
|
||||
uint8_t new_flags = (Packet::HEADER_1) << 6 | (Transport::BROADCAST) << 4 | (packet.flags() & 0b00001111);
|
||||
uint8_t new_flags = (Type::Packet::HEADER_1) << 6 | (Type::Transport::BROADCAST) << 4 | (packet.flags() & 0b00001111);
|
||||
//new_raw = struct.pack("!B", new_flags)
|
||||
new_raw << new_flags;
|
||||
//new_raw += struct.pack("!B", packet.hops)
|
||||
new_raw << packet.hops();
|
||||
//new_raw += packet.raw[(RNS.Identity.TRUNCATED_HASHLENGTH//8)+2:]
|
||||
new_raw << packet.raw().mid((Identity::TRUNCATED_HASHLENGTH/8)+2);
|
||||
new_raw << packet.raw().mid((Type::Identity::TRUNCATED_HASHLENGTH/8)+2);
|
||||
}
|
||||
else if (remaining_hops == 0) {
|
||||
// Just increase hop count and transmit
|
||||
@ -1305,9 +1305,9 @@ using namespace RNS::Utilities;
|
||||
|
||||
Interface &outbound_interface = destination_entry._receiving_interface;
|
||||
|
||||
if (packet.packet_type() == Packet::LINKREQUEST) {
|
||||
if (packet.packet_type() == Type::Packet::LINKREQUEST) {
|
||||
uint64_t now = OS::time();
|
||||
uint64_t proof_timeout = now + Link::ESTABLISHMENT_TIMEOUT_PER_HOP*1000 * std::max((uint8_t)1, remaining_hops);
|
||||
uint64_t proof_timeout = now + Type::Link::ESTABLISHMENT_TIMEOUT_PER_HOP*1000 * std::max((uint8_t)1, remaining_hops);
|
||||
LinkEntry link_entry(
|
||||
now,
|
||||
next_hop,
|
||||
@ -1343,14 +1343,14 @@ using namespace RNS::Utilities;
|
||||
|
||||
// Link transport handling. Directs packets according
|
||||
// to entries in the link tables
|
||||
if (packet.packet_type() != Packet::ANNOUNCE && packet.packet_type() != Packet::LINKREQUEST && packet.context() == Packet::LRPROOF) {
|
||||
if (packet.packet_type() != Type::Packet::ANNOUNCE && packet.packet_type() != Type::Packet::LINKREQUEST && packet.context() == Type::Packet::LRPROOF) {
|
||||
auto link_iter = _link_table.find(packet.destination_hash());
|
||||
if (link_iter != _link_table.end()) {
|
||||
LinkEntry link_entry = (*link_iter).second;
|
||||
// If receiving and outbound interface is
|
||||
// the same for this link, direction doesn't
|
||||
// matter, and we simply send the packet on.
|
||||
Interface outbound_interface(Interface::NONE);
|
||||
Interface outbound_interface({Type::NONE});
|
||||
if (link_entry._outbound_interface == link_entry._receiving_interface) {
|
||||
// But check that taken hops matches one
|
||||
// of the expectede values.
|
||||
@ -1397,11 +1397,11 @@ using namespace RNS::Utilities;
|
||||
// Announce handling. Handles logic related to incoming
|
||||
// announces, queueing rebroadcasts of these, and removal
|
||||
// of queued announce rebroadcasts once handed to the next node.
|
||||
if (packet.packet_type() == Packet::ANNOUNCE) {
|
||||
if (packet.packet_type() == Type::Packet::ANNOUNCE) {
|
||||
extreme("Transport::inbound: Packet is ANNOUNCE");
|
||||
Bytes received_from;
|
||||
//p local_destination = next((d for d in Transport.destinations if d.hash == packet.destination_hash), None)
|
||||
//Destination local_destination(Destination::NONE);
|
||||
//Destination local_destination({Type::NONE});
|
||||
bool found_local = false;
|
||||
for (auto &destination : _destinations) {
|
||||
if (destination.hash() == packet.destination_hash()) {
|
||||
@ -1585,15 +1585,15 @@ using namespace RNS::Utilities;
|
||||
uint8_t announce_hops = packet.hops();
|
||||
uint8_t local_rebroadcasts = 0;
|
||||
bool block_rebroadcasts = false;
|
||||
Interface attached_interface = Interface::NONE;
|
||||
Interface attached_interface = {Type::NONE};
|
||||
|
||||
uint64_t retransmit_timeout = now + (RNS::Cryptography::random() * Transport::PATHFINDER_RW);
|
||||
|
||||
uint64_t expires;
|
||||
if (packet.receiving_interface().mode() == Interface::MODE_ACCESS_POINT) {
|
||||
if (packet.receiving_interface().mode() == Type::Interface::MODE_ACCESS_POINT) {
|
||||
expires = now + Transport::AP_PATH_TIME;
|
||||
}
|
||||
else if (packet.receiving_interface().mode() == Interface::MODE_ROAMING) {
|
||||
else if (packet.receiving_interface().mode() == Type::Interface::MODE_ROAMING) {
|
||||
expires = now + Transport::ROAMING_PATH_TIME;
|
||||
}
|
||||
else {
|
||||
@ -1603,7 +1603,7 @@ using namespace RNS::Utilities;
|
||||
std::set<Bytes> random_blobs;
|
||||
random_blobs.insert(random_blob);
|
||||
|
||||
if (Reticulum::transport_enabled() || from_local_client(packet) && packet.context() != Packet::PATH_RESPONSE) {
|
||||
if (Reticulum::transport_enabled() || from_local_client(packet) && packet.context() != Type::Packet::PATH_RESPONSE) {
|
||||
// Insert announce into announce table for retransmission
|
||||
|
||||
if (rate_blocked) {
|
||||
@ -1630,7 +1630,7 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
}
|
||||
// TODO: Check from_local_client once and store result
|
||||
else if (from_local_client(packet) && packet.context() == Packet::PATH_RESPONSE) {
|
||||
else if (from_local_client(packet) && packet.context() == Type::Packet::PATH_RESPONSE) {
|
||||
// If this is a path response from a local client,
|
||||
// check if any external interfaces have pending
|
||||
// path requests.
|
||||
@ -1661,7 +1661,7 @@ using namespace RNS::Utilities;
|
||||
announce_destination = Destination(announce_identity, Destination.OUT, Destination.SINGLE, "unknown", "unknown");
|
||||
announce_destination.hash(packet.destination_hash());
|
||||
announce_destination.hexhash = announce_destination.hash().toHex();
|
||||
announce_context = Packet::NONE;
|
||||
announce_context = {Type::NONE};
|
||||
announce_data = packet.data();
|
||||
|
||||
// TODO: Shouldn't the context be PATH_RESPONSE in the first case here?
|
||||
@ -1671,7 +1671,7 @@ using namespace RNS::Utilities;
|
||||
Packet new_announce(
|
||||
announce_destination,
|
||||
announce_data,
|
||||
Packet::ANNOUNCE,
|
||||
Type::Packet::ANNOUNCE,
|
||||
context = announce_context,
|
||||
header_type = RNS.Packet.HEADER_2,
|
||||
transport_type = Transport.TRANSPORT,
|
||||
@ -1690,7 +1690,7 @@ using namespace RNS::Utilities;
|
||||
Packet new_announce(
|
||||
announce_destination,
|
||||
announce_data,
|
||||
Packet::ANNOUNCE,
|
||||
Type::Packet::ANNOUNCE,
|
||||
context = announce_context,
|
||||
header_type = RNS.Packet.HEADER_2,
|
||||
transport_type = Transport.TRANSPORT,
|
||||
@ -1720,16 +1720,16 @@ using namespace RNS::Utilities;
|
||||
Destination announce_destination(announce_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, "unknown", "unknown");
|
||||
announce_destination.hash(packet.destination_hash());
|
||||
announce_destination.hexhash = announce_destination.hash().toHex();
|
||||
announce_context = Packet::NONE;
|
||||
announce_context = {Type::NONE};
|
||||
announce_data = packet.data();
|
||||
|
||||
Packet new_announce(
|
||||
announce_destination,
|
||||
announce_data,
|
||||
Packet::ANNOUNCE,
|
||||
context = Packet::PATH_RESPONSE,
|
||||
header_type = Packet::HEADER_2,
|
||||
transport_type = Transport::TRANSPORT,
|
||||
Type::Packet::ANNOUNCE,
|
||||
context = Type::Packet::PATH_RESPONSE,
|
||||
header_type = Type::Packet::HEADER_2,
|
||||
transport_type = Type::Transport::TRANSPORT,
|
||||
transport_id = _identity.hash(),
|
||||
attached_interface = attached_interface
|
||||
);
|
||||
@ -1763,7 +1763,7 @@ using namespace RNS::Utilities;
|
||||
|
||||
// Call externally registered callbacks from apps
|
||||
// wanting to know when an announce arrives
|
||||
if (packet.context() != Packet::PATH_RESPONSE) {
|
||||
if (packet.context() != Type::Packet::PATH_RESPONSE) {
|
||||
for (auto &handler : Transport.announce_handlers) {
|
||||
try {
|
||||
// Check that the announced destination matches
|
||||
@ -1808,7 +1808,7 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
|
||||
// Handling for link requests to local destinations
|
||||
else if (packet.packet_type() == Packet::LINKREQUEST) {
|
||||
else if (packet.packet_type() == Type::Packet::LINKREQUEST) {
|
||||
extreme("Transport::inbound: Packet is LINKREQUEST");
|
||||
if (!packet.transport_id() || packet.transport_id() == _identity.hash()) {
|
||||
for (auto &destination : _destinations) {
|
||||
@ -1823,9 +1823,9 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
|
||||
// Handling for local data packets
|
||||
else if (packet.packet_type() == Packet::DATA) {
|
||||
else if (packet.packet_type() == Type::Packet::DATA) {
|
||||
extreme("Transport::inbound: Packet is DATA");
|
||||
if (packet.destination_type() == Destination::LINK) {
|
||||
if (packet.destination_type() == Type::Destination::LINK) {
|
||||
for (auto &link : _active_links) {
|
||||
if (link.link_id() == packet.destination_hash()) {
|
||||
packet.link(link);
|
||||
@ -1839,10 +1839,10 @@ using namespace RNS::Utilities;
|
||||
packet.destination(destination);
|
||||
const_cast<Destination&>(destination).receive(packet);
|
||||
|
||||
if (destination.proof_strategy() == Destination::PROVE_ALL) {
|
||||
if (destination.proof_strategy() == Type::Destination::PROVE_ALL) {
|
||||
packet.prove();
|
||||
}
|
||||
else if (destination.proof_strategy() == Destination::PROVE_APP) {
|
||||
else if (destination.proof_strategy() == Type::Destination::PROVE_APP) {
|
||||
if (destination.callbacks()._proof_requested) {
|
||||
try {
|
||||
if (destination.callbacks()._proof_requested(packet)) {
|
||||
@ -1860,7 +1860,7 @@ using namespace RNS::Utilities;
|
||||
}
|
||||
|
||||
// Handling for proofs and link-request proofs
|
||||
else if (packet.packet_type() == Packet::PROOF) {
|
||||
else if (packet.packet_type() == Type::Packet::PROOF) {
|
||||
extreme("Transport::inbound: Packet is PROOF");
|
||||
/*
|
||||
if packet.context == RNS.Packet.LRPROOF:
|
||||
@ -2080,8 +2080,8 @@ using namespace RNS::Utilities;
|
||||
|
||||
/*static*/ void Transport::register_destination(Destination &destination) {
|
||||
extreme("Transport: Registering destination " + destination.toString());
|
||||
destination.mtu(Reticulum::MTU);
|
||||
if (destination.direction() == Destination::IN) {
|
||||
destination.mtu(Type::Reticulum::MTU);
|
||||
if (destination.direction() == Type::Destination::IN) {
|
||||
for (auto ®istered_destination : _destinations) {
|
||||
if (destination.hash() == registered_destination.hash()) {
|
||||
//raise KeyError("Attempt to register an already registered destination.")
|
||||
@ -2092,7 +2092,7 @@ using namespace RNS::Utilities;
|
||||
_destinations.insert(destination);
|
||||
|
||||
if (_owner.is_connected_to_shared_instance()) {
|
||||
if (destination.type() == Destination::SINGLE) {
|
||||
if (destination.type() == Type::Destination::SINGLE) {
|
||||
destination.announce({}, true);
|
||||
}
|
||||
}
|
||||
@ -2122,12 +2122,12 @@ using namespace RNS::Utilities;
|
||||
/*
|
||||
extreme("Transport: Activating link " + link.toString());
|
||||
if (_pending_links.find(link) != _pending_links.end()) {
|
||||
if (link.status() != Link::ACTIVE) {
|
||||
if (link.status() != Type::Link::ACTIVE) {
|
||||
throw std::runtime_error("Invalid link state for link activation: " + link.status_string());
|
||||
}
|
||||
_pending_links.erase(link);
|
||||
_active_links.insert(link);
|
||||
link.status(Link::ACTIVE);
|
||||
link.status(Type::Link::ACTIVE);
|
||||
}
|
||||
else {
|
||||
error("Attempted to activate a link that was not in the pending table");
|
||||
@ -2166,7 +2166,7 @@ Deregisters an announce handler.
|
||||
}
|
||||
}
|
||||
|
||||
return {Interface::NONE};
|
||||
return {Type::NONE};
|
||||
}
|
||||
|
||||
/*static*/ bool Transport::should_cache(const Packet &packet) {
|
||||
@ -2236,11 +2236,11 @@ Deregisters an announce handler.
|
||||
}
|
||||
*/
|
||||
// MOCK
|
||||
return {Packet::NONE};
|
||||
return {Type::NONE};
|
||||
}
|
||||
|
||||
/*static*/ bool Transport::cache_request_packet(const Packet &packet) {
|
||||
if (packet.data().size() == Identity::HASHLENGTH/8) {
|
||||
if (packet.data().size() == Type::Identity::HASHLENGTH/8) {
|
||||
const Packet &cached_packet = get_cached_packet(packet.data());
|
||||
|
||||
if (cached_packet) {
|
||||
@ -2270,7 +2270,7 @@ Deregisters an announce handler.
|
||||
else {
|
||||
// The packet is not in the local cache,
|
||||
// query the network.
|
||||
Packet request(destination, packet_hash, Packet::DATA, Packet::CACHE_REQUEST);
|
||||
Packet request(destination, packet_hash, Type::Packet::DATA, Type::Packet::CACHE_REQUEST);
|
||||
request.send();
|
||||
}
|
||||
}
|
||||
@ -2329,7 +2329,7 @@ Deregisters an announce handler.
|
||||
return destination_entry._receiving_interface;
|
||||
}
|
||||
else {
|
||||
return {Interface::NONE};
|
||||
return {Type::NONE};
|
||||
}
|
||||
}
|
||||
|
||||
@ -2354,7 +2354,7 @@ will announce it.
|
||||
:param destination_hash: A destination hash as *bytes*.
|
||||
:param on_interface: If specified, the path request will only be sent on this interface. In normal use, Reticulum handles this automatically, and this parameter should not be used.
|
||||
*/
|
||||
/*static*/ void Transport::request_path(const Bytes &destination_hash, const Interface &on_interface /*= {Interface::NONE}*/, const Bytes &tag /*= {}*/, bool recursive /*= false*/) {
|
||||
/*static*/ void Transport::request_path(const Bytes &destination_hash, const Interface &on_interface /*= {Type::NONE}*/, const Bytes &tag /*= {}*/, bool recursive /*= false*/) {
|
||||
/*
|
||||
if tag == None:
|
||||
request_tag = RNS.Identity.get_random_hash()
|
||||
@ -2474,7 +2474,7 @@ will announce it.
|
||||
Transport.pending_local_path_requests[destination_hash] = attached_interface
|
||||
|
||||
//local_destination = next((d for d in Transport.destinations if d.hash == destination_hash), None)
|
||||
Destination local_destination(Destination::NONE);
|
||||
Destination local_destination({Type::NONE});
|
||||
for (auto &destination : _destinations) {
|
||||
if (destination.hash() == destination_hash) {
|
||||
local_destination = destination;
|
||||
|
@ -3,10 +3,10 @@
|
||||
#include "Reticulum.h"
|
||||
#include "Link.h"
|
||||
// CBA TODO resolve circular dependency with following header file
|
||||
//#include "Packet.h"
|
||||
#include "Packet.h"
|
||||
#include "Bytes.h"
|
||||
#include "None.h"
|
||||
#include "Interfaces/Interface.h"
|
||||
#include "Type.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
@ -133,6 +133,7 @@ namespace RNS {
|
||||
|
||||
public:
|
||||
// Constants
|
||||
/*
|
||||
enum types {
|
||||
BROADCAST = 0x00,
|
||||
TRANSPORT = 0x01,
|
||||
@ -140,6 +141,7 @@ namespace RNS {
|
||||
TUNNEL = 0x03,
|
||||
NONE = 0xFF,
|
||||
};
|
||||
*/
|
||||
|
||||
enum reachabilities {
|
||||
REACHABILITY_UNREACHABLE = 0x00,
|
||||
@ -168,7 +170,7 @@ namespace RNS {
|
||||
static const uint8_t PATH_REQUEST_RW = 2; // Path request random window
|
||||
static const uint8_t PATH_REQUEST_MI = 5; // Minimum interval in seconds for automated path requests
|
||||
|
||||
static constexpr const float LINK_TIMEOUT = Link::STALE_TIME * 1.25;
|
||||
static constexpr const float LINK_TIMEOUT = Type::Link::STALE_TIME * 1.25;
|
||||
static const uint16_t REVERSE_TIMEOUT = 30*60; // Reverse table entries are removed after 30 minutes
|
||||
static const uint32_t DESTINATION_TIMEOUT = 60*60*24*7; // Destination table entries are removed if unused for one week
|
||||
static const uint16_t MAX_RECEIPTS = 1024; // Maximum number of receipts to keep track of
|
||||
@ -181,7 +183,7 @@ namespace RNS {
|
||||
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 inbound(const Bytes &raw, const Interface &interface = {Type::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);
|
||||
@ -204,7 +206,7 @@ namespace RNS {
|
||||
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 request_path(const Bytes &destination_hash, const Interface &on_interface = {Type::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);
|
||||
|
321
src/Type.h
Normal file
321
src/Type.h
Normal file
@ -0,0 +1,321 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cryptography/Fernet.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace RNS { namespace Type {
|
||||
|
||||
// generic empty object constructor type
|
||||
enum NoneConstructor {
|
||||
NONE
|
||||
};
|
||||
|
||||
namespace Reticulum {
|
||||
|
||||
// Future minimum will probably be locked in at 251 bytes to support
|
||||
// networks with segments of different MTUs. Absolute minimum is 219.
|
||||
static const uint16_t MTU = 500;
|
||||
/*
|
||||
The MTU that Reticulum adheres to, and will expect other peers to
|
||||
adhere to. By default, the MTU is 507 bytes. In custom RNS network
|
||||
implementations, it is possible to change this value, but doing so will
|
||||
completely break compatibility with all other RNS networks. An identical
|
||||
MTU is a prerequisite for peers to communicate in the same network.
|
||||
|
||||
Unless you really know what you are doing, the MTU should be left at
|
||||
the default value.
|
||||
*/
|
||||
|
||||
static const uint16_t MAX_QUEUED_ANNOUNCES = 16384;
|
||||
static const uint32_t QUEUED_ANNOUNCE_LIFE = 60*60*24;
|
||||
|
||||
static const uint8_t ANNOUNCE_CAP = 2;
|
||||
/*
|
||||
The maximum percentage of interface bandwidth that, at any given time,
|
||||
may be used to propagate announces. If an announce was scheduled for
|
||||
broadcasting on an interface, but doing so would exceed the allowed
|
||||
bandwidth allocation, the announce will be queued for transmission
|
||||
when there is bandwidth available.
|
||||
|
||||
Reticulum will always prioritise propagating announces with fewer
|
||||
hops, ensuring that distant, large networks with many peers on fast
|
||||
links don't overwhelm the capacity of smaller networks on slower
|
||||
mediums. If an announce remains queued for an extended amount of time,
|
||||
it will eventually be dropped.
|
||||
|
||||
This value will be applied by default to all created interfaces,
|
||||
but it can be configured individually on a per-interface basis.
|
||||
*/
|
||||
|
||||
static const uint16_t MINIMUM_BITRATE = 500;
|
||||
|
||||
// TODO: To reach the 300bps level without unreasonably impacting
|
||||
// performance on faster links, we need a mechanism for setting
|
||||
// this value more intelligently. One option could be inferring it
|
||||
// from interface speed, but a better general approach would most
|
||||
// probably be to let Reticulum somehow continously build a map of
|
||||
// per-hop latencies and use this map for the timeout calculation.
|
||||
static const uint8_t DEFAULT_PER_HOP_TIMEOUT = 6;
|
||||
|
||||
static const uint16_t HASHLENGTH = 256; // In bits
|
||||
// Length of truncated hashes in bits.
|
||||
static const uint16_t TRUNCATED_HASHLENGTH = 128; // In bits
|
||||
|
||||
static const uint16_t HEADER_MINSIZE = 2+1+(TRUNCATED_HASHLENGTH/8)*1; // In bytes
|
||||
static const uint16_t HEADER_MAXSIZE = 2+1+(TRUNCATED_HASHLENGTH/8)*2; // In bytes
|
||||
static const uint16_t IFAC_MIN_SIZE = 1;
|
||||
//zIFAC_SALT = bytes.fromhex("adf54d882c9a9b80771eb4995d702d4a3e733391b2a0f53f416d9f907e55cff8")
|
||||
|
||||
static const uint16_t MDU = MTU - HEADER_MAXSIZE - IFAC_MIN_SIZE;
|
||||
|
||||
static const uint32_t RESOURCE_CACHE = 24*60*60;
|
||||
static const uint16_t JOB_INTERVAL = 5*60;
|
||||
static const uint16_t CLEAN_INTERVAL = 15*60;
|
||||
static const uint16_t PERSIST_INTERVAL = 60*60*12;
|
||||
static const uint16_t GRACIOUS_PERSIST_INTERVAL = 60*5;
|
||||
|
||||
static const uint8_t DESTINATION_LENGTH = TRUNCATED_HASHLENGTH/8; // In bytes
|
||||
|
||||
}
|
||||
|
||||
namespace Identity {
|
||||
|
||||
//static const char CURVE[] = "Curve25519";
|
||||
static constexpr const char* CURVE = "Curve25519";
|
||||
// The curve used for Elliptic Curve DH key exchanges
|
||||
|
||||
static const uint16_t KEYSIZE = 256*2;
|
||||
// X25519 key size in bits. A complete key is the concatenation of a 256 bit encryption key, and a 256 bit signing key.
|
||||
|
||||
// Non-configurable constants
|
||||
static const uint8_t FERNET_OVERHEAD = Cryptography::Fernet::FERNET_OVERHEAD;
|
||||
static const uint8_t AES128_BLOCKSIZE = 16; // In bytes
|
||||
static const uint16_t HASHLENGTH = Reticulum::HASHLENGTH; // In bits
|
||||
static const uint16_t SIGLENGTH = KEYSIZE; // In bits
|
||||
|
||||
static const uint8_t NAME_HASH_LENGTH = 80;
|
||||
static const uint16_t TRUNCATED_HASHLENGTH = Reticulum::TRUNCATED_HASHLENGTH; // In bits
|
||||
// Constant specifying the truncated hash length (in bits) used by Reticulum
|
||||
// for addressable hashes and other purposes. Non-configurable.
|
||||
|
||||
}
|
||||
|
||||
namespace Destination {
|
||||
|
||||
enum types {
|
||||
SINGLE = 0x00,
|
||||
GROUP = 0x01,
|
||||
PLAIN = 0x02,
|
||||
LINK = 0x03,
|
||||
};
|
||||
|
||||
enum proof_strategies {
|
||||
PROVE_NONE = 0x21,
|
||||
PROVE_APP = 0x22,
|
||||
PROVE_ALL = 0x23,
|
||||
};
|
||||
|
||||
enum request_policies {
|
||||
ALLOW_NONE = 0x00,
|
||||
ALLOW_ALL = 0x01,
|
||||
ALLOW_LIST = 0x02,
|
||||
};
|
||||
|
||||
enum directions {
|
||||
IN = 0x11,
|
||||
OUT = 0x12,
|
||||
};
|
||||
|
||||
const uint8_t PR_TAG_WINDOW = 30;
|
||||
|
||||
}
|
||||
|
||||
namespace Link {
|
||||
|
||||
static constexpr const char* CURVE = Identity::CURVE;
|
||||
// The curve used for Elliptic Curve DH key exchanges
|
||||
|
||||
static const uint16_t ECPUBSIZE = 32+32;
|
||||
static const uint8_t KEYSIZE = 32;
|
||||
|
||||
//static const uint16_t MDU = floor((Reticulum::MTU-Reticulum::IFAC_MIN_SIZE-Reticulum::HEADER_MINSIZE-Identity::FERNET_OVERHEAD)/Identity::AES128_BLOCKSIZE)*Identity::AES128_BLOCKSIZE - 1;
|
||||
static const uint16_t MDU = ((Reticulum::MTU-Reticulum::IFAC_MIN_SIZE-Reticulum::HEADER_MINSIZE-Identity::FERNET_OVERHEAD)/Identity::AES128_BLOCKSIZE)*Identity::AES128_BLOCKSIZE - 1;
|
||||
|
||||
static const uint8_t ESTABLISHMENT_TIMEOUT_PER_HOP = Reticulum::DEFAULT_PER_HOP_TIMEOUT;
|
||||
// Timeout for link establishment in seconds per hop to destination.
|
||||
|
||||
static const uint16_t TRAFFIC_TIMEOUT_FACTOR = 6;
|
||||
static const uint16_t KEEPALIVE_TIMEOUT_FACTOR = 4;
|
||||
// RTT timeout factor used in link timeout calculation.
|
||||
static const uint8_t STALE_GRACE = 2;
|
||||
// Grace period in seconds used in link timeout calculation.
|
||||
static const uint16_t KEEPALIVE = 360;
|
||||
// Interval for sending keep-alive packets on established links in seconds.
|
||||
static const uint16_t STALE_TIME = 2*KEEPALIVE;
|
||||
/*
|
||||
If no traffic or keep-alive packets are received within this period, the
|
||||
link will be marked as stale, and a final keep-alive packet will be sent.
|
||||
If after this no traffic or keep-alive packets are received within ``RTT`` *
|
||||
``KEEPALIVE_TIMEOUT_FACTOR`` + ``STALE_GRACE``, the link is considered timed out,
|
||||
and will be torn down.
|
||||
*/
|
||||
|
||||
enum status {
|
||||
PENDING = 0x00,
|
||||
HANDSHAKE = 0x01,
|
||||
ACTIVE = 0x02,
|
||||
STALE = 0x03,
|
||||
CLOSED = 0x04
|
||||
};
|
||||
|
||||
enum teardown_reasons {
|
||||
TIMEOUT = 0x01,
|
||||
INITIATOR_CLOSED = 0x02,
|
||||
DESTINATION_CLOSED = 0x03,
|
||||
};
|
||||
|
||||
enum resource_strategies {
|
||||
ACCEPT_NONE = 0x00,
|
||||
ACCEPT_APP = 0x01,
|
||||
ACCEPT_ALL = 0x02,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Interface {
|
||||
|
||||
// Interface mode definitions
|
||||
enum modes {
|
||||
MODE_NONE = 0x00,
|
||||
MODE_FULL = 0x01,
|
||||
MODE_POINT_TO_POINT = 0x04,
|
||||
MODE_ACCESS_POINT = 0x08,
|
||||
MODE_ROAMING = 0x10,
|
||||
MODE_BOUNDARY = 0x20,
|
||||
MODE_GATEWAY = 0x40,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Packet {
|
||||
|
||||
// Packet types
|
||||
enum types {
|
||||
DATA = 0x00, // Data packets
|
||||
ANNOUNCE = 0x01, // Announces
|
||||
LINKREQUEST = 0x02, // Link requests
|
||||
PROOF = 0x03, // Proofs
|
||||
};
|
||||
|
||||
// Header types
|
||||
enum header_types {
|
||||
HEADER_1 = 0x00, // Normal header format
|
||||
HEADER_2 = 0x01, // Header format used for packets in transport
|
||||
};
|
||||
|
||||
// Packet context types
|
||||
enum context_types {
|
||||
CONTEXT_NONE = 0x00, // Generic data packet
|
||||
RESOURCE = 0x01, // Packet is part of a resource
|
||||
RESOURCE_ADV = 0x02, // Packet is a resource advertisement
|
||||
RESOURCE_REQ = 0x03, // Packet is a resource part request
|
||||
RESOURCE_HMU = 0x04, // Packet is a resource hashmap update
|
||||
RESOURCE_PRF = 0x05, // Packet is a resource proof
|
||||
RESOURCE_ICL = 0x06, // Packet is a resource initiator cancel message
|
||||
RESOURCE_RCL = 0x07, // Packet is a resource receiver cancel message
|
||||
CACHE_REQUEST = 0x08, // Packet is a cache request
|
||||
REQUEST = 0x09, // Packet is a request
|
||||
RESPONSE = 0x0A, // Packet is a response to a request
|
||||
PATH_RESPONSE = 0x0B, // Packet is a response to a path request
|
||||
COMMAND = 0x0C, // Packet is a command
|
||||
COMMAND_STATUS = 0x0D, // Packet is a status of an executed command
|
||||
CHANNEL = 0x0E, // Packet contains link channel data
|
||||
KEEPALIVE = 0xFA, // Packet is a keepalive packet
|
||||
LINKIDENTIFY = 0xFB, // Packet is a link peer identification proof
|
||||
LINKCLOSE = 0xFC, // Packet is a link close message
|
||||
LINKPROOF = 0xFD, // Packet is a link packet proof
|
||||
LRRTT = 0xFE, // Packet is a link request round-trip time measurement
|
||||
LRPROOF = 0xFF, // Packet is a link request proof
|
||||
};
|
||||
|
||||
// This is used to calculate allowable
|
||||
// payload sizes
|
||||
static const uint16_t HEADER_MAXSIZE = Reticulum::HEADER_MAXSIZE;
|
||||
static const uint16_t MDU = Reticulum::MDU;
|
||||
|
||||
// With an MTU of 500, the maximum of data we can
|
||||
// send in a single encrypted packet is given by
|
||||
// the below calculation; 383 bytes.
|
||||
//static const uint16_t ENCRYPTED_MDU = floor((Reticulum::MDU-Identity::FERNET_OVERHEAD-Identity::KEYSIZE/16)/Identity::AES128_BLOCKSIZE)*Identity::AES128_BLOCKSIZE - 1;
|
||||
//static const uint16_t ENCRYPTED_MDU;
|
||||
static const uint16_t ENCRYPTED_MDU = ((Reticulum::MDU-Identity::FERNET_OVERHEAD-Identity::KEYSIZE/16)/Identity::AES128_BLOCKSIZE)*Identity::AES128_BLOCKSIZE - 1;
|
||||
// The maximum size of the payload data in a single encrypted packet
|
||||
static const uint16_t PLAIN_MDU = MDU;
|
||||
// The maximum size of the payload data in a single unencrypted packet
|
||||
|
||||
static const uint8_t TIMEOUT_PER_HOP = Reticulum::DEFAULT_PER_HOP_TIMEOUT;
|
||||
|
||||
}
|
||||
|
||||
namespace PacketReceipt {
|
||||
|
||||
// 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;
|
||||
|
||||
}
|
||||
|
||||
namespace Transport {
|
||||
|
||||
enum types {
|
||||
BROADCAST = 0x00,
|
||||
TRANSPORT = 0x01,
|
||||
RELAY = 0x02,
|
||||
TUNNEL = 0x03,
|
||||
NONE = 0xFF,
|
||||
};
|
||||
|
||||
enum reachabilities {
|
||||
REACHABILITY_UNREACHABLE = 0x00,
|
||||
REACHABILITY_DIRECT = 0x01,
|
||||
REACHABILITY_TRANSPORT = 0x02,
|
||||
};
|
||||
|
||||
static constexpr const char* APP_NAME = "rnstransport";
|
||||
|
||||
static const uint8_t PATHFINDER_M = 128; // Max hops
|
||||
// Maximum amount of hops that Reticulum will transport a packet.
|
||||
|
||||
static const uint8_t PATHFINDER_R = 1; // Retransmit retries
|
||||
static const uint8_t PATHFINDER_G = 5; // Retry grace period
|
||||
static constexpr const float PATHFINDER_RW = 0.5; // Random window for announce rebroadcast
|
||||
static const uint32_t PATHFINDER_E = 60*60*24*7; // Path expiration of one week
|
||||
static const uint32_t AP_PATH_TIME = 60*60*24; // Path expiration of one day for Access Point paths
|
||||
static const uint32_t ROAMING_PATH_TIME = 60*60*6; // Path expiration of 6 hours for Roaming paths
|
||||
|
||||
// TODO: Calculate an optimal number for this in
|
||||
// various situations
|
||||
static const uint8_t LOCAL_REBROADCASTS_MAX = 2; // How many local rebroadcasts of an announce is allowed
|
||||
|
||||
static const uint8_t PATH_REQUEST_TIMEOUT = 15; // Default timuout for client path requests in seconds
|
||||
static constexpr const float PATH_REQUEST_GRACE = 0.35; // Grace time before a path announcement is made, allows directly reachable peers to respond first
|
||||
static const uint8_t PATH_REQUEST_RW = 2; // Path request random window
|
||||
static const uint8_t PATH_REQUEST_MI = 5; // Minimum interval in seconds for automated path requests
|
||||
|
||||
static constexpr const float LINK_TIMEOUT = Link::STALE_TIME * 1.25;
|
||||
static const uint16_t REVERSE_TIMEOUT = 30*60; // Reverse table entries are removed after 30 minutes
|
||||
static const uint32_t DESTINATION_TIMEOUT = 60*60*24*7; // Destination table entries are removed if unused for one week
|
||||
static const uint16_t MAX_RECEIPTS = 1024; // Maximum number of receipts to keep track of
|
||||
static const uint8_t MAX_RATE_TIMESTAMPS = 16; // Maximum number of announce timestamps to keep per destination
|
||||
|
||||
}
|
||||
|
||||
} }
|
10
src/main.cpp
10
src/main.cpp
@ -175,7 +175,7 @@ void setup() {
|
||||
// 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::Type::Destination::IN, RNS::Type::Destination::SINGLE, "test", "context");
|
||||
// 23.0% (+0.4%)
|
||||
|
||||
/*
|
||||
@ -197,7 +197,7 @@ void setup() {
|
||||
}
|
||||
*/
|
||||
|
||||
destination.set_proof_strategy(RNS::Destination::PROVE_ALL);
|
||||
destination.set_proof_strategy(RNS::Type::Destination::PROVE_ALL);
|
||||
|
||||
//zRNS::head("Registering announce handler with Transport...", RNS::LOG_EXTREME);
|
||||
//zannounce_handler = ExampleAnnounceHandler(
|
||||
@ -213,7 +213,7 @@ void setup() {
|
||||
destination.announce(RNS::bytesFromString(fruits[rand() % 7]));
|
||||
// 23.9% (+0.8%)
|
||||
|
||||
/*
|
||||
/**/
|
||||
// test data send packet
|
||||
RNS::head("Creating send packet...", RNS::LOG_EXTREME);
|
||||
RNS::Packet send_packet(destination, "The quick brown fox jumps over the lazy dog");
|
||||
@ -227,13 +227,13 @@ void setup() {
|
||||
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::Type::NONE}, send_packet.raw());
|
||||
recv_packet.unpack();
|
||||
RNS::extreme("Test recv_packet: " + recv_packet.debugString());
|
||||
|
||||
RNS::head("Spoofing recv packet to destination...", RNS::LOG_EXTREME);
|
||||
destination.receive(recv_packet);
|
||||
*/
|
||||
/**/
|
||||
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
|
Loading…
Reference in New Issue
Block a user