diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index 897290cc..0fb5825e 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -636,6 +636,17 @@ void DataStore::loadChannels(DataStoreHost* host) { if (!success) break; // EOF + // Sanitize scope_name — reject if it contains non-region characters + // (catches garbage from uninitialised memory in early channels3 files) + ch.scope_name[30] = '\0'; // force null-terminate + for (int s = 0; ch.scope_name[s]; s++) { + char sc = ch.scope_name[s]; + if (!((sc >= 'a' && sc <= 'z') || (sc >= '0' && sc <= '9') || sc == '-')) { + memset(ch.scope_name, 0, sizeof(ch.scope_name)); // invalid — clear + break; + } + } + if (host->onChannelLoaded(channel_idx, ch)) { channel_idx++; } else { diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index e0242cc7..ef0542cb 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -1633,6 +1633,17 @@ void MyMesh::handleCmdFrame(size_t len) { memcpy(&secs, &cmd_frame[1], 4); uint32_t curr = getRTCClock()->getCurrentTime(); if (secs >= curr) { + // Adjust stored advert timestamps if clock jumps significantly + if (advert_paths && secs > curr + 60) { + uint32_t delta = secs - curr; + for (int i = 0; i < ADVERT_PATH_TABLE_SIZE; i++) { + if (advert_paths[i].recv_timestamp > 0) { + advert_paths[i].recv_timestamp += delta; + } + } + Serial.printf("[ClockSync] Adjusted %d advert timestamps by +%lu seconds\n", + ADVERT_PATH_TABLE_SIZE, (unsigned long)delta); + } getRTCClock()->setCurrentTime(secs); writeOKFrame(); } else { @@ -2105,6 +2116,11 @@ void MyMesh::handleCmdFrame(size_t len) { } else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 2 + 32 + 16) { uint8_t channel_idx = cmd_frame[1]; ChannelDetails channel; + // Preserve existing scope_name if channel already exists + ChannelDetails existing; + if (getChannel(channel_idx, existing) && existing.name[0] != '\0') { + memcpy(channel.scope_name, existing.scope_name, sizeof(channel.scope_name)); + } StrHelper::strncpy(channel.name, (char *)&cmd_frame[2], 32); memset(channel.channel.secret, 0, sizeof(channel.channel.secret)); memcpy(channel.channel.secret, &cmd_frame[2 + 32], 16); // NOTE: only 128-bit supported @@ -3054,6 +3070,17 @@ void MyMesh::checkCLIRescueCmd() { } else if (memcmp(cli_command, "clock sync ", 11) == 0) { uint32_t epoch = (uint32_t)strtoul(&cli_command[11], nullptr, 10); if (epoch > 1704067200UL && epoch < 2082758400UL) { + // Adjust stored advert timestamps if clock jumps significantly + uint32_t curr = getRTCClock()->getCurrentTime(); + if (advert_paths && epoch > curr + 60) { + uint32_t delta = epoch - curr; + for (int i = 0; i < ADVERT_PATH_TABLE_SIZE; i++) { + if (advert_paths[i].recv_timestamp > 0) { + advert_paths[i].recv_timestamp += delta; + } + } + Serial.printf(" > adjusted advert timestamps by +%lu seconds\n", (unsigned long)delta); + } getRTCClock()->setCurrentTime(epoch); Serial.printf(" > clock synced to %lu\n", (unsigned long)epoch); } else { diff --git a/src/helpers/ChannelDetails.h b/src/helpers/ChannelDetails.h index 528f06ef..de290646 100644 --- a/src/helpers/ChannelDetails.h +++ b/src/helpers/ChannelDetails.h @@ -7,4 +7,6 @@ struct ChannelDetails { mesh::GroupChannel channel; char name[32]; char scope_name[31]; // Region scope name (e.g. "au-nsw"), empty = use device default + + ChannelDetails() { memset(name, 0, sizeof(name)); memset(scope_name, 0, sizeof(scope_name)); } }; \ No newline at end of file