* companion radio: connection status now supported (Keep_alive pings, etc)

This commit is contained in:
Scott Powell 2025-03-02 20:15:13 +11:00
parent 0a5bcb9e2c
commit 1a4063bbe8
4 changed files with 168 additions and 9 deletions

View file

@ -126,6 +126,8 @@ static uint32_t _atoi(const char* sp) {
#define CMD_SEND_RAW_DATA 25
#define CMD_SEND_LOGIN 26
#define CMD_SEND_STATUS_REQ 27
#define CMD_HAS_CONNECTION 28
#define CMD_LOGOUT 29 // 'Disconnect'
#define RESP_CODE_OK 0
#define RESP_CODE_ERR 1
@ -435,7 +437,7 @@ protected:
expected_ack_crc = 0; // reset our expected hash, now that we have received ACK
return true;
}
return false;
return checkConnectionsAck(data);
}
void queueMessage(const ContactInfo& from, uint8_t txt_type, uint8_t path_len, uint32_t sender_timestamp, const uint8_t* extra, int extra_len, const char *text) {
@ -465,14 +467,17 @@ protected:
}
void onMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override {
markConnectionActive(from); // in case this is from a server, and we have a connection
queueMessage(from, TXT_TYPE_PLAIN, path_len, sender_timestamp, NULL, 0, text);
}
void onCommandDataRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override {
markConnectionActive(from); // in case this is from a server, and we have a connection
queueMessage(from, TXT_TYPE_CLI_DATA, path_len, sender_timestamp, NULL, 0, text);
}
void onSignedMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override {
markConnectionActive(from);
saveContacts(); // from.sync_since change needs to be persisted
queueMessage(from, TXT_TYPE_SIGNED_PLAIN, path_len, sender_timestamp, sender_prefix, 4, text);
}
@ -513,7 +518,10 @@ protected:
out_frame[i++] = PUSH_CODE_LOGIN_SUCCESS;
out_frame[i++] = 0; // legacy: is_admin = false
} else if (data[4] == RESP_SERVER_LOGIN_OK) { // new login response
// keep_alive_interval = data[5] * 16
uint16_t keep_alive_secs = ((uint16_t)data[5]) * 16;
if (keep_alive_secs > 0) {
startConnection(contact, keep_alive_secs);
}
out_frame[i++] = PUSH_CODE_LOGIN_SUCCESS;
out_frame[i++] = data[6]; // permissions (eg. is_admin)
} else {
@ -1021,6 +1029,17 @@ public:
} else {
writeErrFrame(); // contact not found
}
} else if (cmd_frame[0] == CMD_HAS_CONNECTION && len >= 1+PUB_KEY_SIZE) {
uint8_t* pub_key = &cmd_frame[1];
if (hasConnectionTo(pub_key)) {
writeOKFrame();
} else {
writeErrFrame();
}
} else if (cmd_frame[0] == CMD_LOGOUT && len >= 1+PUB_KEY_SIZE) {
uint8_t* pub_key = &cmd_frame[1];
stopConnection(pub_key);
writeOKFrame();
} else {
writeErrFrame();
MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]);
@ -1050,6 +1069,8 @@ public:
_serial->writeFrame(out_frame, 5);
_iter_started = false;
}
} else if (!_serial->isWriteBusy()) {
checkConnections();
}
}
};

View file

@ -117,7 +117,8 @@ struct PostInfo {
#define CLIENT_KEEP_ALIVE_SECS 128
#define REQ_TYPE_KEEP_ALIVE 1
#define REQ_TYPE_GET_STATUS 0x01 // same as _GET_STATS
#define REQ_TYPE_KEEP_ALIVE 0x02
#define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ
@ -436,12 +437,11 @@ protected:
uint32_t forceSince = 0;
if (len >= 9) { // optional - last post_timestamp client received
memcpy(&forceSince, &data[5], 4); // NOTE: this may be 0, if part of decrypted PADDING!
} else {
memcpy(&data[5], &forceSince, 4); // make sure there are zeroes in payload (for ack_hash calc below)
}
if (forceSince > 0) {
client->sync_since = forceSince; // force-update the 'sync since'
len = 9; // for ACK hash calc below
} else {
len = 5; // for ACK hash calc below
}
uint32_t now = getRTCClock()->getCurrentTime();
@ -455,7 +455,7 @@ protected:
// RULE: only send keep_alive response DIRECT!
if (client->out_path_len >= 0) {
uint32_t ack_hash; // calc ACK to prove to sender that we got request
mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, len, client->id.pub_key, PUB_KEY_SIZE);
mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 9, client->id.pub_key, PUB_KEY_SIZE);
auto reply = createAck(ack_hash);
if (reply) {