* redesigned TRACE packet structure
This commit is contained in:
@@ -710,10 +710,6 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) override {
|
|
||||||
// TODO: write an out_frame
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const override {
|
uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const override {
|
||||||
return SEND_TIMEOUT_BASE_MILLIS + (FLOOD_SEND_TIMEOUT_FACTOR * pkt_airtime_millis);
|
return SEND_TIMEOUT_BASE_MILLIS + (FLOOD_SEND_TIMEOUT_FACTOR * pkt_airtime_millis);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,8 +273,6 @@ protected:
|
|||||||
if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH || pkt->getPayloadType() == PAYLOAD_TYPE_REQ
|
if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH || pkt->getPayloadType() == PAYLOAD_TYPE_REQ
|
||||||
|| pkt->getPayloadType() == PAYLOAD_TYPE_RESPONSE || pkt->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) {
|
|| pkt->getPayloadType() == PAYLOAD_TYPE_RESPONSE || pkt->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) {
|
||||||
f.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[1], (uint32_t)pkt->payload[0]);
|
f.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[1], (uint32_t)pkt->payload[0]);
|
||||||
} else if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) {
|
|
||||||
f.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[2], (uint32_t)pkt->payload[1]);
|
|
||||||
} else {
|
} else {
|
||||||
f.printf("\n");
|
f.printf("\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,10 +285,6 @@ protected:
|
|||||||
// not supported
|
// not supported
|
||||||
}
|
}
|
||||||
|
|
||||||
void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) override {
|
|
||||||
// TODO: write an out_frame
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const override {
|
uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const override {
|
||||||
return SEND_TIMEOUT_BASE_MILLIS + (FLOOD_SEND_TIMEOUT_FACTOR * pkt_airtime_millis);
|
return SEND_TIMEOUT_BASE_MILLIS + (FLOOD_SEND_TIMEOUT_FACTOR * pkt_airtime_millis);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,8 +140,6 @@ void Dispatcher::checkRecv() {
|
|||||||
if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH || pkt->getPayloadType() == PAYLOAD_TYPE_REQ
|
if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH || pkt->getPayloadType() == PAYLOAD_TYPE_REQ
|
||||||
|| pkt->getPayloadType() == PAYLOAD_TYPE_RESPONSE || pkt->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) {
|
|| pkt->getPayloadType() == PAYLOAD_TYPE_RESPONSE || pkt->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) {
|
||||||
Serial.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[1], (uint32_t)pkt->payload[0]);
|
Serial.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[1], (uint32_t)pkt->payload[0]);
|
||||||
} else if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) {
|
|
||||||
Serial.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[2], (uint32_t)pkt->payload[1]);
|
|
||||||
} else {
|
} else {
|
||||||
Serial.printf("\n");
|
Serial.printf("\n");
|
||||||
}
|
}
|
||||||
|
|||||||
99
src/Mesh.cpp
99
src/Mesh.cpp
@@ -41,6 +41,30 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
|||||||
return ACTION_RELEASE;
|
return ACTION_RELEASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pkt->isRouteDirect() && pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) {
|
||||||
|
if (pkt->path_len < MAX_PATH_SIZE) {
|
||||||
|
uint8_t i = 0;
|
||||||
|
uint32_t trace_tag;
|
||||||
|
memcpy(&trace_tag, &pkt->payload[i], 4); i += 4;
|
||||||
|
uint32_t auth_code;
|
||||||
|
memcpy(&auth_code, &pkt->payload[i], 4); i += 4;
|
||||||
|
uint8_t flags = pkt->payload[i++];
|
||||||
|
|
||||||
|
uint8_t len = pkt->payload_len - i;
|
||||||
|
if (pkt->path_len >= len) { // TRACE has reached end of given path
|
||||||
|
onTraceRecv(pkt, trace_tag, auth_code, flags, pkt->path, &pkt->payload[i], len);
|
||||||
|
} else if (self_id.isHashMatch(&pkt->payload[i + pkt->path_len]) && allowPacketForward(pkt) && !_tables->hasSeen(pkt)) {
|
||||||
|
// append SNR (Not hash!)
|
||||||
|
pkt->path[pkt->path_len] = (int8_t) (pkt->getSNR()*4);
|
||||||
|
pkt->path_len += PATH_HASH_SIZE;
|
||||||
|
|
||||||
|
uint32_t d = getDirectRetransmitDelay(pkt);
|
||||||
|
return ACTION_RETRANSMIT_DELAYED(5, d); // schedule with priority 5 (for now), maybe make configurable?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ACTION_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
if (pkt->isRouteDirect() && pkt->path_len >= PATH_HASH_SIZE) {
|
if (pkt->isRouteDirect() && pkt->path_len >= PATH_HASH_SIZE) {
|
||||||
if (self_id.isHashMatch(pkt->path) && allowPacketForward(pkt)) {
|
if (self_id.isHashMatch(pkt->path) && allowPacketForward(pkt)) {
|
||||||
if (_tables->hasSeen(pkt)) return ACTION_RELEASE; // don't retransmit!
|
if (_tables->hasSeen(pkt)) return ACTION_RELEASE; // don't retransmit!
|
||||||
@@ -49,16 +73,6 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
|||||||
pkt->path_len -= PATH_HASH_SIZE;
|
pkt->path_len -= PATH_HASH_SIZE;
|
||||||
memcpy(pkt->path, &pkt->path[PATH_HASH_SIZE], pkt->path_len);
|
memcpy(pkt->path, &pkt->path[PATH_HASH_SIZE], pkt->path_len);
|
||||||
|
|
||||||
if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE && pkt->payload_len + PATH_HASH_SIZE+1 < MAX_PACKET_PAYLOAD) {
|
|
||||||
if ((pkt->payload[0] & 3) == 0) {
|
|
||||||
// append our hash + SNR
|
|
||||||
pkt->payload_len += self_id.copyHashTo(&pkt->payload[pkt->payload_len]);
|
|
||||||
pkt->payload[pkt->payload_len++] = (int8_t) (pkt->getSNR()*4);
|
|
||||||
} else {
|
|
||||||
// unknown flags:type, don't append any info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t d = getDirectRetransmitDelay(pkt);
|
uint32_t d = getDirectRetransmitDelay(pkt);
|
||||||
return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority
|
return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority
|
||||||
}
|
}
|
||||||
@@ -80,16 +94,11 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PAYLOAD_TYPE_TRACE:
|
|
||||||
case PAYLOAD_TYPE_PATH:
|
case PAYLOAD_TYPE_PATH:
|
||||||
case PAYLOAD_TYPE_REQ:
|
case PAYLOAD_TYPE_REQ:
|
||||||
case PAYLOAD_TYPE_RESPONSE:
|
case PAYLOAD_TYPE_RESPONSE:
|
||||||
case PAYLOAD_TYPE_TXT_MSG: {
|
case PAYLOAD_TYPE_TXT_MSG: {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) {
|
|
||||||
//uint8_t flags = pkt->payload[i]; // reserved for now
|
|
||||||
i++; // skip over
|
|
||||||
}
|
|
||||||
uint8_t dest_hash = pkt->payload[i++];
|
uint8_t dest_hash = pkt->payload[i++];
|
||||||
uint8_t src_hash = pkt->payload[i++];
|
uint8_t src_hash = pkt->payload[i++];
|
||||||
|
|
||||||
@@ -112,12 +121,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
|||||||
|
|
||||||
// decrypt, checking MAC is valid
|
// decrypt, checking MAC is valid
|
||||||
uint8_t data[MAX_PACKET_PAYLOAD];
|
uint8_t data[MAX_PACKET_PAYLOAD];
|
||||||
int len;
|
int len = Utils::MACThenDecrypt(secret, data, macAndData, pkt->payload_len - i);
|
||||||
if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) {
|
|
||||||
len = Utils::MACThenDecrypt(secret, data, macAndData, CIPHER_MAC_SIZE+CIPHER_BLOCK_SIZE); // encrypted part is fixed-len
|
|
||||||
} else {
|
|
||||||
len = Utils::MACThenDecrypt(secret, data, macAndData, pkt->payload_len - i);
|
|
||||||
}
|
|
||||||
if (len > 0) { // success!
|
if (len > 0) { // success!
|
||||||
if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH) {
|
if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH) {
|
||||||
int k = 0;
|
int k = 0;
|
||||||
@@ -133,8 +137,6 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
|||||||
if (rpath) sendDirect(rpath, path, path_len);
|
if (rpath) sendDirect(rpath, path, path_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) {
|
|
||||||
onPeerTraceRecv(pkt, j, secret, data);
|
|
||||||
} else {
|
} else {
|
||||||
onPeerDataRecv(pkt, pkt->getPayloadType(), j, secret, data, len);
|
onPeerDataRecv(pkt, pkt->getPayloadType(), j, secret, data, len);
|
||||||
}
|
}
|
||||||
@@ -265,16 +267,6 @@ DispatcherAction Mesh::routeRecvPacket(Packet* packet) {
|
|||||||
// append this node's hash to 'path'
|
// append this node's hash to 'path'
|
||||||
packet->path_len += self_id.copyHashTo(&packet->path[packet->path_len]);
|
packet->path_len += self_id.copyHashTo(&packet->path[packet->path_len]);
|
||||||
|
|
||||||
if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE && (packet->payload[0] & 3) != 0) {
|
|
||||||
// flags:type must be zero (otherwise, some future/unknown sub-type)
|
|
||||||
return ACTION_RELEASE; // don't forward, just discard
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE && packet->payload_len + 1 < MAX_PACKET_PAYLOAD) {
|
|
||||||
// append packet SNR
|
|
||||||
packet->payload[packet->payload_len++] = (int8_t) (packet->getSNR()*4);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t d = getRetransmitDelay(packet);
|
uint32_t d = getRetransmitDelay(packet);
|
||||||
// as this propagates outwards, give it lower and lower priority
|
// as this propagates outwards, give it lower and lower priority
|
||||||
return ACTION_RETRANSMIT_DELAYED(packet->path_len, d); // give priority to closer sources, than ones further away
|
return ACTION_RETRANSMIT_DELAYED(packet->path_len, d); // give priority to closer sources, than ones further away
|
||||||
@@ -364,7 +356,7 @@ Packet* Mesh::createPathReturn(const uint8_t* dest_hash, const uint8_t* secret,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t data_len) {
|
Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t data_len) {
|
||||||
if (type == PAYLOAD_TYPE_TXT_MSG || type == PAYLOAD_TYPE_REQ || type == PAYLOAD_TYPE_RESPONSE || type == PAYLOAD_TYPE_TRACE) {
|
if (type == PAYLOAD_TYPE_TXT_MSG || type == PAYLOAD_TYPE_REQ || type == PAYLOAD_TYPE_RESPONSE) {
|
||||||
if (data_len + CIPHER_MAC_SIZE + CIPHER_BLOCK_SIZE-1 > MAX_PACKET_PAYLOAD) return NULL;
|
if (data_len + CIPHER_MAC_SIZE + CIPHER_BLOCK_SIZE-1 > MAX_PACKET_PAYLOAD) return NULL;
|
||||||
} else {
|
} else {
|
||||||
return NULL; // invalid type
|
return NULL; // invalid type
|
||||||
@@ -378,9 +370,6 @@ Packet* Mesh::createDatagram(uint8_t type, const Identity& dest, const uint8_t*
|
|||||||
packet->header = (type << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
|
packet->header = (type << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
|
||||||
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
if (type == PAYLOAD_TYPE_TRACE) {
|
|
||||||
packet->payload[len++] = 0; // reserved: flags:type
|
|
||||||
}
|
|
||||||
len += dest.copyHashTo(&packet->payload[len]); // dest hash
|
len += dest.copyHashTo(&packet->payload[len]); // dest hash
|
||||||
len += self_id.copyHashTo(&packet->payload[len]); // src hash
|
len += self_id.copyHashTo(&packet->payload[len]); // src hash
|
||||||
len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len);
|
len += Utils::encryptThenMAC(secret, &packet->payload[len], data, data_len);
|
||||||
@@ -468,7 +457,28 @@ Packet* Mesh::createRawData(const uint8_t* data, size_t len) {
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Packet* Mesh::createTrace(uint32_t tag, uint32_t auth_code, uint8_t flags) {
|
||||||
|
Packet* packet = obtainNewPacket();
|
||||||
|
if (packet == NULL) {
|
||||||
|
MESH_DEBUG_PRINTLN("%s Mesh::createTrace(): error, packet pool empty", getLogDateTime());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
packet->header = (PAYLOAD_TYPE_TRACE << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
|
||||||
|
|
||||||
|
memcpy(packet->payload, &tag, 4);
|
||||||
|
memcpy(&packet->payload[4], &auth_code, 4);
|
||||||
|
packet->payload[8] = flags;
|
||||||
|
packet->payload_len = 9; // NOTE: path will be appended to payload[] later
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
void Mesh::sendFlood(Packet* packet, uint32_t delay_millis) {
|
void Mesh::sendFlood(Packet* packet, uint32_t delay_millis) {
|
||||||
|
if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE) {
|
||||||
|
MESH_DEBUG_PRINTLN("%s Mesh::sendFlood(): TRACE type not suspported", getLogDateTime());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
packet->header &= ~PH_ROUTE_MASK;
|
packet->header &= ~PH_ROUTE_MASK;
|
||||||
packet->header |= ROUTE_TYPE_FLOOD;
|
packet->header |= ROUTE_TYPE_FLOOD;
|
||||||
packet->path_len = 0;
|
packet->path_len = 0;
|
||||||
@@ -490,11 +500,20 @@ void Mesh::sendDirect(Packet* packet, const uint8_t* path, uint8_t path_len, uin
|
|||||||
packet->header &= ~PH_ROUTE_MASK;
|
packet->header &= ~PH_ROUTE_MASK;
|
||||||
packet->header |= ROUTE_TYPE_DIRECT;
|
packet->header |= ROUTE_TYPE_DIRECT;
|
||||||
|
|
||||||
memcpy(packet->path, path, packet->path_len = path_len);
|
uint8_t pri;
|
||||||
|
if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE) { // TRACE packets are different
|
||||||
|
// for TRACE packets, path is appended to end of PAYLOAD. (path is used for SNR's)
|
||||||
|
memcpy(&packet->payload[packet->payload_len], path, path_len);
|
||||||
|
packet->payload_len += path_len;
|
||||||
|
|
||||||
|
packet->path_len = 0;
|
||||||
|
pri = 5; // maybe make this configurable
|
||||||
|
} else {
|
||||||
|
memcpy(packet->path, path, packet->path_len = path_len);
|
||||||
|
pri = 0;
|
||||||
|
}
|
||||||
_tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
_tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
||||||
|
sendPacket(packet, pri, delay_millis);
|
||||||
sendPacket(packet, 0, delay_millis);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::sendZeroHop(Packet* packet, uint32_t delay_millis) {
|
void Mesh::sendZeroHop(Packet* packet, uint32_t delay_millis) {
|
||||||
|
|||||||
17
src/Mesh.h
17
src/Mesh.h
@@ -105,13 +105,16 @@ protected:
|
|||||||
virtual void onPeerDataRecv(Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) { }
|
virtual void onPeerDataRecv(Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A (now verified) TRACE packet has been received (by a known peer).
|
* \brief A TRACE packet has been received. (and has reached the end of its given path)
|
||||||
* NOTE: these can be received multiple times (per sender/msg-id), via different routes
|
* NOTE: this may have been initiated by another node.
|
||||||
* \param sender_idx index of peer, [0..n) where n is what searchPeersByHash() returned
|
* \param tag a random (unique-ish) tag set by initiator
|
||||||
* \param secret the pre-calculated shared-secret (handy for sending response packet)
|
* \param auth_code a code to authenticate the packet
|
||||||
* \param data decrypted data from payload (fixed length, one CIPHER_BLOCK)
|
* \param flags zero for now
|
||||||
|
* \param path_snrs single byte SNR*4 for each hop in the path
|
||||||
|
* \param path_hashes hashes if each repeater in the path
|
||||||
|
* \param path_len length of the path_snrs[] and path_hashes[] arrays
|
||||||
*/
|
*/
|
||||||
virtual void onPeerTraceRecv(Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* data) { }
|
virtual void onTraceRecv(Packet* packet, uint32_t tag, uint32_t auth_code, uint8_t flags, const uint8_t* path_snrs, const uint8_t* path_hashes, uint8_t path_len) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A path TO peer (sender_idx) has been received. (also with optional 'extra' data encoded)
|
* \brief A path TO peer (sender_idx) has been received. (also with optional 'extra' data encoded)
|
||||||
@@ -192,6 +195,7 @@ public:
|
|||||||
Packet* createPathReturn(const uint8_t* dest_hash, const uint8_t* secret, const uint8_t* path, uint8_t path_len, uint8_t extra_type, const uint8_t*extra, size_t extra_len);
|
Packet* createPathReturn(const uint8_t* dest_hash, const uint8_t* secret, const uint8_t* path, uint8_t path_len, uint8_t extra_type, const uint8_t*extra, size_t extra_len);
|
||||||
Packet* createPathReturn(const Identity& dest, const uint8_t* secret, const uint8_t* path, uint8_t path_len, uint8_t extra_type, const uint8_t*extra, size_t extra_len);
|
Packet* createPathReturn(const Identity& dest, const uint8_t* secret, const uint8_t* path, uint8_t path_len, uint8_t extra_type, const uint8_t*extra, size_t extra_len);
|
||||||
Packet* createRawData(const uint8_t* data, size_t len);
|
Packet* createRawData(const uint8_t* data, size_t len);
|
||||||
|
Packet* createTrace(uint32_t tag, uint32_t auth_code, uint8_t flags = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief send a locally-generated Packet with flood routing
|
* \brief send a locally-generated Packet with flood routing
|
||||||
@@ -207,6 +211,7 @@ public:
|
|||||||
* \brief send a locally-generated Packet to just neigbor nodes (zero hops)
|
* \brief send a locally-generated Packet to just neigbor nodes (zero hops)
|
||||||
*/
|
*/
|
||||||
void sendZeroHop(Packet* packet, uint32_t delay_millis=0);
|
void sendZeroHop(Packet* packet, uint32_t delay_millis=0);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,7 @@ void Packet::calculatePacketHash(uint8_t* hash) const {
|
|||||||
SHA256 sha;
|
SHA256 sha;
|
||||||
uint8_t t = getPayloadType();
|
uint8_t t = getPayloadType();
|
||||||
sha.update(&t, 1);
|
sha.update(&t, 1);
|
||||||
if (t == PAYLOAD_TYPE_TRACE) {
|
sha.update(payload, payload_len);
|
||||||
sha.update(payload, 3+CIPHER_MAC_SIZE+CIPHER_BLOCK_SIZE); // the 'content' part of TRACE packets is just the fixed-len encrypted part
|
|
||||||
} else {
|
|
||||||
sha.update(payload, payload_len);
|
|
||||||
}
|
|
||||||
sha.finalize(hash, MAX_HASH_SIZE);
|
sha.finalize(hash, MAX_HASH_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -166,50 +166,6 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseChatMesh::onPeerTraceRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* data) {
|
|
||||||
int i = matching_peer_indexes[sender_idx];
|
|
||||||
if (i < 0 || i >= num_contacts) {
|
|
||||||
MESH_DEBUG_PRINTLN("onPeerTraceRecv: Invalid sender idx: %d", i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((packet->payload[0] & 3) != 0) {
|
|
||||||
MESH_DEBUG_PRINTLN("onPeerTraceRecv: unknown TRACE sub-type: %u", (uint32_t)packet->payload[0]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContactInfo& from = contacts[i];
|
|
||||||
|
|
||||||
uint32_t timestamp;
|
|
||||||
memcpy(×tamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong)
|
|
||||||
uint8_t sender_flags = data[4];
|
|
||||||
|
|
||||||
int j = 3 + CIPHER_MAC_SIZE + CIPHER_BLOCK_SIZE; // skip fixed-len part
|
|
||||||
|
|
||||||
uint8_t path_hashes[64];
|
|
||||||
int8_t path_snr[65];
|
|
||||||
uint16_t len;
|
|
||||||
if (packet->isRouteFlood()) {
|
|
||||||
memcpy(path_hashes, packet->path, len = packet->path_len);
|
|
||||||
memset(path_snr, 0, sizeof(path_snr));
|
|
||||||
memcpy(path_snr, &packet->payload[j], packet->payload_len - j); // 'track' should just contain SNRs
|
|
||||||
} else {
|
|
||||||
len = 0;
|
|
||||||
while (j + 1 < packet->payload_len) {
|
|
||||||
path_hashes[len] = packet->payload[j++]; // pairs of Hash + SNR
|
|
||||||
path_snr[len] = packet->payload[j++];
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
path_snr[len] = (int8_t)(packet->getSNR()*4); // also include last hop (to this node)
|
|
||||||
|
|
||||||
onContactTraceRecv(from, timestamp, path_hashes, path_snr, len);
|
|
||||||
|
|
||||||
if (sender_flags & 1) { // the 'wants reply' flag
|
|
||||||
// TODO: send a TRACE packet back
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseChatMesh::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 BaseChatMesh::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) {
|
||||||
@@ -304,25 +260,6 @@ int BaseChatMesh::sendMessage(const ContactInfo& recipient, uint32_t timestamp,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseChatMesh::sendContactTraceDirect(const ContactInfo& recipient, bool wantReply) {
|
|
||||||
if (recipient.out_path_len < 0) return false; // Error: no known path
|
|
||||||
|
|
||||||
uint8_t temp[CIPHER_BLOCK_SIZE];
|
|
||||||
memset(temp, 0, sizeof(temp));
|
|
||||||
|
|
||||||
uint32_t timestamp = getRTCClock()->getCurrentTime();
|
|
||||||
memcpy(temp, ×tamp, 4);
|
|
||||||
temp[4] = wantReply ? 1 : 0;
|
|
||||||
// TODO: any other data to encrypt??
|
|
||||||
|
|
||||||
auto pkt = createDatagram(PAYLOAD_TYPE_TRACE, recipient.id, recipient.shared_secret, temp, sizeof(temp));
|
|
||||||
if (pkt) {
|
|
||||||
sendDirect(pkt, recipient.out_path, recipient.out_path_len);
|
|
||||||
return true; // success
|
|
||||||
}
|
|
||||||
return false; // error
|
|
||||||
}
|
|
||||||
|
|
||||||
int BaseChatMesh::sendCommandData(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char* text, uint32_t& est_timeout) {
|
int BaseChatMesh::sendCommandData(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char* text, uint32_t& est_timeout) {
|
||||||
int text_len = strlen(text);
|
int text_len = strlen(text);
|
||||||
if (text_len > MAX_TEXT_LEN) return MSG_SEND_FAILED;
|
if (text_len > MAX_TEXT_LEN) return MSG_SEND_FAILED;
|
||||||
|
|||||||
@@ -114,7 +114,6 @@ protected:
|
|||||||
virtual void onSendTimeout() = 0;
|
virtual void onSendTimeout() = 0;
|
||||||
virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) = 0;
|
virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) = 0;
|
||||||
virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0;
|
virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0;
|
||||||
virtual void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) = 0;
|
|
||||||
|
|
||||||
// storage concepts, for sub-classes to override/implement
|
// storage concepts, for sub-classes to override/implement
|
||||||
virtual int getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) { return 0; } // not implemented
|
virtual int getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) { return 0; } // not implemented
|
||||||
@@ -126,7 +125,6 @@ protected:
|
|||||||
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
|
void getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) override;
|
||||||
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 onPeerTraceRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* data) override;
|
|
||||||
void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override;
|
void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override;
|
||||||
#ifdef MAX_GROUP_CHANNELS
|
#ifdef MAX_GROUP_CHANNELS
|
||||||
int searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel channels[], int max_matches) override;
|
int searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel channels[], int max_matches) override;
|
||||||
@@ -151,7 +149,6 @@ public:
|
|||||||
bool shareContactZeroHop(const ContactInfo& contact);
|
bool shareContactZeroHop(const ContactInfo& contact);
|
||||||
uint8_t exportContact(const ContactInfo& contact, uint8_t dest_buf[]);
|
uint8_t exportContact(const ContactInfo& contact, uint8_t dest_buf[]);
|
||||||
bool importContact(const uint8_t src_buf[], uint8_t len);
|
bool importContact(const uint8_t src_buf[], uint8_t len);
|
||||||
bool sendContactTraceDirect(const ContactInfo& recipient, bool wantReply);
|
|
||||||
void resetPathTo(ContactInfo& recipient);
|
void resetPathTo(ContactInfo& recipient);
|
||||||
void scanRecentContacts(int last_n, ContactVisitor* visitor);
|
void scanRecentContacts(int last_n, ContactVisitor* visitor);
|
||||||
ContactInfo* searchContactsByPrefix(const char* name_prefix);
|
ContactInfo* searchContactsByPrefix(const char* name_prefix);
|
||||||
|
|||||||
Reference in New Issue
Block a user