SensorMesh: add the possibility to receive msgs from admin
This commit is contained in:
@@ -613,6 +613,23 @@ void SensorMesh::getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SensorMesh::sendAckTo(const ContactInfo& dest, uint32_t ack_hash) {
|
||||||
|
if (dest.out_path_len < 0) {
|
||||||
|
mesh::Packet* ack = createAck(ack_hash);
|
||||||
|
if (ack) sendFlood(ack, TXT_ACK_DELAY);
|
||||||
|
} else {
|
||||||
|
uint32_t d = TXT_ACK_DELAY;
|
||||||
|
if (getExtraAckTransmitCount() > 0) {
|
||||||
|
mesh::Packet* a1 = createMultiAck(ack_hash, 1);
|
||||||
|
if (a1) sendDirect(a1, dest.out_path, dest.out_path_len, d);
|
||||||
|
d += 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh::Packet* a2 = createAck(ack_hash);
|
||||||
|
if (a2) sendDirect(a2, dest.out_path, dest.out_path_len, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) {
|
void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) {
|
||||||
int i = matching_peer_indexes[sender_idx];
|
int i = matching_peer_indexes[sender_idx];
|
||||||
if (i < 0 || i >= num_contacts) {
|
if (i < 0 || i >= num_contacts) {
|
||||||
@@ -656,38 +673,55 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
|
|||||||
memcpy(&sender_timestamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong)
|
memcpy(&sender_timestamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong)
|
||||||
uint flags = (data[4] >> 2); // message attempt number, and other flags
|
uint flags = (data[4] >> 2); // message attempt number, and other flags
|
||||||
|
|
||||||
if (!(flags == TXT_TYPE_CLI_DATA)) {
|
if (sender_timestamp > from.last_timestamp) { // prevent replay attacks
|
||||||
MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported text type received: flags=%02x", (uint32_t)flags);
|
if (flags == TXT_TYPE_PLAIN) {
|
||||||
} else if (sender_timestamp > from.last_timestamp) { // prevent replay attacks
|
bool handled = handleIncomingMsg(from, sender_timestamp, &data[5], flags, len - 5);
|
||||||
from.last_timestamp = sender_timestamp;
|
if (handled) { // if msg was handled then send an ack
|
||||||
from.last_activity = getRTCClock()->getCurrentTime();
|
uint32_t ack_hash; // calc truncated hash of the message timestamp + text + sender pub_key, to prove to sender that we got it
|
||||||
|
mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 5 + strlen((char *)&data[5]), from.id.pub_key, PUB_KEY_SIZE);
|
||||||
|
|
||||||
// len can be > original length, but 'text' will be padded with zeroes
|
if (packet->isRouteFlood()) {
|
||||||
data[len] = 0; // need to make a C string again, with null terminator
|
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK
|
||||||
|
mesh::Packet* path = createPathReturn(from.id, secret, packet->path, packet->path_len,
|
||||||
uint8_t temp[166];
|
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4);
|
||||||
char *command = (char *) &data[5];
|
if (path) sendFlood(path, TXT_ACK_DELAY);
|
||||||
char *reply = (char *) &temp[5];
|
|
||||||
handleCommand(sender_timestamp, command, reply);
|
|
||||||
|
|
||||||
int text_len = strlen(reply);
|
|
||||||
if (text_len > 0) {
|
|
||||||
uint32_t timestamp = getRTCClock()->getCurrentTimeUnique();
|
|
||||||
if (timestamp == sender_timestamp) {
|
|
||||||
// WORKAROUND: the two timestamps need to be different, in the CLI view
|
|
||||||
timestamp++;
|
|
||||||
}
|
|
||||||
memcpy(temp, ×tamp, 4); // mostly an extra blob to help make packet_hash unique
|
|
||||||
temp[4] = (TXT_TYPE_CLI_DATA << 2);
|
|
||||||
|
|
||||||
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from.id, secret, temp, 5 + text_len);
|
|
||||||
if (reply) {
|
|
||||||
if (from.out_path_len < 0) {
|
|
||||||
sendFlood(reply, CLI_REPLY_DELAY_MILLIS);
|
|
||||||
} else {
|
} else {
|
||||||
sendDirect(reply, from.out_path, from.out_path_len, CLI_REPLY_DELAY_MILLIS);
|
sendAckTo(from, ack_hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (flags == TXT_TYPE_CLI_DATA) {
|
||||||
|
from.last_timestamp = sender_timestamp;
|
||||||
|
from.last_activity = getRTCClock()->getCurrentTime();
|
||||||
|
|
||||||
|
// len can be > original length, but 'text' will be padded with zeroes
|
||||||
|
data[len] = 0; // need to make a C string again, with null terminator
|
||||||
|
|
||||||
|
uint8_t temp[166];
|
||||||
|
char *command = (char *) &data[5];
|
||||||
|
char *reply = (char *) &temp[5];
|
||||||
|
handleCommand(sender_timestamp, command, reply);
|
||||||
|
|
||||||
|
int text_len = strlen(reply);
|
||||||
|
if (text_len > 0) {
|
||||||
|
uint32_t timestamp = getRTCClock()->getCurrentTimeUnique();
|
||||||
|
if (timestamp == sender_timestamp) {
|
||||||
|
// WORKAROUND: the two timestamps need to be different, in the CLI view
|
||||||
|
timestamp++;
|
||||||
|
}
|
||||||
|
memcpy(temp, ×tamp, 4); // mostly an extra blob to help make packet_hash unique
|
||||||
|
temp[4] = (TXT_TYPE_CLI_DATA << 2);
|
||||||
|
|
||||||
|
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from.id, secret, temp, 5 + text_len);
|
||||||
|
if (reply) {
|
||||||
|
if (from.out_path_len < 0) {
|
||||||
|
sendFlood(reply, CLI_REPLY_DELAY_MILLIS);
|
||||||
|
} else {
|
||||||
|
sendDirect(reply, from.out_path, from.out_path_len, CLI_REPLY_DELAY_MILLIS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported text type received: flags=%02x", (uint32_t)flags);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MESH_DEBUG_PRINTLN("onPeerDataRecv: possible replay attack detected");
|
MESH_DEBUG_PRINTLN("onPeerDataRecv: possible replay attack detected");
|
||||||
@@ -695,6 +729,15 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SensorMesh::handleIncomingMsg(ContactInfo& from, uint32_t timestamp, uint8_t* data, uint flags, size_t len) {
|
||||||
|
MESH_DEBUG_PRINT("handleIncomingMsg: unhandled msg from ");
|
||||||
|
#ifdef MESH_DEBUG
|
||||||
|
mesh::Utils::printHex(Serial, from.id.pub_key, PUB_KEY_SIZE);
|
||||||
|
Serial.printf(": %s\n", data);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool SensorMesh::onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) {
|
bool SensorMesh::onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) {
|
||||||
int i = matching_peer_indexes[sender_idx];
|
int i = matching_peer_indexes[sender_idx];
|
||||||
if (i < 0 || i >= num_contacts) {
|
if (i < 0 || i >= num_contacts) {
|
||||||
|
|||||||
@@ -140,7 +140,8 @@ protected:
|
|||||||
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
|
void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override;
|
||||||
bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;
|
bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;
|
||||||
void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override;
|
void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override;
|
||||||
|
virtual bool handleIncomingMsg(ContactInfo& from, uint32_t timestamp, uint8_t* data, uint flags, size_t len);
|
||||||
|
void sendAckTo(const ContactInfo& dest, uint32_t ack_hash);
|
||||||
private:
|
private:
|
||||||
FILESYSTEM* _fs;
|
FILESYSTEM* _fs;
|
||||||
unsigned long next_local_advert, next_flood_advert;
|
unsigned long next_local_advert, next_flood_advert;
|
||||||
|
|||||||
Reference in New Issue
Block a user