Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ build_flags =
-DRNS_ENABLE_REMOTE_PROVISIONING
-DUSTORE_ENABLE_LOG
-DUSTORE_USE_UNIVERSALFS
; Divergent features
;-DRNS_SAME_INTERFACE_PATH_REQUESTS=0
;-DRNS_REJECT_BLACKHOLED_ANNOUNCE=0
;-DRNS_BLOCK_UNRESPONSIVE_ANNOUNCE=0
;-DRNS_NEIGHBOR_PROBING=0
-DRNS_NEIGHBOR_PATH_REQUEST=1
lib_deps =
ArduinoJson@^7.4.2
MsgPack@^0.4.2
Expand Down
63 changes: 56 additions & 7 deletions src/microReticulum/Packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,19 @@ bool PacketReceipt::validate_link_proof(const Bytes& proof, const Link& link, co
//z _object->_proof_packet = proof_packet;
//z link.last_proof(_object->_concluded_at);

if (_object->_callbacks._delivery) {
// Prefer std::function handler over legacy
// function-pointer callback so capture-bearing handlers
// (e.g. neighbor-probe outcomes) are invoked first.
if (_object->_callbacks._delivery_fn) {
try {
_object->_callbacks._delivery_fn(*this);
}
catch (const std::exception& e) {
ERRORF("An error occurred while evaluating external delivery handler for %s", link.toString().c_str());
ERRORF("The contained exception was: %s", e.what());
}
}
else if (_object->_callbacks._delivery) {
try {
_object->_callbacks._delivery(*this);
}
Expand Down Expand Up @@ -973,7 +985,17 @@ bool PacketReceipt::validate_proof(const Bytes& proof, const Packet& proof_packe
_object->_concluded_at = OS::time();
//z _object->_proof_packet = proof_packet;

if (_object->_callbacks._delivery) {
// Prefer std::function handler over legacy
// function-pointer callback.
if (_object->_callbacks._delivery_fn) {
try {
_object->_callbacks._delivery_fn(*this);
}
catch (const std::exception& e) {
ERRORF("Error while executing proof validated handler. The contained exception was: %s", e.what());
}
}
else if (_object->_callbacks._delivery) {
try {
_object->_callbacks._delivery(*this);
}
Expand Down Expand Up @@ -1004,7 +1026,17 @@ bool PacketReceipt::validate_proof(const Bytes& proof, const Packet& proof_packe
_object->_concluded_at = OS::time();
//z _object->_proof_packet = proof_packet;

if (_object->_callbacks._delivery) {
// Prefer std::function handler over legacy
// function-pointer callback.
if (_object->_callbacks._delivery_fn) {
try {
_object->_callbacks._delivery_fn(*this);
}
catch (const std::exception& e) {
ERRORF("Error while executing proof validated handler. The contained exception was: %s", e.what());
}
}
else if (_object->_callbacks._delivery) {
try {
_object->_callbacks._delivery(*this);
}
Expand Down Expand Up @@ -1036,10 +1068,27 @@ void PacketReceipt::check_timeout() {

_object->_concluded_at = Utilities::OS::time();

if (_object->_callbacks._timeout) {
//z thread = threading.Thread(target=self.callbacks.timeout, args=(self,))
//z thread.daemon = True
//z thread.start();
// Pre-existing latent gap: the Python reference dispatches the
// timeout callback from a background thread; the C++ port has no
// thread runtime here, so the dispatch was left as a //z stub
// and never fired. Invoke synchronously instead.
// Prefer std::function handler over legacy
// function-pointer callback so capture-bearing handlers fire.
if (_object->_callbacks._timeout_fn) {
try {
_object->_callbacks._timeout_fn(*this);
}
catch (const std::exception& e) {
ERRORF("Error while executing timeout handler. The contained exception was: %s", e.what());
}
}
else if (_object->_callbacks._timeout) {
try {
_object->_callbacks._timeout(*this);
}
catch (const std::exception& e) {
ERRORF("Error while executing timeout callback. The contained exception was: %s", e.what());
}
}
}
}
Expand Down
31 changes: 30 additions & 1 deletion src/microReticulum/Packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include <memory>
#include <cassert>
#include <functional>
#include <limits>
#include <stdint.h>
#include <time.h>
Expand Down Expand Up @@ -56,9 +57,20 @@ namespace RNS {
public:
using delivery = void(*)(const PacketReceipt& packet_receipt);
using timeout = void(*)(const PacketReceipt& packet_receipt);
// New std::function-based handler variants added to let
// neighbor-probe outcome callbacks capture neighbor_hash by
// value. The Python reference already supports captured state
// via closures; the C++ port previously exposed only plain
// function pointers. Function-pointer setters above remain
// (marked deprecated) for source compatibility with existing
// out-of-tree firmware.
using delivery_handler = std::function<void(const PacketReceipt& packet_receipt)>;
using timeout_handler = std::function<void(const PacketReceipt& packet_receipt)>;
public:
delivery _delivery = nullptr;
timeout _timeout = nullptr;
delivery_handler _delivery_fn;
timeout_handler _timeout_fn;
friend class PacketReceipt;
};

Expand Down Expand Up @@ -97,26 +109,43 @@ namespace RNS {
// :param timeout: The timeout in seconds.
inline void set_timeout(int16_t timeout) { assert(_object); _object->_timeout = timeout; }

// Deprecated function-pointer setter retained for source compat
// with existing firmware; new code should use set_delivery_handler
// which accepts a std::function (capture-friendly).
/*
Sets a function that gets called if a successfull delivery has been proven.

:param callback: A *callable* with the signature *callback(packet_receipt)*
*/
RNS_DEPRECATED("use set_delivery_handler (std::function)")
inline void set_delivery_callback(Callbacks::delivery callback) {
assert(_object);
_object->_callbacks._delivery = callback;
}

/*
Sets a function that gets called if the delivery times out.

:param callback: A *callable* with the signature *callback(packet_receipt)*
*/
RNS_DEPRECATED("use set_timeout_handler (std::function)")
inline void set_timeout_callback(Callbacks::timeout callback) {
assert(_object);
_object->_callbacks._timeout = callback;
}

// New std::function-based setters accept callables with
// captured state (e.g. lambdas closing over neighbor_hash). The
// dispatcher in Packet.cpp prefers the handler over the legacy
// function-pointer if both are set.
inline void set_delivery_handler(Callbacks::delivery_handler handler) {
assert(_object);
_object->_callbacks._delivery_fn = std::move(handler);
}
inline void set_timeout_handler(Callbacks::timeout_handler handler) {
assert(_object);
_object->_callbacks._timeout_fn = std::move(handler);
}

// getters
inline const Bytes& hash() const { assert(_object); return _object->_hash; }
inline Type::PacketReceipt::Status status() const { assert(_object); return _object->_status; }
Expand Down
9 changes: 9 additions & 0 deletions src/microReticulum/Provisioning/BuiltinNamespaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ namespace RNS { namespace Provisioning {
.metric_int("Paths Added", Ns::Info::Metrics::Field::PathsAdded, []() { return RNS::Transport::paths_added(); })
.metric_int("Paths Updated", Ns::Info::Metrics::Field::PathsUpdated, []() { return RNS::Transport::paths_updated(); })
.metric_int("Paths Failed", Ns::Info::Metrics::Field::PathsFailed, []() { return RNS::Transport::paths_failed(); })
.metric_int("Paths Unresponsive", Ns::Info::Metrics::Field::PathsUnresponsive, []() { return RNS::Transport::paths_responsive(); })
.metric_int("Paths Responsive", Ns::Info::Metrics::Field::PathsResponsive, []() { return RNS::Transport::paths_unresponsive(); })
.metric_int("Paths Unknown", Ns::Info::Metrics::Field::PathsUnknown, []() { return RNS::Transport::paths_unknown(); })
#if RNS_NEIGHBOR_PROBING
.metric_int("Probes Received", Ns::Info::Metrics::Field::ProbesReceived, []() { return RNS::Transport::probes_received(); })
.metric_int("Probes Sent", Ns::Info::Metrics::Field::ProbesSent, []() { return RNS::Transport::probes_sent(); })
.metric_int("Probes Skipped", Ns::Info::Metrics::Field::ProbesSkipped, []() { return RNS::Transport::probes_skipped(); })
.metric_int("Probes Failed", Ns::Info::Metrics::Field::ProbesFailed, []() { return RNS::Transport::probes_failed(); })
#endif
.end()
.end();
}
Expand Down
7 changes: 7 additions & 0 deletions src/microReticulum/Provisioning/Ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ namespace RNS { namespace Provisioning { namespace Ns {
constexpr fid_t PathsAdded = 7;
constexpr fid_t PathsUpdated = 8;
constexpr fid_t PathsFailed = 9;
constexpr fid_t PathsUnresponsive = 10;
constexpr fid_t PathsResponsive = 11;
constexpr fid_t PathsUnknown = 12;
constexpr fid_t ProbesReceived = 13;
constexpr fid_t ProbesSent = 14;
constexpr fid_t ProbesSkipped = 15;
constexpr fid_t ProbesFailed = 16;
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/microReticulum/Reticulum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ using namespace RNS::Utilities;
/*static*/ bool Reticulum::__use_implicit_proof = true;
/*static*/ bool Reticulum::__allow_probes = false;
/*static*/ bool Reticulum::__publish_blackhole_enabled = false;
#if RNS_NEIGHBOR_PROBING
// DIVERGENCE: passive neighbor-probing defaults — feature on, path-request
// fallback off. Effective only when transport_enabled() is also true.
/*static*/ bool Reticulum::__neighbor_probing_enabled = true;
#endif
/*static*/ bool Reticulum::panic_on_interface_error = false;

/*static*/ uint16_t Reticulum::_persist_interval = PERSIST_INTERVAL;
Expand Down
17 changes: 17 additions & 0 deletions src/microReticulum/Reticulum.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ namespace RNS {
static bool __use_implicit_proof;
static bool __allow_probes;
static bool __publish_blackhole_enabled;
#if RNS_NEIGHBOR_PROBING
// DIVERGENCE: runtime toggles for passive neighbor-liveness
// inference and its optional path-request fallback. The Python
// reference plan parses these from the [reticulum] INI block;
// microReticulum has no INI parser, so they're exposed as static
// accessors only.
static bool __neighbor_probing_enabled;
#endif
static bool panic_on_interface_error;

static uint16_t _persist_interval;
Expand Down Expand Up @@ -169,6 +177,15 @@ namespace RNS {
inline static bool probe_destination_enabled() { return __allow_probes; }
inline static void probe_destination_enabled(bool allow_probes) { __allow_probes = allow_probes; }

#if RNS_NEIGHBOR_PROBING
// DIVERGENCE: master toggle for passive neighbor-liveness
// inference. Effective only when transport_enabled() is also
// true; the local side typically also wants
// probe_destination_enabled() so peers can probe it reciprocally.
inline static bool neighbor_probing_enabled() { return __neighbor_probing_enabled; }
inline static void neighbor_probing_enabled(bool v) { __neighbor_probing_enabled = v; }
#endif

// getters/setters
inline bool is_connected_to_shared_instance() const { assert(_object); return _object->_is_connected_to_shared_instance; }
inline static uint16_t persist_interval() { return _persist_interval; }
Expand Down
Loading
Loading