~ubuntu-branches/ubuntu/intrepid/miro/intrepid

« back to all changes in this revision

Viewing changes to portable/libtorrent/include/libtorrent/kademlia/node.hpp

  • Committer: Bazaar Package Importer
  • Author(s): Christopher James Halse Rogers
  • Date: 2008-02-09 13:37:10 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080209133710-9rs90q6gckvp1b6i
Tags: 1.1.2-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Copyright (c) 2006, Arvid Norberg
 
4
All rights reserved.
 
5
 
 
6
Redistribution and use in source and binary forms, with or without
 
7
modification, are permitted provided that the following conditions
 
8
are met:
 
9
 
 
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.
 
18
 
 
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.
 
30
 
 
31
*/
 
32
 
 
33
#ifndef NODE_HPP
 
34
#define NODE_HPP
 
35
 
 
36
#include <algorithm>
 
37
#include <map>
 
38
#include <set>
 
39
 
 
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>
 
44
 
 
45
#include <libtorrent/io.hpp>
 
46
#include <libtorrent/session_settings.hpp>
 
47
#include <libtorrent/assert.hpp>
 
48
 
 
49
#include <boost/cstdint.hpp>
 
50
#include <boost/optional.hpp>
 
51
#include <boost/iterator/transform_iterator.hpp>
 
52
#include <boost/ref.hpp>
 
53
 
 
54
#include "libtorrent/socket.hpp"
 
55
 
 
56
namespace libtorrent { namespace dht
 
57
{
 
58
 
 
59
using asio::ip::udp;
 
60
 
 
61
#ifdef TORRENT_DHT_VERBOSE_LOGGING
 
62
TORRENT_DECLARE_LOG(node);
 
63
#endif
 
64
 
 
65
// this is the entry for every peer
 
66
// the timestamp is there to make it possible
 
67
// to remove stale peers
 
68
struct peer_entry
 
69
{
 
70
        tcp::endpoint addr;
 
71
        ptime added;
 
72
};
 
73
 
 
74
// this is a group. It contains a set of group members
 
75
struct torrent_entry
 
76
{
 
77
        std::set<peer_entry> peers;
 
78
};
 
79
 
 
80
inline bool operator<(peer_entry const& lhs, peer_entry const& rhs)
 
81
{
 
82
        return lhs.addr.address() == rhs.addr.address()
 
83
                ? lhs.addr.port() < rhs.addr.port()
 
84
                : lhs.addr.address() < rhs.addr.address();
 
85
}
 
86
 
 
87
struct null_type {};
 
88
 
 
89
class announce_observer : public observer
 
90
{
 
91
public:
 
92
        announce_observer(boost::pool<>& allocator
 
93
                , sha1_hash const& info_hash
 
94
                , int listen_port
 
95
                , entry const& write_token)
 
96
                : observer(allocator)
 
97
                , m_info_hash(info_hash)
 
98
                , m_listen_port(listen_port)
 
99
                , m_token(write_token)
 
100
        {}
 
101
 
 
102
        void send(msg& m)
 
103
        {
 
104
                m.port = m_listen_port;
 
105
                m.info_hash = m_info_hash;
 
106
                m.write_token = m_token;
 
107
        }
 
108
 
 
109
        void timeout() {}
 
110
        void reply(msg const&) {}
 
111
        void abort() {}
 
112
 
 
113
private:
 
114
        sha1_hash m_info_hash;
 
115
        int m_listen_port;
 
116
        entry m_token;
 
117
};
 
118
 
 
119
class get_peers_observer : public observer
 
120
{
 
121
public:
 
122
        get_peers_observer(sha1_hash const& info_hash
 
123
                , int listen_port
 
124
                , rpc_manager& rpc
 
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)
 
129
                , m_rpc(rpc)
 
130
                , m_fun(f)
 
131
        {}
 
132
 
 
133
        void send(msg& m)
 
134
        {
 
135
                m.port = m_listen_port;
 
136
                m.info_hash = m_info_hash;
 
137
        }
 
138
 
 
139
        void timeout() {}
 
140
        void reply(msg const& r)
 
141
        {
 
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);
 
146
        }
 
147
        void abort() {}
 
148
 
 
149
private:
 
150
        sha1_hash m_info_hash;
 
151
        int m_listen_port;
 
152
        rpc_manager& m_rpc;
 
153
        boost::function<void(std::vector<tcp::endpoint> const&, sha1_hash const&)> m_fun;
 
154
};
 
155
 
 
156
 
 
157
 
 
158
class node_impl : boost::noncopyable
 
159
{
 
160
typedef std::map<node_id, torrent_entry> table_t;
 
161
public:
 
162
        node_impl(boost::function<void(msg const&)> const& f
 
163
                , dht_settings const& settings, boost::optional<node_id> node_id);
 
164
 
 
165
        virtual ~node_impl() {}
 
166
 
 
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);
 
173
                
 
174
        void incoming(msg const& m);
 
175
 
 
176
        void refresh();
 
177
        void refresh_bucket(int bucket);
 
178
        int bucket_size(int bucket);
 
179
 
 
180
        typedef routing_table::iterator iterator;
 
181
        
 
182
        iterator begin() const { return m_table.begin(); }
 
183
        iterator end() const { return m_table.end(); }
 
184
 
 
185
        typedef table_t::iterator data_iterator;
 
186
 
 
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(); }
 
191
 
 
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()); }
 
195
 
 
196
#ifdef TORRENT_DHT_VERBOSE_LOGGING
 
197
        void print_state(std::ostream& os) const
 
198
        { m_table.print_state(os); }
 
199
#endif
 
200
 
 
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);
 
204
 
 
205
        bool verify_token(msg const& m);
 
206
        entry generate_token(msg const& m);
 
207
        
 
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();
 
212
 
 
213
        // generates a new secret number used to generate write tokens
 
214
        void new_write_key();
 
215
 
 
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);
 
220
 
 
221
        void replacement_cache(bucket_t& nodes) const
 
222
        { m_table.replacement_cache(nodes); }
 
223
 
 
224
protected:
 
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;
 
229
 
 
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);
 
233
 
 
234
        dht_settings const& m_settings;
 
235
        
 
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;
 
240
 
 
241
private:
 
242
        void incoming_request(msg const& h);
 
243
 
 
244
        node_id m_id;
 
245
        routing_table m_table;
 
246
        rpc_manager m_rpc;
 
247
        table_t m_map;
 
248
        
 
249
        ptime m_last_tracker_tick;
 
250
 
 
251
        // secret random numbers used to create write tokens
 
252
        int m_secret[2];
 
253
};
 
254
 
 
255
 
 
256
} } // namespace libtorrent::dht
 
257
 
 
258
#endif // NODE_HPP
 
259