|
|
|
@ -39,11 +39,6 @@ int Mesh::searchChannelsByHash(const uint8_t* hash, GroupChannel channels[], int |
|
|
|
} |
|
|
|
|
|
|
|
DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
|
if (pkt->getPayloadVer() > PAYLOAD_VER_1) { // not supported in this firmware version
|
|
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): unsupported packet version", getLogDateTime()); |
|
|
|
return ACTION_RELEASE; |
|
|
|
} |
|
|
|
|
|
|
|
if (pkt->isRouteDirect() && pkt->getPayloadType() == PAYLOAD_TYPE_TRACE) { |
|
|
|
if (pkt->path_len < MAX_PATH_SIZE) { |
|
|
|
uint8_t i = 0; |
|
|
|
@ -70,14 +65,14 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
|
} |
|
|
|
|
|
|
|
if (pkt->isRouteDirect() && pkt->getPayloadType() == PAYLOAD_TYPE_CONTROL && (pkt->payload[0] & 0x80) != 0) { |
|
|
|
if (pkt->path_len == 0) { |
|
|
|
if (pkt->getPathHashCount() == 0) { |
|
|
|
onControlDataRecv(pkt); |
|
|
|
} |
|
|
|
// just zero-hop control packets allowed (for this subset of payloads)
|
|
|
|
return ACTION_RELEASE; |
|
|
|
} |
|
|
|
|
|
|
|
if (pkt->isRouteDirect() && pkt->path_len >= PATH_HASH_SIZE) { |
|
|
|
if (pkt->isRouteDirect() && pkt->getPathHashCount() > 0) { |
|
|
|
// check for 'early received' ACK
|
|
|
|
if (pkt->getPayloadType() == PAYLOAD_TYPE_ACK) { |
|
|
|
int i = 0; |
|
|
|
@ -88,7 +83,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (self_id.isHashMatch(pkt->path) && allowPacketForward(pkt)) { |
|
|
|
if (self_id.isHashMatch(pkt->path, pkt->getPathHashSize()) && allowPacketForward(pkt)) { |
|
|
|
if (pkt->getPayloadType() == PAYLOAD_TYPE_MULTIPART) { |
|
|
|
return forwardMultipartDirect(pkt); |
|
|
|
} else if (pkt->getPayloadType() == PAYLOAD_TYPE_ACK) { |
|
|
|
@ -158,7 +153,9 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
|
if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH) { |
|
|
|
int k = 0; |
|
|
|
uint8_t path_len = data[k++]; |
|
|
|
uint8_t* path = &data[k]; k += path_len; |
|
|
|
uint8_t hash_size = (path_len >> 6) + 1; |
|
|
|
uint8_t hash_count = path_len & 63; |
|
|
|
uint8_t* path = &data[k]; k += hash_size*hash_count; |
|
|
|
uint8_t extra_type = data[k++] & 0x0F; // upper 4 bits reserved for future use
|
|
|
|
uint8_t* extra = &data[k]; |
|
|
|
uint8_t extra_len = len - k; // remainder of packet (may be padded with zeroes!)
|
|
|
|
@ -293,8 +290,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
|
if (type == PAYLOAD_TYPE_ACK && pkt->payload_len >= 5) { // a multipart ACK
|
|
|
|
Packet tmp; |
|
|
|
tmp.header = pkt->header; |
|
|
|
tmp.path_len = pkt->path_len; |
|
|
|
memcpy(tmp.path, pkt->path, pkt->path_len); |
|
|
|
tmp.path_len = Packet::copyPath(tmp.path, pkt->path, pkt->path_len); |
|
|
|
tmp.payload_len = pkt->payload_len - 1; |
|
|
|
memcpy(tmp.payload, &pkt->payload[1], tmp.payload_len); |
|
|
|
|
|
|
|
@ -321,27 +317,25 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
|
|
|
|
|
void Mesh::removeSelfFromPath(Packet* pkt) { |
|
|
|
// remove our hash from 'path'
|
|
|
|
pkt->path_len -= PATH_HASH_SIZE; |
|
|
|
#if 0 |
|
|
|
memcpy(pkt->path, &pkt->path[PATH_HASH_SIZE], pkt->path_len); |
|
|
|
#elif PATH_HASH_SIZE == 1 |
|
|
|
for (int k = 0; k < pkt->path_len; k++) { // shuffle bytes by 1
|
|
|
|
pkt->path[k] = pkt->path[k + 1]; |
|
|
|
pkt->setPathHashCount(pkt->getPathHashCount() - 1); // decrement the count
|
|
|
|
|
|
|
|
uint8_t sz = pkt->getPathHashSize(); |
|
|
|
for (int k = 0; k < pkt->getPathHashCount()*sz; k += sz) { // shuffle path by 1 'entry'
|
|
|
|
memcpy(&pkt->path[k], &pkt->path[k + sz], sz); |
|
|
|
} |
|
|
|
#else |
|
|
|
#error "need path remove impl" |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
DispatcherAction Mesh::routeRecvPacket(Packet* packet) { |
|
|
|
uint8_t n = packet->getPathHashCount(); |
|
|
|
if (packet->isRouteFlood() && !packet->isMarkedDoNotRetransmit() |
|
|
|
&& packet->path_len + PATH_HASH_SIZE <= MAX_PATH_SIZE && allowPacketForward(packet)) { |
|
|
|
&& (n + 1)*packet->getPathHashSize() <= MAX_PATH_SIZE && allowPacketForward(packet)) { |
|
|
|
// append this node's hash to 'path'
|
|
|
|
packet->path_len += self_id.copyHashTo(&packet->path[packet->path_len]); |
|
|
|
self_id.copyHashTo(&packet->path[n * packet->getPathHashSize()], packet->getPathHashSize()); |
|
|
|
packet->setPathHashCount(n + 1); |
|
|
|
|
|
|
|
uint32_t d = getRetransmitDelay(packet); |
|
|
|
// 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->getPathHashCount(), d); // give priority to closer sources, than ones further away
|
|
|
|
} |
|
|
|
return ACTION_RELEASE; |
|
|
|
} |
|
|
|
@ -353,8 +347,7 @@ DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) { |
|
|
|
if (type == PAYLOAD_TYPE_ACK && pkt->payload_len >= 5) { // a multipart ACK
|
|
|
|
Packet tmp; |
|
|
|
tmp.header = pkt->header; |
|
|
|
tmp.path_len = pkt->path_len; |
|
|
|
memcpy(tmp.path, pkt->path, pkt->path_len); |
|
|
|
tmp.path_len = Packet::copyPath(tmp.path, pkt->path, pkt->path_len); |
|
|
|
tmp.payload_len = pkt->payload_len - 1; |
|
|
|
memcpy(tmp.payload, &pkt->payload[1], tmp.payload_len); |
|
|
|
|
|
|
|
@ -376,7 +369,7 @@ void Mesh::routeDirectRecvAcks(Packet* packet, uint32_t delay_millis) { |
|
|
|
delay_millis += getDirectRetransmitDelay(packet) + 300; |
|
|
|
auto a1 = createMultiAck(crc, extra); |
|
|
|
if (a1) { |
|
|
|
memcpy(a1->path, packet->path, a1->path_len = packet->path_len); |
|
|
|
a1->path_len = Packet::copyPath(a1->path, packet->path, packet->path_len); |
|
|
|
a1->header &= ~PH_ROUTE_MASK; |
|
|
|
a1->header |= ROUTE_TYPE_DIRECT; |
|
|
|
sendPacket(a1, 0, delay_millis); |
|
|
|
@ -386,7 +379,7 @@ void Mesh::routeDirectRecvAcks(Packet* packet, uint32_t delay_millis) { |
|
|
|
|
|
|
|
auto a2 = createAck(crc); |
|
|
|
if (a2) { |
|
|
|
memcpy(a2->path, packet->path, a2->path_len = packet->path_len); |
|
|
|
a2->path_len = Packet::copyPath(a2->path, packet->path, packet->path_len); |
|
|
|
a2->header &= ~PH_ROUTE_MASK; |
|
|
|
a2->header |= ROUTE_TYPE_DIRECT; |
|
|
|
sendPacket(a2, 0, delay_millis); |
|
|
|
@ -439,7 +432,10 @@ Packet* Mesh::createPathReturn(const Identity& dest, const uint8_t* secret, cons |
|
|
|
} |
|
|
|
|
|
|
|
Packet* Mesh::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) { |
|
|
|
if (path_len + extra_len + 5 > MAX_COMBINED_PATH) return NULL; // too long!!
|
|
|
|
uint8_t path_hash_size = (path_len >> 6) + 1; |
|
|
|
uint8_t path_hash_count = path_len & 63; |
|
|
|
|
|
|
|
if (path_hash_count*path_hash_size + extra_len + 5 > MAX_COMBINED_PATH) return NULL; // too long!!
|
|
|
|
|
|
|
|
Packet* packet = obtainNewPacket(); |
|
|
|
if (packet == NULL) { |
|
|
|
@ -457,7 +453,7 @@ Packet* Mesh::createPathReturn(const uint8_t* dest_hash, const uint8_t* secret, |
|
|
|
uint8_t data[MAX_PACKET_PAYLOAD]; |
|
|
|
|
|
|
|
data[data_len++] = path_len; |
|
|
|
memcpy(&data[data_len], path, path_len); data_len += path_len; |
|
|
|
memcpy(&data[data_len], path, path_hash_count*path_hash_size); data_len += path_hash_count*path_hash_size; |
|
|
|
if (extra_len > 0) { |
|
|
|
data[data_len++] = extra_type; |
|
|
|
memcpy(&data[data_len], extra, extra_len); data_len += extra_len; |
|
|
|
@ -624,15 +620,19 @@ Packet* Mesh::createControlData(const uint8_t* data, size_t len) { |
|
|
|
return packet; |
|
|
|
} |
|
|
|
|
|
|
|
void Mesh::sendFlood(Packet* packet, uint32_t delay_millis) { |
|
|
|
void Mesh::sendFlood(Packet* packet, uint32_t delay_millis, uint8_t path_hash_size) { |
|
|
|
if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE) { |
|
|
|
MESH_DEBUG_PRINTLN("%s Mesh::sendFlood(): TRACE type not suspported", getLogDateTime()); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (path_hash_size == 0 || path_hash_size > 3) { |
|
|
|
MESH_DEBUG_PRINTLN("%s Mesh::sendFlood(): invalid path_hash_size", getLogDateTime()); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
packet->header &= ~PH_ROUTE_MASK; |
|
|
|
packet->header |= ROUTE_TYPE_FLOOD; |
|
|
|
packet->path_len = 0; |
|
|
|
packet->setPathHashSizeAndCount(path_hash_size, 0); |
|
|
|
|
|
|
|
_tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
|
|
|
|
|
@ -647,17 +647,21 @@ void Mesh::sendFlood(Packet* packet, uint32_t delay_millis) { |
|
|
|
sendPacket(packet, pri, delay_millis); |
|
|
|
} |
|
|
|
|
|
|
|
void Mesh::sendFlood(Packet* packet, uint16_t* transport_codes, uint32_t delay_millis) { |
|
|
|
void Mesh::sendFlood(Packet* packet, uint16_t* transport_codes, uint32_t delay_millis, uint8_t path_hash_size) { |
|
|
|
if (packet->getPayloadType() == PAYLOAD_TYPE_TRACE) { |
|
|
|
MESH_DEBUG_PRINTLN("%s Mesh::sendFlood(): TRACE type not suspported", getLogDateTime()); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (path_hash_size == 0 || path_hash_size > 3) { |
|
|
|
MESH_DEBUG_PRINTLN("%s Mesh::sendFlood(): invalid path_hash_size", getLogDateTime()); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
packet->header &= ~PH_ROUTE_MASK; |
|
|
|
packet->header |= ROUTE_TYPE_TRANSPORT_FLOOD; |
|
|
|
packet->transport_codes[0] = transport_codes[0]; |
|
|
|
packet->transport_codes[1] = transport_codes[1]; |
|
|
|
packet->path_len = 0; |
|
|
|
packet->setPathHashSizeAndCount(path_hash_size, 0); |
|
|
|
|
|
|
|
_tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
|
|
|
|
|
@ -679,13 +683,13 @@ void Mesh::sendDirect(Packet* packet, const uint8_t* path, uint8_t path_len, uin |
|
|
|
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); |
|
|
|
memcpy(&packet->payload[packet->payload_len], path, path_len); // NOTE: path_len here can be > 64, and NOT in the new scheme
|
|
|
|
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); |
|
|
|
packet->path_len = Packet::copyPath(packet->path, path, path_len); |
|
|
|
if (packet->getPayloadType() == PAYLOAD_TYPE_PATH) { |
|
|
|
pri = 1; // slightly less priority
|
|
|
|
} else { |
|
|
|
|