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

« back to all changes in this revision

Viewing changes to portable/libtorrent/include/libtorrent/bt_peer_connection.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) 2003 - 2006, Arvid Norberg
 
4
Copyright (c) 2007, Arvid Norberg, Un Shyam
 
5
All rights reserved.
 
6
 
 
7
Redistribution and use in source and binary forms, with or without
 
8
modification, are permitted provided that the following conditions
 
9
are met:
 
10
 
 
11
    * Redistributions of source code must retain the above copyright
 
12
      notice, this list of conditions and the following disclaimer.
 
13
    * Redistributions in binary form must reproduce the above copyright
 
14
      notice, this list of conditions and the following disclaimer in
 
15
      the documentation and/or other materials provided with the distribution.
 
16
    * Neither the name of the author nor the names of its
 
17
      contributors may be used to endorse or promote products derived
 
18
      from this software without specific prior written permission.
 
19
 
 
20
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
21
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
22
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
23
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
24
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
25
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
26
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
27
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
28
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
29
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
30
POSSIBILITY OF SUCH DAMAGE.
 
31
 
 
32
*/
 
33
 
 
34
#ifndef TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
 
35
#define TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
 
36
 
 
37
#include <ctime>
 
38
#include <algorithm>
 
39
#include <vector>
 
40
#include <deque>
 
41
#include <string>
 
42
 
 
43
#include "libtorrent/debug.hpp"
 
44
 
 
45
#ifdef _MSC_VER
 
46
#pragma warning(push, 1)
 
47
#endif
 
48
 
 
49
#include <boost/smart_ptr.hpp>
 
50
#include <boost/noncopyable.hpp>
 
51
#include <boost/array.hpp>
 
52
#include <boost/optional.hpp>
 
53
#include <boost/cstdint.hpp>
 
54
 
 
55
#ifdef _MSC_VER
 
56
#pragma warning(pop)
 
57
#endif
 
58
 
 
59
#include "libtorrent/buffer.hpp"
 
60
#include "libtorrent/peer_connection.hpp"
 
61
#include "libtorrent/socket.hpp"
 
62
#include "libtorrent/peer_id.hpp"
 
63
#include "libtorrent/storage.hpp"
 
64
#include "libtorrent/stat.hpp"
 
65
#include "libtorrent/alert.hpp"
 
66
#include "libtorrent/torrent_handle.hpp"
 
67
#include "libtorrent/torrent.hpp"
 
68
#include "libtorrent/peer_request.hpp"
 
69
#include "libtorrent/piece_block_progress.hpp"
 
70
#include "libtorrent/config.hpp"
 
71
#include "libtorrent/pe_crypto.hpp"
 
72
 
 
73
namespace libtorrent
 
