From d07abc39b6bb402dea3ee1643ae0297c647fd226 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Mon, 24 Mar 2025 00:25:36 +1100 Subject: [PATCH] * room server: new config "allow.read.only" --- examples/simple_room_server/main.cpp | 38 +++++++++++++++++++--------- src/helpers/CommonCLI.cpp | 10 ++++++-- src/helpers/CommonCLI.h | 2 +- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 7aa495e1..12a576d2 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -79,6 +79,12 @@ /* ------------------------------ Code -------------------------------- */ +enum RoomPermission { + ADMIN, + GUEST, + READ_ONLY +}; + struct ClientInfo { mesh::Identity id; uint32_t last_timestamp; // by THEIR clock @@ -87,7 +93,7 @@ struct ClientInfo { uint32_t pending_ack; uint32_t push_post_timestamp; unsigned long ack_timeout; - bool is_admin; + RoomPermission permission; uint8_t push_failures; uint8_t secret[PUB_KEY_SIZE]; int out_path_len; @@ -299,13 +305,16 @@ protected: memcpy(&sender_timestamp, data, 4); memcpy(&sender_sync_since, &data[4], 4); // sender's "sync messags SINCE x" timestamp - bool is_admin; + RoomPermission perm; data[len] = 0; // ensure null terminator if (strcmp((char *) &data[8], _prefs.password) == 0) { // check for valid admin password - is_admin = true; + perm = RoomPermission::ADMIN; } else { - is_admin = false; - if (strcmp((char *) &data[8], _prefs.guest_password) != 0) { // check the room/public password + if (strcmp((char *) &data[8], _prefs.guest_password) == 0) { // check the room/public password + perm = RoomPermission::GUEST; + } else if (_prefs.allow_read_only) { + perm = RoomPermission::READ_ONLY; + } else { MESH_DEBUG_PRINTLN("Incorrect room password"); return; // no response. Client will timeout } @@ -318,7 +327,7 @@ protected: } MESH_DEBUG_PRINTLN("Login success!"); - client->is_admin = is_admin; + client->permission = perm; client->last_timestamp = sender_timestamp; client->sync_since = sender_sync_since; client->pending_ack = 0; @@ -332,7 +341,7 @@ protected: // TODO: maybe reply with count of messages waiting to be synced for THIS client? reply_data[4] = RESP_SERVER_LOGIN_OK; reply_data[5] = (CLIENT_KEEP_ALIVE_SECS >> 4); // NEW: recommended keep-alive interval (secs / 16) - reply_data[6] = is_admin ? 1 : 0; + reply_data[6] = (perm == RoomPermission::ADMIN ? 1 : (perm == RoomPermission::GUEST ? 0 : 2)); reply_data[7] = 0; // FUTURE: reserved memcpy(&reply_data[8], "OK", 2); // REVISIT: not really needed @@ -409,7 +418,7 @@ protected: uint8_t temp[166]; bool send_ack; if (flags == TXT_TYPE_CLI_DATA) { - if (client->is_admin) { + if (client->permission == RoomPermission::ADMIN) { if (is_retry) { temp[5] = 0; // no reply } else { @@ -422,11 +431,16 @@ protected: send_ack = false; // and no ACK... user shoudn't be sending these } } else { // TXT_TYPE_PLAIN - if (!is_retry) { - addPost(client, (const char *) &data[5]); + if (client->permission == RoomPermission::READ_ONLY) { + temp[5] = 0; // no reply + send_ack = false; // no ACK + } else { + if (!is_retry) { + addPost(client, (const char *) &data[5]); + } + temp[5] = 0; // no reply (ACK is enough) + send_ack = true; } - temp[5] = 0; // no reply (ACK is enough) - send_ack = true; } uint32_t delay_millis; diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index b9950dd1..b83bb26d 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -37,7 +37,7 @@ void CommonCLI::loadPrefs(FILESYSTEM* fs) { file.read(pad, 4); // 108 file.read((uint8_t *) &_prefs->sf, sizeof(_prefs->sf)); // 112 file.read((uint8_t *) &_prefs->cr, sizeof(_prefs->cr)); // 113 - file.read((uint8_t *) &_prefs->reserved1, sizeof(_prefs->reserved1)); // 114 + file.read((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114 file.read((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2)); // 115 file.read((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116 file.read(pad, 4); // 120 @@ -88,7 +88,7 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) { file.write(pad, 4); // 108 file.write((uint8_t *) &_prefs->sf, sizeof(_prefs->sf)); // 112 file.write((uint8_t *) &_prefs->cr, sizeof(_prefs->cr)); // 113 - file.write((uint8_t *) &_prefs->reserved1, sizeof(_prefs->reserved1)); // 114 + file.write((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114 file.write((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2)); // 115 file.write((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116 file.write(pad, 4); // 120 @@ -155,6 +155,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch const char* config = &command[4]; if (memcmp(config, "af", 2) == 0) { sprintf(reply, "> %s", StrHelper::ftoa(_prefs->airtime_factor)); + } else if (memcmp(config, "allow.read.only", 15) == 0) { + sprintf(reply, "> %s", _prefs->allow_read_only ? "on" : "off"); } else if (memcmp(config, "flood.advert.interval", 21) == 0) { sprintf(reply, "> %d", ((uint32_t) _prefs->flood_advert_interval)); } else if (memcmp(config, "advert.interval", 15) == 0) { @@ -195,6 +197,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch _prefs->airtime_factor = atof(&config[3]); savePrefs(); strcpy(reply, "OK"); + } else if (memcmp(config, "allow.read.only ", 16) == 0) { + _prefs->allow_read_only = memcmp(&config[16], "on", 2) == 0; + savePrefs(); + strcpy(reply, "OK"); } else if (memcmp(config, "flood.advert.interval ", 22) == 0) { int hours = _atoi(&config[22]); if (hours > 0 && hours < 3) { diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index 309ee134..4a6a6454 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -20,7 +20,7 @@ struct NodePrefs { // persisted to file uint32_t guard; uint8_t sf; uint8_t cr; - uint8_t reserved1; + uint8_t allow_read_only; uint8_t reserved2; float bw; uint8_t flood_max;