00001
00002
00003
00004
00005
00006
00007
00008 #include <libtorrent/kademlia/closest_nodes.hpp>
00009 #include <libtorrent/kademlia/routing_table.hpp>
00010 #include <libtorrent/kademlia/rpc_manager.hpp>
00011
00012 namespace libtorrent { namespace dht
00013 {
00014
00015 using asio::ip::udp;
00016
00017 typedef boost::shared_ptr<observer> observer_ptr;
00018
00019 class closest_nodes_observer : public observer
00020 {
00021 public:
00022 closest_nodes_observer(
00023 boost::intrusive_ptr<traversal_algorithm> const& algorithm
00024 , node_id self
00025 , node_id target)
00026 : m_algorithm(algorithm)
00027 , m_target(target)
00028 , m_self(self)
00029 {}
00030 ~closest_nodes_observer();
00031
00032 void send(msg& p)
00033 {
00034 p.info_hash = m_target;
00035 }
00036
00037 void timeout();
00038 void reply(msg const&);
00039 void abort() { m_algorithm = 0; }
00040
00041 private:
00042 boost::intrusive_ptr<traversal_algorithm> m_algorithm;
00043 node_id const m_target;
00044 node_id const m_self;
00045 };
00046
00047 closest_nodes_observer::~closest_nodes_observer()
00048 {
00049 if (m_algorithm) m_algorithm->failed(m_self, true);
00050 }
00051
00052 void closest_nodes_observer::reply(msg const& in)
00053 {
00054 if (!m_algorithm)
00055 {
00056 assert(false);
00057 return;
00058 }
00059
00060 if (!in.nodes.empty())
00061 {
00062 for (msg::nodes_t::const_iterator i = in.nodes.begin()
00063 , end(in.nodes.end()); i != end; ++i)
00064 {
00065 m_algorithm->traverse(i->id, i->addr);
00066 }
00067 }
00068 m_algorithm->finished(m_self);
00069 m_algorithm = 0;
00070 }
00071
00072 void closest_nodes_observer::timeout()
00073 {
00074 if (!m_algorithm) return;
00075 m_algorithm->failed(m_self);
00076 m_algorithm = 0;
00077 }
00078
00079 closest_nodes::closest_nodes(
00080 node_id target
00081 , int branch_factor
00082 , int max_results
00083 , routing_table& table
00084 , rpc_manager& rpc
00085 , done_callback const& callback
00086 )
00087 : traversal_algorithm(
00088 target
00089 , branch_factor
00090 , max_results
00091 , table
00092 , rpc
00093 , table.begin()
00094 , table.end()
00095 )
00096 , m_done_callback(callback)
00097 {
00098 boost::intrusive_ptr<closest_nodes> self(this);
00099 add_requests();
00100 }
00101
00102 void closest_nodes::invoke(node_id const& id, udp::endpoint addr)
00103 {
00104 observer_ptr p(new closest_nodes_observer(this, id, m_target));
00105 m_rpc.invoke(messages::find_node, addr, p);
00106 }
00107
00108 void closest_nodes::done()
00109 {
00110 std::vector<node_entry> results;
00111 int result_size = m_table.bucket_size();
00112 if (result_size > (int)m_results.size()) result_size = (int)m_results.size();
00113 for (std::vector<result>::iterator i = m_results.begin()
00114 , end(m_results.begin() + result_size); i != end; ++i)
00115 {
00116 results.push_back(node_entry(i->id, i->addr));
00117 }
00118 m_done_callback(results);
00119 }
00120
00121 void closest_nodes::initiate(
00122 node_id target
00123 , int branch_factor
00124 , int max_results
00125 , routing_table& table
00126 , rpc_manager& rpc
00127 , done_callback const& callback
00128 )
00129 {
00130 new closest_nodes(target, branch_factor, max_results, table, rpc, callback);
00131 }
00132
00133 } }
00134