self-limiting handlers fix

This commit is contained in:
liquidraver
2026-09-20 22:21:29 +02:00
parent bf3dad8737
commit ad23dcbdb6
4 changed files with 42 additions and 7 deletions
+6
View File
@@ -1371,11 +1371,17 @@ void RepeaterMesh::handleCommand(uint32_t sender_timestamp, char* command, char*
while (*command == ' ') command++;
uint8_t hdr_used = 0;
if (strlen(command) > 4 && command[2] == '|') {
memcpy(reply, command, 3);
reply += 3;
command += 3;
hdr_used = 3;
}
/* Tell the shared CLI how much of the caller's buffer is already spent, so
* the self-limiting handlers do not write past temp[5 + CLI_REMOTE_REPLY_SIZE].
* Set unconditionally: a stale value would shrink the next reply. */
_cli.setReplyHeaderUsed(hdr_used);
#if IS_ENABLED(CONFIG_ZEPHCORE_REPEATER_UPLINK) && IS_ENABLED(CONFIG_MQTT_LIB)
if (handleUplinkCommand(command, reply)) {
+6
View File
@@ -1030,11 +1030,17 @@ void RoomServerMesh::handleCommand(uint32_t sender_timestamp, char* command, cha
while (*command == ' ') command++;
uint8_t hdr_used = 0;
if (strlen(command) > 4 && command[2] == '|') {
memcpy(reply, command, 3);
reply += 3;
command += 3;
hdr_used = 3;
}
/* Tell the shared CLI how much of the caller's buffer is already spent, so
* the self-limiting handlers do not write past temp[5 + CLI_REMOTE_REPLY_SIZE].
* Set unconditionally: a stale value would shrink the next reply. */
_cli.setReplyHeaderUsed(hdr_used);
// ACL commands - supports BOTH formats for app compatibility:
// Old Arduino: setperm {pubkey-hex} {permissions} (pubkey is long, perms is short)
+10 -6
View File
@@ -683,9 +683,15 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
} else if (memcmp(config, "tz.offset", 9) == 0) {
snprintf(reply, CLI_REPLY_SIZE, "> %d", (int)_prefs->tz_offset);
} else if (memcmp(config, "gps diag", 8) == 0) {
// What the last module-configuration attempt actually did.
/* What the last module-configuration attempt actually did.
* Self-limits on the remote path like cad.stats/meshtimesync:
* gps_get_diag_report() bounds itself by the length it is
* handed, and the full report (long module version + wide
* counters + the no-GPS_SAT_DIAG tail) can exceed the
* caller's packet buffer. */
size_t cap = replyCap(sender_timestamp);
reply[0] = '>'; reply[1] = ' ';
gps_get_diag_report(reply + 2, CLI_REPLY_SIZE - 2);
gps_get_diag_report(reply + 2, cap - 2);
} else if (memcmp(config, "gps duty", 8) == 0) {
uint32_t s = gps_get_poll_interval_sec(); // now-effective value
if (s == 0) strcpy(reply, "> always on (0)");
@@ -706,8 +712,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
/* Runtime state + per-level probe stats live in the radio.
* ZephCore-only; must stay ahead of the "cad" prefix match below.
* Remote replies get the truncated buffer like meshtimesync. */
size_t cap = (sender_timestamp == 0) ? CLI_REPLY_SIZE
: CLI_REMOTE_REPLY_SIZE;
size_t cap = replyCap(sender_timestamp);
int n = snprintf(reply, cap, "> ");
if (_callbacks->formatCadStatus(reply + n, (int)cap - n) == 0) {
strcpy(reply, "not available");
@@ -758,8 +763,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
/* Only the local USB CLI (sender_timestamp == 0) gets the
* full evidence table; remote replies are truncated to the
* packet buffer. */
size_t cap = (sender_timestamp == 0) ? CLI_REPLY_SIZE
: CLI_REMOTE_REPLY_SIZE;
size_t cap = replyCap(sender_timestamp);
ts->formatStatus(reply, cap, getRTCClock()->getCurrentTime(),
(uint32_t)(k_uptime_get() / 1000),
_prefs->meshtimesync != 0);
+20 -1
View File
@@ -134,6 +134,18 @@ class CommonCLI {
int64_t _reboot_deadline_ms;
static void rebootWorkHandler(struct k_work *work);
/* Bytes the caller already consumed at the head of the reply buffer before
* handing it to us — see setReplyHeaderUsed(). */
uint8_t _reply_hdr_used;
/* Space a handler may write at `reply`, terminator included. Local USB
* gets the full buffer; a remote reply rides in the caller's packet buffer
* and must also leave room for whatever the caller wrote ahead of us. */
size_t replyCap(uint32_t sender_timestamp) const {
return (sender_timestamp == 0) ? CLI_REPLY_SIZE
: (CLI_REMOTE_REPLY_SIZE - _reply_hdr_used);
}
mesh::RTCClock* getRTCClock() { return _rtc; }
void savePrefs();
void scheduleReboot(uint8_t type);
@@ -142,11 +154,18 @@ public:
CommonCLI(mesh::MainBoard& board, mesh::RTCClock& rtc, ClientACL& acl,
NodePrefs* prefs, CommonCLICallbacks* callbacks)
: _board(&board), _rtc(&rtc), _acl(&acl), _prefs(prefs), _callbacks(callbacks),
_pending_reboot(REBOOT_NONE), _reboot_deadline_ms(0)
_pending_reboot(REBOOT_NONE), _reboot_deadline_ms(0), _reply_hdr_used(0)
{
k_work_init_delayable(&_reboot_work, rebootWorkHandler);
}
/* Roles that strip the `XX|` request-tag prefix echo those 3 bytes into the
* head of the reply buffer and advance `reply` past them before calling us.
* Their buffer is still only 5 + CLI_REMOTE_REPLY_SIZE, so the self-limiting
* handlers have to subtract what was already written or they overrun it.
* Call this on EVERY dispatch, with 0 when no prefix was stripped. */
void setReplyHeaderUsed(uint8_t n) { _reply_hdr_used = n; }
void handleCommand(uint32_t sender_timestamp, const char* command, char* reply);
uint8_t buildAdvertData(uint8_t node_type, uint8_t* app_data);