2025-08-26 21:05:36 -06:00
|
|
|
#include <unity.h>
|
2024-07-03 06:55:06 -06:00
|
|
|
|
2025-08-26 21:05:36 -06:00
|
|
|
#include "../common/filesystem/FileSystem.h"
|
2025-08-21 17:29:26 -06:00
|
|
|
|
|
|
|
|
#include <Reticulum.h>
|
|
|
|
|
#include <Transport.h>
|
|
|
|
|
#include <Log.h>
|
2024-07-03 06:55:06 -06:00
|
|
|
|
2026-01-21 12:38:13 -07:00
|
|
|
#ifdef ARDUINO
|
|
|
|
|
const char destination_table_path[] = "/destination_table";
|
|
|
|
|
#else
|
|
|
|
|
const char destination_table_path[] = "destination_table";
|
|
|
|
|
#endif
|
2025-08-21 17:29:26 -06:00
|
|
|
|
2024-08-14 21:59:23 -06:00
|
|
|
class InInterface : public RNS::InterfaceImpl {
|
2024-07-16 10:40:46 -06:00
|
|
|
public:
|
2024-08-14 21:59:23 -06:00
|
|
|
InInterface(const char *name = "InInterface") : RNS::InterfaceImpl(name) {
|
|
|
|
|
_OUT = false;
|
|
|
|
|
_IN = true;
|
2024-07-16 10:40:46 -06:00
|
|
|
}
|
|
|
|
|
virtual ~InInterface() {
|
2024-08-14 21:59:23 -06:00
|
|
|
_name = "(deleted)";
|
2024-07-16 10:40:46 -06:00
|
|
|
}
|
2025-08-21 17:29:26 -06:00
|
|
|
// Incoming interface only, send_outgoing not currently implemented
|
|
|
|
|
virtual void send_outgoing(const RNS::Bytes &data) {}
|
2025-08-26 21:05:36 -06:00
|
|
|
// Incoming is be handled automatically by InterfaceImpl::handle_incoming called via Interface::handle_incoming from OutInterface
|
2024-07-16 10:40:46 -06:00
|
|
|
};
|
|
|
|
|
|
2024-08-14 21:59:23 -06:00
|
|
|
class OutInterface : public RNS::InterfaceImpl {
|
2024-07-16 10:40:46 -06:00
|
|
|
public:
|
2024-08-14 21:59:23 -06:00
|
|
|
OutInterface(RNS::Interface& in_interface, const char *name = "OutInterface") : RNS::InterfaceImpl(name), _in_interface(in_interface) {
|
|
|
|
|
_OUT = true;
|
|
|
|
|
_IN = false;
|
2024-07-16 10:40:46 -06:00
|
|
|
}
|
|
|
|
|
virtual ~OutInterface() {
|
2024-08-14 21:59:23 -06:00
|
|
|
_name = "(deleted)";
|
2024-07-16 10:40:46 -06:00
|
|
|
}
|
2024-08-14 21:59:23 -06:00
|
|
|
virtual void send_outgoing(const RNS::Bytes &data) {
|
2026-03-01 10:59:33 -07:00
|
|
|
HEADF(RNS::LOG_TRACE, "OutInterface.send_outgoing: data: %s", data.toHex().c_str());
|
2025-08-21 17:29:26 -06:00
|
|
|
|
|
|
|
|
// Loop data back to InInterface for testing
|
2025-08-26 21:05:36 -06:00
|
|
|
// NOTE: This sends the incoming data directory to RNS::Interface (which relays to Transport)
|
|
|
|
|
// and does not actually go through InInterface.
|
2024-08-14 21:59:23 -06:00
|
|
|
_in_interface.handle_incoming(data);
|
2025-08-21 17:29:26 -06:00
|
|
|
|
|
|
|
|
// Perform post-send housekeeping
|
|
|
|
|
InterfaceImpl::handle_outgoing(data);
|
2024-07-16 10:40:46 -06:00
|
|
|
}
|
|
|
|
|
private:
|
2024-08-14 21:59:23 -06:00
|
|
|
RNS::Interface& _in_interface;
|
2024-07-16 10:40:46 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Test AnnounceHandler
|
|
|
|
|
class ExampleAnnounceHandler : public RNS::AnnounceHandler {
|
|
|
|
|
public:
|
|
|
|
|
ExampleAnnounceHandler(const char* aspect_filter = nullptr) : AnnounceHandler(aspect_filter) {}
|
|
|
|
|
virtual ~ExampleAnnounceHandler() {}
|
|
|
|
|
virtual void received_announce(const RNS::Bytes& destination_hash, const RNS::Identity& announced_identity, const RNS::Bytes& app_data) {
|
|
|
|
|
INFO("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
2026-03-01 10:59:33 -07:00
|
|
|
INFOF("ExampleAnnounceHandler: destination hash: %s", destination_hash.toHex().c_str());
|
2024-07-16 10:40:46 -06:00
|
|
|
if (announced_identity) {
|
2026-03-01 10:59:33 -07:00
|
|
|
INFOF("ExampleAnnounceHandler: announced identity hash: %s", announced_identity.hash().toHex().c_str());
|
|
|
|
|
INFOF("ExampleAnnounceHandler: announced identity app data: %s", announced_identity.app_data().toHex().c_str());
|
2024-07-16 10:40:46 -06:00
|
|
|
}
|
|
|
|
|
if (app_data) {
|
2026-03-01 10:59:33 -07:00
|
|
|
INFOF("ExampleAnnounceHandler: app data text: \"%s\"", app_data.toString().c_str());
|
2024-07-16 10:40:46 -06:00
|
|
|
}
|
|
|
|
|
INFO("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//ExampleAnnounceHandler announce_handler((const char*)"example_utilities.announcesample.fruits");
|
|
|
|
|
//RNS::HAnnounceHandler announce_handler(new ExampleAnnounceHandler("example_utilities.announcesample.fruits"));
|
|
|
|
|
RNS::HAnnounceHandler announce_handler(new ExampleAnnounceHandler());
|
|
|
|
|
|
|
|
|
|
// Test packet receive callback
|
2025-08-21 17:29:26 -06:00
|
|
|
//void(*)(const Bytes& data, const Packet& packet)
|
2024-07-16 10:40:46 -06:00
|
|
|
void onPacket(const RNS::Bytes& data, const RNS::Packet& packet) {
|
|
|
|
|
INFO("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
2026-03-01 10:59:33 -07:00
|
|
|
INFOF("onPacket: data: %s", data.toHex().c_str());
|
|
|
|
|
INFOF("onPacket: text: \"%s\"", data.toString().c_str());
|
|
|
|
|
//TRACEF("onPacket: %s", packet.debugString().c_str());
|
2024-07-16 10:40:46 -06:00
|
|
|
INFO("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
|
|
|
|
}
|
2024-07-03 06:55:06 -06:00
|
|
|
|
2024-07-16 10:40:46 -06:00
|
|
|
// Ping packet receive callback
|
2025-08-21 17:29:26 -06:00
|
|
|
//void(*)(const Bytes& data, const Packet& packet)
|
2024-07-16 10:40:46 -06:00
|
|
|
void onPingPacket(const RNS::Bytes& data, const RNS::Packet& packet) {
|
|
|
|
|
INFO("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
2026-03-01 10:59:33 -07:00
|
|
|
INFOF("onPingPacket: data: %s", data.toHex().c_str());
|
|
|
|
|
INFOF("onPingPacket: text: \"%s\"", data.toString().c_str());
|
|
|
|
|
//TRACEF("onPingPacket: %s", packet.debugString().c_str());
|
2024-07-16 10:40:46 -06:00
|
|
|
INFO("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
2024-07-03 06:55:06 -06:00
|
|
|
}
|
|
|
|
|
|
2024-07-16 10:40:46 -06:00
|
|
|
|
|
|
|
|
RNS::Reticulum reticulum({RNS::Type::NONE});
|
|
|
|
|
RNS::Identity identity({RNS::Type::NONE});
|
|
|
|
|
RNS::Destination destination({RNS::Type::NONE});
|
2024-08-14 21:59:23 -06:00
|
|
|
RNS::Interface in_interface(new InInterface());
|
|
|
|
|
RNS::Interface out_interface(new OutInterface(in_interface));
|
2024-07-16 10:40:46 -06:00
|
|
|
|
2024-07-03 06:55:06 -06:00
|
|
|
void testReticulum() {
|
2024-07-03 11:30:01 -06:00
|
|
|
HEAD("Running testReticulum...", RNS::LOG_TRACE);
|
2024-07-03 06:55:06 -06:00
|
|
|
|
2025-08-21 17:29:26 -06:00
|
|
|
HEAD("Registering Filesystem with OS...", RNS::LOG_TRACE);
|
2026-01-21 12:38:13 -07:00
|
|
|
RNS::FileSystem reticulum_filesystem = new FileSystem();
|
2025-08-21 17:29:26 -06:00
|
|
|
((FileSystem*)reticulum_filesystem.get())->init();
|
|
|
|
|
RNS::Utilities::OS::register_filesystem(reticulum_filesystem);
|
|
|
|
|
|
2024-07-16 10:40:46 -06:00
|
|
|
HEAD("Registering Interface instances with Transport...", RNS::LOG_TRACE);
|
|
|
|
|
RNS::Transport::register_interface(in_interface);
|
|
|
|
|
RNS::Transport::register_interface(out_interface);
|
|
|
|
|
|
|
|
|
|
RNS::Bytes transport_prv_bytes;
|
|
|
|
|
#ifdef ARDUINO
|
|
|
|
|
transport_prv_bytes.assignHex("CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE");
|
|
|
|
|
#else
|
|
|
|
|
transport_prv_bytes.assignHex("BABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABEBABE");
|
|
|
|
|
#endif
|
|
|
|
|
RNS::Identity transport_identity(false);
|
|
|
|
|
transport_identity.load_private_key(transport_prv_bytes);
|
|
|
|
|
RNS::Transport::identity(transport_identity);
|
|
|
|
|
|
|
|
|
|
HEAD("Creating Reticulum instance...", RNS::LOG_TRACE);
|
2024-07-03 06:55:06 -06:00
|
|
|
reticulum = RNS::Reticulum();
|
|
|
|
|
reticulum.transport_enabled(true);
|
|
|
|
|
reticulum.probe_destination_enabled(true);
|
|
|
|
|
reticulum.start();
|
|
|
|
|
|
2024-07-16 10:40:46 -06:00
|
|
|
HEAD("Creating Identity instance...", RNS::LOG_TRACE);
|
|
|
|
|
// new identity
|
|
|
|
|
identity = RNS::Identity(false);
|
|
|
|
|
RNS::Bytes prv_bytes;
|
|
|
|
|
#ifdef ARDUINO
|
|
|
|
|
prv_bytes.assignHex("78E7D93E28D55871608FF13329A226CABC3903A357388A035B360162FF6321570B092E0583772AB80BC425F99791DF5CA2CA0A985FF0415DAB419BBC64DDFAE8");
|
|
|
|
|
#else
|
|
|
|
|
prv_bytes.assignHex("E0D43398EDC974EBA9F4A83463691A08F4D306D4E56BA6B275B8690A2FBD9852E9EBE7C03BC45CAEC9EF8E78C830037210BFB9986F6CA2DEE2B5C28D7B4DE6B0");
|
|
|
|
|
#endif
|
|
|
|
|
identity.load_private_key(prv_bytes);
|
|
|
|
|
// 22.6% (+0.7%)
|
|
|
|
|
|
|
|
|
|
HEAD("Creating Destination instance...", RNS::LOG_TRACE);
|
|
|
|
|
//RNS::Destination destination(identity, RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "app", "aspects");
|
|
|
|
|
destination = RNS::Destination(identity, RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "app", "aspects");
|
|
|
|
|
// 23.0% (+0.4%)
|
|
|
|
|
|
|
|
|
|
// Register DATA packet callback
|
|
|
|
|
HEAD("Registering packet callback with Destination...", RNS::LOG_TRACE);
|
|
|
|
|
destination.set_packet_callback(onPacket);
|
|
|
|
|
destination.set_proof_strategy(RNS::Type::Destination::PROVE_ALL);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// Register PING packet callback
|
|
|
|
|
HEAD("Creating PING Destination instance...", RNS::LOG_TRACE);
|
|
|
|
|
RNS::Destination ping_destination(identity, RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "example_utilities", "echo.request");
|
|
|
|
|
|
|
|
|
|
HEAD("Registering packet callback with PING Destination...", RNS::LOG_TRACE);
|
|
|
|
|
ping_destination.set_packet_callback(onPingPacket);
|
|
|
|
|
ping_destination.set_proof_strategy(RNS::Type::Destination::PROVE_ALL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HEAD("Registering announce handler with Transport...", RNS::LOG_TRACE);
|
|
|
|
|
RNS::Transport::register_announce_handler(announce_handler);
|
|
|
|
|
|
|
|
|
|
HEAD("Announcing destination...", RNS::LOG_TRACE);
|
|
|
|
|
// test path
|
|
|
|
|
//destination.announce(RNS::bytesFromString("test"), true, nullptr, RNS::bytesFromString("test_tag"));
|
|
|
|
|
// test packet send
|
|
|
|
|
destination.announce(RNS::bytesFromString("test"));
|
|
|
|
|
// 23.9% (+0.8%)
|
2024-07-03 06:55:06 -06:00
|
|
|
|
2025-08-26 21:05:36 -06:00
|
|
|
HEAD("Destroying Reticulum instance...", RNS::LOG_TRACE);
|
2024-07-03 06:55:06 -06:00
|
|
|
reticulum = {RNS::Type::NONE};
|
2026-01-21 12:38:13 -07:00
|
|
|
|
|
|
|
|
RNS::Utilities::OS::remove_file(destination_table_path);
|
2024-07-03 06:55:06 -06:00
|
|
|
}
|
|
|
|
|
|
2025-08-26 21:05:36 -06:00
|
|
|
|
2024-07-03 06:55:06 -06:00
|
|
|
void setUp(void) {
|
2025-08-26 21:05:36 -06:00
|
|
|
// set stuff up here before each test
|
2024-07-03 06:55:06 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tearDown(void) {
|
2025-08-26 21:05:36 -06:00
|
|
|
// clean stuff up here after each test
|
2024-07-03 06:55:06 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int runUnityTests(void) {
|
|
|
|
|
UNITY_BEGIN();
|
2025-08-26 21:05:36 -06:00
|
|
|
RUN_TEST(testReticulum);
|
2024-07-03 06:55:06 -06:00
|
|
|
return UNITY_END();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For native dev-platform or for some embedded frameworks
|
|
|
|
|
int main(void) {
|
|
|
|
|
return runUnityTests();
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-26 21:05:36 -06:00
|
|
|
#ifdef ARDUINO
|
2024-07-03 06:55:06 -06:00
|
|
|
// For Arduino framework
|
|
|
|
|
void setup() {
|
|
|
|
|
// Wait ~2 seconds before the Unity test runner
|
|
|
|
|
// establishes connection with a board Serial interface
|
|
|
|
|
delay(2000);
|
2025-08-26 21:05:36 -06:00
|
|
|
|
2024-07-03 06:55:06 -06:00
|
|
|
runUnityTests();
|
|
|
|
|
}
|
|
|
|
|
void loop() {}
|
2025-08-26 21:05:36 -06:00
|
|
|
#endif
|
2024-07-03 06:55:06 -06:00
|
|
|
|
|
|
|
|
// For ESP-IDF framework
|
|
|
|
|
void app_main() {
|
|
|
|
|
runUnityTests();
|
|
|
|
|
}
|