diff --git a/src/reticulum/LXMFManager.cpp b/src/reticulum/LXMFManager.cpp index 7e41256..3d7f9d6 100644 --- a/src/reticulum/LXMFManager.cpp +++ b/src/reticulum/LXMFManager.cpp @@ -152,22 +152,12 @@ 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()); - // 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) { + if (linkBytes.size() <= RNS::Type::Reticulum::MDU) { 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); } } diff --git a/src/transport/LoRaInterface.cpp b/src/transport/LoRaInterface.cpp index c96b13d..e58335f 100644 --- a/src/transport/LoRaInterface.cpp +++ b/src/transport/LoRaInterface.cpp @@ -46,6 +46,15 @@ void LoRaInterface::send_outgoing(const RNS::Bytes& data) { return; } + // Reject packets that exceed the LoRa MTU (255 bytes including 1-byte header). + // Sending truncated packets corrupts encryption (HMAC failures on receiver). + if (data.size() + RNODE_HEADER_L > MAX_PACKET_SIZE) { + Serial.printf("[LORA_IF] TX DROPPED: packet too large (%d + %d = %d > %d)\n", + (int)data.size(), RNODE_HEADER_L, + (int)(data.size() + RNODE_HEADER_L), MAX_PACKET_SIZE); + return; + } + // Build RNode-compatible 1-byte header: // Upper nibble: random sequence number (for split-packet tracking) // Lower nibble: flags (FLAG_SPLIT=0x01 if packet won't fit in single frame)