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