diff --git a/include/libtorrent/kademlia/find_data.hpp b/include/libtorrent/kademlia/find_data.hpp index 5c6134914..b3d4f3489 100644 --- a/include/libtorrent/kademlia/find_data.hpp +++ b/include/libtorrent/kademlia/find_data.hpp @@ -59,7 +59,7 @@ class node_impl; //TODO: 3 rename this class to get_peers, since that's what it does // find_data is an unnecessarily generic name -class find_data : public traversal_algorithm +struct find_data : traversal_algorithm { public: typedef boost::function const&)> data_callback; @@ -83,7 +83,8 @@ public: protected: virtual void done(); - observer_ptr new_observer(void* ptr, udp::endpoint const& ep, node_id const& id); + observer_ptr new_observer(void* ptr, udp::endpoint const& ep + , node_id const& id); virtual bool invoke(observer_ptr o); data_callback m_data_callback; @@ -95,9 +96,8 @@ protected: bool m_noseeds:1; }; -class obfuscated_get_peers : public find_data +struct obfuscated_get_peers : find_data { -public: typedef find_data::nodes_callback done_callback; obfuscated_get_peers(node_impl& node, node_id target @@ -109,7 +109,8 @@ public: protected: - observer_ptr new_observer(void* ptr, udp::endpoint const& ep, node_id const& id); + observer_ptr new_observer(void* ptr, udp::endpoint const& ep + , node_id const& id); virtual bool invoke(observer_ptr o); virtual void done(); private: @@ -118,13 +119,22 @@ private: bool m_obfuscated; }; -class find_data_observer : public observer +struct find_data_observer : traversal_observer { -public: find_data_observer( boost::intrusive_ptr const& algorithm , udp::endpoint const& ep, node_id const& id) - : observer(algorithm, ep, id) + : traversal_observer(algorithm, ep, id) + {} + void reply(msg const&); +}; + +struct obfuscated_find_data_observer : traversal_observer +{ + obfuscated_find_data_observer( + boost::intrusive_ptr const& algorithm + , udp::endpoint const& ep, node_id const& id) + : traversal_observer(algorithm, ep, id) {} void reply(msg const&); }; diff --git a/include/libtorrent/kademlia/refresh.hpp b/include/libtorrent/kademlia/refresh.hpp index 0079d39e9..8dbf8a90d 100644 --- a/include/libtorrent/kademlia/refresh.hpp +++ b/include/libtorrent/kademlia/refresh.hpp @@ -55,7 +55,8 @@ public: protected: - observer_ptr new_observer(void* ptr, udp::endpoint const& ep, node_id const& id); + observer_ptr new_observer(void* ptr, udp::endpoint const& ep + , node_id const& id); virtual bool invoke(observer_ptr o); }; diff --git a/include/libtorrent/kademlia/traversal_algorithm.hpp b/include/libtorrent/kademlia/traversal_algorithm.hpp index 212570963..96f88b2d0 100644 --- a/include/libtorrent/kademlia/traversal_algorithm.hpp +++ b/include/libtorrent/kademlia/traversal_algorithm.hpp @@ -121,6 +121,18 @@ protected: int m_num_target_nodes; }; +struct traversal_observer : observer +{ + traversal_observer( + boost::intrusive_ptr const& algorithm + , udp::endpoint const& ep, node_id const& id) + : observer(algorithm, ep, id) + {} + + // parses out "nodes" and keeps traversing + void reply(msg const&); +}; + } } // namespace libtorrent::dht #endif // TRAVERSAL_ALGORITHM_050324_HPP diff --git a/src/kademlia/find_data.cpp b/src/kademlia/find_data.cpp index 7860386f9..95f945d43 100644 --- a/src/kademlia/find_data.cpp +++ b/src/kademlia/find_data.cpp @@ -122,44 +122,35 @@ void find_data_observer::reply(msg const& m) static_cast(m_algorithm.get())->got_peers(peer_list); } - // look for nodes - n = r->dict_find_string("nodes"); - if (n) + traversal_observer::reply(m); + + done(); +} + +void obfuscated_find_data_observer::reply(msg const& m) +{ + lazy_entry const* r = m.message.dict_find_dict("r"); + if (!r) { - std::vector node_list; - char const* nodes = n->string_ptr(); - char const* end = nodes + n->string_length(); - - while (end - nodes >= 26) - { - node_id id; - std::copy(nodes, nodes + 20, id.begin()); - nodes += 20; - m_algorithm->traverse(id, read_v4_endpoint(nodes)); - } - } - - n = r->dict_find_list("nodes2"); - if (n) - { - for (int i = 0; i < n->list_size(); ++i) - { - lazy_entry const* p = n->list_at(0); - if (p->type() != lazy_entry::string_t) continue; - if (p->string_length() < 6 + 20) continue; - char const* in = p->string_ptr(); - - node_id id; - std::copy(in, in + 20, id.begin()); - in += 20; - if (p->string_length() == 6 + 20) - m_algorithm->traverse(id, read_v4_endpoint(in)); -#if TORRENT_USE_IPV6 - else if (p->string_length() == 18 + 20) - m_algorithm->traverse(id, read_v6_endpoint(in)); +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(traversal) << "[" << m_algorithm.get() + << "] missing response dict"; #endif - } + return; } + + lazy_entry const* id = r->dict_find_string("id"); + if (!id || id->string_length() != 20) + { +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(traversal) << "[" << m_algorithm.get() + << "] invalid id in response"; +#endif + return; + } + + traversal_observer::reply(m); + done(); } @@ -271,16 +262,28 @@ obfuscated_get_peers::obfuscated_get_peers( { } -char const* obfuscated_get_peers::name() const { return !m_obfuscated ? find_data::name() : "get_peers [obfuscated]"; } +char const* obfuscated_get_peers::name() const +{ return !m_obfuscated ? find_data::name() : "get_peers [obfuscated]"; } observer_ptr obfuscated_get_peers::new_observer(void* ptr , udp::endpoint const& ep, node_id const& id) { - observer_ptr o(new (ptr) find_data_observer(this, ep, id)); + if (m_obfuscated) + { + observer_ptr o(new (ptr) obfuscated_find_data_observer(this, ep, id)); #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS - o->m_in_constructor = false; + o->m_in_constructor = false; #endif - return o; + return o; + } + else + { + observer_ptr o(new (ptr) find_data_observer(this, ep, id)); +#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS + o->m_in_constructor = false; +#endif + return o; + } } bool obfuscated_get_peers::invoke(observer_ptr o) diff --git a/src/kademlia/traversal_algorithm.cpp b/src/kademlia/traversal_algorithm.cpp index ee6a86291..71574b4aa 100644 --- a/src/kademlia/traversal_algorithm.cpp +++ b/src/kademlia/traversal_algorithm.cpp @@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include "libtorrent/broadcast_socket.hpp" // for cidr_distance +#include // for read_*_endpoint #include @@ -49,6 +50,11 @@ namespace libtorrent { namespace dht TORRENT_DEFINE_LOG(traversal) #endif +using detail::read_v4_endpoint; +#if TORRENT_USE_IPV6 +using detail::read_v6_endpoint; +#endif + observer_ptr traversal_algorithm::new_observer(void* ptr , udp::endpoint const& ep, node_id const& id) { @@ -464,5 +470,35 @@ void traversal_algorithm::status(dht_lookup& l) l.last_sent = last_sent; } +void traversal_observer::reply(msg const& m) +{ + lazy_entry const* r = m.message.dict_find_dict("r"); + if (!r) + { +#ifdef TORRENT_DHT_VERBOSE_LOGGING + TORRENT_LOG(traversal) << "[" << m_algorithm.get() + << "] missing response dict"; +#endif + return; + } + + // look for nodes + lazy_entry const* n = r->dict_find_string("nodes"); + if (n) + { + std::vector node_list; + char const* nodes = n->string_ptr(); + char const* end = nodes + n->string_length(); + + while (end - nodes >= 26) + { + node_id id; + std::copy(nodes, nodes + 20, id.begin()); + nodes += 20; + m_algorithm->traverse(id, read_v4_endpoint(nodes)); + } + } +} + } } // namespace libtorrent::dht