74
{
 
75
        class torrent;
 
76
 
 
77
        namespace detail
 
78
        {
 
79
                struct session_impl;
 
80
        }
 
81
 
 
82
        class TORRENT_EXPORT bt_peer_connection
 
83
                : public peer_connection
 
84
        {
 
85
        friend class invariant_access;
 
86
        public:
 
87
 
 
88
                // this is the constructor where the we are the active part.
 
89
                // The peer_conenction should handshake and verify that the
 
90
                // other end has the correct id
 
91
                bt_peer_connection(
 
92
                        aux::session_impl& ses
 
93
                        , boost::weak_ptr<torrent> t
 
94
                        , boost::shared_ptr<socket_type> s
 
95
                        , tcp::endpoint const& remote
 
96
                        , policy::peer* peerinfo);
 
97
 
 
98
                // with this constructor we have been contacted and we still don't
 
99
                // know which torrent the connection belongs to
 
100
                bt_peer_connection(
 
101
                        aux::session_impl& ses
 
102
                        , boost::shared_ptr<socket_type> s
 
103
                        , policy::peer* peerinfo);
 
104
 
 
105
                ~bt_peer_connection();
 
106
                
 
107
#ifndef TORRENT_DISABLE_ENCRYPTION
 
108
                bool supports_encryption() const
 
109
                { return m_encrypted; }
 
110
#endif
 
111
 
 
112
                enum message_type
 
113
                {
 
114
        // standard messages
 
115
                        msg_choke = 0,
 
116
                        msg_unchoke,
 
117
                        msg_interested,
 
118
                        msg_not_interested,
 
119
                        msg_have,
 
120
                        msg_bitfield,
 
121
                        msg_request,
 
122
                        msg_piece,
 
123
                        msg_cancel,
 
124
                        // DHT extension
 
125
                        msg_dht_port,
 
126
                        // FAST extension
 
127
                        msg_suggest_piece = 0xd,
 
128
                        msg_have_all,
 
129
                        msg_have_none,
 
130
                        msg_reject_request,
 
131
                        msg_allowed_fast,
 
132
                        
 
133
                        // extension protocol message
 
134
                        msg_extended = 20,
 
135
 
 
136
                        num_supported_messages
 
137
                };
 
138
 
 
139
                // called from the main loop when this connection has any
 
140
                // work to do.
 
141
 
 
142
                void on_sent(asio::error_code const& error
 
143
                        , std::size_t bytes_transferred);
 
144
                void on_receive(asio::error_code const& error
 
145
                        , std::size_t bytes_transferred);
 
146
                
 
147
                virtual void get_specific_peer_info(peer_info& p) const;
 
148
                virtual bool in_handshake() const;
 
149
 
 
150
#ifndef TORRENT_DISABLE_EXTENSIONS
 
151
                bool support_extensions() const { return m_supports_extensions; }
 
152
 
 
153
                template <class T>
 
154
                T* supports_extension() const
 
155
                {
 
156
                        for (extension_list_t::const_iterator i = m_extensions.begin()
 
157
                                , end(m_extensions.end()); i != end; ++i)
 
158
                        {
 
159
                                T* ret = dynamic_cast<T*>(i->get());
 
160
                                if (ret) return ret;
 
161
                        }
 
162
                        return 0;
 
163
                }
 
164
#endif
 
165
 
 
166
                // the message handlers are called
 
167
                // each time a recv() returns some new
 
168
                // data, the last time it will be called
 
169
                // is when the entire packet has been
 
170
                // received, then it will no longer
 
171
                // be called. i.e. most handlers need
 
172
                // to check how much of the packet they
 
173
                // have received before any processing
 
174
                void on_keepalive();
 
175
                void on_choke(int received);
 
176
                void on_unchoke(int received);
 
177
                void on_interested(int received);
 
178
                void on_not_interested(int received);
 
179
                void on_have(int received);
 
180
                void on_bitfield(int received);
 
181
                void on_request(int received);
 
182
                void on_piece(int received);
 
183
                void on_cancel(int received);
 
184
 
 
185
                // DHT extension
 
186
                void on_dht_port(int received);
 
187
 
 
188
                // FAST extension
 
189
                void on_suggest_piece(int received);
 
190
                void on_have_all(int received);
 
191
                void on_have_none(int received);
 
192
                void on_reject_request(int received);
 
193
                void on_allowed_fast(int received);
 
194
 
 
195
                void on_extended(int received);
 
196
 
 
197
                void on_extended_handshake();
 
198
 
 
199
                typedef void (bt_peer_connection::*message_handler)(int received);
 
200
 
 
201
                // the following functions appends messages
 
202
                // to the send buffer
 
203
                void write_choke();
 
204
                void write_unchoke();
 
205
                void write_interested();
 
206
                void write_not_interested();
 
207
                void write_request(peer_request const& r);
 
208
                void write_cancel(peer_request const& r);
 
209
                void write_bitfield(std::vector<bool> const& bitfield);
 
210
                void write_have(int index);
 
211
                void write_piece(peer_request const& r, char* buffer);
 
212
                void write_handshake();
 
213
#ifndef TORRENT_DISABLE_EXTENSIONS
 
214
                void write_extensions();
 
215
#endif
 
216
                void write_chat_message(const std::string& msg);
 
217
                void write_metadata(std::pair<int, int> req);
 
218
                void write_metadata_request(std::pair<int, int> req);
 
219
                void write_keepalive();
 
220
 
 
221
                // DHT extension
 
222
                void write_dht_port(int listen_port);
 
223
 
 
224
                // FAST extension
 
225
                void write_have_all();
 
226
                void write_have_none();
 
227
                void write_reject_request(peer_request const&);
 
228
                void write_allow_fast(int piece);
 
229
                
 
230
                void on_connected();
 
231
                void on_metadata();
 
232
 
 
233
#ifndef NDEBUG
 
234
                void check_invariant() const;
 
235
                ptime m_last_choke;
 
236
#endif
 
237
 
 
238
        private:
 
239
 
 
240
                bool dispatch_message(int received);
 
241
                // returns the block currently being
 
242
                // downloaded. And the progress of that
 
243
                // block. If the peer isn't downloading
 
244
                // a piece for the moment, the boost::optional
 
245
                // will be invalid.
 
246
                boost::optional<piece_block_progress> downloading_piece_progress() const;
 
247
 
 
248
#ifndef TORRENT_DISABLE_ENCRYPTION
 
249
 
 
250
                // if (is_local()), we are 'a' otherwise 'b'
 
251
                //
 
252
                // 1. a -> b dhkey, pad
 
253
                // 2. b -> a dhkey, pad
 
254
                // 3. a -> b sync, payload
 
255
                // 4. b -> a sync, payload
 
256
                // 5. a -> b payload
 
257
 
 
258
                void write_pe1_2_dhkey();
 
259
                void write_pe3_sync();
 
260
                void write_pe4_sync(int crypto_select);
 
261
 
 
262
                void write_pe_vc_cryptofield(buffer::interval& write_buf, 
 
263
                                                                         int crypto_field, int pad_size);
 
264
 
 
265
                // stream key (info hash of attached torrent)
 
266
                // secret is the DH shared secret
 
267
                // initializes m_RC4_handler
 
268
                void init_pe_RC4_handler(char const* secret, sha1_hash const& stream_key);
 
269
 
 
270
                // these functions encrypt the send buffer if m_rc4_encrypted
 
271
                // is true, otherwise it passes the call to the
 
272
                // peer_connection functions of the same names
 
273
                void send_buffer(char* buf, int size);
 
274
                buffer::interval allocate_send_buffer(int size);
 
275
                template <class Destructor>
 
276
                void append_send_buffer(char* buffer, int size, Destructor const& destructor)
 
277
                {
 
278
#ifndef TORRENT_DISABLE_ENCRYPTION
 
279
                        if (m_rc4_encrypted)
 
280
                                m_RC4_handler->encrypt(buffer, size);
 
281
#endif
 
282
                        peer_connection::append_send_buffer(buffer, size, destructor);
 
283
                }
 
284
                void setup_send();
 
285
 
 
286
                // Returns offset at which bytestream (src, src + src_size)
 
287
                // matches bytestream(target, target + target_size).
 
288
                // If no sync found, return -1
 
289
                int get_syncoffset(char const* src, int src_size,
 
290
                                                   char const* target, int target_size) const;
 
291
#endif
 
292
 
 
293
                enum state
 
294
                {
 
295
#ifndef TORRENT_DISABLE_ENCRYPTION
 
296
                        read_pe_dhkey = 0,
 
297
                        read_pe_syncvc,
 
298
                        read_pe_synchash,
 
299
                        read_pe_skey_vc,
 
300
                        read_pe_cryptofield,
 
301
                        read_pe_pad,
 
302
                        read_pe_ia,
 
303
                        init_bt_handshake,
 
304
                        read_protocol_identifier,
 
305
#else
 
306
                        read_protocol_identifier = 0,
 
307
#endif
 
308
                        read_info_hash,
 
309
                        read_peer_id,
 
310
 
 
311
                        // handshake complete
 
312
                        read_packet_size,
 
313
                        read_packet
 
314
                };
 
315
                
 
316
#ifndef TORRENT_DISABLE_ENCRYPTION
 
317
                enum
 
318
                {
 
319
                        handshake_len = 68,
 
320
                        dh_key_len = 96
 
321
                };
 
322
#endif
 
323
 
 
324
                std::string m_client_version;
 
325
 
 
326
                // state of on_receive
 
327
                state m_state;
 
328
 
 
329
                // the timeout in seconds
 
330
                int m_timeout;
 
331
 
 
332
                static const message_handler m_message_handler[num_supported_messages];
 
333
 
 
334
                // this is a queue of ranges that describes
 
335
                // where in the send buffer actual payload
 
336
                // data is located. This is currently
 
337
                // only used to be able to gather statistics
 
338
                // seperately on payload and protocol data.
 
339
                struct range
 
340
                {
 
341
                        range(int s, int l)
 
342
                                : start(s)
 
343
                                , length(l)
 
344
                        {
 
345
                                TORRENT_ASSERT(s >= 0);
 
346
                                TORRENT_ASSERT(l > 0);
 
347
                        }
 
348
                        int start;
 
349
                        int length;
 
350
                };
 
351
                static bool range_below_zero(const range& r)
 
352
                { return r.start < 0; }
 
353
                std::deque<range> m_payloads;
 
354
 
 
355
#ifndef TORRENT_DISABLE_EXTENSIONS
 
356
                // this is set to true if the handshake from
 
357
                // the peer indicated that it supports the
 
358
                // extension protocol
 
359
                bool m_supports_extensions;
 
360
#endif
 
361
                bool m_supports_dht_port;
 
362
                bool m_supports_fast;
 
363
 
 
364
#ifndef TORRENT_DISABLE_ENCRYPTION
 
365
                // this is set to true after the encryption method has been
 
366
                // succesfully negotiated (either plaintext or rc4), to signal
 
367
                // automatic encryption/decryption.
 
368
                bool m_encrypted;
 
369
 
 
370
                // true if rc4, false if plaintext
 
371
                bool m_rc4_encrypted;
 
372
 
 
373
                // used to disconnect peer if sync points are not found within
 
374
                // the maximum number of bytes
 
375
                int m_sync_bytes_read;
 
376
 
 
377
                // hold information about latest allocated send buffer
 
378
                // need to check for non zero (begin, end) for operations with this
 
379
                buffer::interval m_enc_send_buffer;
 
380
                
 
381
                // initialized during write_pe1_2_dhkey, and destroyed on
 
382
                // creation of m_RC4_handler. Cannot reinitialize once
 
383
                // initialized.
 
384
                boost::scoped_ptr<DH_key_exchange> m_DH_key_exchange;
 
385
                
 
386
                // if RC4 is negotiated, this is used for
 
387
                // encryption/decryption during the entire session. Destroyed
 
388
                // if plaintext is selected
 
389
                boost::scoped_ptr<RC4_handler> m_RC4_handler;
 
390
                
 
391
                // (outgoing only) synchronize verification constant with
 
392
                // remote peer, this will hold RC4_decrypt(vc). Destroyed
 
393
                // after the sync step.
 
394
                boost::scoped_array<char> m_sync_vc;
 
395
 
 
396
                // (incoming only) synchronize hash with remote peer, holds
 
397
                // the sync hash (hash("req1",secret)). Destroyed after the
 
398
                // sync step.
 
399
                boost::scoped_ptr<sha1_hash> m_sync_hash;
 
400
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
 
401
 
 
402
#ifndef NDEBUG
 
403
                // this is set to true when the client's
 
404
                // bitfield is sent to this peer
 
405
                bool m_sent_bitfield;
 
406
 
 
407
                bool m_in_constructor;
 
408
                
 
409
                bool m_sent_handshake;
 
410
#endif
 
411
 
 
412
        };
 
413
}
 
414
 
 
415
#endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
 
416