mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-01 21:08:19 +00:00
sync with vnailla dev
This commit is contained in:
@@ -83,6 +83,7 @@ LOG_MODULE_REGISTER(zephcore_companion, CONFIG_ZEPHCORE_MAIN_LOG_LEVEL);
|
||||
#define CMD_SEND_CHANNEL_DATA 0x3E
|
||||
#define CMD_SET_DEFAULT_FLOOD_SCOPE 0x3F /* v11+ */
|
||||
#define CMD_GET_DEFAULT_FLOOD_SCOPE 0x40 /* v11+ */
|
||||
#define CMD_SEND_RAW_PACKET 0x41 /* v12+ */
|
||||
|
||||
/* Response packet types */
|
||||
#define PACKET_OK 0x00
|
||||
@@ -3132,6 +3133,26 @@ bool CompanionMesh::handleProtocolFrame(const uint8_t *data, size_t len)
|
||||
}
|
||||
return true;
|
||||
|
||||
case CMD_SEND_RAW_PACKET:
|
||||
if (len >= 4) {
|
||||
mesh::Packet *pkt = obtainNewPacket();
|
||||
if (pkt) {
|
||||
uint8_t priority = data[1];
|
||||
if (tryParsePacket(pkt, &data[2], len - 2)) {
|
||||
sendPacket(pkt, priority, 0);
|
||||
sendPacketOk();
|
||||
} else {
|
||||
releasePacket(pkt);
|
||||
sendPacketError(ERR_ILLEGAL_ARG);
|
||||
}
|
||||
} else {
|
||||
sendPacketError(ERR_TABLE_FULL);
|
||||
}
|
||||
} else {
|
||||
sendPacketError(ERR_ILLEGAL_ARG);
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -52,19 +52,19 @@ mesh::Packet *BaseChatMesh::createSelfAdvert(const char *name, double lat, doubl
|
||||
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) {
|
||||
mesh::Packet *ack = createAck(ack_hash);
|
||||
mesh::Packet *ack = createAck(ack_hash, ack_len);
|
||||
if (ack) sendFloodScoped(dest, ack, TXT_ACK_DELAY);
|
||||
} else {
|
||||
uint32_t d = TXT_ACK_DELAY;
|
||||
if (getExtraAckTransmitCount() > 0) {
|
||||
mesh::Packet *a1 = createMultiAck(ack_hash, 1);
|
||||
mesh::Packet *a1 = createMultiAck(ack_hash, ack_len, 1);
|
||||
if (a1) sendDirect(a1, dest.out_path, dest.out_path_len, d);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -254,16 +254,18 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender
|
||||
from.lastmod = getRTCClock()->getCurrentTime();
|
||||
onMessageRecv(from, packet, timestamp, (const char *)&data[5]);
|
||||
|
||||
uint32_t ack_hash;
|
||||
mesh::Utils::sha256((uint8_t *)&ack_hash, 4, data, 5 + strlen((char *)&data[5]),
|
||||
from.id.pub_key, PUB_KEY_SIZE);
|
||||
int text_len = strlen((char *)&data[5]);
|
||||
uint8_t ack_hash[6];
|
||||
mesh::Utils::sha256(ack_hash, 4, data, 5 + text_len, from.id.pub_key, PUB_KEY_SIZE);
|
||||
ack_hash[4] = data[5 + text_len + 1]; // attempt byte (makes hash unique across retries)
|
||||
getRNG()->random(&ack_hash[5], 1); // random byte (makes hash unique per delivery node)
|
||||
|
||||
if (packet->isRouteFlood()) {
|
||||
mesh::Packet *path = createPathReturn(from.id, secret, packet->path, packet->path_len,
|
||||
PAYLOAD_TYPE_ACK, (uint8_t *)&ack_hash, 4);
|
||||
PAYLOAD_TYPE_ACK, ack_hash, 6);
|
||||
if (path) sendFloodScoped(from, path, TXT_ACK_DELAY);
|
||||
} else {
|
||||
sendAckTo(from, ack_hash);
|
||||
sendAckTo(from, ack_hash, 6);
|
||||
}
|
||||
} else if (flags == TXT_TYPE_CLI_DATA) {
|
||||
onCommandDataRecv(from, packet, timestamp, (const char *)&data[5]);
|
||||
@@ -288,7 +290,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender
|
||||
PAYLOAD_TYPE_ACK, (uint8_t *)&ack_hash, 4);
|
||||
if (path) sendFloodScoped(from, path, TXT_ACK_DELAY);
|
||||
} else {
|
||||
sendAckTo(from, ack_hash);
|
||||
sendAckTo(from, (uint8_t *)&ack_hash, 4);
|
||||
}
|
||||
}
|
||||
} else if (type == PAYLOAD_TYPE_REQ && len > 4) {
|
||||
|
||||
@@ -94,7 +94,7 @@ class BaseChatMesh : public mesh::Mesh {
|
||||
|
||||
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:
|
||||
BaseChatMesh(mesh::Radio &radio, mesh::MillisecondClock &ms, mesh::RNG &rng, mesh::RTCClock &rtc,
|
||||
|
||||
@@ -118,10 +118,11 @@ public:
|
||||
bool millisHasNowPassed(uint32_t timestamp) const;
|
||||
uint32_t futureMillis(int millis_from_now) const;
|
||||
|
||||
bool tryParsePacket(Packet *pkt, const uint8_t *raw, int len);
|
||||
|
||||
private:
|
||||
void updateTxBudget();
|
||||
uint32_t getMaxTxBudgetMs() const;
|
||||
bool tryParsePacket(Packet *pkt, const uint8_t *raw, int len);
|
||||
void checkRecv();
|
||||
void checkSend();
|
||||
};
|
||||
|
||||
@@ -90,8 +90,10 @@ public:
|
||||
MeshTables *getTables() const { return _tables; }
|
||||
|
||||
Packet *createAdvert(const LocalIdentity &id, const uint8_t *app_data = nullptr, size_t app_data_len = 0);
|
||||
Packet *createAck(uint32_t ack_crc);
|
||||
Packet *createMultiAck(uint32_t ack_crc, uint8_t remaining);
|
||||
Packet *createAck(const uint8_t *ack, uint8_t len);
|
||||
Packet *createAck(uint32_t ack_crc) { return createAck((const 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((const uint8_t *)&ack_crc, 4, remaining); }
|
||||
Packet *createControlData(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);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* SimpleMeshTables - hash-based deduplication
|
||||
* SimpleMeshTables - hash-based packet deduplication
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@@ -10,44 +10,21 @@
|
||||
|
||||
namespace mesh {
|
||||
|
||||
#define MAX_PACKET_HASHES 128
|
||||
#define MAX_PACKET_ACKS 64
|
||||
#define MAX_PACKET_HASHES (128+32)
|
||||
|
||||
class SimpleMeshTables : public MeshTables {
|
||||
uint8_t _hashes[MAX_PACKET_HASHES * MAX_HASH_SIZE];
|
||||
int _next_idx;
|
||||
uint32_t _acks[MAX_PACKET_ACKS];
|
||||
int _next_ack_idx;
|
||||
uint32_t _direct_dups, _flood_dups;
|
||||
|
||||
public:
|
||||
SimpleMeshTables() {
|
||||
memset(_hashes, 0, sizeof(_hashes));
|
||||
_next_idx = 0;
|
||||
memset(_acks, 0, sizeof(_acks));
|
||||
_next_ack_idx = 0;
|
||||
_direct_dups = _flood_dups = 0;
|
||||
}
|
||||
|
||||
bool hasSeen(const 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++;
|
||||
} else {
|
||||
_flood_dups++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_acks[_next_ack_idx] = ack;
|
||||
_next_ack_idx = (_next_ack_idx + 1) % MAX_PACKET_ACKS;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t hash[MAX_HASH_SIZE];
|
||||
packet->calculatePacketHash(hash);
|
||||
const uint8_t *sp = _hashes;
|
||||
@@ -67,24 +44,13 @@ public:
|
||||
}
|
||||
|
||||
void clear(const 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]) {
|
||||
_acks[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint8_t hash[MAX_HASH_SIZE];
|
||||
packet->calculatePacketHash(hash);
|
||||
uint8_t *sp = _hashes;
|
||||
for (int i = 0; i < MAX_PACKET_HASHES; i++, sp += MAX_HASH_SIZE) {
|
||||
if (memcmp(hash, sp, MAX_HASH_SIZE) == 0) {
|
||||
memset(sp, 0, MAX_HASH_SIZE);
|
||||
break;
|
||||
}
|
||||
uint8_t hash[MAX_HASH_SIZE];
|
||||
packet->calculatePacketHash(hash);
|
||||
uint8_t *sp = _hashes;
|
||||
for (int i = 0; i < MAX_PACKET_HASHES; i++, sp += MAX_HASH_SIZE) {
|
||||
if (memcmp(hash, sp, MAX_HASH_SIZE) == 0) {
|
||||
memset(sp, 0, MAX_HASH_SIZE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-9
@@ -127,9 +127,21 @@ DispatcherAction Mesh::forwardMultipartDirect(Packet *pkt)
|
||||
void Mesh::routeDirectRecvAcks(Packet *packet, uint32_t delay_millis)
|
||||
{
|
||||
if (!packet->isMarkedDoNotRetransmit()) {
|
||||
uint32_t crc;
|
||||
memcpy(&crc, packet->payload, 4);
|
||||
Packet *a2 = createAck(crc);
|
||||
uint8_t extra = getExtraAckTransmitCount();
|
||||
while (extra > 0) {
|
||||
delay_millis += getDirectRetransmitDelay(packet) + 300;
|
||||
Packet *a1 = createMultiAck(packet->payload, packet->payload_len, extra);
|
||||
if (a1) {
|
||||
/* Trusted source: packet->path is MAX_PATH_SIZE-sized. */
|
||||
a1->path_len = Packet::copyPath(a1->path, packet->path, MAX_PATH_SIZE, packet->path_len);
|
||||
a1->header &= ~PH_ROUTE_MASK;
|
||||
a1->header |= ROUTE_TYPE_DIRECT;
|
||||
sendPacket(a1, 0, delay_millis);
|
||||
}
|
||||
extra--;
|
||||
}
|
||||
|
||||
Packet *a2 = createAck(packet->payload, packet->payload_len);
|
||||
if (a2) {
|
||||
/* Trusted source: packet->path is MAX_PATH_SIZE-sized. */
|
||||
a2->path_len = Packet::copyPath(a2->path, packet->path, MAX_PATH_SIZE, packet->path_len);
|
||||
@@ -439,24 +451,24 @@ Packet *Mesh::createAdvert(const LocalIdentity &id, const uint8_t *app_data, siz
|
||||
return packet;
|
||||
}
|
||||
|
||||
Packet *Mesh::createAck(uint32_t ack_crc)
|
||||
Packet *Mesh::createAck(const uint8_t *ack, uint8_t len)
|
||||
{
|
||||
Packet *packet = obtainNewPacket();
|
||||
if (packet == nullptr) return nullptr;
|
||||
packet->header = (PAYLOAD_TYPE_ACK << PH_TYPE_SHIFT);
|
||||
memcpy(packet->payload, &ack_crc, 4);
|
||||
packet->payload_len = 4;
|
||||
memcpy(packet->payload, ack, len);
|
||||
packet->payload_len = len;
|
||||
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();
|
||||
if (packet == nullptr) return nullptr;
|
||||
packet->header = (PAYLOAD_TYPE_MULTIPART << PH_TYPE_SHIFT);
|
||||
packet->payload[0] = (remaining << 4) | PAYLOAD_TYPE_ACK;
|
||||
memcpy(&packet->payload[1], &ack_crc, 4);
|
||||
packet->payload_len = 5;
|
||||
memcpy(&packet->payload[1], ack, len);
|
||||
packet->payload_len = 1 + len;
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user