Implement radio2, tempradio2, radioat2 and tempradioat2 across Mesh roles, with RX-only/RX+TX operation, optional preambles and persistent cross-TX policy. Keep temporary OTA traffic on its profile by default and maintain independent retry ownership and backoff for each profile. Use slow-first receive scanning with 4.8-symbol visits and automatic preambles rounded up in steps of eight. Preserve pending RX, restore power saving on exit, and discard work bound to changed or expired profiles. Restore the infrastructure path.hash.mode setter and report unsupported extra.sf settings consistently. Add CLI, scheduling, scan and retry tests, setup documentation, and the V4/XIAO hardware validation results. Validation: 1,422 native tests, eight KISS tests, 63 final focused profile tests, 18 checks from the staged source, sanitizer-enabled OTA transfers, and builds for V4 Mesh roles, Full XIAO Companion and nRF52 T1000-E. Hardware checks cover reception, cross-TX policy, expiry, reboot and OTA discovery while receiving main-channel adverts.
109 lines
3.0 KiB
C++
109 lines
3.0 KiB
C++
#include "Packet.h"
|
|
#include <string.h>
|
|
#include <SHA256.h>
|
|
|
|
namespace mesh {
|
|
|
|
Packet::Packet() {
|
|
header = 0;
|
|
path_len = 0;
|
|
payload_len = 0;
|
|
_rssi = 0;
|
|
_snr = 0;
|
|
tx_cr = 0;
|
|
flood_retry_policy = FLOOD_RETRY_POLICY_DEFAULT;
|
|
radio_generation = radio_origin_generation = 0;
|
|
radio_profile = radio_origin = 0;
|
|
radio_bound = false; radio_local = true;
|
|
}
|
|
|
|
bool Packet::isValidPathLen(uint8_t path_len) {
|
|
uint8_t hash_count = path_len & 63;
|
|
uint8_t hash_size = (path_len >> 6) + 1;
|
|
if (hash_size == 4) return false; // Reserved for future
|
|
return hash_count*hash_size <= MAX_PATH_SIZE;
|
|
}
|
|
|
|
size_t Packet::writePath(uint8_t* dest, const uint8_t* src, uint8_t path_len) {
|
|
uint8_t hash_count = path_len & 63;
|
|
uint8_t hash_size = (path_len >> 6) + 1;
|
|
size_t len = hash_count*hash_size;
|
|
if (len > MAX_PATH_SIZE) {
|
|
MESH_DEBUG_PRINTLN("Packet::copyPath, invalid path_len=%d", (uint32_t)path_len);
|
|
return 0; // Error
|
|
}
|
|
memcpy(dest, src, len);
|
|
return len;
|
|
}
|
|
|
|
uint8_t Packet::copyPath(uint8_t* dest, const uint8_t* src, uint8_t path_len) {
|
|
writePath(dest, src, path_len);
|
|
return path_len;
|
|
}
|
|
|
|
int Packet::getRawLength() const {
|
|
return 2 + getPathByteLen() + payload_len + (hasTransportCodes() ? 4 : 0);
|
|
}
|
|
|
|
void Packet::calculatePacketHash(uint8_t* hash) const {
|
|
SHA256 sha;
|
|
uint8_t t = getPayloadType();
|
|
sha.update(&t, 1);
|
|
if (t == PAYLOAD_TYPE_TRACE) {
|
|
sha.update(&path_len, sizeof(path_len)); // CAVEAT: TRACE packets can revisit same node on return path
|
|
}
|
|
sha.update(payload, payload_len);
|
|
sha.finalize(hash, MAX_HASH_SIZE);
|
|
}
|
|
|
|
uint8_t Packet::writeTo(uint8_t dest[]) const {
|
|
uint8_t i = 0;
|
|
dest[i++] = header;
|
|
if (hasTransportCodes()) {
|
|
memcpy(&dest[i], &transport_codes[0], 2); i += 2;
|
|
memcpy(&dest[i], &transport_codes[1], 2); i += 2;
|
|
}
|
|
dest[i++] = path_len;
|
|
i += writePath(&dest[i], path, path_len);
|
|
memcpy(&dest[i], payload, payload_len); i += payload_len;
|
|
return i;
|
|
}
|
|
|
|
bool Packet::readFrom(const uint8_t src[], uint8_t len) {
|
|
if (src == NULL || len < 2) return false; // header + path_len
|
|
|
|
uint8_t i = 0;
|
|
_rssi = 0;
|
|
_snr = 0;
|
|
tx_cr = 0;
|
|
flood_retry_policy = FLOOD_RETRY_POLICY_DEFAULT;
|
|
radio_generation = radio_origin_generation = 0;
|
|
radio_profile = radio_origin = 0;
|
|
radio_bound = false; radio_local = true;
|
|
header = src[i++];
|
|
if (getPayloadVer() > PAYLOAD_VER_1) return false;
|
|
|
|
if (hasTransportCodes()) {
|
|
if ((uint16_t)i + sizeof(transport_codes) + 1 > len) return false;
|
|
memcpy(&transport_codes[0], &src[i], 2); i += 2;
|
|
memcpy(&transport_codes[1], &src[i], 2); i += 2;
|
|
} else {
|
|
transport_codes[0] = transport_codes[1] = 0;
|
|
}
|
|
|
|
if (i >= len) return false;
|
|
path_len = src[i++];
|
|
if (!isValidPathLen(path_len)) return false; // bad encoding
|
|
|
|
uint8_t bl = getPathByteLen();
|
|
if ((uint16_t)i + bl > len) return false;
|
|
memcpy(path, &src[i], bl); i += bl;
|
|
|
|
payload_len = len - i;
|
|
if (payload_len > sizeof(payload)) return false; // bad encoding
|
|
memcpy(payload, &src[i], payload_len); //i += payload_len;
|
|
return true; // success
|
|
}
|
|
|
|
}
|