|
@@ -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;
|
|
|
|
|
- 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);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ int 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, 0, delay_millis);
|
|
|
|
|
|
|
+ sendPacket(packet, pri, delay_millis);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Mesh::sendZeroHop(Packet* packet, uint32_t delay_millis) {
|
|
void Mesh::sendZeroHop(Packet* packet, uint32_t delay_millis) {
|