diff --git a/platformio.ini b/platformio.ini index e4dc544..ac10be7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -24,10 +24,10 @@ build_flags = -DRNS_CONTAINER_ALLOCATOR=RNS_PSRAM_POOL_ALLOCATOR -DRNS_PSRAM_POOL_BUFFER_SIZE=2048000 ; Raise microReticulum table caps — all containers go to 2MB PSRAM pool - -DRNS_KNOWN_DESTINATIONS_MAX=500 - -DRNS_HASHLIST_MAX=500 - -DRNS_PATH_TABLE_MAX=500 - -DRNS_ANNOUNCE_TABLE_MAX=500 + -DRNS_KNOWN_DESTINATIONS_MAX=256 + -DRNS_HASHLIST_MAX=256 + -DRNS_PATH_TABLE_MAX=256 + -DRNS_ANNOUNCE_TABLE_MAX=128 -DRNS_RECEIPTS_MAX=64 -DRNS_QUEUED_ANNOUNCES_MAX=64 -DRNS_RANDOM_BLOBS_MAX=128 diff --git a/src/config/Config.h b/src/config/Config.h index 8345190..51fe3d1 100644 --- a/src/config/Config.h +++ b/src/config/Config.h @@ -47,7 +47,7 @@ #define TCP_CONNECT_TIMEOUT_MS 5000 // --- Announce Flood Defense --- -#define RATDECK_MAX_ANNOUNCES_PER_SEC 8 // Transport-level rate limit (before Ed25519 verify) +#define RATDECK_MAX_ANNOUNCES_PER_SEC 5 // Transport-level rate limit (before Ed25519 verify) // --- Limits --- #define RATDECK_MAX_NODES 200 // PSRAM allows more diff --git a/src/main.cpp b/src/main.cpp index 877bc4e..51827ef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -895,12 +895,15 @@ void loop() { } // 4. Reticulum loop (radio RX via LoRaInterface) — throttle to ~100Hz + unsigned long rnsDuration = 0; { static unsigned long lastRNS = 0; unsigned long now = millis(); if (now - lastRNS >= 10) { lastRNS = now; + unsigned long rnsStart = millis(); rns.loop(); + rnsDuration = millis() - rnsStart; } } @@ -973,14 +976,17 @@ void loop() { } } - // 8. WiFi + TCP loops (with global budget) - if (wifiImpl) wifiImpl->loop(); + // 8. WiFi + TCP loops (with global budget) — skip if RNS was overloaded { - unsigned long tcpBudgetStart = millis(); - for (auto* tcp : tcpClients) { - if (millis() - tcpBudgetStart >= TCP_GLOBAL_BUDGET_MS) break; - tcp->loop(); - yield(); + bool skipTcp = (rnsDuration > 200); + if (!skipTcp && wifiImpl) wifiImpl->loop(); + if (!skipTcp) { + unsigned long tcpBudgetStart = millis(); + for (auto* tcp : tcpClients) { + if (millis() - tcpBudgetStart >= TCP_GLOBAL_BUDGET_MS) break; + tcp->loop(); + yield(); + } } } diff --git a/src/reticulum/ReticulumManager.cpp b/src/reticulum/ReticulumManager.cpp index a19e29b..eafe930 100644 --- a/src/reticulum/ReticulumManager.cpp +++ b/src/reticulum/ReticulumManager.cpp @@ -3,6 +3,8 @@ #include "config/Config.h" #include #include +#include +#include bool LittleFSFileSystem::init() { return true; } bool LittleFSFileSystem::file_exists(const char* p) { return LittleFS.exists(p); } @@ -98,15 +100,38 @@ bool ReticulumManager::begin(SX1262* radio, FlashStore* flash) { _reticulum.start(); Serial.println("[RNS] Reticulum started (Endpoint)"); - // Layer 1: Transport-level announce rate limiter — filters BEFORE Ed25519 verify + // Layer 1: Transport-level announce filter — runs BEFORE Ed25519 verify RNS::Transport::set_filter_packet_callback([](const RNS::Packet& packet) -> bool { - if (packet.packet_type() == RNS::Type::Packet::ANNOUNCE) { - static unsigned long windowStart = 0; - static unsigned int count = 0; - unsigned long now = millis(); - if (now - windowStart >= 1000) { windowStart = now; count = 0; } - if (++count > RATDECK_MAX_ANNOUNCES_PER_SEC) return false; + if (packet.packet_type() != RNS::Type::Packet::ANNOUNCE) return true; + + unsigned long now = millis(); + + // Rate limit window (per-second) + static unsigned long windowStart = 0; + static unsigned int count = 0; + if (now - windowStart >= 1000) { windowStart = now; count = 0; } + + // Adaptive rate: tighter during first 60s boot flood, then normal + unsigned int maxRate = (now < 60000) ? 3 : RATDECK_MAX_ANNOUNCES_PER_SEC; + if (++count > maxRate) return false; + + // Skip re-validation of known paths (saves ~100ms Ed25519 per announce) + // Allow through if hop count improved, or once per 5 min for name/ratchet updates + if (RNS::Transport::has_path(packet.destination_hash())) { + static std::map lastRevalidate; + std::string destHex = packet.destination_hash().toHex(); + + uint8_t existingHops = RNS::Transport::hops_to(packet.destination_hash()); + if (packet.hops() < existingHops) return true; // Better path, allow + + auto it = lastRevalidate.find(destHex); + if (it != lastRevalidate.end() && (now - it->second) < 300000) return false; + lastRevalidate[destHex] = now; + + // Cap map size to prevent unbounded growth + if (lastRevalidate.size() > 300) lastRevalidate.clear(); } + return true; });