3 Copyright (c) 2003 - 2006, Arvid Norberg
4 Copyright (c) 2007, Arvid Norberg, Un Shyam
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
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.
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.
34 #ifndef TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
35 #define TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
43 #include "libtorrent/debug.hpp"
46 #pragma warning(push, 1)
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>
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"
82 class TORRENT_EXPORT bt_peer_connection
83 : public peer_connection
85 friend class invariant_access
;
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
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
);
98 // with this constructor we have been contacted and we still don't
99 // know which torrent the connection belongs to
101 aux::session_impl
& ses
102 , boost::shared_ptr
<socket_type
> s
103 , tcp::endpoint
const& remote
104 , policy::peer
* peerinfo
);
108 ~bt_peer_connection();
110 #ifndef TORRENT_DISABLE_ENCRYPTION
111 bool supports_encryption() const
112 { return m_encrypted
; }
130 msg_suggest_piece
= 0xd,
136 // extension protocol message
139 num_supported_messages
142 // called from the main loop when this connection has any
145 void on_sent(error_code
const& error
146 , std::size_t bytes_transferred
);
147 void on_receive(error_code
const& error
148 , std::size_t bytes_transferred
);
150 virtual void get_specific_peer_info(peer_info
& p
) const;
151 virtual bool in_handshake() const;
153 #ifndef TORRENT_DISABLE_EXTENSIONS
154 bool support_extensions() const { return m_supports_extensions
; }
157 T
* supports_extension() const
159 for (extension_list_t::const_iterator i
= m_extensions
.begin()
160 , end(m_extensions
.end()); i
!= end
; ++i
)
162 T
* ret
= dynamic_cast<T
*>(i
->get());
169 // the message handlers are called
170 // each time a recv() returns some new
171 // data, the last time it will be called
172 // is when the entire packet has been
173 // received, then it will no longer
174 // be called. i.e. most handlers need
175 // to check how much of the packet they
176 // have received before any processing
178 void on_choke(int received
);
179 void on_unchoke(int received
);
180 void on_interested(int received
);
181 void on_not_interested(int received
);
182 void on_have(int received
);
183 void on_bitfield(int received
);
184 void on_request(int received
);
185 void on_piece(int received
);
186 void on_cancel(int received
);
189 void on_dht_port(int received
);
192 void on_suggest_piece(int received
);
193 void on_have_all(int received
);
194 void on_have_none(int received
);
195 void on_reject_request(int received
);
196 void on_allowed_fast(int received
);
198 void on_extended(int received
);
200 void on_extended_handshake();
202 typedef void (bt_peer_connection::*message_handler
)(int received
);
204 // the following functions appends messages
205 // to the send buffer
207 void write_unchoke();
208 void write_interested();
209 void write_not_interested();
210 void write_request(peer_request
const& r
);
211 void write_cancel(peer_request
const& r
);
212 void write_bitfield();
213 void write_have(int index
);
214 void write_piece(peer_request
const& r
, disk_buffer_holder
& buffer
);
215 void write_handshake();
216 #ifndef TORRENT_DISABLE_EXTENSIONS
217 void write_extensions();
219 void write_chat_message(const std::string
& msg
);
220 void write_metadata(std::pair
<int, int> req
);
221 void write_metadata_request(std::pair
<int, int> req
);
222 void write_keepalive();
225 void write_dht_port(int listen_port
);
228 void write_have_all();
229 void write_have_none();
230 void write_reject_request(peer_request
const&);
231 void write_allow_fast(int piece
);
237 void check_invariant() const;
243 bool dispatch_message(int received
);
244 // returns the block currently being
245 // downloaded. And the progress of that
246 // block. If the peer isn't downloading
247 // a piece for the moment, the boost::optional
249 boost::optional
<piece_block_progress
> downloading_piece_progress() const;
251 #ifndef TORRENT_DISABLE_ENCRYPTION
253 // if (is_local()), we are 'a' otherwise 'b'
255 // 1. a -> b dhkey, pad
256 // 2. b -> a dhkey, pad
257 // 3. a -> b sync, payload
258 // 4. b -> a sync, payload
261 void write_pe1_2_dhkey();
262 void write_pe3_sync();
263 void write_pe4_sync(int crypto_select
);
265 void write_pe_vc_cryptofield(buffer::interval
& write_buf
,
266 int crypto_field
, int pad_size
);
268 // stream key (info hash of attached torrent)
269 // secret is the DH shared secret
270 // initializes m_RC4_handler
271 void init_pe_RC4_handler(char const* secret
, sha1_hash
const& stream_key
);
275 // these functions encrypt the send buffer if m_rc4_encrypted
276 // is true, otherwise it passes the call to the
277 // peer_connection functions of the same names
278 void send_buffer(char* buf
, int size
, int flags
= 0);
279 buffer::interval
allocate_send_buffer(int size
);
280 template <class Destructor
>
281 void append_send_buffer(char* buffer
, int size
, Destructor
const& destructor
)
283 #ifndef TORRENT_DISABLE_ENCRYPTION
285 m_RC4_handler
->encrypt(buffer
, size
);
287 peer_connection::append_send_buffer(buffer
, size
, destructor
);
293 // Returns offset at which bytestream (src, src + src_size)
294 // matches bytestream(target, target + target_size).
295 // If no sync found, return -1
296 int get_syncoffset(char const* src
, int src_size
,
297 char const* target
, int target_size
) const;
302 #ifndef TORRENT_DISABLE_ENCRYPTION
311 read_protocol_identifier
,
313 read_protocol_identifier
= 0,
318 // handshake complete
323 #ifndef TORRENT_DISABLE_ENCRYPTION
331 std::string m_client_version
;
333 // state of on_receive
336 // the timeout in seconds
339 static const message_handler m_message_handler
[num_supported_messages
];
341 // this is a queue of ranges that describes
342 // where in the send buffer actual payload
343 // data is located. This is currently
344 // only used to be able to gather statistics
345 // seperately on payload and protocol data.
352 TORRENT_ASSERT(s
>= 0);
353 TORRENT_ASSERT(l
> 0);
358 static bool range_below_zero(const range
& r
)
359 { return r
.start
< 0; }
360 std::deque
<range
> m_payloads
;
362 #ifndef TORRENT_DISABLE_EXTENSIONS
363 // this is set to true if the handshake from
364 // the peer indicated that it supports the
365 // extension protocol
366 bool m_supports_extensions
;
367 char m_reserved_bits
[20];
369 bool m_supports_dht_port
;
370 bool m_supports_fast
;
372 #ifndef TORRENT_DISABLE_ENCRYPTION
373 // this is set to true after the encryption method has been
374 // succesfully negotiated (either plaintext or rc4), to signal
375 // automatic encryption/decryption.
378 // true if rc4, false if plaintext
379 bool m_rc4_encrypted
;
381 // used to disconnect peer if sync points are not found within
382 // the maximum number of bytes
383 int m_sync_bytes_read
;
385 // hold information about latest allocated send buffer
386 // need to check for non zero (begin, end) for operations with this
387 buffer::interval m_enc_send_buffer
;
389 // initialized during write_pe1_2_dhkey, and destroyed on
390 // creation of m_RC4_handler. Cannot reinitialize once
392 boost::scoped_ptr
<dh_key_exchange
> m_dh_key_exchange
;
394 // if RC4 is negotiated, this is used for
395 // encryption/decryption during the entire session. Destroyed
396 // if plaintext is selected
397 boost::scoped_ptr
<RC4_handler
> m_RC4_handler
;
399 // (outgoing only) synchronize verification constant with
400 // remote peer, this will hold RC4_decrypt(vc). Destroyed
401 // after the sync step.
402 boost::scoped_array
<char> m_sync_vc
;
404 // (incoming only) synchronize hash with remote peer, holds
405 // the sync hash (hash("req1",secret)). Destroyed after the
407 boost::scoped_ptr
<sha1_hash
> m_sync_hash
;
408 #endif // #ifndef TORRENT_DISABLE_ENCRYPTION
411 // this is set to true when the client's
412 // bitfield is sent to this peer
413 bool m_sent_bitfield
;
415 bool m_in_constructor
;
417 bool m_sent_handshake
;
423 #endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED