diff --git a/src/radio/SX1262.cpp b/src/radio/SX1262.cpp index d99cceb..59a8c9e 100644 --- a/src/radio/SX1262.cpp +++ b/src/radio/SX1262.cpp @@ -367,6 +367,9 @@ size_t SX1262::write(uint8_t byte) { return write(&byte, 1); } size_t SX1262::write(const uint8_t* buffer, size_t size) { if ((_payloadLength + size) > MAX_PACKET_SIZE) { + Serial.printf("[SX1262] WARNING: write() truncating %d->%d bytes (payload=%d max=%d)\n", + (int)size, (int)(MAX_PACKET_SIZE - _payloadLength), + (int)_payloadLength, (int)MAX_PACKET_SIZE); size = MAX_PACKET_SIZE - _payloadLength; } writeBuffer(buffer, size); diff --git a/src/reticulum/LXMFManager.cpp b/src/reticulum/LXMFManager.cpp index 3d7f9d6..7e41256 100644 --- a/src/reticulum/LXMFManager.cpp +++ b/src/reticulum/LXMFManager.cpp @@ -152,12 +152,22 @@ bool LXMFManager::sendDirect(LXMFMessage& msg) { linkPayload.insert(linkPayload.end(), msg.destHash.data(), msg.destHash.data() + 16); linkPayload.insert(linkPayload.end(), payload.begin(), payload.end()); RNS::Bytes linkBytes(linkPayload.data(), linkPayload.size()); - if (linkBytes.size() <= RNS::Type::Reticulum::MDU) { + // Token encryption adds ~48 bytes (IV:16 + HMAC:32 + AES padding). + // LoRa packets are max 255 bytes (1 header + 19 Reticulum H1 + encrypted). + // If the plaintext is too large, Token output exceeds LoRa MTU and + // SX1262::write() silently truncates, corrupting the HMAC. + // Cap link delivery to 180 bytes to stay safely under the limit. + // Larger messages fall through to opportunistic delivery. + static constexpr size_t LORA_SAFE_LINK_PAYLOAD = 180; + if (linkBytes.size() <= LORA_SAFE_LINK_PAYLOAD) { Serial.printf("[LXMF] sending via link: %d bytes to %s\n", (int)linkBytes.size(), msg.destHash.toHex().substr(0, 8).c_str()); RNS::Packet packet(_outLink, linkBytes); RNS::PacketReceipt receipt = packet.send(); if (receipt) { sent = true; } + } else { + Serial.printf("[LXMF] link payload too large for LoRa (%d > %d), using opportunistic\n", + (int)linkBytes.size(), (int)LORA_SAFE_LINK_PAYLOAD); } }