00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef TRAVERSAL_ALGORITHM_050324_HPP
00034 #define TRAVERSAL_ALGORITHM_050324_HPP
00035
00036 #include <vector>
00037 #include <set>
00038
00039 #include <libtorrent/kademlia/node_id.hpp>
00040 #include <libtorrent/kademlia/routing_table.hpp>
00041 #include <libtorrent/kademlia/logging.hpp>
00042
00043 #include <boost/noncopyable.hpp>
00044 #include <boost/intrusive_ptr.hpp>
00045 #include <boost/bind.hpp>
00046
00047 namespace libtorrent { namespace dht
00048 {
00049 #ifdef TORRENT_DHT_VERBOSE_LOGGING
00050 TORRENT_DECLARE_LOG(traversal);
00051 #endif
00052
00053 class rpc_manager;
00054
00055
00056 class traversal_algorithm : boost::noncopyable
00057 {
00058 public:
00059 void traverse(node_id const& id, udp::endpoint addr);
00060 void finished(node_id const& id);
00061 void failed(node_id const& id, bool prevent_request = false);
00062 virtual ~traversal_algorithm() {}
00063
00064 protected:
00065 template<class InIt>
00066 traversal_algorithm(
00067 node_id target
00068 , int branch_factor
00069 , int max_results
00070 , routing_table& table
00071 , rpc_manager& rpc
00072 , InIt start
00073 , InIt end
00074 );
00075
00076 void add_requests();
00077 void add_entry(node_id const& id, udp::endpoint addr, unsigned char flags);
00078
00079 virtual void done() = 0;
00080 virtual void invoke(node_id const& id, udp::endpoint addr) = 0;
00081
00082 struct result
00083 {
00084 result(node_id const& id, udp::endpoint addr, unsigned char f = 0)
00085 : id(id), addr(addr), flags(f)
00086 {}
00087
00088 node_id id;
00089 udp::endpoint addr;
00090 enum { queried = 1, initial = 2 };
00091 unsigned char flags;
00092 };
00093
00094 std::vector<result>::iterator last_iterator();
00095
00096 friend void intrusive_ptr_add_ref(traversal_algorithm* p)
00097 {
00098 p->m_ref_count++;
00099 }
00100
00101 friend void intrusive_ptr_release(traversal_algorithm* p)
00102 {
00103 if (--p->m_ref_count == 0)
00104 delete p;
00105 }
00106
00107 int m_ref_count;
00108
00109 node_id m_target;
00110 int m_branch_factor;
00111 int m_max_results;
00112 std::vector<result> m_results;
00113 std::set<udp::endpoint> m_failed;
00114 routing_table& m_table;
00115 rpc_manager& m_rpc;
00116 int m_invoke_count;
00117 };
00118
00119 template<class InIt>
00120 traversal_algorithm::traversal_algorithm(
00121 node_id target
00122 , int branch_factor
00123 , int max_results
00124 , routing_table& table
00125 , rpc_manager& rpc
00126 , InIt start
00127 , InIt end
00128 )
00129 : m_ref_count(0)
00130 , m_target(target)
00131 , m_branch_factor(branch_factor)
00132 , m_max_results(max_results)
00133 , m_table(table)
00134 , m_rpc(rpc)
00135 , m_invoke_count(0)
00136 {
00137 using boost::bind;
00138
00139 for (InIt i = start; i != end; ++i)
00140 {
00141 add_entry(i->id, i->addr, result::initial);
00142 }
00143
00144
00145
00146 if (start == end)
00147 {
00148 for (routing_table::router_iterator i = table.router_begin()
00149 , end(table.router_end()); i != end; ++i)
00150 {
00151 add_entry(node_id(0), *i, result::initial);
00152 }
00153 }
00154
00155 }
00156
00157 } }
00158
00159 #endif // TRAVERSAL_ALGORITHM_050324_HPP
00160