Browse Source

* support for sending 5-byte ACKs

pull/2594/head
Scott Powell 3 weeks ago
parent
commit
f6e6fdaa05
  1. 19
      src/Mesh.cpp
  2. 6
      src/Mesh.h
  3. 18
      src/helpers/BaseChatMesh.cpp
  4. 2
      src/helpers/BaseChatMesh.h
  5. 55
      src/helpers/SimpleMeshTables.h

19
src/Mesh.cpp

@ -361,13 +361,10 @@ DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) {
void Mesh::routeDirectRecvAcks(Packet* packet, uint32_t delay_millis) { void Mesh::routeDirectRecvAcks(Packet* packet, uint32_t delay_millis) {
if (!packet->isMarkedDoNotRetransmit()) { if (!packet->isMarkedDoNotRetransmit()) {
uint32_t crc;
memcpy(&crc, packet->payload, 4);
uint8_t extra = getExtraAckTransmitCount(); uint8_t extra = getExtraAckTransmitCount();
while (extra > 0) { while (extra > 0) {
delay_millis += getDirectRetransmitDelay(packet) + 300; delay_millis += getDirectRetransmitDelay(packet) + 300;
auto a1 = createMultiAck(crc, extra); auto a1 = createMultiAck(packet->payload, packet->payload_len, extra);
if (a1) { if (a1) {
a1->path_len = Packet::copyPath(a1->path, packet->path, packet->path_len); a1->path_len = Packet::copyPath(a1->path, packet->path, packet->path_len);
a1->header &= ~PH_ROUTE_MASK; a1->header &= ~PH_ROUTE_MASK;
@ -377,7 +374,7 @@ void Mesh::routeDirectRecvAcks(Packet* packet, uint32_t delay_millis) {
extra--; extra--;
} }
auto a2 = createAck(crc); auto a2 = createAck(packet->payload, packet->payload_len);
if (a2) { if (a2) {
a2->path_len = Packet::copyPath(a2->path, packet->path, packet->path_len); a2->path_len = Packet::copyPath(a2->path, packet->path, packet->path_len);
a2->header &= ~PH_ROUTE_MASK; a2->header &= ~PH_ROUTE_MASK;
@ -543,7 +540,7 @@ Packet* Mesh::createGroupDatagram(uint8_t type, const GroupChannel& channel, con
return packet; return packet;
} }
Packet* Mesh::createAck(uint32_t ack_crc) { Packet* Mesh::createAck(const uint8_t* ack, uint8_t len) {
Packet* packet = obtainNewPacket(); Packet* packet = obtainNewPacket();
if (packet == NULL) { if (packet == NULL) {
MESH_DEBUG_PRINTLN("%s Mesh::createAck(): error, packet pool empty", getLogDateTime()); MESH_DEBUG_PRINTLN("%s Mesh::createAck(): error, packet pool empty", getLogDateTime());
@ -551,13 +548,13 @@ Packet* Mesh::createAck(uint32_t ack_crc) {
} }
packet->header = (PAYLOAD_TYPE_ACK << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later packet->header = (PAYLOAD_TYPE_ACK << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
memcpy(packet->payload, &ack_crc, 4); memcpy(packet->payload, ack, len);
packet->payload_len = 4; packet->payload_len = len;
return packet; return packet;
} }
Packet* Mesh::createMultiAck(uint32_t ack_crc, uint8_t remaining) { Packet* Mesh::createMultiAck(const uint8_t* ack, uint8_t len, uint8_t remaining) {
Packet* packet = obtainNewPacket(); Packet* packet = obtainNewPacket();
if (packet == NULL) { if (packet == NULL) {
MESH_DEBUG_PRINTLN("%s Mesh::createMultiAck(): error, packet pool empty", getLogDateTime()); MESH_DEBUG_PRINTLN("%s Mesh::createMultiAck(): error, packet pool empty", getLogDateTime());
@ -566,8 +563,8 @@ Packet* Mesh::createMultiAck(uint32_t ack_crc, uint8_t remaining) {
packet->header = (PAYLOAD_TYPE_MULTIPART << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later packet->header = (PAYLOAD_TYPE_MULTIPART << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
packet->payload[0] = (remaining << 4) | PAYLOAD_TYPE_ACK; packet->payload[0] = (remaining << 4) | PAYLOAD_TYPE_ACK;
memcpy(&packet->payload[1], &ack_crc, 4); memcpy(&packet->payload[1], ack, len);
packet->payload_len = 5; packet->payload_len = 1 + len;
return packet; return packet;
} }

6
src/Mesh.h

@ -185,8 +185,10 @@ public:
Packet* createDatagram(uint8_t type, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t len); Packet* createDatagram(uint8_t type, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t len);
Packet* createAnonDatagram(uint8_t type, const LocalIdentity& sender, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t data_len); Packet* createAnonDatagram(uint8_t type, const LocalIdentity& sender, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t data_len);
Packet* createGroupDatagram(uint8_t type, const GroupChannel& channel, const uint8_t* data, size_t data_len); Packet* createGroupDatagram(uint8_t type, const GroupChannel& channel, const uint8_t* data, size_t data_len);
Packet* createAck(uint32_t ack_crc); Packet* createAck(const uint8_t* ack, uint8_t len);
Packet* createMultiAck(uint32_t ack_crc, uint8_t remaining); Packet* createAck(uint32_t ack_crc) { return createAck((uint8_t *) &ack_crc, 4); }
Packet* createMultiAck(const uint8_t* ack, uint8_t len, uint8_t remaining);
Packet* createMultiAck(uint32_t ack_crc, uint8_t remaining) { return createMultiAck((uint8_t *)&ack_crc, 4, remaining); }
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);

18
src/helpers/BaseChatMesh.cpp

@ -38,9 +38,9 @@ mesh::Packet* BaseChatMesh::createSelfAdvert(const char* name, double lat, doubl
return createAdvert(self_id, app_data, app_data_len); return createAdvert(self_id, app_data, app_data_len);
} }
void BaseChatMesh::sendAckTo(const ContactInfo& dest, uint32_t ack_hash) { void BaseChatMesh::sendAckTo(const ContactInfo& dest, const uint8_t* ack_hash, uint8_t ack_len) {
if (dest.out_path_len == OUT_PATH_UNKNOWN) { if (dest.out_path_len == OUT_PATH_UNKNOWN) {
mesh::Packet* ack = createAck(ack_hash); mesh::Packet* ack = createAck(ack_hash, ack_len);
if (ack) sendFloodScoped(dest, ack, TXT_ACK_DELAY); if (ack) sendFloodScoped(dest, ack, TXT_ACK_DELAY);
} else { } else {
uint32_t d = TXT_ACK_DELAY; uint32_t d = TXT_ACK_DELAY;
@ -50,7 +50,7 @@ void BaseChatMesh::sendAckTo(const ContactInfo& dest, uint32_t ack_hash) {
d += 300; d += 300;
} }
mesh::Packet* a2 = createAck(ack_hash); mesh::Packet* a2 = createAck(ack_hash, ack_len);
if (a2) sendDirect(a2, dest.out_path, dest.out_path_len, d); if (a2) sendDirect(a2, dest.out_path, dest.out_path_len, d);
} }
} }
@ -218,16 +218,18 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
from.lastmod = getRTCClock()->getCurrentTime(); // update last heard time from.lastmod = getRTCClock()->getCurrentTime(); // update last heard time
onMessageRecv(from, packet, timestamp, (const char *) &data[5]); // let UI know onMessageRecv(from, packet, timestamp, (const char *) &data[5]); // let UI know
uint32_t ack_hash; // calc truncated hash of the message timestamp + text + sender pub_key, to prove to sender that we got it uint8_t ack_hash[5]; // 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); mesh::Utils::sha256(ack_hash, 4, data, 5 + strlen((char *)&data[5]), from.id.pub_key, PUB_KEY_SIZE);
// NEW: append (potential) extended attempt byte (to make packethash unique)
ack_hash[4] = data[len - 1];
if (packet->isRouteFlood()) { if (packet->isRouteFlood()) {
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK // 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, mesh::Packet* path = createPathReturn(from.id, secret, packet->path, packet->path_len,
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4); PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 5);
if (path) sendFloodScoped(from, path, TXT_ACK_DELAY); if (path) sendFloodScoped(from, path, TXT_ACK_DELAY);
} else { } else {
sendAckTo(from, ack_hash); sendAckTo(from, ack_hash, 5);
} }
} else if (flags == TXT_TYPE_CLI_DATA) { } else if (flags == TXT_TYPE_CLI_DATA) {
onCommandDataRecv(from, packet, timestamp, (const char *) &data[5]); // let UI know onCommandDataRecv(from, packet, timestamp, (const char *) &data[5]); // let UI know
@ -254,7 +256,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4); PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4);
if (path) sendFloodScoped(from, path, TXT_ACK_DELAY); if (path) sendFloodScoped(from, path, TXT_ACK_DELAY);
} else { } else {
sendAckTo(from, ack_hash); sendAckTo(from, (uint8_t *) &ack_hash);
} }
} else { } else {
MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported message type: %u", (uint32_t) flags); MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported message type: %u", (uint32_t) flags);

2
src/helpers/BaseChatMesh.h

@ -72,7 +72,7 @@ class BaseChatMesh : public mesh::Mesh {
ConnectionInfo connections[MAX_CONNECTIONS]; ConnectionInfo connections[MAX_CONNECTIONS];
mesh::Packet* composeMsgPacket(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char *text, uint32_t& expected_ack); mesh::Packet* composeMsgPacket(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char *text, uint32_t& expected_ack);
void sendAckTo(const ContactInfo& dest, uint32_t ack_hash); void sendAckTo(const ContactInfo& dest, const uint8_t* ack_hash, uint8_t ack_len=4);
protected: protected:
BaseChatMesh(mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::PacketManager& mgr, mesh::MeshTables& tables) BaseChatMesh(mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::PacketManager& mgr, mesh::MeshTables& tables)

55
src/helpers/SimpleMeshTables.h

@ -6,22 +6,17 @@
#include <FS.h> #include <FS.h>
#endif #endif
#define MAX_PACKET_HASHES 128 #define MAX_PACKET_HASHES (128+32)
#define MAX_PACKET_ACKS 64
class SimpleMeshTables : public mesh::MeshTables { class SimpleMeshTables : public mesh::MeshTables {
uint8_t _hashes[MAX_PACKET_HASHES*MAX_HASH_SIZE]; uint8_t _hashes[MAX_PACKET_HASHES*MAX_HASH_SIZE];
int _next_idx; int _next_idx;
uint32_t _acks[MAX_PACKET_ACKS];
int _next_ack_idx;
uint32_t _direct_dups, _flood_dups; uint32_t _direct_dups, _flood_dups;
public: public:
SimpleMeshTables() { SimpleMeshTables() {
memset(_hashes, 0, sizeof(_hashes)); memset(_hashes, 0, sizeof(_hashes));
_next_idx = 0; _next_idx = 0;
memset(_acks, 0, sizeof(_acks));
_next_ack_idx = 0;
_direct_dups = _flood_dups = 0; _direct_dups = _flood_dups = 0;
} }
@ -29,37 +24,14 @@ public:
void restoreFrom(File f) { void restoreFrom(File f) {
f.read(_hashes, sizeof(_hashes)); f.read(_hashes, sizeof(_hashes));
f.read((uint8_t *) &_next_idx, sizeof(_next_idx)); f.read((uint8_t *) &_next_idx, sizeof(_next_idx));
f.read((uint8_t *) &_acks[0], sizeof(_acks));
f.read((uint8_t *) &_next_ack_idx, sizeof(_next_ack_idx));
} }
void saveTo(File f) { void saveTo(File f) {
f.write(_hashes, sizeof(_hashes)); f.write(_hashes, sizeof(_hashes));
f.write((const uint8_t *) &_next_idx, sizeof(_next_idx)); f.write((const uint8_t *) &_next_idx, sizeof(_next_idx));
f.write((const uint8_t *) &_acks[0], sizeof(_acks));
f.write((const uint8_t *) &_next_ack_idx, sizeof(_next_ack_idx));
} }
#endif #endif
bool hasSeen(const mesh::Packet* packet) override { bool hasSeen(const mesh::Packet* packet) override {
if (packet->getPayloadType() == PAYLOAD_TYPE_ACK) {
uint32_t ack;
memcpy(&ack, packet->payload, 4);
for (int i = 0; i < MAX_PACKET_ACKS; i++) {
if (ack == _acks[i]) {
if (packet->isRouteDirect()) {
_direct_dups++; // keep some stats
} else {
_flood_dups++;
}
return true;
}
}
_acks[_next_ack_idx] = ack;
_next_ack_idx = (_next_ack_idx + 1) % MAX_PACKET_ACKS; // cyclic table
return false;
}
uint8_t hash[MAX_HASH_SIZE]; uint8_t hash[MAX_HASH_SIZE];
packet->calculatePacketHash(hash); packet->calculatePacketHash(hash);
@ -81,25 +53,14 @@ public:
} }
void clear(const mesh::Packet* packet) override { void clear(const mesh::Packet* packet) override {
if (packet->getPayloadType() == PAYLOAD_TYPE_ACK) { uint8_t hash[MAX_HASH_SIZE];
uint32_t ack; packet->calculatePacketHash(hash);
memcpy(&ack, packet->payload, 4);
for (int i = 0; i < MAX_PACKET_ACKS; i++) {
if (ack == _acks[i]) {
_acks[i] = 0;
break;
}
}
} else {
uint8_t hash[MAX_HASH_SIZE];
packet->calculatePacketHash(hash);
uint8_t* sp = _hashes; uint8_t* sp = _hashes;
for (int i = 0; i < MAX_PACKET_HASHES; i++, sp += MAX_HASH_SIZE) { for (int i = 0; i < MAX_PACKET_HASHES; i++, sp += MAX_HASH_SIZE) {
if (memcmp(hash, sp, MAX_HASH_SIZE) == 0) { if (memcmp(hash, sp, MAX_HASH_SIZE) == 0) {
memset(sp, 0, MAX_HASH_SIZE); memset(sp, 0, MAX_HASH_SIZE);
break; break;
}
} }
} }
} }

Loading…
Cancel
Save