mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-01 22:38:19 +00:00
try to guard accidental region load command
This commit is contained in:
@@ -96,7 +96,7 @@ Regions control which flood packets the repeater forwards. The region tree is hi
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `region` | Export the current region map (indented text tree) |
|
||||
| `region load` | Enter interactive region load mode. Paste indented region lines; send a blank line to commit |
|
||||
| `region load` | Enter interactive region load mode. Paste indented region lines; send a blank line to commit. Any unindented command (e.g. `reboot`) aborts the load without committing, and then runs |
|
||||
| `region save` | Save the current region map to persistent storage |
|
||||
| `region def <token> [...]` | Cursor-walk bulk region builder — define a hierarchy in one line (see below) |
|
||||
| `region put <name> [<parent>]` | Create a region; default parent is the wildcard root. Flood is **allowed** by default (use `region denyf` to deny) |
|
||||
@@ -346,5 +346,5 @@ Changes are persisted immediately unless noted. Some require a reboot.
|
||||
|
||||
- **USB-only commands** — `get acl`, `get prv.key`, `set freq`, `log` (dump), `stats-packets`, `stats-radio`, `stats-core`, `erase` — are blocked when the command arrives over the mesh (remote admin). These are the only ones gated on `sender_timestamp == 0`; `get public.key` and `set prv.key` are **not** among them.
|
||||
- **Adaptive contention window** — `txdelay`, `rxdelay`, and `direct.txdelay` are accepted and stored for Arduino prefs compatibility but have no effect. Use `get txdelay` to inspect the current adaptive state and `set backoff.multiplier` to tune reactive backoff.
|
||||
- **Region load mode** — after `region load`, every line received is parsed as a region entry until a blank line is sent. The loaded map is only committed to the live region tree at that point; use `region save` to persist it.
|
||||
- **Region load mode** — after `region load`, every line received is parsed as a region entry until a blank line is sent. The loaded map is only committed to the live region tree at that point; use `region save` to persist it. Region rows must be indented by at least one space, so an **unindented line that starts with a name character aborts the mode and is executed as a normal command** — the escape hatch if a `region load` is started by accident or a client dies mid-transfer. An abort discards the partial map, leaving the live region tree untouched. The exported wildcard header line `*` stays unindented and is ignored as before, so pasting the output of `region` still loads cleanly.
|
||||
- **Reboot delay** — `start dfu`, `start ota` (nRF52 BLE-DFU path only), `reboot`, `clkreboot` and `erase` defer the reset by **2 seconds** so the reply can be transmitted over LoRa first. On a companion the handler then keeps deferring in 20 ms steps until the BLE/USB transport has drained, up to a further 3 s grace. On ESP32 `start ota` starts a WiFi AP + HTTP server and does **not** reboot.
|
||||
|
||||
@@ -1351,7 +1351,7 @@ void RepeaterMesh::resetDutyCycleTimeoutRestarts() {
|
||||
|
||||
void RepeaterMesh::handleCommand(uint32_t sender_timestamp, char* command, char* reply) {
|
||||
if (region_load_active) {
|
||||
handleRegionLoadLine(command, reply);
|
||||
handleRegionLoadLine(sender_timestamp, command, reply);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ class RepeaterMesh : public mesh::Mesh, public CommonCLICallbacks {
|
||||
/* Region-definition CLI (defined in app/RepeaterRegionCLI.cpp).
|
||||
* handleRegionLoadLine: a continuation line during `region load`.
|
||||
* handleRegionCommand: a `region ...` command. */
|
||||
void handleRegionLoadLine(char* command, char* reply);
|
||||
void handleRegionLoadLine(uint32_t sender_timestamp, char* command, char* reply);
|
||||
void handleRegionCommand(char* command, char* reply);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -57,7 +57,7 @@ static bool processRegionDefSegment(RegionMap* map, char* tok, RegionEntry** cur
|
||||
}
|
||||
/* ---------------------------------------- */
|
||||
|
||||
void RepeaterMesh::handleRegionLoadLine(char* command, char* reply) {
|
||||
void RepeaterMesh::handleRegionLoadLine(uint32_t sender_timestamp, char* command, char* reply) {
|
||||
if (StrHelper::isBlank(command)) {
|
||||
region_map = temp_map;
|
||||
region_load_active = false;
|
||||
@@ -67,6 +67,22 @@ void RepeaterMesh::handleRegionLoadLine(char* command, char* reply) {
|
||||
while (*np == ' ') np++;
|
||||
int indent = np - command;
|
||||
|
||||
/* An unindented, name-like line is a typed command, not a region row:
|
||||
* real rows are indent >= 1 (load_stack[0] is the wildcard), and the
|
||||
* one unindented line a client legitimately sends is the exported
|
||||
* wildcard header "*", whose '*' is not a name char. Without this,
|
||||
* `region load` is only escapable by a blank line -- which the USB
|
||||
* reader discards (main_repeater.cpp) and a dead remote-admin client
|
||||
* never sends, stranding the CLI until a reboot. Abort without
|
||||
* committing temp_map and run the command. Must come BEFORE the
|
||||
* name-terminator write below, which would truncate `set foo 1` to
|
||||
* `set`. */
|
||||
if (indent == 0 && RegionMap::is_name_char((uint8_t)*np)) {
|
||||
region_load_active = false;
|
||||
handleCommand(sender_timestamp, command, reply);
|
||||
return;
|
||||
}
|
||||
|
||||
char* ep = np;
|
||||
while (RegionMap::is_name_char(*ep)) ep++;
|
||||
if (*ep) { *ep++ = 0; }
|
||||
|
||||
@@ -1008,11 +1008,11 @@ void RoomServerMesh::resetDutyCycleTimeoutRestarts() {
|
||||
}
|
||||
|
||||
/* Region-def CLI (handleRegionLoadLine / handleRegionCommand) and its static
|
||||
* parser helpers live in app/RepeaterRegionCLI.cpp. */
|
||||
* parser helpers live in app/RoomServerRegionCLI.cpp. */
|
||||
|
||||
void RoomServerMesh::handleCommand(uint32_t sender_timestamp, char* command, char* reply) {
|
||||
if (region_load_active) {
|
||||
handleRegionLoadLine(command, reply);
|
||||
handleRegionLoadLine(sender_timestamp, command, reply);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -120,10 +120,10 @@ class RoomServerMesh : public mesh::Mesh, public CommonCLICallbacks {
|
||||
void sendFloodScoped(const TransportKey& scope, mesh::Packet* pkt, uint32_t delay_millis, uint8_t path_hash_size);
|
||||
void sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, uint8_t path_hash_size);
|
||||
|
||||
/* Region-definition CLI (defined in app/RepeaterRegionCLI.cpp).
|
||||
/* Region-definition CLI (defined in app/RoomServerRegionCLI.cpp).
|
||||
* handleRegionLoadLine: a continuation line during `region load`.
|
||||
* handleRegionCommand: a `region ...` command. */
|
||||
void handleRegionLoadLine(char* command, char* reply);
|
||||
void handleRegionLoadLine(uint32_t sender_timestamp, char* command, char* reply);
|
||||
void handleRegionCommand(char* command, char* reply);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -57,7 +57,7 @@ static bool processRegionDefSegment(RegionMap* map, char* tok, RegionEntry** cur
|
||||
}
|
||||
/* ---------------------------------------- */
|
||||
|
||||
void RoomServerMesh::handleRegionLoadLine(char* command, char* reply) {
|
||||
void RoomServerMesh::handleRegionLoadLine(uint32_t sender_timestamp, char* command, char* reply) {
|
||||
if (StrHelper::isBlank(command)) {
|
||||
region_map = temp_map;
|
||||
region_load_active = false;
|
||||
@@ -67,6 +67,22 @@ void RoomServerMesh::handleRegionLoadLine(char* command, char* reply) {
|
||||
while (*np == ' ') np++;
|
||||
int indent = np - command;
|
||||
|
||||
/* An unindented, name-like line is a typed command, not a region row:
|
||||
* real rows are indent >= 1 (load_stack[0] is the wildcard), and the
|
||||
* one unindented line a client legitimately sends is the exported
|
||||
* wildcard header "*", whose '*' is not a name char. Without this,
|
||||
* `region load` is only escapable by a blank line -- which the USB
|
||||
* reader discards (main_repeater.cpp) and a dead remote-admin client
|
||||
* never sends, stranding the CLI until a reboot. Abort without
|
||||
* committing temp_map and run the command. Must come BEFORE the
|
||||
* name-terminator write below, which would truncate `set foo 1` to
|
||||
* `set`. */
|
||||
if (indent == 0 && RegionMap::is_name_char((uint8_t)*np)) {
|
||||
region_load_active = false;
|
||||
handleCommand(sender_timestamp, command, reply);
|
||||
return;
|
||||
}
|
||||
|
||||
char* ep = np;
|
||||
while (RegionMap::is_name_char(*ep)) ep++;
|
||||
if (*ep) { *ep++ = 0; }
|
||||
|
||||
Reference in New Issue
Block a user