diff --git a/include/libtorrent/kademlia/dht_tracker.hpp b/include/libtorrent/kademlia/dht_tracker.hpp index cbb11336f..ef07b1b91 100644 --- a/include/libtorrent/kademlia/dht_tracker.hpp +++ b/include/libtorrent/kademlia/dht_tracker.hpp @@ -90,6 +90,7 @@ namespace libtorrent { namespace dht // translate bittorrent kademlia message into the generic kademlia message // used by the library void on_receive(udp::endpoint const& ep, char const* pkt, int size); + void on_unreachable(udp::endpoint const& ep); private: diff --git a/include/libtorrent/kademlia/node.hpp b/include/libtorrent/kademlia/node.hpp index 44341bb1a..88a1677f1 100644 --- a/include/libtorrent/kademlia/node.hpp +++ b/include/libtorrent/kademlia/node.hpp @@ -172,6 +172,7 @@ public: void(std::vector const&)> f); void add_router_node(udp::endpoint router); + void unreachable(udp::endpoint const& ep); void incoming(msg const& m); void refresh(); diff --git a/include/libtorrent/kademlia/rpc_manager.hpp b/include/libtorrent/kademlia/rpc_manager.hpp index 05bb10836..837c091dd 100644 --- a/include/libtorrent/kademlia/rpc_manager.hpp +++ b/include/libtorrent/kademlia/rpc_manager.hpp @@ -81,6 +81,8 @@ public: , routing_table& table, send_fun const& sf); ~rpc_manager(); + void unreachable(udp::endpoint const& ep); + // returns true if the node needs a refresh bool incoming(msg const&); time_duration tick(); diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index 07ca76d04..7ce6d7fa6 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -372,6 +372,12 @@ namespace libtorrent { namespace dht m_dht.announce(ih, listen_port, f); } + + void dht_tracker::on_unreachable(udp::endpoint const& ep) + { + m_dht.unreachable(ep); + } + // translate bittorrent kademlia message into the generice kademlia message // used by the library void dht_tracker::on_receive(udp::endpoint const& ep, char const* buf, int bytes_transferred) diff --git a/src/kademlia/node.cpp b/src/kademlia/node.cpp index 6ea433040..c3f1cb6e1 100644 --- a/src/kademlia/node.cpp +++ b/src/kademlia/node.cpp @@ -243,6 +243,11 @@ void node_impl::refresh_bucket(int bucket) try } catch (std::exception&) {} +void node_impl::unreachable(udp::endpoint const& ep) +{ + m_rpc.unreachable(ep); +} + void node_impl::incoming(msg const& m) { if (m_rpc.incoming(m)) diff --git a/src/kademlia/rpc_manager.cpp b/src/kademlia/rpc_manager.cpp index 4319fc4b8..384be2eed 100644 --- a/src/kademlia/rpc_manager.cpp +++ b/src/kademlia/rpc_manager.cpp @@ -159,6 +159,39 @@ void rpc_manager::check_invariant() const } #endif +void rpc_manager::unreachable(udp::endpoint const& ep) +{ +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(rpc) << time_now_string() << " PORT_UNREACHABLE [ ip: " << ep << " ]"; +#endif + int num_active = m_oldest_transaction_id < m_next_transaction_id + ? m_next_transaction_id - m_oldest_transaction_id + : max_transactions - m_next_transaction_id + m_oldest_transaction_id; + TORRENT_ASSERT((m_oldest_transaction_id + num_active) % max_transactions + == m_next_transaction_id); + int tid = m_oldest_transaction_id; + for (int i = 0; i < num_active; ++i, ++tid) + { + if (tid >= max_transactions) tid = 0; + observer_ptr const& o = m_transactions[tid]; + if (!o) continue; + if (o->target_addr != ep) continue; + observer_ptr ptr = m_transactions[tid]; + m_transactions[tid] = 0; + if (tid == m_oldest_transaction_id) + { + ++m_oldest_transaction_id; + if (m_oldest_transaction_id >= max_transactions) + m_oldest_transaction_id = 0; + } +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(rpc) << " found transaction [ tid: " << tid << " ]"; +#endif + ptr->timeout(); + return; + } +} + bool rpc_manager::incoming(msg const& m) { INVARIANT_CHECK; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 6ca5445cc..05574ca15 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -718,6 +718,11 @@ namespace aux { { if (e) { + if (e == asio::error::connection_refused + || e == asio::error::connection_reset + || e == asio::error::connection_aborted) + m_dht->on_unreachable(ep); + if (m_alerts.should_post(alert::info)) { std::string msg = "UDP socket error from '"