3
Copyright (c) 2006, Arvid Norberg
6
Redistribution and use in source and binary forms, with or without
7
modification, are permitted provided that the following conditions
10
* Redistributions of source code must retain the above copyright
11
notice, this list of conditions and the following disclaimer.
12
* Redistributions in binary form must reproduce the above copyright
13
notice, this list of conditions and the following disclaimer in
14
the documentation and/or other materials provided with the distribution.
15
* Neither the name of the author nor the names of its
16
contributors may be used to endorse or promote products derived
17
from this software without specific prior written permission.
19
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
POSSIBILITY OF SUCH DAMAGE.
40
#include <libtorrent/kademlia/routing_table.hpp>
41
#include <libtorrent/kademlia/rpc_manager.hpp>
42
#include <libtorrent/kademlia/node_id.hpp>
43
#include <libtorrent/kademlia/msg.hpp>
45
#include <libtorrent/io.hpp>
46
#include <libtorrent/session_settings.hpp>
47
#include <libtorrent/assert.hpp>
49
#include <boost/cstdint.hpp>
50
#include <boost/optional.hpp>
51
#include <boost/iterator/transform_iterator.hpp>
52
#include <boost/ref.hpp>
54
#include "libtorrent/socket.hpp"
56
namespace libtorrent { namespace dht
61
#ifdef TORRENT_DHT_VERBOSE_LOGGING
62
TORRENT_DECLARE_LOG(node);
65
// this is the entry for every peer
66
// the timestamp is there to make it possible
67
// to remove stale peers
74
// this is a group. It contains a set of group members
77
std::set<peer_entry> peers;
80
inline bool operator<(peer_entry const& lhs, peer_entry const& rhs)
82
return lhs.addr.address() == rhs.addr.address()
83
? lhs.addr.port() < rhs.addr.port()
84
: lhs.addr.address() < rhs.addr.address();
89
class announce_observer : public observer
92
announce_observer(boost::pool<>& allocator
93
, sha1_hash const& info_hash
95
, entry const& write_token)
97
, m_info_hash(info_hash)
98
, m_listen_port(listen_port)
99
, m_token(write_token)
104
m.port = m_listen_port;
105
m.info_hash = m_info_hash;
106
m.write_token = m_token;
110
void reply(msg const&) {}
114
sha1_hash m_info_hash;
119
class get_peers_observer : public observer
122
get_peers_observer(sha1_hash const& info_hash
125
, boost::function<void(std::vector<tcp::endpoint> const&, sha1_hash const&)> f)
126
: observer(rpc.allocator())
127
, m_info_hash(info_hash)
128
, m_listen_port(listen_port)
135
m.port = m_listen_port;
136
m.info_hash = m_info_hash;
140
void reply(msg const& r)
142
m_rpc.invoke(messages::announce_peer, r.addr
143
, observer_ptr(new (m_rpc.allocator().malloc()) announce_observer(
144
m_rpc.allocator(), m_info_hash, m_listen_port, r.write_token)));
145
m_fun(r.peers, m_info_hash);
150
sha1_hash m_info_hash;
153
boost::function<void(std::vector<tcp::endpoint> const&, sha1_hash const&)> m_fun;
158
class node_impl : boost::noncopyable
160
typedef std::map<node_id, torrent_entry> table_t;
162
node_impl(boost::function<void(msg const&)> const& f
163
, dht_settings const& settings, boost::optional<node_id> node_id);
165
virtual ~node_impl() {}
167
void refresh(node_id const& id, boost::function0<void> f);
168
void bootstrap(std::vector<udp::endpoint> const& nodes
169
, boost::function0<void> f);
170
void find_node(node_id const& id, boost::function<
171
void(std::vector<node_entry> const&)> f);
172
void add_router_node(udp::endpoint router);
174
void incoming(msg const& m);
177
void refresh_bucket(int bucket);
178
int bucket_size(int bucket);
180
typedef routing_table::iterator iterator;
182
iterator begin() const { return m_table.begin(); }
183
iterator end() const { return m_table.end(); }
185
typedef table_t::iterator data_iterator;
187
node_id const& nid() const { return m_id; }
188
boost::tuple<int, int> size() const{ return m_table.size(); }
189
size_type num_global_nodes() const
190
{ return m_table.num_global_nodes(); }
192
data_iterator begin_data() { return m_map.begin(); }
193
data_iterator end_data() { return m_map.end(); }
194
int data_size() const { return int(m_map.size()); }
196
#ifdef TORRENT_DHT_VERBOSE_LOGGING
197
void print_state(std::ostream& os) const
198
{ m_table.print_state(os); }
201
void announce(sha1_hash const& info_hash, int listen_port
202
, boost::function<void(std::vector<tcp::endpoint> const&
203
, sha1_hash const&)> f);
205
bool verify_token(msg const& m);
206
entry generate_token(msg const& m);
208
// the returned time is the delay until connection_timeout()
209
// should be called again the next time
210
time_duration connection_timeout();
211
time_duration refresh_timeout();
213
// generates a new secret number used to generate write tokens
214
void new_write_key();
216
// pings the given node, and adds it to
217
// the routing table if it respons and if the
218
// bucket is not full.
219
void add_node(udp::endpoint node);
221
void replacement_cache(bucket_t& nodes) const
222
{ m_table.replacement_cache(nodes); }
225
// is called when a find data request is received. Should
226
// return false if the data is not stored on this node. If
227
// the data is stored, it should be serialized into 'data'.
228
bool on_find(msg const& m, std::vector<tcp::endpoint>& peers) const;
230
// this is called when a store request is received. The data
231
// is store-parameters and the data to be stored.
232
void on_announce(msg const& m, msg& reply);
234
dht_settings const& m_settings;
236
// the maximum number of peers to send in a get_peers
237
// reply. Ordinary trackers usually limit this to 50.
238
// 50 => 6 * 50 = 250 bytes + packet overhead
239
int m_max_peers_reply;
242
void incoming_request(msg const& h);
245
routing_table m_table;
249
ptime m_last_tracker_tick;
251
// secret random numbers used to create write tokens
256
} } // namespace libtorrent::dht