diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 2d441e6c..09399daf 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include /* ------------------------------ Config -------------------------------- */ @@ -271,10 +272,10 @@ protected: } else if (type == PAYLOAD_TYPE_TXT_MSG && len > 5) { // a CLI command uint32_t sender_timestamp; memcpy(&sender_timestamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong) - uint flags = data[4]; // message attempt number, and other flags + uint flags = (data[4] >> 2); // message attempt number, and other flags - if (flags != 0) { - MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported CLI text received: flags=%02x", (uint32_t)flags); + if (!(flags == TXT_TYPE_PLAIN || flags == TXT_TYPE_CLI_DATA)) { + MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported text type received: flags=%02x", (uint32_t)flags); } else if (sender_timestamp > client->last_timestamp) { // prevent replay attacks client->last_timestamp = sender_timestamp; @@ -303,7 +304,7 @@ protected: timestamp++; } memcpy(temp, ×tamp, 4); // mostly an extra blob to help make packet_hash unique - temp[4] = 0; + temp[4] = (TXT_TYPE_PLAIN << 2); // TODO: change this to TXT_TYPE_CLI_DATA soon // calc expected ACK reply //mesh::Utils::sha256((uint8_t *)&expected_ack_crc, 4, temp, 5 + text_len, self_id.pub_key, PUB_KEY_SIZE); diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index c885bac7..a5dc63e4 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include /* ------------------------------ Config -------------------------------- */ @@ -171,22 +172,13 @@ class MyMesh : public mesh::Mesh { next_push = futureMillis(PUSH_NOTIFY_DELAY_MILLIS); } - void handleCommand(ClientInfo* client, const char* command, char reply[]) { - if (*command == '+') { - addPost(client, &command[1], reply); - } else { - strcpy(reply, "?"); // unknown command - } - } - void pushPostToClient(ClientInfo* client, PostInfo& post) { int len = 0; memcpy(&reply_data[len], &post.post_timestamp, 4); len += 4; // this is a PAST timestamp... but should be accepted by client - reply_data[len++] = 0; // plain text + reply_data[len++] = (TXT_TYPE_SIGNED_PLAIN << 2); // 'signed' plain text - // encode prefix of post.author.pub_key (in hex) - mesh::Utils::toHex((char *) &reply_data[len], post.author.pub_key, 4); len += 8; // just first 4 bytes (8 hex chars) - reply_data[len++] = ':'; + // encode prefix of post.author.pub_key + memcpy(&reply_data[len], post.author.pub_key, 4); len += 4; // just first 4 bytes int text_len = strlen(post.text); memcpy(&reply_data[len], post.text, text_len); len += text_len; @@ -324,10 +316,10 @@ protected: if (type == PAYLOAD_TYPE_TXT_MSG && len > 5) { // a CLI command uint32_t sender_timestamp; memcpy(&sender_timestamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong) - uint flags = data[4]; // message attempt number, and other flags + uint flags = (data[4] >> 2); // message attempt number, and other flags - if (flags != 0) { - MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported command type received: flags=%02x", (uint32_t)flags); + if (!(flags == TXT_TYPE_PLAIN || flags == TXT_TYPE_CLI_DATA)) { + MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported command flags received: flags=%02x", (uint32_t)flags); } else if (sender_timestamp > client->last_timestamp) { // prevent replay attacks client->last_timestamp = sender_timestamp; @@ -350,12 +342,14 @@ protected: } uint8_t temp[166]; - if (client->is_admin) { - if (!handleAdminCommand(sender_timestamp, (const char *) &data[5], (char *) &temp[5])) { - handleCommand(client, (const char *) &data[5], (char *) &temp[5]); + if (flags == TXT_TYPE_CLI_DATA) { + if (client->is_admin) { + handleAdminCommand(sender_timestamp, (const char *) &data[5], (char *) &temp[5]); + } else { + strcpy((char *) &temp[5], "auth-err"); } - } else { - handleCommand(client, (const char *) &data[5], (char *) &temp[5]); + } else { // TXT_TYPE_PLAIN + addPost(client, (const char *) &data[5], (char *) &temp[5]); } int text_len = strlen((char *) &temp[5]); @@ -365,7 +359,7 @@ protected: now++; } memcpy(temp, &now, 4); // mostly an extra blob to help make packet_hash unique - temp[4] = 0; // attempt and flags + temp[4] = (TXT_TYPE_PLAIN << 2); // attempt and flags // calc expected ACK reply //mesh::Utils::sha256((uint8_t *)&expected_ack_crc, 4, temp, 5 + text_len, self_id.pub_key, PUB_KEY_SIZE); @@ -441,7 +435,7 @@ public: } } - bool handleAdminCommand(uint32_t sender_timestamp, const char* command, char reply[]) { + void handleAdminCommand(uint32_t sender_timestamp, const char* command, char reply[]) { while (*command == ' ') command++; // skip leading spaces if (memcmp(command, "reboot", 6) == 0) { @@ -471,11 +465,8 @@ public: } else if (memcmp(command, "ver", 3) == 0) { strcpy(reply, FIRMWARE_VER_TEXT); } else { - // unknown command - reply[0] = 0; - return false; + strcpy(reply, "?"); // unknown command } - return true; } void loop() { diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index a27468cb..17ba9638 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -68,9 +68,17 @@ #error "need to provide a 'board' object" #endif -/* -------------------------------------------------------------------------------------- */ +// Believe it or not, this std C function is busted on some platforms! +static uint32_t _atoi(const char* sp) { + uint32_t n = 0; + while (*sp && *sp >= '0' && *sp <= '9') { + n *= 10; + n += (*sp++ - '0'); + } + return n; +} -static int curr_contact_idx = 0; +/* -------------------------------------------------------------------------------------- */ class MyMesh : public BaseChatMesh, ContactVisitor { FILESYSTEM* _fs; @@ -148,6 +156,16 @@ class MyMesh : public BaseChatMesh, ContactVisitor { } } + void setClock(uint32_t timestamp) { + uint32_t curr = getRTCClock()->getCurrentTime(); + if (timestamp > curr) { + getRTCClock()->setCurrentTime(timestamp); + Serial.println(" (OK - clock set!)"); + } else { + Serial.println(" (ERR: clock cannot go backwards)"); + } + } + protected: void onDiscoveredContact(ContactInfo& contact, bool is_new) override { // TODO: if not in favs, prompt to add as fav(?) @@ -183,13 +201,7 @@ protected: Serial.printf(" %s\n", text); if (strcmp(text, "clock sync") == 0) { // special text command - uint32_t curr = getRTCClock()->getCurrentTime(); - if (sender_timestamp > curr) { - getRTCClock()->setCurrentTime(sender_timestamp + 1); - Serial.println(" (OK - clock set!)"); - } else { - Serial.println(" (ERR: clock cannot go backwards)"); - } + setClock(sender_timestamp + 1); } } @@ -305,6 +317,9 @@ public: self_name[sizeof(self_name)-1] = 0; IdentityStore store(*_fs, "/identity"); // update IdentityStore store.save("_main", self_id, self_name); + } else if (memcmp(command, "time ", 5) == 0) { // set time (to epoch seconds) + uint32_t secs = _atoi(&command[5]); + setClock(secs); } else if (memcmp(command, "to ", 3) == 0) { // set current recipient curr_recipient = searchContactsByPrefix(&command[3]); if (curr_recipient) { @@ -336,6 +351,7 @@ public: Serial.printf("Hello %s, Commands:\n", self_name); Serial.println(" name "); Serial.println(" clock"); + Serial.println(" time "); Serial.println(" list {n}"); Serial.println(" to "); Serial.println(" to"); diff --git a/src/helpers/AdvertDataHelpers.cpp b/src/helpers/AdvertDataHelpers.cpp index b6ad0bbf..5972bce2 100644 --- a/src/helpers/AdvertDataHelpers.cpp +++ b/src/helpers/AdvertDataHelpers.cpp @@ -46,7 +46,6 @@ if (nlen > 0) { memcpy(_name, &app_data[i], nlen); _name[nlen] = 0; // set null terminator - MESH_DEBUG_PRINTLN("AdvertDataParser: _flags=%u, _name=%s", (uint32_t)_flags, _name); } _valid = true; } diff --git a/src/helpers/TxtDataHelpers.h b/src/helpers/TxtDataHelpers.h new file mode 100644 index 00000000..667eb61a --- /dev/null +++ b/src/helpers/TxtDataHelpers.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +#define TXT_TYPE_PLAIN 0 // a plain text message +#define TXT_TYPE_CLI_DATA 1 // a CLI command +#define TXT_TYPE_SIGNED_PLAIN 2 // plain text, signed by sender