diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index 33cb1b43e..972ecb005 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -696,7 +696,6 @@ bool MyMesh::addFilterChannel(const char *psk) { if (len != 16 && len != 32) return false; mesh::Utils::sha256(ch->hash, sizeof(ch->hash), ch->secret, len); - StrHelper::strncpy(filter_channel_psk[num_filter_channels], psk, FILTER_PSK_LEN); num_filter_channels++; return true; } @@ -781,32 +780,64 @@ void MyMesh::loadChannelFilter() { #endif if (!f) return; - char line[FILTER_PSK_LEN + 8]; - while (f.available()) { - int n = f.readBytesUntil('\n', (uint8_t *)line, sizeof(line) - 1); - line[n] = 0; - while (n > 0 && (line[n - 1] == '\r' || line[n - 1] == ' ')) line[--n] = 0; - if (n < 3 || line[1] != ' ') continue; - - const char *val = &line[2]; - if (line[0] == 'C') { - addFilterChannel(val); - } else if (line[0] == 'K' && num_block_keywords < MAX_FILTER_TERMS) { - StrHelper::strncpy(block_keywords[num_block_keywords++], val, FILTER_TERM_LEN); - } else if (line[0] == 'S' && num_block_senders < MAX_FILTER_TERMS) { - StrHelper::strncpy(block_senders[num_block_senders++], val, FILTER_TERM_LEN); - } + if (f.read() != CHANNEL_FILTER_FMT) { f.close(); return; } // unknown/legacy file -> start empty + + int n = f.read(); + if (n < 0 || n > MAX_FILTER_CHANNELS) { f.close(); return; } + for (int i = 0; i < n; i++) { + auto ch = &filter_channels[num_filter_channels]; + if (f.readBytes((char *)ch->hash, sizeof(ch->hash)) != sizeof(ch->hash)) break; + if (f.readBytes((char *)ch->secret, sizeof(ch->secret)) != sizeof(ch->secret)) break; + num_filter_channels++; + } + + n = f.read(); + if (n < 0 || n > MAX_FILTER_TERMS) { f.close(); return; } + for (int i = 0; i < n; i++) { + int l = f.read(); + if (l < 0 || l >= FILTER_TERM_LEN) break; + if (f.readBytes(block_keywords[num_block_keywords], l) != (size_t)l) break; + block_keywords[num_block_keywords][l] = 0; + num_block_keywords++; + } + + n = f.read(); + if (n < 0 || n > MAX_FILTER_TERMS) { f.close(); return; } + for (int i = 0; i < n; i++) { + int l = f.read(); + if (l < 0 || l >= FILTER_TERM_LEN) break; + if (f.readBytes(block_senders[num_block_senders], l) != (size_t)l) break; + block_senders[num_block_senders][l] = 0; + num_block_senders++; } f.close(); } +// Binary layout: [fmt][n_chan]{hash[1] secret[32]}* [n_kw]{len text}* [n_snd]{len text}* +// Channel keys are never displayed, so the decoded GroupChannel is stored directly +// rather than the original PSK string. void MyMesh::saveChannelFilter() { _fs->remove(CHANNEL_FILTER_FILE); File f = openAppend(CHANNEL_FILTER_FILE); if (!f) return; - for (int i = 0; i < num_filter_channels; i++) f.printf("C %s\n", filter_channel_psk[i]); - for (int i = 0; i < num_block_keywords; i++) f.printf("K %s\n", block_keywords[i]); - for (int i = 0; i < num_block_senders; i++) f.printf("S %s\n", block_senders[i]); + f.write((uint8_t)CHANNEL_FILTER_FMT); + f.write((uint8_t)num_filter_channels); + for (int i = 0; i < num_filter_channels; i++) { + f.write(filter_channels[i].hash, sizeof(filter_channels[i].hash)); + f.write(filter_channels[i].secret, sizeof(filter_channels[i].secret)); + } + f.write((uint8_t)num_block_keywords); + for (int i = 0; i < num_block_keywords; i++) { + uint8_t l = strlen(block_keywords[i]); + f.write(l); + f.write((const uint8_t *)block_keywords[i], l); + } + f.write((uint8_t)num_block_senders); + for (int i = 0; i < num_block_senders; i++) { + uint8_t l = strlen(block_senders[i]); + f.write(l); + f.write((const uint8_t *)block_senders[i], l); + } f.close(); } diff --git a/examples/simple_repeater/MyMesh.h b/examples/simple_repeater/MyMesh.h index 97c8cefff..a62592259 100644 --- a/examples/simple_repeater/MyMesh.h +++ b/examples/simple_repeater/MyMesh.h @@ -90,7 +90,7 @@ struct NeighbourInfo { #define MAX_FILTER_TERMS 8 #endif #define FILTER_TERM_LEN 24 -#define FILTER_PSK_LEN 68 // fits a 64-char hex key, a 44-char base64 PSK, or "public" +#define CHANNEL_FILTER_FMT 1 // on-disk format version for CHANNEL_FILTER_FILE #endif class MyMesh : public mesh::Mesh, public CommonCLICallbacks { @@ -129,7 +129,6 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { #ifdef WITH_CHANNEL_FILTER mesh::GroupChannel filter_channels[MAX_FILTER_CHANNELS]; - char filter_channel_psk[MAX_FILTER_CHANNELS][FILTER_PSK_LEN]; uint8_t num_filter_channels; char block_keywords[MAX_FILTER_TERMS][FILTER_TERM_LEN]; uint8_t num_block_keywords;