mirror of
https://github.com/Colorado-Mesh/meshcore-bot-firmware.git
synced 2026-08-11 08:10:29 +00:00
forge: step 12 — harden emergency forwarding
This commit is contained in:
@@ -0,0 +1,92 @@
|
|||||||
|
diff --git a/examples/companion_radio/BotTypes.h b/examples/companion_radio/BotTypes.h
|
||||||
|
index 5eb71c6..7ee34c8 100644
|
||||||
|
--- a/examples/companion_radio/BotTypes.h
|
||||||
|
+++ b/examples/companion_radio/BotTypes.h
|
||||||
|
@@ -17,8 +17,6 @@
|
||||||
|
#define BOT_COMMAND_COOLDOWN_MILLIS 5000UL
|
||||||
|
#define BOT_EMERGENCY_PREFIX "EMERGENCY MESSAGE FROM "
|
||||||
|
#define BOT_EMERGENCY_MAX_PARTS 3
|
||||||
|
-#define BOT_EMERGENCY_RATE_LIMIT_MILLIS 60000UL
|
||||||
|
-#define BOT_EMERGENCY_RATE_LIMIT_COUNT 3
|
||||||
|
#define BOT_PENDING_EMERGENCY_SLOTS BOT_EMERGENCY_MAX_PARTS
|
||||||
|
#define BOT_COORDINATOR_PENDING_SLOTS 8
|
||||||
|
#define BOT_COORDINATOR_RECENT_SLOTS 16
|
||||||
|
diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp
|
||||||
|
index 895be4b..89e130b 100644
|
||||||
|
--- a/examples/companion_radio/MyMesh.cpp
|
||||||
|
+++ b/examples/companion_radio/MyMesh.cpp
|
||||||
|
@@ -960,23 +960,7 @@ bool MyMesh::findBotChannel(BotChannelKind kind, uint8_t &channel_idx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool MyMesh::isEmergencyRateLimited() {
|
||||||
|
- unsigned long now = _ms->getMillis();
|
||||||
|
- if (!emergency_rate_window_started || millisHasNowPassed(emergency_rate_window_started + BOT_EMERGENCY_RATE_LIMIT_MILLIS)) {
|
||||||
|
- emergency_rate_window_started = now;
|
||||||
|
- emergency_rate_count = 0;
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
- return emergency_rate_count >= BOT_EMERGENCY_RATE_LIMIT_COUNT;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void MyMesh::recordEmergencyRateLimitEvent() {
|
||||||
|
- if (emergency_rate_count < 0xFF) emergency_rate_count++;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
bool MyMesh::enqueueEmergencyForward(const BotMessage &message) {
|
||||||
|
- if (isEmergencyRateLimited()) return false;
|
||||||
|
-
|
||||||
|
BotEmergencyForward forward;
|
||||||
|
if (!EmergencyForwarder::format(message, forward)) return false;
|
||||||
|
|
||||||
|
@@ -999,7 +983,6 @@ bool MyMesh::enqueueEmergencyForward(const BotMessage &message) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- recordEmergencyRateLimitEvent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1175,10 +1158,10 @@ void MyMesh::sendQueuedEmergencyForwards() {
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
bot_stats.emergency_forwards++;
|
||||||
|
+ pending->active = false;
|
||||||
|
} else {
|
||||||
|
bot_stats.emergency_forward_failures++;
|
||||||
|
}
|
||||||
|
- pending->active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1561,8 +1544,6 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
||||||
|
ResponseCoordinator::clear(bot_coordinator_pending, BOT_COORDINATOR_PENDING_SLOTS);
|
||||||
|
ResponseCoordinator::clearRecent(bot_coordinator_recent, BOT_COORDINATOR_RECENT_SLOTS);
|
||||||
|
KnownBotRegistry::clear(known_bot_entries, BOT_KNOWN_BOT_SLOTS);
|
||||||
|
- emergency_rate_window_started = 0;
|
||||||
|
- emergency_rate_count = 0;
|
||||||
|
next_bot_local_advert = 0;
|
||||||
|
next_bot_flood_advert = 0;
|
||||||
|
#endif
|
||||||
|
diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h
|
||||||
|
index e25f9a5..20497b7 100644
|
||||||
|
--- a/examples/companion_radio/MyMesh.h
|
||||||
|
+++ b/examples/companion_radio/MyMesh.h
|
||||||
|
@@ -218,8 +218,6 @@ private:
|
||||||
|
BotFingerprint response_fingerprint);
|
||||||
|
bool enqueueEmergencyForward(const BotMessage &message);
|
||||||
|
bool findBotChannel(BotChannelKind kind, uint8_t &channel_idx);
|
||||||
|
- bool isEmergencyRateLimited();
|
||||||
|
- void recordEmergencyRateLimitEvent();
|
||||||
|
void sendQueuedBotResponses();
|
||||||
|
void sendQueuedEmergencyForwards();
|
||||||
|
void tickBot();
|
||||||
|
@@ -285,8 +283,6 @@ private:
|
||||||
|
BotCoordinatorPending bot_coordinator_pending[BOT_COORDINATOR_PENDING_SLOTS];
|
||||||
|
BotCoordinatorRecent bot_coordinator_recent[BOT_COORDINATOR_RECENT_SLOTS];
|
||||||
|
BotKnownBotEntry known_bot_entries[BOT_KNOWN_BOT_SLOTS];
|
||||||
|
- unsigned long emergency_rate_window_started;
|
||||||
|
- uint8_t emergency_rate_count;
|
||||||
|
unsigned long next_bot_local_advert;
|
||||||
|
unsigned long next_bot_flood_advert;
|
||||||
|
#endif
|
||||||
@@ -65,6 +65,31 @@ require_pattern 'recordBotObservation\(|sendQueuedEmergencyForwards\(|tickBot\('
|
|||||||
"${MESHCORE_DIR}/examples/companion_radio/MyMesh.cpp"
|
"${MESHCORE_DIR}/examples/companion_radio/MyMesh.cpp"
|
||||||
require_pattern '_prefs\.path_hash_mode[[:space:]]*=[[:space:]]*1' 'bot firmware defaults to two-byte path hashes' \
|
require_pattern '_prefs\.path_hash_mode[[:space:]]*=[[:space:]]*1' 'bot firmware defaults to two-byte path hashes' \
|
||||||
"${MESHCORE_DIR}/examples/companion_radio/MyMesh.cpp"
|
"${MESHCORE_DIR}/examples/companion_radio/MyMesh.cpp"
|
||||||
|
if grep -R -n -E 'BOT_EMERGENCY_RATE_LIMIT|isEmergencyRateLimited|recordEmergencyRateLimitEvent|emergency_rate_window_started|emergency_rate_count' \
|
||||||
|
"${MESHCORE_DIR}/examples/companion_radio"; then
|
||||||
|
echo "Emergency forwarding must not be globally rate limited or dropped by a bot-local quota." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! python3 - "${MESHCORE_DIR}/examples/companion_radio/MyMesh.cpp" <<'PY'
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
text = open(sys.argv[1], encoding="utf-8").read()
|
||||||
|
start = text.find("void MyMesh::sendQueuedEmergencyForwards() {")
|
||||||
|
end = text.find("bool MyMesh::sendBotSelfAdvert", start)
|
||||||
|
if start < 0 or end < 0:
|
||||||
|
sys.exit(1)
|
||||||
|
body = text[start:end]
|
||||||
|
success_block = re.search(r"if \(success\) \{(?P<block>.*?)\n \} else \{", body, re.S)
|
||||||
|
if not success_block or "pending->active = false;" not in success_block.group("block"):
|
||||||
|
sys.exit(1)
|
||||||
|
else_block = re.search(r"\} else \{(?P<block>.*?)\n \}\n \}", body, re.S)
|
||||||
|
if else_block and "pending->active = false;" in else_block.group("block"):
|
||||||
|
sys.exit(1)
|
||||||
|
PY
|
||||||
|
then
|
||||||
|
echo "Emergency forwards must stay queued after failed public sends." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
require_pattern 'CMESH_BOT_ENABLED=1' 'production bot build flag is enabled' \
|
require_pattern 'CMESH_BOT_ENABLED=1' 'production bot build flag is enabled' \
|
||||||
"${MESHCORE_DIR}/platformio.ini"
|
"${MESHCORE_DIR}/platformio.ini"
|
||||||
require_pattern 'ENABLE_PRIVATE_KEY_IMPORT=0' 'private key import disabled in production bot flags' \
|
require_pattern 'ENABLE_PRIVATE_KEY_IMPORT=0' 'private key import disabled in production bot flags' \
|
||||||
|
|||||||
Reference in New Issue
Block a user