|
|
@ -55,7 +55,8 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
uint16_t offset = (uint16_t)pkt->path_len << path_sz; |
|
|
uint16_t offset = (uint16_t)pkt->path_len << path_sz; |
|
|
if (offset >= len) { // TRACE has reached end of given path
|
|
|
if (offset >= len) { // TRACE has reached end of given path
|
|
|
onTraceRecv(pkt, trace_tag, auth_code, flags, pkt->path, &pkt->payload[i], len); |
|
|
onTraceRecv(pkt, trace_tag, auth_code, flags, pkt->path, &pkt->payload[i], len); |
|
|
} else if (self_id.isHashMatch(&pkt->payload[i + offset], 1 << path_sz) && allowPacketForward(pkt) && !_tables->hasSeen(pkt)) { |
|
|
} else if (self_id.isHashMatch(&pkt->payload[i + offset], 1 << path_sz) && allowPacketForward(pkt) && !_tables->wasSeen(pkt)) { |
|
|
|
|
|
_tables->markSeen(pkt); |
|
|
// append SNR (Not hash!)
|
|
|
// append SNR (Not hash!)
|
|
|
pkt->path[pkt->path_len++] = (int8_t) (pkt->getSNR()*4); |
|
|
pkt->path[pkt->path_len++] = (int8_t) (pkt->getSNR()*4); |
|
|
|
|
|
|
|
|
@ -89,14 +90,16 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
if (pkt->getPayloadType() == PAYLOAD_TYPE_MULTIPART) { |
|
|
if (pkt->getPayloadType() == PAYLOAD_TYPE_MULTIPART) { |
|
|
return forwardMultipartDirect(pkt); |
|
|
return forwardMultipartDirect(pkt); |
|
|
} else if (pkt->getPayloadType() == PAYLOAD_TYPE_ACK) { |
|
|
} else if (pkt->getPayloadType() == PAYLOAD_TYPE_ACK) { |
|
|
if (!_tables->hasSeen(pkt)) { // don't retransmit!
|
|
|
if (!_tables->wasSeen(pkt)) { // don't retransmit!
|
|
|
|
|
|
_tables->markSeen(pkt); |
|
|
removeSelfFromPath(pkt); |
|
|
removeSelfFromPath(pkt); |
|
|
routeDirectRecvAcks(pkt, 0); |
|
|
routeDirectRecvAcks(pkt, 0); |
|
|
} |
|
|
} |
|
|
return ACTION_RELEASE; |
|
|
return ACTION_RELEASE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (!_tables->hasSeen(pkt)) { |
|
|
if (!_tables->wasSeen(pkt)) { |
|
|
|
|
|
_tables->markSeen(pkt); |
|
|
removeSelfFromPath(pkt); |
|
|
removeSelfFromPath(pkt); |
|
|
|
|
|
|
|
|
uint32_t d = getDirectRetransmitDelay(pkt); |
|
|
uint32_t d = getDirectRetransmitDelay(pkt); |
|
|
@ -117,7 +120,8 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
memcpy(&ack_crc, &pkt->payload[i], 4); i += 4; |
|
|
memcpy(&ack_crc, &pkt->payload[i], 4); i += 4; |
|
|
if (i > pkt->payload_len) { |
|
|
if (i > pkt->payload_len) { |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete ACK packet", getLogDateTime()); |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete ACK packet", getLogDateTime()); |
|
|
} else if (!_tables->hasSeen(pkt)) { |
|
|
} else if (!_tables->wasSeen(pkt)) { |
|
|
|
|
|
_tables->markSeen(pkt); |
|
|
onAckRecv(pkt, ack_crc); |
|
|
onAckRecv(pkt, ack_crc); |
|
|
action = routeRecvPacket(pkt); |
|
|
action = routeRecvPacket(pkt); |
|
|
} |
|
|
} |
|
|
@ -134,7 +138,8 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
uint8_t* macAndData = &pkt->payload[i]; // MAC + encrypted data
|
|
|
uint8_t* macAndData = &pkt->payload[i]; // MAC + encrypted data
|
|
|
if (i + CIPHER_MAC_SIZE >= pkt->payload_len) { |
|
|
if (i + CIPHER_MAC_SIZE >= pkt->payload_len) { |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete data packet", getLogDateTime()); |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete data packet", getLogDateTime()); |
|
|
} else if (!_tables->hasSeen(pkt)) { |
|
|
} else if (!_tables->wasSeen(pkt)) { |
|
|
|
|
|
_tables->markSeen(pkt); |
|
|
// NOTE: this is a 'first packet wins' impl. When receiving from multiple paths, the first to arrive wins.
|
|
|
// NOTE: this is a 'first packet wins' impl. When receiving from multiple paths, the first to arrive wins.
|
|
|
// For flood mode, the path may not be the 'best' in terms of hops.
|
|
|
// For flood mode, the path may not be the 'best' in terms of hops.
|
|
|
// FUTURE: could send back multiple paths, using createPathReturn(), and let sender choose which to use(?)
|
|
|
// FUTURE: could send back multiple paths, using createPathReturn(), and let sender choose which to use(?)
|
|
|
@ -197,7 +202,8 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
uint8_t* macAndData = &pkt->payload[i]; // MAC + encrypted data
|
|
|
uint8_t* macAndData = &pkt->payload[i]; // MAC + encrypted data
|
|
|
if (i + 2 >= pkt->payload_len) { |
|
|
if (i + 2 >= pkt->payload_len) { |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete data packet", getLogDateTime()); |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete data packet", getLogDateTime()); |
|
|
} else if (!_tables->hasSeen(pkt)) { |
|
|
} else if (!_tables->wasSeen(pkt)) { |
|
|
|
|
|
_tables->markSeen(pkt); |
|
|
if (self_id.isHashMatch(&dest_hash)) { |
|
|
if (self_id.isHashMatch(&dest_hash)) { |
|
|
Identity sender(sender_pub_key); |
|
|
Identity sender(sender_pub_key); |
|
|
|
|
|
|
|
|
@ -224,7 +230,8 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
uint8_t* macAndData = &pkt->payload[i]; // MAC + encrypted data
|
|
|
uint8_t* macAndData = &pkt->payload[i]; // MAC + encrypted data
|
|
|
if (i + 2 >= pkt->payload_len) { |
|
|
if (i + 2 >= pkt->payload_len) { |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete data packet", getLogDateTime()); |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete data packet", getLogDateTime()); |
|
|
} else if (!_tables->hasSeen(pkt)) { |
|
|
} else if (!_tables->wasSeen(pkt)) { |
|
|
|
|
|
_tables->markSeen(pkt); |
|
|
// scan channels DB, for all matching hashes of 'channel_hash' (max 4 matches supported ATM)
|
|
|
// scan channels DB, for all matching hashes of 'channel_hash' (max 4 matches supported ATM)
|
|
|
GroupChannel channels[4]; |
|
|
GroupChannel channels[4]; |
|
|
int num = searchChannelsByHash(&channel_hash, channels, 4); |
|
|
int num = searchChannelsByHash(&channel_hash, channels, 4); |
|
|
@ -255,7 +262,8 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete advertisement packet", getLogDateTime()); |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): incomplete advertisement packet", getLogDateTime()); |
|
|
} else if (self_id.matches(id.pub_key)) { |
|
|
} else if (self_id.matches(id.pub_key)) { |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): receiving SELF advert packet", getLogDateTime()); |
|
|
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): receiving SELF advert packet", getLogDateTime()); |
|
|
} else if (!_tables->hasSeen(pkt)) { |
|
|
} else if (!_tables->wasSeen(pkt)) { |
|
|
|
|
|
_tables->markSeen(pkt); |
|
|
uint8_t* app_data = &pkt->payload[i]; |
|
|
uint8_t* app_data = &pkt->payload[i]; |
|
|
int app_data_len = pkt->payload_len - i; |
|
|
int app_data_len = pkt->payload_len - i; |
|
|
if (app_data_len > MAX_ADVERT_DATA_SIZE) { app_data_len = MAX_ADVERT_DATA_SIZE; } |
|
|
if (app_data_len > MAX_ADVERT_DATA_SIZE) { app_data_len = MAX_ADVERT_DATA_SIZE; } |
|
|
@ -282,7 +290,8 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case PAYLOAD_TYPE_RAW_CUSTOM: { |
|
|
case PAYLOAD_TYPE_RAW_CUSTOM: { |
|
|
if (pkt->isRouteDirect() && !_tables->hasSeen(pkt)) { |
|
|
if (pkt->isRouteDirect() && !_tables->wasSeen(pkt)) { |
|
|
|
|
|
_tables->markSeen(pkt); |
|
|
onRawDataRecv(pkt); |
|
|
onRawDataRecv(pkt); |
|
|
//action = routeRecvPacket(pkt); don't flood route these (yet)
|
|
|
//action = routeRecvPacket(pkt); don't flood route these (yet)
|
|
|
} |
|
|
} |
|
|
@ -300,7 +309,8 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { |
|
|
tmp.payload_len = pkt->payload_len - 1; |
|
|
tmp.payload_len = pkt->payload_len - 1; |
|
|
memcpy(tmp.payload, &pkt->payload[1], tmp.payload_len); |
|
|
memcpy(tmp.payload, &pkt->payload[1], tmp.payload_len); |
|
|
|
|
|
|
|
|
if (!_tables->hasSeen(&tmp)) { |
|
|
if (!_tables->wasSeen(&tmp)) { |
|
|
|
|
|
_tables->markSeen(&tmp); |
|
|
uint32_t ack_crc; |
|
|
uint32_t ack_crc; |
|
|
memcpy(&ack_crc, tmp.payload, 4); |
|
|
memcpy(&ack_crc, tmp.payload, 4); |
|
|
|
|
|
|
|
|
@ -357,7 +367,8 @@ DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) { |
|
|
tmp.payload_len = pkt->payload_len - 1; |
|
|
tmp.payload_len = pkt->payload_len - 1; |
|
|
memcpy(tmp.payload, &pkt->payload[1], tmp.payload_len); |
|
|
memcpy(tmp.payload, &pkt->payload[1], tmp.payload_len); |
|
|
|
|
|
|
|
|
if (!_tables->hasSeen(&tmp)) { // don't retransmit!
|
|
|
if (!_tables->wasSeen(&tmp)) { // don't retransmit!
|
|
|
|
|
|
_tables->markSeen(&tmp); |
|
|
removeSelfFromPath(&tmp); |
|
|
removeSelfFromPath(&tmp); |
|
|
routeDirectRecvAcks(&tmp, ((uint32_t)remaining + 1) * 300); // expect multipart ACKs 300ms apart (x2)
|
|
|
routeDirectRecvAcks(&tmp, ((uint32_t)remaining + 1) * 300); // expect multipart ACKs 300ms apart (x2)
|
|
|
} |
|
|
} |
|
|
@ -637,7 +648,7 @@ void Mesh::sendFlood(Packet* packet, uint32_t delay_millis, uint8_t path_hash_si |
|
|
packet->header |= ROUTE_TYPE_FLOOD; |
|
|
packet->header |= ROUTE_TYPE_FLOOD; |
|
|
packet->setPathHashSizeAndCount(path_hash_size, 0); |
|
|
packet->setPathHashSizeAndCount(path_hash_size, 0); |
|
|
|
|
|
|
|
|
_tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
_tables->markSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
|
|
|
|
|
|
uint8_t pri; |
|
|
uint8_t pri; |
|
|
if (packet->getPayloadType() == PAYLOAD_TYPE_PATH) { |
|
|
if (packet->getPayloadType() == PAYLOAD_TYPE_PATH) { |
|
|
@ -666,7 +677,7 @@ void Mesh::sendFlood(Packet* packet, uint16_t* transport_codes, uint32_t delay_m |
|
|
packet->transport_codes[1] = transport_codes[1]; |
|
|
packet->transport_codes[1] = transport_codes[1]; |
|
|
packet->setPathHashSizeAndCount(path_hash_size, 0); |
|
|
packet->setPathHashSizeAndCount(path_hash_size, 0); |
|
|
|
|
|
|
|
|
_tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
_tables->markSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
|
|
|
|
|
|
uint8_t pri; |
|
|
uint8_t pri; |
|
|
if (packet->getPayloadType() == PAYLOAD_TYPE_PATH) { |
|
|
if (packet->getPayloadType() == PAYLOAD_TYPE_PATH) { |
|
|
@ -699,7 +710,7 @@ void Mesh::sendDirect(Packet* packet, const uint8_t* path, uint8_t path_len, uin |
|
|
pri = 0; |
|
|
pri = 0; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
_tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
_tables->markSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
sendPacket(packet, pri, delay_millis); |
|
|
sendPacket(packet, pri, delay_millis); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -709,7 +720,7 @@ void Mesh::sendZeroHop(Packet* packet, uint32_t delay_millis) { |
|
|
|
|
|
|
|
|
packet->path_len = 0; // path_len of zero means Zero Hop
|
|
|
packet->path_len = 0; // path_len of zero means Zero Hop
|
|
|
|
|
|
|
|
|
_tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
_tables->markSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
|
|
|
|
|
|
sendPacket(packet, 0, delay_millis); |
|
|
sendPacket(packet, 0, delay_millis); |
|
|
} |
|
|
} |
|
|
@ -722,7 +733,7 @@ void Mesh::sendZeroHop(Packet* packet, uint16_t* transport_codes, uint32_t delay |
|
|
|
|
|
|
|
|
packet->path_len = 0; // path_len of zero means Zero Hop
|
|
|
packet->path_len = 0; // path_len of zero means Zero Hop
|
|
|
|
|
|
|
|
|
_tables->hasSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
_tables->markSeen(packet); // mark this packet as already sent in case it is rebroadcast back to us
|
|
|
|
|
|
|
|
|
sendPacket(packet, 0, delay_millis); |
|
|
sendPacket(packet, 0, delay_millis); |
|
|
} |
|
|
} |
|
|
|