diff --git a/src/Interface.h b/src/Interface.h index 3a8c229..4b0c07a 100644 --- a/src/Interface.h +++ b/src/Interface.h @@ -194,6 +194,8 @@ namespace RNS { inline bool FIXED_MTU() const { assert(_impl); return _impl->_FIXED_MTU; } inline double announce_allowed_at() const { assert(_impl); return _impl->_announce_allowed_at; } inline float announce_cap() const { assert(_impl); return _impl->_announce_cap; } + inline size_t rxb() const { assert(_impl); return _impl->_rxb; } + inline size_t txb() const { assert(_impl); return _impl->_txb; } inline std::list& announce_queue() const { assert(_impl); return _impl->_announce_queue; } inline bool is_connected_to_shared_instance() const { assert(_impl); return _impl->_is_connected_to_shared_instance; } inline bool is_local_shared_instance() const { assert(_impl); return _impl->_is_local_shared_instance; } diff --git a/src/Transport.cpp b/src/Transport.cpp index 2951493..81b7bb4 100644 --- a/src/Transport.cpp +++ b/src/Transport.cpp @@ -620,6 +620,22 @@ Transport::DestinationEntry empty_destination_entry; ERRORF("jobs: failed to cull discovery path requests: %s", e.what()); } + // Cull the path requests table + try { + std::vector stale_path_requests; + for (const auto& [destination_hash, timestamp] : _path_requests) { + if (OS::time() > (timestamp + DESTINATION_TIMEOUT)) { + stale_path_requests.push_back(destination_hash); + } + } + for (const Bytes& destination_hash : stale_path_requests) { + _path_requests.erase(destination_hash); + } + } + catch (const std::exception& e) { + ERRORF("jobs: failed to cull path requests: %s", e.what()); + } + // Cull the tunnel table try { count = 0; @@ -1332,8 +1348,25 @@ Transport::DestinationEntry empty_destination_entry; } if (accept) { TRACE("Transport::inbound: Packet accepted by filter"); - // CBA ACCUMULATES - _packet_hashlist.insert(packet.packet_hash()); + + // Defer hashlist insertion for packets belonging to links in + // our link table, and for LRPROOF packets. On shared-medium + // interfaces (e.g. LoRa), a packet may arrive on the "wrong" + // interface first. Premature hash insertion would cause the + // correct arrival to be filtered as a duplicate. + // Reference: Python Transport.py lines 1362-1373 + bool remember_packet_hash = true; + if (_link_table.find(packet.destination_hash()) != _link_table.end()) { + remember_packet_hash = false; + } + if (packet.packet_type() == Type::Packet::PROOF && packet.context() == Type::Packet::LRPROOF) { + remember_packet_hash = false; + } + if (remember_packet_hash) { + // CBA ACCUMULATES + _packet_hashlist.insert(packet.packet_hash()); + } + cache_packet(packet); // Check special conditions for local clients connected @@ -1517,7 +1550,7 @@ Transport::DestinationEntry empty_destination_entry; else { if (nh_mtu < path_mtu || (ph_mtu != 0 && ph_mtu < path_mtu)) { try { - path_mtu = std::min(nh_mtu, ph_mtu); + path_mtu = std::min(nh_mtu, (ph_mtu > 0) ? ph_mtu : nh_mtu); Bytes clamped_mtu = Link::signalling_bytes(path_mtu, mode); DEBUGF("Clamping link MTU to %u", path_mtu); new_raw = new_raw.left(new_raw.size()-Type::Link::LINK_MTU_SIZE)+clamped_mtu; @@ -1579,7 +1612,7 @@ Transport::DestinationEntry empty_destination_entry; auto link_iter = _link_table.find(packet.destination_hash()); if (link_iter != _link_table.end()) { TRACE("Transport::inbound: Found link entry, handling link transport"); - LinkEntry link_entry = (*link_iter).second; + LinkEntry& link_entry = (*link_iter).second; // If receiving and outbound interface is // the same for this link, direction doesn't // matter, and we simply send the packet on. @@ -1625,6 +1658,8 @@ Transport::DestinationEntry empty_destination_entry; new_raw << packet.raw().mid(2); transmit(outbound_interface, new_raw); link_entry._timestamp = OS::time(); + // Deferred hashlist insertion for link transport packets + _packet_hashlist.insert(packet.packet_hash()); } else { //p pass @@ -1874,6 +1909,7 @@ Transport::DestinationEntry empty_destination_entry; if (iter != _pending_local_path_requests.end()) { //p desiring_interface = Transport.pending_local_path_requests.pop(packet.destination_hash) //const Interface& desiring_interface = (*iter).second; + _pending_local_path_requests.erase(iter); retransmit_timeout = now; retries = PATHFINDER_R; @@ -3131,6 +3167,33 @@ TRACEF("announce_packet str: %s", announce_packet.toString().c_str()); _announce_table.insert({announce_packet.destination_hash(), announce_entry}); // CBA IMMEDIATE CULL cull_announce_table(); + + // Send PATH_RESPONSE immediately for local client requests + // rather than waiting for the jobs() loop. On resource- + // constrained platforms (e.g. ESP32), continuous TCP backbone + // data can starve the cooperative jobs() loop for many + // seconds, causing path discovery timeouts for local clients. + if (is_from_local_client) { + Identity imm_identity(Identity::recall(announce_packet.destination_hash())); + if (imm_identity) { + Destination imm_destination(imm_identity, Type::Destination::OUT, Type::Destination::SINGLE, announce_packet.destination_hash()); + Packet imm_packet( + imm_destination, + attached_interface, + announce_packet.data(), + Type::Packet::ANNOUNCE, + Type::Packet::PATH_RESPONSE, + Type::Transport::TRANSPORT, + Type::Packet::HEADER_2, + _identity.hash(), + true, + announce_packet.context_flag() + ); + imm_packet.hops(announce_hops); + imm_packet.send(); + _announce_table.erase(announce_packet.destination_hash()); + } + } } } }