mirror of
https://github.com/ratspeak/ratdeck.git
synced 2026-08-23 11:09:53 +00:00
Fix LXMF bidirectional messaging, increase known_destinations cap
Outbound (Ratdeck→Python) was broken because Identity::recall() could never find the recipient. Root cause: OS::time() returns seconds since boot on ESP32, but persisted known_destinations entries carried timestamps from the previous session. New announces got timestamp ~31s while persisted entries had ~5000s, so the LRU cull immediately removed the new entry. The microReticulum Identity.cpp fix (timestamp normalization on load) is in .pio/libdeps and must be upstreamed to ratspeak/microReticulum separately. Changes: - known_destinations cap 256→512 (PSRAM pool was 1% used, plenty of room) - Fix link delivery destHash: onLinkEstablished callback was passing link_id instead of LXMF destination hash, corrupting conversation routing - Add diagnostic logging: [LXMF-DIAG], [TCP-DIAG], [HEART-DIAG], [DIAG-PROOF] for tracing link establishment, proof routing, and interface status
This commit is contained in:
+1
-1
@@ -24,7 +24,7 @@ build_flags =
|
||||
-DRNS_CONTAINER_ALLOCATOR=RNS_PSRAM_POOL_ALLOCATOR
|
||||
-DRNS_PSRAM_POOL_BUFFER_SIZE=2048000
|
||||
; Raise microReticulum table caps — all containers go to 2MB PSRAM pool
|
||||
-DRNS_KNOWN_DESTINATIONS_MAX=256
|
||||
-DRNS_KNOWN_DESTINATIONS_MAX=512
|
||||
-DRNS_HASHLIST_MAX=256
|
||||
-DRNS_PATH_TABLE_MAX=256
|
||||
-DRNS_ANNOUNCE_TABLE_MAX=128
|
||||
|
||||
@@ -1055,6 +1055,15 @@ void loop() {
|
||||
radioOnline ? "ON" : "OFF",
|
||||
sdStore.isReady() ? "OK" : "FAIL",
|
||||
flash.isReady() ? "OK" : "FAIL");
|
||||
// Diagnostic: show registered transport interfaces and TCP connection status
|
||||
{
|
||||
auto& ifaces = RNS::Transport::get_interfaces();
|
||||
int tcpUp = 0;
|
||||
for (auto* tcp : tcpClients) { if (tcp && tcp->isConnected()) tcpUp++; }
|
||||
Serial.printf("[HEART-DIAG] ifaces=%d tcp=%d/%d wifi=%s\n",
|
||||
(int)ifaces.size(), tcpUp, (int)tcpClients.size(),
|
||||
wifiSTAConnected ? "STA" : (wifiImpl ? "AP" : "OFF"));
|
||||
}
|
||||
maxLoopTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,13 +226,22 @@ void LXMFManager::onOutLinkClosed(RNS::Link& link) {
|
||||
|
||||
void LXMFManager::onLinkEstablished(RNS::Link& link) {
|
||||
if (!_instance) return;
|
||||
Serial.printf("[LXMF-DIAG] onLinkEstablished fired! link_id=%s status=%d\n",
|
||||
link.link_id().toHex().substr(0, 16).c_str(), (int)link.status());
|
||||
link.set_packet_callback([](const RNS::Bytes& data, const RNS::Packet& packet) {
|
||||
if (!_instance) return;
|
||||
_instance->processIncoming(data.data(), data.size(), packet.destination_hash());
|
||||
Serial.printf("[LXMF-DIAG] Link packet received! %d bytes pkt_dest=%s\n",
|
||||
(int)data.size(), packet.destination_hash().toHex().substr(0, 16).c_str());
|
||||
// Link delivery: data already contains [dest:16][src:16][sig:64][msgpack]
|
||||
// Do NOT use packet.destination_hash() — that's the link_id, not the LXMF dest.
|
||||
// Pass empty Bytes so processIncoming uses the destHash from unpackFull().
|
||||
_instance->processIncoming(data.data(), data.size(), RNS::Bytes());
|
||||
});
|
||||
}
|
||||
|
||||
void LXMFManager::processIncoming(const uint8_t* data, size_t len, const RNS::Bytes& destHash) {
|
||||
Serial.printf("[LXMF-DIAG] processIncoming: %d bytes callerDestHash=%s\n",
|
||||
(int)len, destHash.size() > 0 ? destHash.toHex().substr(0, 16).c_str() : "EMPTY(link)");
|
||||
LXMFMessage msg;
|
||||
if (!LXMFMessage::unpackFull(data, len, msg)) {
|
||||
Serial.printf("[LXMF] Failed to unpack incoming message (%d bytes)\n", (int)len);
|
||||
@@ -240,6 +249,10 @@ void LXMFManager::processIncoming(const uint8_t* data, size_t len, const RNS::By
|
||||
}
|
||||
if (_rns && msg.sourceHash == _rns->destination().hash()) return;
|
||||
|
||||
Serial.printf("[LXMF-DIAG] unpackFull OK: src=%s dest=%s content_len=%d\n",
|
||||
msg.sourceHash.toHex().substr(0, 8).c_str(),
|
||||
msg.destHash.toHex().substr(0, 8).c_str(), (int)msg.content.size());
|
||||
|
||||
// Deduplication: skip messages we've already processed
|
||||
std::string msgIdHex = msg.messageId.toHex();
|
||||
if (_seenMessageIds.count(msgIdHex)) {
|
||||
@@ -252,7 +265,11 @@ void LXMFManager::processIncoming(const uint8_t* data, size_t len, const RNS::By
|
||||
_seenMessageIds.erase(_seenMessageIds.begin());
|
||||
}
|
||||
|
||||
msg.destHash = destHash;
|
||||
// Only overwrite destHash if caller provided a real one (non-link delivery).
|
||||
// For link delivery, unpackFull already parsed the correct destHash from the payload.
|
||||
if (destHash.size() > 0) {
|
||||
msg.destHash = destHash;
|
||||
}
|
||||
Serial.printf("[LXMF] Message from %s (%d bytes) content_len=%d\n",
|
||||
msg.sourceHash.toHex().substr(0, 8).c_str(), (int)len, (int)msg.content.size());
|
||||
if (_store) { _store->saveMessage(msg); }
|
||||
|
||||
@@ -138,6 +138,16 @@ void TCPClientInterface::send_outgoing(const RNS::Bytes& data) {
|
||||
uint8_t header_type = (flags >> 6) & 0x01;
|
||||
uint8_t packet_type = flags & 0x03;
|
||||
|
||||
// Diagnostic: identify packet types going through TCP
|
||||
static const char* pt_names[] = {"DATA", "ANNOUNCE", "LINKREQ", "PROOF"};
|
||||
Serial.printf("[TCP-DIAG] send: %d bytes ht=%d pt=%s(%d) to %s:%d\n",
|
||||
(int)data.size(), header_type,
|
||||
(packet_type < 4) ? pt_names[packet_type] : "?", packet_type,
|
||||
_host.c_str(), _port);
|
||||
if (packet_type == 0x03) {
|
||||
Serial.printf("[TCP-DIAG] *** PROOF packet being sent via TCP! ***\n");
|
||||
}
|
||||
|
||||
if (packet_type != 0x01) { // Not ANNOUNCE
|
||||
if (header_type == 0) {
|
||||
// Header1 → wrap as Header2 (handles hops==1, hops==0, unknown path)
|
||||
|
||||
Reference in New Issue
Block a user