merged Steven Siloti's peer crypto patch into trunk
This commit is contained in:
parent
179df62379
commit
658e2ceefd
|
@ -53,6 +53,7 @@ set(sources
|
||||||
peer_list
|
peer_list
|
||||||
puff
|
puff
|
||||||
random
|
random
|
||||||
|
receive_buffer
|
||||||
request_blocks
|
request_blocks
|
||||||
resolver
|
resolver
|
||||||
rss
|
rss
|
||||||
|
|
1
Jamfile
1
Jamfile
|
@ -549,6 +549,7 @@ SOURCES =
|
||||||
proxy_base
|
proxy_base
|
||||||
puff
|
puff
|
||||||
random
|
random
|
||||||
|
receive_buffer
|
||||||
rss
|
rss
|
||||||
session
|
session
|
||||||
session_impl
|
session_impl
|
||||||
|
|
|
@ -1112,7 +1112,7 @@ int main(int argc, char* argv[])
|
||||||
" share ratio rather than downloading\n"
|
" share ratio rather than downloading\n"
|
||||||
" -K enable piece suggestions of read cache\n"
|
" -K enable piece suggestions of read cache\n"
|
||||||
" -r <IP:port> connect to specified peer\n"
|
" -r <IP:port> connect to specified peer\n"
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
" -e force encrypted bittorrent connections\n"
|
" -e force encrypted bittorrent connections\n"
|
||||||
#endif
|
#endif
|
||||||
"\n QUEING OPTIONS\n"
|
"\n QUEING OPTIONS\n"
|
||||||
|
@ -1288,7 +1288,7 @@ int main(int argc, char* argv[])
|
||||||
--i;
|
--i;
|
||||||
break;
|
break;
|
||||||
case 'l': settings.set_int(settings_pack::listen_queue_size, atoi(arg)); break;
|
case 'l': settings.set_int(settings_pack::listen_queue_size, atoi(arg)); break;
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
case 'e':
|
case 'e':
|
||||||
{
|
{
|
||||||
settings.set_int(settings_pack::out_enc_policy, settings_pack::pe_forced);
|
settings.set_int(settings_pack::out_enc_policy, settings_pack::pe_forced);
|
||||||
|
|
|
@ -347,7 +347,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void maybe_update_udp_mapping(int nat, int local_port, int external_port);
|
void maybe_update_udp_mapping(int nat, int local_port, int external_port);
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
torrent const* find_encrypted_torrent(
|
torrent const* find_encrypted_torrent(
|
||||||
sha1_hash const& info_hash, sha1_hash const& xor_mask);
|
sha1_hash const& info_hash, sha1_hash const& xor_mask);
|
||||||
|
|
||||||
|
@ -740,7 +740,7 @@ namespace libtorrent
|
||||||
tracker_manager m_tracker_manager;
|
tracker_manager m_tracker_manager;
|
||||||
torrent_map m_torrents;
|
torrent_map m_torrents;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
// this maps obfuscated hashes to torrents. It's only
|
// this maps obfuscated hashes to torrents. It's only
|
||||||
// used when encryption is enabled
|
// used when encryption is enabled
|
||||||
torrent_map m_obfuscated_torrents;
|
torrent_map m_obfuscated_torrents;
|
||||||
|
|
|
@ -278,7 +278,7 @@ namespace libtorrent { namespace aux
|
||||||
virtual boost::asio::ssl::context* ssl_ctx() = 0 ;
|
virtual boost::asio::ssl::context* ssl_ctx() = 0 ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
virtual torrent const* find_encrypted_torrent(
|
virtual torrent const* find_encrypted_torrent(
|
||||||
sha1_hash const& info_hash, sha1_hash const& xor_mask) = 0;
|
sha1_hash const& info_hash, sha1_hash const& xor_mask) = 0;
|
||||||
virtual void add_obfuscated_hash(sha1_hash const& obfuscated
|
virtual void add_obfuscated_hash(sha1_hash const& obfuscated
|
||||||
|
|
|
@ -104,11 +104,14 @@ namespace libtorrent
|
||||||
|
|
||||||
~bt_peer_connection();
|
~bt_peer_connection();
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
bool supports_encryption() const
|
bool supports_encryption() const
|
||||||
{ return m_encrypted; }
|
{ return m_encrypted; }
|
||||||
bool rc4_encrypted() const
|
bool rc4_encrypted() const
|
||||||
{ return m_rc4_encrypted; }
|
{ return m_rc4_encrypted; }
|
||||||
|
|
||||||
|
void switch_send_crypto(boost::shared_ptr<crypto_plugin> crypto);
|
||||||
|
void switch_recv_crypto(boost::shared_ptr<crypto_plugin> crypto);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual int type() const { return peer_connection::bittorrent_connection; }
|
virtual int type() const { return peer_connection::bittorrent_connection; }
|
||||||
|
@ -161,9 +164,15 @@ namespace libtorrent
|
||||||
, std::size_t bytes_transferred);
|
, std::size_t bytes_transferred);
|
||||||
void on_receive(error_code const& error
|
void on_receive(error_code const& error
|
||||||
, std::size_t bytes_transferred);
|
, std::size_t bytes_transferred);
|
||||||
|
void on_receive_impl(std::size_t bytes_transferred);
|
||||||
|
|
||||||
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
virtual int hit_send_barrier(std::vector<asio::mutable_buffer>& iovec);
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void get_specific_peer_info(peer_info& p) const;
|
virtual void get_specific_peer_info(peer_info& p) const;
|
||||||
virtual bool in_handshake() const;
|
virtual bool in_handshake() const;
|
||||||
|
bool packet_finished() const { return m_recv_buffer.packet_finished(); }
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
bool supports_holepunch() const { return m_holepunch_id != 0; }
|
bool supports_holepunch() const { return m_holepunch_id != 0; }
|
||||||
|
@ -260,7 +269,7 @@ namespace libtorrent
|
||||||
// will be invalid.
|
// will be invalid.
|
||||||
boost::optional<piece_block_progress> downloading_piece_progress() const;
|
boost::optional<piece_block_progress> downloading_piece_progress() const;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
|
||||||
// if (is_local()), we are 'a' otherwise 'b'
|
// if (is_local()), we are 'a' otherwise 'b'
|
||||||
//
|
//
|
||||||
|
@ -287,6 +296,9 @@ namespace libtorrent
|
||||||
// If no sync found, return -1
|
// If no sync found, return -1
|
||||||
int get_syncoffset(char const* src, int src_size
|
int get_syncoffset(char const* src, int src_size
|
||||||
, char const* target, int target_size) const;
|
, char const* target, int target_size) const;
|
||||||
|
|
||||||
|
// helper to cut down on boilerplate
|
||||||
|
void rc4_decrypt(char* pos, int len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -299,19 +311,11 @@ public:
|
||||||
, void* userdata = NULL, block_cache_reference ref
|
, void* userdata = NULL, block_cache_reference ref
|
||||||
= block_cache_reference());
|
= block_cache_reference());
|
||||||
|
|
||||||
virtual void send_buffer(char const* begin, int size, int flags = 0
|
|
||||||
, void (*fun)(char*, int, void*) = 0, void* userdata = 0);
|
|
||||||
|
|
||||||
virtual void append_send_buffer(char* buffer, int size
|
|
||||||
, chained_buffer::free_buffer_fun destructor = &nop
|
|
||||||
, void* userdata = NULL, block_cache_reference ref
|
|
||||||
= block_cache_reference(), bool encrypted = false);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum state_t
|
enum state_t
|
||||||
{
|
{
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
read_pe_dhkey = 0,
|
read_pe_dhkey = 0,
|
||||||
read_pe_syncvc,
|
read_pe_syncvc,
|
||||||
read_pe_synchash,
|
read_pe_synchash,
|
||||||
|
@ -332,7 +336,7 @@ private:
|
||||||
read_packet
|
read_packet
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
handshake_len = 68,
|
handshake_len = 68,
|
||||||
|
@ -360,7 +364,7 @@ private:
|
||||||
// and can send bittorrent messages
|
// and can send bittorrent messages
|
||||||
bool m_sent_handshake:1;
|
bool m_sent_handshake:1;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
// this is set to true after the encryption method has been
|
// this is set to true after the encryption method has been
|
||||||
// succesfully negotiated (either plaintext or rc4), to signal
|
// succesfully negotiated (either plaintext or rc4), to signal
|
||||||
// automatic encryption/decryption.
|
// automatic encryption/decryption.
|
||||||
|
@ -368,6 +372,8 @@ private:
|
||||||
|
|
||||||
// true if rc4, false if plaintext
|
// true if rc4, false if plaintext
|
||||||
bool m_rc4_encrypted:1;
|
bool m_rc4_encrypted:1;
|
||||||
|
|
||||||
|
crypto_receive_buffer m_recv_buffer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string m_client_version;
|
std::string m_client_version;
|
||||||
|
@ -395,16 +401,20 @@ private:
|
||||||
|
|
||||||
std::vector<range> m_payloads;
|
std::vector<range> m_payloads;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
// initialized during write_pe1_2_dhkey, and destroyed on
|
// initialized during write_pe1_2_dhkey, and destroyed on
|
||||||
// creation of m_enc_handler. Cannot reinitialize once
|
// creation of m_enc_handler. Cannot reinitialize once
|
||||||
// initialized.
|
// initialized.
|
||||||
boost::scoped_ptr<dh_key_exchange> m_dh_key_exchange;
|
boost::scoped_ptr<dh_key_exchange> m_dh_key_exchange;
|
||||||
|
|
||||||
|
// used during an encrypted handshake then moved
|
||||||
|
// into m_enc_handler if rc4 encryption is negotiated
|
||||||
|
// otherwise it is destroyed when the handshake completes
|
||||||
|
boost::shared_ptr<rc4_handler> m_rc4;
|
||||||
|
|
||||||
// if encryption is negotiated, this is used for
|
// if encryption is negotiated, this is used for
|
||||||
// encryption/decryption during the entire session. Destroyed
|
// encryption/decryption during the entire session.
|
||||||
// if plaintext is selected
|
encryption_handler m_enc_handler;
|
||||||
boost::scoped_ptr<encryption_handler> m_enc_handler;
|
|
||||||
|
|
||||||
// (outgoing only) synchronize verification constant with
|
// (outgoing only) synchronize verification constant with
|
||||||
// remote peer, this will hold rc4_decrypt(vc). Destroyed
|
// remote peer, this will hold rc4_decrypt(vc). Destroyed
|
||||||
|
@ -415,11 +425,11 @@ private:
|
||||||
// the sync hash (hash("req1",secret)). Destroyed after the
|
// the sync hash (hash("req1",secret)). Destroyed after the
|
||||||
// sync step.
|
// sync step.
|
||||||
boost::scoped_ptr<sha1_hash> m_sync_hash;
|
boost::scoped_ptr<sha1_hash> m_sync_hash;
|
||||||
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
|
#endif // #if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
|
||||||
static const message_handler m_message_handler[num_supported_messages];
|
static const message_handler m_message_handler[num_supported_messages];
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
// used to disconnect peer if sync points are not found within
|
// used to disconnect peer if sync points are not found within
|
||||||
// the maximum number of bytes
|
// the maximum number of bytes
|
||||||
int m_sync_bytes_read;
|
int m_sync_bytes_read;
|
||||||
|
|
|
@ -88,6 +88,10 @@ namespace libtorrent
|
||||||
, free_buffer_fun destructor, void* userdata
|
, free_buffer_fun destructor, void* userdata
|
||||||
, block_cache_reference ref = block_cache_reference());
|
, block_cache_reference ref = block_cache_reference());
|
||||||
|
|
||||||
|
void prepend_buffer(char* buffer, int s, int used_size
|
||||||
|
, free_buffer_fun destructor, void* userdata
|
||||||
|
, block_cache_reference ref = block_cache_reference());
|
||||||
|
|
||||||
// returns the number of bytes available at the
|
// returns the number of bytes available at the
|
||||||
// end of the last chained buffer.
|
// end of the last chained buffer.
|
||||||
int space_in_last_buffer();
|
int space_in_last_buffer();
|
||||||
|
@ -106,9 +110,13 @@ namespace libtorrent
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
void build_mutable_iovec(int bytes, std::vector<asio::mutable_buffer>& vec);
|
||||||
|
|
||||||
~chained_buffer();
|
~chained_buffer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <typename Buffer>
|
||||||
|
void build_vec(int bytes, std::vector<Buffer>& vec);
|
||||||
|
|
||||||
// this is the list of all the buffers we want to
|
// this is the list of all the buffers we want to
|
||||||
// send
|
// send
|
||||||
|
|
|
@ -450,6 +450,34 @@ namespace libtorrent
|
||||||
virtual bool write_request(peer_request const&) { return false; }
|
virtual bool write_request(peer_request const&) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TORRENT_EXPORT crypto_plugin
|
||||||
|
{
|
||||||
|
// hidden
|
||||||
|
virtual ~crypto_plugin() {}
|
||||||
|
|
||||||
|
virtual void set_incoming_key(unsigned char const* key, int len) = 0;
|
||||||
|
virtual void set_outgoing_key(unsigned char const* key, int len) = 0;
|
||||||
|
|
||||||
|
// encrypted the provided buffers and returns the number of bytes which
|
||||||
|
// are now ready to be sent to the lower layer. This must be at least
|
||||||
|
// as large as the number of bytes passed in and may be larger if there
|
||||||
|
// is additional data to be inserted at the head of the send buffer.
|
||||||
|
// The additional data is retrived from the passed in vector. The
|
||||||
|
// vector must be cleared if no additional data is to be inserted.
|
||||||
|
virtual int encrypt(std::vector<boost::asio::mutable_buffer>& /*send_vec*/) = 0;
|
||||||
|
|
||||||
|
// decrypt the provided buffers.
|
||||||
|
// consume is set to the number of bytes which should be trimmed from the
|
||||||
|
// head of the buffers, default is 0
|
||||||
|
//
|
||||||
|
// produce is set to the number of bytes of payload which are now ready to
|
||||||
|
// be sent to the upper layer. default is the number of bytes passed in receive_vec
|
||||||
|
//
|
||||||
|
// packet_size is set to the minimum number of bytes which must be read to
|
||||||
|
// advance the next step of decryption. default is 0
|
||||||
|
virtual void decrypt(std::vector<boost::asio::mutable_buffer>& /*receive_vec*/
|
||||||
|
, int& /* consume */, int& /*produce*/, int& /*packet_size*/) = 0;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define DHT_OBSERVER_HPP
|
#define DHT_OBSERVER_HPP
|
||||||
|
|
||||||
#include "libtorrent/address.hpp"
|
#include "libtorrent/address.hpp"
|
||||||
|
#include "libtorrent/kademlia/msg.hpp"
|
||||||
|
|
||||||
namespace libtorrent { namespace dht
|
namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
|
||||||
#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
|
#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
|
||||||
#define TORRENT_PE_CRYPTO_HPP_INCLUDED
|
#define TORRENT_PE_CRYPTO_HPP_INCLUDED
|
||||||
|
@ -52,7 +52,12 @@ void TORRENT_EXTRA_EXPORT rc4_init(const unsigned char* in, unsigned long len, r
|
||||||
unsigned long TORRENT_EXTRA_EXPORT rc4_encrypt(unsigned char *out, unsigned long outlen, rc4 *state);
|
unsigned long TORRENT_EXTRA_EXPORT rc4_encrypt(unsigned char *out, unsigned long outlen, rc4 *state);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "libtorrent/receive_buffer.hpp"
|
||||||
#include "libtorrent/peer_id.hpp" // For sha1_hash
|
#include "libtorrent/peer_id.hpp" // For sha1_hash
|
||||||
|
#include "libtorrent/extensions.hpp"
|
||||||
#include "libtorrent/assert.hpp"
|
#include "libtorrent/assert.hpp"
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
|
@ -87,14 +92,39 @@ namespace libtorrent
|
||||||
|
|
||||||
struct encryption_handler
|
struct encryption_handler
|
||||||
{
|
{
|
||||||
virtual void set_incoming_key(unsigned char const* key, int len) = 0;
|
int encrypt(std::vector<asio::mutable_buffer>& iovec);
|
||||||
virtual void set_outgoing_key(unsigned char const* key, int len) = 0;
|
int decrypt(crypto_receive_buffer& recv_buffer, std::size_t& bytes_transferred);
|
||||||
virtual void encrypt(char* pos, int len) = 0;
|
|
||||||
virtual void decrypt(char* pos, int len) = 0;
|
bool switch_send_crypto(boost::shared_ptr<crypto_plugin> crypto
|
||||||
virtual ~encryption_handler() {}
|
, int pending_encryption);
|
||||||
|
|
||||||
|
void switch_recv_crypto(boost::shared_ptr<crypto_plugin> crypto
|
||||||
|
, crypto_receive_buffer& recv_buffer);
|
||||||
|
|
||||||
|
bool is_send_plaintext() const
|
||||||
|
{
|
||||||
|
return m_send_barriers.empty() || m_send_barriers.back().next != INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_recv_plaintext() const
|
||||||
|
{
|
||||||
|
return m_dec_handler.get() == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct barrier
|
||||||
|
{
|
||||||
|
barrier(boost::shared_ptr<crypto_plugin> plugin, int next)
|
||||||
|
: enc_handler(plugin), next(next) {}
|
||||||
|
boost::shared_ptr<crypto_plugin> enc_handler;
|
||||||
|
// number of bytes to next barrier
|
||||||
|
int next;
|
||||||
|
};
|
||||||
|
std::list<barrier> m_send_barriers;
|
||||||
|
boost::shared_ptr<crypto_plugin> m_dec_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rc4_handler : encryption_handler
|
struct TORRENT_EXTRA_EXPORT rc4_handler : crypto_plugin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Input longkeys must be 20 bytes
|
// Input longkeys must be 20 bytes
|
||||||
|
@ -108,39 +138,8 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_incoming_key(unsigned char const* key, int len)
|
void set_incoming_key(unsigned char const* key, int len);
|
||||||
{
|
void set_outgoing_key(unsigned char const* key, int len);
|
||||||
m_decrypt = true;
|
|
||||||
#ifdef TORRENT_USE_GCRYPT
|
|
||||||
gcry_cipher_close(m_rc4_incoming);
|
|
||||||
gcry_cipher_open(&m_rc4_incoming, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0);
|
|
||||||
gcry_cipher_setkey(m_rc4_incoming, key, len);
|
|
||||||
#elif defined TORRENT_USE_OPENSSL
|
|
||||||
RC4_set_key(&m_remote_key, len, key);
|
|
||||||
#else
|
|
||||||
rc4_init(key, len, &m_rc4_incoming);
|
|
||||||
#endif
|
|
||||||
// Discard first 1024 bytes
|
|
||||||
char buf[1024];
|
|
||||||
decrypt(buf, 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_outgoing_key(unsigned char const* key, int len)
|
|
||||||
{
|
|
||||||
m_encrypt = true;
|
|
||||||
#ifdef TORRENT_USE_GCRYPT
|
|
||||||
gcry_cipher_close(m_rc4_outgoing);
|
|
||||||
gcry_cipher_open(&m_rc4_outgoing, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0);
|
|
||||||
gcry_cipher_setkey(m_rc4_outgoing, key, len);
|
|
||||||
#elif defined TORRENT_USE_OPENSSL
|
|
||||||
RC4_set_key(&m_local_key, len, key);
|
|
||||||
#else
|
|
||||||
rc4_init(key, len, &m_rc4_outgoing);
|
|
||||||
#endif
|
|
||||||
// Discard first 1024 bytes
|
|
||||||
char buf[1024];
|
|
||||||
encrypt(buf, 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
~rc4_handler()
|
~rc4_handler()
|
||||||
{
|
{
|
||||||
|
@ -150,37 +149,11 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void encrypt(char* pos, int len)
|
int encrypt(std::vector<boost::asio::mutable_buffer>& buf);
|
||||||
{
|
void decrypt(std::vector<boost::asio::mutable_buffer>& buf
|
||||||
if (!m_encrypt) return;
|
, int& consume
|
||||||
|
, int& produce
|
||||||
TORRENT_ASSERT(len >= 0);
|
, int& packet_size);
|
||||||
TORRENT_ASSERT(pos);
|
|
||||||
|
|
||||||
#ifdef TORRENT_USE_GCRYPT
|
|
||||||
gcry_cipher_encrypt(m_rc4_outgoing, pos, len, 0, 0);
|
|
||||||
#elif defined TORRENT_USE_OPENSSL
|
|
||||||
RC4(&m_local_key, len, (const unsigned char*)pos, (unsigned char*)pos);
|
|
||||||
#else
|
|
||||||
rc4_encrypt((unsigned char*)pos, len, &m_rc4_outgoing);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void decrypt(char* pos, int len)
|
|
||||||
{
|
|
||||||
if (!m_decrypt) return;
|
|
||||||
|
|
||||||
TORRENT_ASSERT(len >= 0);
|
|
||||||
TORRENT_ASSERT(pos);
|
|
||||||
|
|
||||||
#ifdef TORRENT_USE_GCRYPT
|
|
||||||
gcry_cipher_decrypt(m_rc4_incoming, pos, len, 0, 0);
|
|
||||||
#elif defined TORRENT_USE_OPENSSL
|
|
||||||
RC4(&m_remote_key, len, (const unsigned char*)pos, (unsigned char*)pos);
|
|
||||||
#else
|
|
||||||
rc4_encrypt((unsigned char*)pos, len, &m_rc4_incoming);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef TORRENT_USE_GCRYPT
|
#ifdef TORRENT_USE_GCRYPT
|
||||||
|
|
|
@ -85,6 +85,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/piece_picker.hpp" // for piece_block
|
#include "libtorrent/piece_picker.hpp" // for piece_block
|
||||||
#include "libtorrent/socket.hpp" // for tcp::endpoint
|
#include "libtorrent/socket.hpp" // for tcp::endpoint
|
||||||
#include "libtorrent/io_service_fwd.hpp"
|
#include "libtorrent/io_service_fwd.hpp"
|
||||||
|
#include "libtorrent/receive_buffer.hpp"
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
@ -198,8 +199,6 @@ namespace libtorrent
|
||||||
, m_choked(true)
|
, m_choked(true)
|
||||||
, m_corked(false)
|
, m_corked(false)
|
||||||
, m_ignore_stats(false)
|
, m_ignore_stats(false)
|
||||||
, m_recv_pos(0)
|
|
||||||
, m_packet_size(0)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -272,15 +271,6 @@ namespace libtorrent
|
||||||
// when this is set, the transfer stats for this connection
|
// when this is set, the transfer stats for this connection
|
||||||
// is not included in the torrent or session stats
|
// is not included in the torrent or session stats
|
||||||
bool m_ignore_stats:1;
|
bool m_ignore_stats:1;
|
||||||
|
|
||||||
// the byte offset in m_recv_buffer that we have
|
|
||||||
// are passing on to the upper layer. This is
|
|
||||||
// always <= m_recv_end
|
|
||||||
int m_recv_pos:24;
|
|
||||||
|
|
||||||
// the size (in bytes) of the bittorrent message
|
|
||||||
// we're currently receiving
|
|
||||||
int m_packet_size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TORRENT_EXTRA_EXPORT peer_connection
|
class TORRENT_EXTRA_EXPORT peer_connection
|
||||||
|
@ -680,21 +670,18 @@ namespace libtorrent
|
||||||
return boost::optional<piece_block_progress>();
|
return boost::optional<piece_block_progress>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// these functions are virtual to let bt_peer_connection hook into them
|
|
||||||
// and encrypt the content
|
|
||||||
enum message_type_flags { message_type_request = 1 };
|
enum message_type_flags { message_type_request = 1 };
|
||||||
virtual void send_buffer(char const* begin, int size, int flags = 0
|
void send_buffer(char const* begin, int size, int flags = 0);
|
||||||
, void (*fun)(char*, int, void*) = 0, void* userdata = 0);
|
void setup_send();
|
||||||
virtual void setup_send();
|
|
||||||
|
|
||||||
void cork_socket() { TORRENT_ASSERT(!m_corked); m_corked = true; }
|
void cork_socket() { TORRENT_ASSERT(!m_corked); m_corked = true; }
|
||||||
bool is_corked() const { return m_corked; }
|
bool is_corked() const { return m_corked; }
|
||||||
void uncork_socket();
|
void uncork_socket();
|
||||||
|
|
||||||
virtual void append_send_buffer(char* buffer, int size
|
void append_send_buffer(char* buffer, int size
|
||||||
, chained_buffer::free_buffer_fun destructor = &nop
|
, chained_buffer::free_buffer_fun destructor = &nop
|
||||||
, void* userdata = NULL, block_cache_reference ref
|
, void* userdata = NULL, block_cache_reference ref
|
||||||
= block_cache_reference(), bool encrypted = false);
|
= block_cache_reference());
|
||||||
|
|
||||||
virtual void append_const_send_buffer(char const* buffer, int size
|
virtual void append_const_send_buffer(char const* buffer, int size
|
||||||
, chained_buffer::free_buffer_fun destructor = &nop
|
, chained_buffer::free_buffer_fun destructor = &nop
|
||||||
|
@ -719,13 +706,6 @@ namespace libtorrent
|
||||||
int send_buffer_capacity() const
|
int send_buffer_capacity() const
|
||||||
{ return m_send_buffer.capacity(); }
|
{ return m_send_buffer.capacity(); }
|
||||||
|
|
||||||
int packet_size() const { return m_packet_size; }
|
|
||||||
|
|
||||||
bool packet_finished() const
|
|
||||||
{ return m_packet_size <= m_recv_pos; }
|
|
||||||
|
|
||||||
int receive_pos() const { return m_recv_pos; }
|
|
||||||
|
|
||||||
void max_out_request_queue(int s)
|
void max_out_request_queue(int s)
|
||||||
{ m_max_out_request_queue = s; }
|
{ m_max_out_request_queue = s; }
|
||||||
int max_out_request_queue() const
|
int max_out_request_queue() const
|
||||||
|
@ -802,43 +782,9 @@ namespace libtorrent
|
||||||
virtual void on_sent(error_code const& error
|
virtual void on_sent(error_code const& error
|
||||||
, std::size_t bytes_transferred) = 0;
|
, std::size_t bytes_transferred) = 0;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
virtual int hit_send_barrier(std::vector<asio::mutable_buffer>& iovec) { return INT_MAX; }
|
||||||
buffer::interval wr_recv_buffer()
|
|
||||||
{
|
|
||||||
if (m_recv_buffer.empty())
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(m_recv_pos == 0);
|
|
||||||
return buffer::interval(0,0);
|
|
||||||
}
|
|
||||||
TORRENT_ASSERT(!m_disk_recv_buffer);
|
|
||||||
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
|
|
||||||
int rcv_pos = (std::min)(m_recv_pos, int(m_recv_buffer.size()));
|
|
||||||
return buffer::interval(&m_recv_buffer[0] + m_recv_start
|
|
||||||
, &m_recv_buffer[0] + m_recv_start + rcv_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<buffer::interval, buffer::interval> wr_recv_buffers(int bytes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
buffer::const_interval receive_buffer() const
|
|
||||||
{
|
|
||||||
if (m_recv_buffer.empty())
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(m_recv_pos == 0);
|
|
||||||
return buffer::interval(0,0);
|
|
||||||
}
|
|
||||||
int rcv_pos = (std::min)(m_recv_pos, int(m_recv_buffer.size()));
|
|
||||||
return buffer::const_interval(&m_recv_buffer[0] + m_recv_start
|
|
||||||
, &m_recv_buffer[0] + m_recv_start + rcv_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool allocate_disk_receive_buffer(int disk_buffer_size);
|
bool allocate_disk_receive_buffer(int disk_buffer_size);
|
||||||
char* release_disk_receive_buffer();
|
|
||||||
bool has_disk_receive_buffer() const { return m_disk_recv_buffer; }
|
|
||||||
void cut_receive_buffer(int size, int packet_size, int offset = 0);
|
|
||||||
void reset_recv_buffer(int packet_size);
|
|
||||||
void normalize_receive_buffer();
|
|
||||||
void set_soft_packet_size(int size) { m_soft_packet_size = size; }
|
|
||||||
|
|
||||||
// if allow_encrypted is false, and the torrent 'ih' turns out
|
// if allow_encrypted is false, and the torrent 'ih' turns out
|
||||||
// to be an encrypted torrent (AES-256 encrypted) the peer will
|
// to be an encrypted torrent (AES-256 encrypted) the peer will
|
||||||
|
@ -865,6 +811,14 @@ namespace libtorrent
|
||||||
void receive_data_impl(error_code const& error
|
void receive_data_impl(error_code const& error
|
||||||
, std::size_t bytes_transferred, int read_loops);
|
, std::size_t bytes_transferred, int read_loops);
|
||||||
|
|
||||||
|
void set_send_barrier(int bytes)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(bytes == INT_MAX || bytes <= send_buffer_size());
|
||||||
|
m_send_barrier = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_send_barrier() const { return m_send_barrier; }
|
||||||
|
|
||||||
virtual int timeout() const;
|
virtual int timeout() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -913,8 +867,7 @@ namespace libtorrent
|
||||||
char m_channel_state[2];
|
char m_channel_state[2];
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
receive_buffer m_recv_buffer;
|
||||||
buffer m_recv_buffer;
|
|
||||||
|
|
||||||
// number of bytes this peer can send and receive
|
// number of bytes this peer can send and receive
|
||||||
int m_quota[2];
|
int m_quota[2];
|
||||||
|
@ -923,9 +876,6 @@ namespace libtorrent
|
||||||
// picker and will request from this peer.
|
// picker and will request from this peer.
|
||||||
std::vector<pending_block> m_request_queue;
|
std::vector<pending_block> m_request_queue;
|
||||||
|
|
||||||
// the start of the logical receive buffer
|
|
||||||
int m_recv_start:24;
|
|
||||||
|
|
||||||
// this is the limit on the number of outstanding requests
|
// this is the limit on the number of outstanding requests
|
||||||
// we have to this peer. This is initialized to the settings
|
// we have to this peer. This is initialized to the settings
|
||||||
// in the session_settings structure. But it may be lowered
|
// in the session_settings structure. But it may be lowered
|
||||||
|
@ -1036,12 +986,6 @@ namespace libtorrent
|
||||||
// for the round-robin unchoke algorithm.
|
// for the round-robin unchoke algorithm.
|
||||||
size_type m_uploaded_at_last_unchoke;
|
size_type m_uploaded_at_last_unchoke;
|
||||||
|
|
||||||
// some messages needs to be read from the socket
|
|
||||||
// buffer in multiple stages. This soft packet
|
|
||||||
// size limits the read size between message handler
|
|
||||||
// dispatch. Ignored when set to 0
|
|
||||||
int m_soft_packet_size;
|
|
||||||
|
|
||||||
// the number of bytes that the other
|
// the number of bytes that the other
|
||||||
// end has to send us in order to respond
|
// end has to send us in order to respond
|
||||||
// to all outstanding piece requests we
|
// to all outstanding piece requests we
|
||||||
|
@ -1068,12 +1012,6 @@ namespace libtorrent
|
||||||
handler_storage<TORRENT_READ_HANDLER_MAX_SIZE> m_read_handler_storage;
|
handler_storage<TORRENT_READ_HANDLER_MAX_SIZE> m_read_handler_storage;
|
||||||
handler_storage<TORRENT_WRITE_HANDLER_MAX_SIZE> m_write_handler_storage;
|
handler_storage<TORRENT_WRITE_HANDLER_MAX_SIZE> m_write_handler_storage;
|
||||||
|
|
||||||
// if this peer is receiving a piece, this
|
|
||||||
// points to a disk buffer that the data is
|
|
||||||
// read into. This eliminates a memcopy from
|
|
||||||
// the receive buffer into the disk buffer
|
|
||||||
disk_buffer_holder m_disk_recv_buffer;
|
|
||||||
|
|
||||||
// we have suggested these pieces to the peer
|
// we have suggested these pieces to the peer
|
||||||
// don't suggest it again
|
// don't suggest it again
|
||||||
bitfield m_sent_suggested_pieces;
|
bitfield m_sent_suggested_pieces;
|
||||||
|
@ -1118,14 +1056,13 @@ namespace libtorrent
|
||||||
// keeps track of the current quotas
|
// keeps track of the current quotas
|
||||||
bandwidth_channel m_bandwidth_channel[num_channels];
|
bandwidth_channel m_bandwidth_channel[num_channels];
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
// statistics about upload and download speeds
|
// statistics about upload and download speeds
|
||||||
// and total amount of uploads and downloads for
|
// and total amount of uploads and downloads for
|
||||||
// this peer
|
// this peer
|
||||||
// TODO: factor this out into its own class with a virtual interface
|
// TODO: factor this out into its own class with a virtual interface
|
||||||
// torrent and session should implement this interface
|
// torrent and session should implement this interface
|
||||||
stat m_statistics;
|
stat m_statistics;
|
||||||
protected:
|
|
||||||
|
|
||||||
// if the timeout is extended for the outstanding
|
// if the timeout is extended for the outstanding
|
||||||
// requests, this is the number of seconds it was
|
// requests, this is the number of seconds it was
|
||||||
|
@ -1146,39 +1083,6 @@ namespace libtorrent
|
||||||
// immediately
|
// immediately
|
||||||
int m_queued_time_critical;
|
int m_queued_time_critical;
|
||||||
|
|
||||||
// the number of valid, received bytes in m_recv_buffer
|
|
||||||
int m_recv_end:24;
|
|
||||||
|
|
||||||
//#error 1 byte
|
|
||||||
|
|
||||||
// recv_buf.begin (start of actual receive buffer)
|
|
||||||
// |
|
|
||||||
// | m_recv_start (logical start of current
|
|
||||||
// | | receive buffer, as perceived by upper layers)
|
|
||||||
// | |
|
|
||||||
// | | m_recv_pos (number of bytes consumed
|
|
||||||
// | | | by upper layer, from logical receive buffer)
|
|
||||||
// | | |
|
|
||||||
// | x---------x
|
|
||||||
// | | | recv_buf.end (end of actual receive buffer)
|
|
||||||
// | | | |
|
|
||||||
// v v v v
|
|
||||||
// *------==========---------
|
|
||||||
// ^
|
|
||||||
// |
|
|
||||||
// |
|
|
||||||
// ------------------->x m_recv_end (end of received data,
|
|
||||||
// beyond this point is garbage)
|
|
||||||
// m_recv_buffer
|
|
||||||
|
|
||||||
// when not using contiguous receive buffers, there
|
|
||||||
// may be a disk_recv_buffer in the mix as well. Whenever
|
|
||||||
// m_disk_recv_buffer_size > 0 (and presumably also
|
|
||||||
// m_disk_recv_buffer != NULL) the disk buffer is imagined
|
|
||||||
// to be appended to the receive buffer right after m_recv_end.
|
|
||||||
|
|
||||||
int m_disk_recv_buffer_size;
|
|
||||||
|
|
||||||
// the number of bytes we are currently reading
|
// the number of bytes we are currently reading
|
||||||
// from disk, that will be added to the send
|
// from disk, that will be added to the send
|
||||||
// buffer as soon as they complete
|
// buffer as soon as they complete
|
||||||
|
@ -1228,6 +1132,9 @@ namespace libtorrent
|
||||||
// us
|
// us
|
||||||
int m_est_reciprocation_rate;
|
int m_est_reciprocation_rate;
|
||||||
|
|
||||||
|
// stop sending data after this many bytes, INT_MAX = inf
|
||||||
|
int m_send_barrier;
|
||||||
|
|
||||||
// the number of request we should queue up
|
// the number of request we should queue up
|
||||||
// at the remote end.
|
// at the remote end.
|
||||||
boost::uint16_t m_desired_queue_size;
|
boost::uint16_t m_desired_queue_size;
|
||||||
|
|
|
@ -142,7 +142,7 @@ namespace libtorrent
|
||||||
// from peer_info.
|
// from peer_info.
|
||||||
unsigned source:6;
|
unsigned source:6;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
// Hints encryption support of torrent_peer. Only effective
|
// Hints encryption support of torrent_peer. Only effective
|
||||||
// for and when the outgoing encryption policy
|
// for and when the outgoing encryption policy
|
||||||
// allows both encrypted and non encrypted
|
// allows both encrypted and non encrypted
|
||||||
|
|
|
@ -98,6 +98,7 @@ libtorrent_rasterbar_la_SOURCES = \
|
||||||
peer_list.cpp \
|
peer_list.cpp \
|
||||||
puff.cpp \
|
puff.cpp \
|
||||||
random.cpp \
|
random.cpp \
|
||||||
|
receive_buffer.cpp \
|
||||||
request_blocks.cpp \
|
request_blocks.cpp \
|
||||||
resolver.cpp \
|
resolver.cpp \
|
||||||
rss.cpp \
|
rss.cpp \
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -85,6 +85,26 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(m_bytes <= m_capacity);
|
TORRENT_ASSERT(m_bytes <= m_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void chained_buffer::prepend_buffer(char* buffer, int s, int used_size
|
||||||
|
, free_buffer_fun destructor, void* userdata
|
||||||
|
, block_cache_reference ref)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(s >= used_size);
|
||||||
|
buffer_t b;
|
||||||
|
b.buf = buffer;
|
||||||
|
b.size = s;
|
||||||
|
b.start = buffer;
|
||||||
|
b.used_size = used_size;
|
||||||
|
b.free_fun = destructor;
|
||||||
|
b.userdata = userdata;
|
||||||
|
b.ref = ref;
|
||||||
|
m_vec.push_front(b);
|
||||||
|
|
||||||
|
m_bytes += used_size;
|
||||||
|
m_capacity += s;
|
||||||
|
TORRENT_ASSERT(m_bytes <= m_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
// returns the number of bytes available at the
|
// returns the number of bytes available at the
|
||||||
// end of the last chained buffer.
|
// end of the last chained buffer.
|
||||||
int chained_buffer::space_in_last_buffer()
|
int chained_buffer::space_in_last_buffer()
|
||||||
|
@ -127,21 +147,31 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
m_tmp_vec.clear();
|
m_tmp_vec.clear();
|
||||||
|
build_vec(to_send, m_tmp_vec);
|
||||||
|
return m_tmp_vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void chained_buffer::build_mutable_iovec(int bytes, std::vector<asio::mutable_buffer> &vec)
|
||||||
|
{
|
||||||
|
build_vec(bytes, vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Buffer>
|
||||||
|
void chained_buffer::build_vec(int bytes, std::vector<Buffer> &vec)
|
||||||
|
{
|
||||||
for (std::deque<buffer_t>::iterator i = m_vec.begin()
|
for (std::deque<buffer_t>::iterator i = m_vec.begin()
|
||||||
, end(m_vec.end()); to_send > 0 && i != end; ++i)
|
, end(m_vec.end()); bytes > 0 && i != end; ++i)
|
||||||
{
|
{
|
||||||
if (i->used_size > to_send)
|
if (i->used_size > bytes)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(to_send > 0);
|
TORRENT_ASSERT(bytes > 0);
|
||||||
m_tmp_vec.push_back(asio::const_buffer(i->start, to_send));
|
vec.push_back(Buffer(i->start, bytes));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TORRENT_ASSERT(i->used_size > 0);
|
TORRENT_ASSERT(i->used_size > 0);
|
||||||
m_tmp_vec.push_back(asio::const_buffer(i->start, i->used_size));
|
vec.push_back(Buffer(i->start, i->used_size));
|
||||||
to_send -= i->used_size;
|
bytes -= i->used_size;
|
||||||
}
|
}
|
||||||
return m_tmp_vec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chained_buffer::clear()
|
void chained_buffer::clear()
|
||||||
|
|
|
@ -120,7 +120,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int receive_buffer_size = receive_buffer().left() - m_parser.body_start();
|
int receive_buffer_size = m_recv_buffer.get().left() - m_parser.body_start();
|
||||||
// TODO: 1 in chunked encoding mode, this assert won't hold.
|
// TODO: 1 in chunked encoding mode, this assert won't hold.
|
||||||
// the chunk headers should be subtracted from the receive_buffer_size
|
// the chunk headers should be subtracted from the receive_buffer_size
|
||||||
TORRENT_ASSERT_VAL(receive_buffer_size <= t->block_size(), receive_buffer_size);
|
TORRENT_ASSERT_VAL(receive_buffer_size <= t->block_size(), receive_buffer_size);
|
||||||
|
@ -225,7 +225,7 @@ namespace libtorrent
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
buffer::const_interval recv_buffer = receive_buffer();
|
buffer::const_interval recv_buffer = m_recv_buffer.get();
|
||||||
|
|
||||||
if (bytes_transferred == 0) break;
|
if (bytes_transferred == 0) break;
|
||||||
TORRENT_ASSERT(recv_buffer.left() > 0);
|
TORRENT_ASSERT(recv_buffer.left() > 0);
|
||||||
|
@ -262,7 +262,7 @@ namespace libtorrent
|
||||||
|
|
||||||
TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
|
TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
|
||||||
|
|
||||||
TORRENT_ASSERT(recv_buffer.left() <= packet_size());
|
TORRENT_ASSERT(recv_buffer.left() <= m_recv_buffer.packet_size());
|
||||||
|
|
||||||
// this means the entire status line hasn't been received yet
|
// this means the entire status line hasn't been received yet
|
||||||
if (m_parser.status_code() == -1)
|
if (m_parser.status_code() == -1)
|
||||||
|
@ -387,15 +387,15 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(chunk_size != 0 || chunk_start.left() <= header_size || chunk_start.begin[header_size] == 'H');
|
TORRENT_ASSERT(chunk_size != 0 || chunk_start.left() <= header_size || chunk_start.begin[header_size] == 'H');
|
||||||
// cut out the chunk header from the receive buffer
|
// cut out the chunk header from the receive buffer
|
||||||
TORRENT_ASSERT(m_chunk_pos + m_body_start < INT_MAX);
|
TORRENT_ASSERT(m_chunk_pos + m_body_start < INT_MAX);
|
||||||
cut_receive_buffer(header_size, t->block_size() + 1024, int(m_chunk_pos + m_body_start));
|
m_recv_buffer.cut(header_size, t->block_size() + 1024, int(m_chunk_pos + m_body_start));
|
||||||
recv_buffer = receive_buffer();
|
recv_buffer = m_recv_buffer.get();
|
||||||
recv_buffer.begin += m_body_start;
|
recv_buffer.begin += m_body_start;
|
||||||
m_chunk_pos += chunk_size;
|
m_chunk_pos += chunk_size;
|
||||||
if (chunk_size == 0)
|
if (chunk_size == 0)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(receive_buffer().left() < m_chunk_pos + m_body_start + 1
|
TORRENT_ASSERT(m_recv_buffer.get().left() < m_chunk_pos + m_body_start + 1
|
||||||
|| receive_buffer()[int(m_chunk_pos + m_body_start)] == 'H'
|
|| m_recv_buffer.get()[int(m_chunk_pos + m_body_start)] == 'H'
|
||||||
|| (m_parser.chunked_encoding() && receive_buffer()[int(m_chunk_pos + m_body_start)] == '\r'));
|
|| (m_parser.chunked_encoding() && m_recv_buffer.get()[int(m_chunk_pos + m_body_start)] == '\r'));
|
||||||
m_chunk_pos = -1;
|
m_chunk_pos = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -440,11 +440,11 @@ namespace libtorrent
|
||||||
if (associated_torrent().expired()) return;
|
if (associated_torrent().expired()) return;
|
||||||
|
|
||||||
int size_to_cut = m_body_start + front_request.length;
|
int size_to_cut = m_body_start + front_request.length;
|
||||||
TORRENT_ASSERT(receive_buffer().left() < size_to_cut + 1
|
TORRENT_ASSERT(m_recv_buffer.get().left() < size_to_cut + 1
|
||||||
|| receive_buffer()[size_to_cut] == 'H'
|
|| m_recv_buffer.get()[size_to_cut] == 'H'
|
||||||
|| (m_parser.chunked_encoding() && receive_buffer()[size_to_cut] == '\r'));
|
|| (m_parser.chunked_encoding() && m_recv_buffer.get()[size_to_cut] == '\r'));
|
||||||
|
|
||||||
cut_receive_buffer(size_to_cut, t->block_size() + 1024);
|
m_recv_buffer.cut(size_to_cut, t->block_size() + 1024);
|
||||||
if (m_response_left == 0) m_chunk_pos = 0;
|
if (m_response_left == 0) m_chunk_pos = 0;
|
||||||
else m_chunk_pos -= front_request.length;
|
else m_chunk_pos -= front_request.length;
|
||||||
bytes_transferred -= payload;
|
bytes_transferred -= payload;
|
||||||
|
|
|
@ -157,7 +157,7 @@ namespace libtorrent
|
||||||
, (tracker_req().event != tracker_request::none) ? event_string[tracker_req().event - 1] : ""
|
, (tracker_req().event != tracker_request::none) ? event_string[tracker_req().event - 1] : ""
|
||||||
, tracker_req().num_want);
|
, tracker_req().num_want);
|
||||||
url += str;
|
url += str;
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
if (settings.get_int(settings_pack::in_enc_policy) != settings_pack::pe_disabled
|
if (settings.get_int(settings_pack::in_enc_policy) != settings_pack::pe_disabled
|
||||||
&& settings.get_bool(settings_pack::announce_crypto_support))
|
&& settings.get_bool(settings_pack::announce_crypto_support))
|
||||||
url += "&supportcrypto=1";
|
url += "&supportcrypto=1";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2007-2014, Un Shyam & Arvid Norberg
|
Copyright (c) 2007-2014, Un Shyam, Arvid Norberg, Steven Siloti
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -30,7 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -301,6 +301,230 @@ get_out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int encryption_handler::encrypt(std::vector<asio::mutable_buffer>& iovec)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(!m_send_barriers.empty());
|
||||||
|
TORRENT_ASSERT(m_send_barriers.front().enc_handler);
|
||||||
|
|
||||||
|
int to_process = m_send_barriers.front().next;
|
||||||
|
|
||||||
|
if (to_process != INT_MAX)
|
||||||
|
{
|
||||||
|
for (std::vector<asio::mutable_buffer>::iterator i = iovec.begin();
|
||||||
|
to_process >= 0; ++i)
|
||||||
|
{
|
||||||
|
if (to_process == 0)
|
||||||
|
{
|
||||||
|
iovec.erase(i, iovec.end());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (to_process < asio::buffer_size(*i))
|
||||||
|
{
|
||||||
|
*i = asio::mutable_buffer(asio::buffer_cast<void*>(*i), to_process);
|
||||||
|
iovec.erase(++i, iovec.end());
|
||||||
|
to_process = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
to_process -= asio::buffer_size(*i);
|
||||||
|
}
|
||||||
|
TORRENT_ASSERT(to_process == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
|
||||||
|
to_process = 0;
|
||||||
|
for (std::vector<asio::mutable_buffer>::iterator i = iovec.begin();
|
||||||
|
i != iovec.end(); ++i)
|
||||||
|
to_process += asio::buffer_size(*i);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int next_barrier = 0;
|
||||||
|
if (iovec.empty() || (next_barrier = m_send_barriers.front().enc_handler->encrypt(iovec)))
|
||||||
|
{
|
||||||
|
if (m_send_barriers.front().next != INT_MAX)
|
||||||
|
{
|
||||||
|
if (m_send_barriers.size() == 1)
|
||||||
|
// transitioning back to plaintext
|
||||||
|
next_barrier = INT_MAX;
|
||||||
|
m_send_barriers.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
|
||||||
|
if (next_barrier != INT_MAX)
|
||||||
|
{
|
||||||
|
int overhead = 0;
|
||||||
|
for (std::vector<asio::mutable_buffer>::iterator i = iovec.begin();
|
||||||
|
i != iovec.end(); ++i)
|
||||||
|
overhead += asio::buffer_size(*i);
|
||||||
|
TORRENT_ASSERT(overhead + to_process == next_barrier);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iovec.clear();
|
||||||
|
}
|
||||||
|
return next_barrier;
|
||||||
|
}
|
||||||
|
|
||||||
|
int encryption_handler::decrypt(crypto_receive_buffer& recv_buffer, std::size_t& bytes_transferred)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(!is_recv_plaintext());
|
||||||
|
int consume = 0;
|
||||||
|
if (recv_buffer.crypto_packet_finished())
|
||||||
|
{
|
||||||
|
std::vector<asio::mutable_buffer> wr_buf;
|
||||||
|
recv_buffer.mutable_buffers(wr_buf, bytes_transferred);
|
||||||
|
int packet_size = 0;
|
||||||
|
int produce = bytes_transferred;
|
||||||
|
m_dec_handler->decrypt(wr_buf, consume, produce, packet_size);
|
||||||
|
TORRENT_ASSERT(packet_size || produce);
|
||||||
|
TORRENT_ASSERT(packet_size >= 0);
|
||||||
|
bytes_transferred = produce;
|
||||||
|
if (packet_size)
|
||||||
|
recv_buffer.crypto_cut(consume, packet_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bytes_transferred = 0;
|
||||||
|
return consume;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool encryption_handler::switch_send_crypto(boost::shared_ptr<crypto_plugin> crypto
|
||||||
|
, int pending_encryption)
|
||||||
|
{
|
||||||
|
bool place_barrier = false;
|
||||||
|
if (!m_send_barriers.empty())
|
||||||
|
{
|
||||||
|
std::list<barrier>::iterator end = m_send_barriers.end(); --end;
|
||||||
|
for (std::list<barrier>::iterator b = m_send_barriers.begin();
|
||||||
|
b != end; ++b)
|
||||||
|
pending_encryption -= b->next;
|
||||||
|
TORRENT_ASSERT(pending_encryption >= 0);
|
||||||
|
m_send_barriers.back().next = pending_encryption;
|
||||||
|
}
|
||||||
|
else if (crypto)
|
||||||
|
place_barrier = true;
|
||||||
|
|
||||||
|
if (crypto)
|
||||||
|
m_send_barriers.push_back(barrier(crypto, INT_MAX));
|
||||||
|
|
||||||
|
return place_barrier;
|
||||||
|
}
|
||||||
|
|
||||||
|
void encryption_handler::switch_recv_crypto(boost::shared_ptr<crypto_plugin> crypto
|
||||||
|
, crypto_receive_buffer& recv_buffer)
|
||||||
|
{
|
||||||
|
m_dec_handler = crypto;
|
||||||
|
int packet_size = 0;
|
||||||
|
if (crypto)
|
||||||
|
{
|
||||||
|
int consume = 0;
|
||||||
|
int produce = 0;
|
||||||
|
std::vector<asio::mutable_buffer> wr_buf;
|
||||||
|
crypto->decrypt(wr_buf, consume, produce, packet_size);
|
||||||
|
TORRENT_ASSERT(wr_buf.empty());
|
||||||
|
TORRENT_ASSERT(consume == 0);
|
||||||
|
TORRENT_ASSERT(produce == 0);
|
||||||
|
}
|
||||||
|
recv_buffer.crypto_reset(packet_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rc4_handler::set_incoming_key(unsigned char const* key, int len)
|
||||||
|
{
|
||||||
|
m_decrypt = true;
|
||||||
|
#ifdef TORRENT_USE_GCRYPT
|
||||||
|
gcry_cipher_close(m_rc4_incoming);
|
||||||
|
gcry_cipher_open(&m_rc4_incoming, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0);
|
||||||
|
gcry_cipher_setkey(m_rc4_incoming, key, len);
|
||||||
|
#elif defined TORRENT_USE_OPENSSL
|
||||||
|
RC4_set_key(&m_remote_key, len, key);
|
||||||
|
#else
|
||||||
|
rc4_init(key, len, &m_rc4_incoming);
|
||||||
|
#endif
|
||||||
|
// Discard first 1024 bytes
|
||||||
|
char buf[1024];
|
||||||
|
std::vector<boost::asio::mutable_buffer> vec(1, boost::asio::mutable_buffer(buf, 1024));
|
||||||
|
int consume = 0;
|
||||||
|
int produce = 0;
|
||||||
|
int packet_size = 0;
|
||||||
|
decrypt(vec, consume, produce, packet_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rc4_handler::set_outgoing_key(unsigned char const* key, int len)
|
||||||
|
{
|
||||||
|
m_encrypt = true;
|
||||||
|
#ifdef TORRENT_USE_GCRYPT
|
||||||
|
gcry_cipher_close(m_rc4_outgoing);
|
||||||
|
gcry_cipher_open(&m_rc4_outgoing, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0);
|
||||||
|
gcry_cipher_setkey(m_rc4_outgoing, key, len);
|
||||||
|
#elif defined TORRENT_USE_OPENSSL
|
||||||
|
RC4_set_key(&m_local_key, len, key);
|
||||||
|
#else
|
||||||
|
rc4_init(key, len, &m_rc4_outgoing);
|
||||||
|
#endif
|
||||||
|
// Discard first 1024 bytes
|
||||||
|
char buf[1024];
|
||||||
|
std::vector<boost::asio::mutable_buffer> vec(1, boost::asio::mutable_buffer(buf, 1024));
|
||||||
|
encrypt(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc4_handler::encrypt(std::vector<boost::asio::mutable_buffer>& buf)
|
||||||
|
{
|
||||||
|
if (!m_encrypt) return 0;
|
||||||
|
if (buf.empty()) return 0;
|
||||||
|
|
||||||
|
int bytes_processed = 0;
|
||||||
|
for (std::vector<boost::asio::mutable_buffer>::iterator i = buf.begin();
|
||||||
|
i != buf.end(); ++i)
|
||||||
|
{
|
||||||
|
char* pos = boost::asio::buffer_cast<char*>(*i);
|
||||||
|
int len = boost::asio::buffer_size(*i);
|
||||||
|
|
||||||
|
TORRENT_ASSERT(len >= 0);
|
||||||
|
TORRENT_ASSERT(pos);
|
||||||
|
|
||||||
|
bytes_processed += len;
|
||||||
|
#ifdef TORRENT_USE_GCRYPT
|
||||||
|
gcry_cipher_encrypt(m_rc4_outgoing, pos, len, 0, 0);
|
||||||
|
#elif defined TORRENT_USE_OPENSSL
|
||||||
|
RC4(&m_local_key, len, (const unsigned char*)pos, (unsigned char*)pos);
|
||||||
|
#else
|
||||||
|
rc4_encrypt((unsigned char*)pos, len, &m_rc4_outgoing);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
buf.clear();
|
||||||
|
return bytes_processed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rc4_handler::decrypt(std::vector<boost::asio::mutable_buffer>& buf
|
||||||
|
, int& consume
|
||||||
|
, int& produce
|
||||||
|
, int& packet_size)
|
||||||
|
{
|
||||||
|
if (!m_decrypt) return;
|
||||||
|
|
||||||
|
int bytes_processed = 0;
|
||||||
|
for (std::vector<boost::asio::mutable_buffer>::iterator i = buf.begin();
|
||||||
|
i != buf.end(); ++i)
|
||||||
|
{
|
||||||
|
char* pos = boost::asio::buffer_cast<char*>(*i);
|
||||||
|
int len = boost::asio::buffer_size(*i);
|
||||||
|
|
||||||
|
TORRENT_ASSERT(len >= 0);
|
||||||
|
TORRENT_ASSERT(pos);
|
||||||
|
|
||||||
|
bytes_processed += len;
|
||||||
|
#ifdef TORRENT_USE_GCRYPT
|
||||||
|
gcry_cipher_decrypt(m_rc4_incoming, pos, len, 0, 0);
|
||||||
|
#elif defined TORRENT_USE_OPENSSL
|
||||||
|
RC4(&m_remote_key, len, (const unsigned char*)pos, (unsigned char*)pos);
|
||||||
|
#else
|
||||||
|
rc4_encrypt((unsigned char*)pos, len, &m_rc4_incoming);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
buf.clear();
|
||||||
|
produce = bytes_processed;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace libtorrent
|
} // namespace libtorrent
|
||||||
|
|
||||||
#if !defined TORRENT_USE_OPENSSL && !defined TORRENT_USE_GCRYPT
|
#if !defined TORRENT_USE_OPENSSL && !defined TORRENT_USE_GCRYPT
|
||||||
|
@ -369,5 +593,5 @@ unsigned long rc4_encrypt(unsigned char *out, unsigned long outlen, rc4 *state)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
|
#endif // #if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
|
||||||
|
|
|
@ -91,11 +91,6 @@ namespace libtorrent
|
||||||
min_request_queue = 2,
|
min_request_queue = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
int round_up8(int v)
|
|
||||||
{
|
|
||||||
return ((v & 7) == 0) ? v : v + (8 - (v & 7));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined TORRENT_REQUEST_LOGGING
|
#if defined TORRENT_REQUEST_LOGGING
|
||||||
void write_request_log(FILE* f, sha1_hash const& ih
|
void write_request_log(FILE* f, sha1_hash const& ih
|
||||||
, peer_connection* p, peer_request const& r)
|
, peer_connection* p, peer_request const& r)
|
||||||
|
@ -142,7 +137,7 @@ namespace libtorrent
|
||||||
, m_peer_info(pack.peerinfo)
|
, m_peer_info(pack.peerinfo)
|
||||||
, m_counters(*pack.stats_counters)
|
, m_counters(*pack.stats_counters)
|
||||||
, m_num_pieces(0)
|
, m_num_pieces(0)
|
||||||
, m_recv_start(0)
|
, m_recv_buffer(*pack.allocator)
|
||||||
, m_max_out_request_queue(m_settings.get_int(settings_pack::max_out_request_queue))
|
, m_max_out_request_queue(m_settings.get_int(settings_pack::max_out_request_queue))
|
||||||
, m_remote(pack.endp)
|
, m_remote(pack.endp)
|
||||||
, m_disk_thread(*pack.disk_thread)
|
, m_disk_thread(*pack.disk_thread)
|
||||||
|
@ -165,16 +160,12 @@ namespace libtorrent
|
||||||
, m_downloaded_at_last_round(0)
|
, m_downloaded_at_last_round(0)
|
||||||
, m_uploaded_at_last_round(0)
|
, m_uploaded_at_last_round(0)
|
||||||
, m_uploaded_at_last_unchoke(0)
|
, m_uploaded_at_last_unchoke(0)
|
||||||
, m_soft_packet_size(0)
|
|
||||||
, m_outstanding_bytes(0)
|
, m_outstanding_bytes(0)
|
||||||
, m_disk_recv_buffer(*pack.allocator, 0)
|
|
||||||
, m_last_seen_complete(0)
|
, m_last_seen_complete(0)
|
||||||
, m_receiving_block(piece_block::invalid)
|
, m_receiving_block(piece_block::invalid)
|
||||||
, m_timeout_extend(0)
|
, m_timeout_extend(0)
|
||||||
, m_extension_outstanding_bytes(0)
|
, m_extension_outstanding_bytes(0)
|
||||||
, m_queued_time_critical(0)
|
, m_queued_time_critical(0)
|
||||||
, m_recv_end(0)
|
|
||||||
, m_disk_recv_buffer_size(0)
|
|
||||||
, m_reading_bytes(0)
|
, m_reading_bytes(0)
|
||||||
, m_picker_options(0)
|
, m_picker_options(0)
|
||||||
, m_num_invalid_requests(0)
|
, m_num_invalid_requests(0)
|
||||||
|
@ -183,6 +174,7 @@ namespace libtorrent
|
||||||
, m_outstanding_writing_bytes(0)
|
, m_outstanding_writing_bytes(0)
|
||||||
, m_download_rate_peak(0)
|
, m_download_rate_peak(0)
|
||||||
, m_upload_rate_peak(0)
|
, m_upload_rate_peak(0)
|
||||||
|
, m_send_barrier(INT_MAX)
|
||||||
, m_desired_queue_size(2)
|
, m_desired_queue_size(2)
|
||||||
, m_speed(slow)
|
, m_speed(slow)
|
||||||
, m_prefer_whole_pieces(0)
|
, m_prefer_whole_pieces(0)
|
||||||
|
@ -820,8 +812,6 @@ namespace libtorrent
|
||||||
m_connecting = false;
|
m_connecting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_disk_recv_buffer_size = 0;
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
m_extensions.clear();
|
m_extensions.clear();
|
||||||
#endif
|
#endif
|
||||||
|
@ -2427,7 +2417,7 @@ namespace libtorrent
|
||||||
check_invariant();
|
check_invariant();
|
||||||
#endif
|
#endif
|
||||||
#if TORRENT_USE_ASSERTS
|
#if TORRENT_USE_ASSERTS
|
||||||
buffer::const_interval recv_buffer = receive_buffer();
|
buffer::const_interval recv_buffer = m_recv_buffer.get();
|
||||||
int recv_pos = recv_buffer.end - recv_buffer.begin;
|
int recv_pos = recv_buffer.end - recv_buffer.begin;
|
||||||
TORRENT_ASSERT(recv_pos >= 9);
|
TORRENT_ASSERT(recv_pos >= 9);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2579,8 +2569,7 @@ namespace libtorrent
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
TORRENT_ASSERT(t);
|
TORRENT_ASSERT(t);
|
||||||
|
|
||||||
TORRENT_ASSERT(!m_disk_recv_buffer);
|
m_recv_buffer.assert_no_disk_buffer();
|
||||||
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
|
|
||||||
|
|
||||||
// we're not receiving any block right now
|
// we're not receiving any block right now
|
||||||
m_receiving_block = piece_block::invalid;
|
m_receiving_block = piece_block::invalid;
|
||||||
|
@ -3990,8 +3979,7 @@ namespace libtorrent
|
||||||
// make sure we free up all send buffers that are owned
|
// make sure we free up all send buffers that are owned
|
||||||
// by the disk thread
|
// by the disk thread
|
||||||
m_send_buffer.clear();
|
m_send_buffer.clear();
|
||||||
m_disk_recv_buffer.reset();
|
m_recv_buffer.free_disk_buffer();
|
||||||
m_disk_recv_buffer_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we cannot do this in a constructor
|
// we cannot do this in a constructor
|
||||||
|
@ -4056,7 +4044,7 @@ namespace libtorrent
|
||||||
if (m_outgoing) m_counters.inc_stats_counter(counters::error_outgoing_peers);
|
if (m_outgoing) m_counters.inc_stats_counter(counters::error_outgoing_peers);
|
||||||
else m_counters.inc_stats_counter(counters::error_incoming_peers);
|
else m_counters.inc_stats_counter(counters::error_incoming_peers);
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
if (type() == bittorrent_connection)
|
if (type() == bittorrent_connection)
|
||||||
{
|
{
|
||||||
bt_peer_connection* bt = static_cast<bt_peer_connection*>(this);
|
bt_peer_connection* bt = static_cast<bt_peer_connection*>(this);
|
||||||
|
@ -4329,8 +4317,8 @@ namespace libtorrent
|
||||||
p.remote_dl_rate = m_remote_dl_rate;
|
p.remote_dl_rate = m_remote_dl_rate;
|
||||||
p.send_buffer_size = m_send_buffer.capacity();
|
p.send_buffer_size = m_send_buffer.capacity();
|
||||||
p.used_send_buffer = m_send_buffer.size();
|
p.used_send_buffer = m_send_buffer.size();
|
||||||
p.receive_buffer_size = m_recv_buffer.capacity() + m_disk_recv_buffer_size;
|
p.receive_buffer_size = m_recv_buffer.capacity();
|
||||||
p.used_receive_buffer = m_recv_pos;
|
p.used_receive_buffer = m_recv_buffer.pos();
|
||||||
p.write_state = m_channel_state[upload_channel];
|
p.write_state = m_channel_state[upload_channel];
|
||||||
p.read_state = m_channel_state[download_channel];
|
p.read_state = m_channel_state[download_channel];
|
||||||
|
|
||||||
|
@ -4367,10 +4355,8 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
TORRENT_ASSERT(m_packet_size > 0);
|
m_recv_buffer.assert_no_disk_buffer();
|
||||||
TORRENT_ASSERT(m_recv_pos <= m_packet_size - disk_buffer_size);
|
TORRENT_ASSERT(m_recv_buffer.pos() <= m_recv_buffer.packet_size() - disk_buffer_size);
|
||||||
TORRENT_ASSERT(!m_disk_recv_buffer);
|
|
||||||
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
|
|
||||||
TORRENT_ASSERT(disk_buffer_size <= 16 * 1024);
|
TORRENT_ASSERT(disk_buffer_size <= 16 * 1024);
|
||||||
|
|
||||||
if (disk_buffer_size == 0) return true;
|
if (disk_buffer_size == 0) return true;
|
||||||
|
@ -4382,13 +4368,15 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
// first free the old buffer
|
// first free the old buffer
|
||||||
m_disk_recv_buffer.reset();
|
m_recv_buffer.free_disk_buffer();
|
||||||
// then allocate a new one
|
// then allocate a new one
|
||||||
|
|
||||||
bool exceeded = false;
|
bool exceeded = false;
|
||||||
m_disk_recv_buffer.reset(m_allocator.allocate_disk_buffer(exceeded, self(), "receive buffer"));
|
m_recv_buffer.assign_disk_buffer(
|
||||||
|
m_allocator.allocate_disk_buffer(exceeded, self(), "receive buffer")
|
||||||
|
, disk_buffer_size);
|
||||||
|
|
||||||
if (!m_disk_recv_buffer)
|
if (!m_recv_buffer.has_disk_buffer())
|
||||||
{
|
{
|
||||||
disconnect(errors::no_memory, op_alloc_recvbuf);
|
disconnect(errors::no_memory, op_alloc_recvbuf);
|
||||||
return false;
|
return false;
|
||||||
|
@ -4404,84 +4392,9 @@ namespace libtorrent
|
||||||
m_channel_state[download_channel] |= peer_info::bw_disk;
|
m_channel_state[download_channel] |= peer_info::bw_disk;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_disk_recv_buffer_size = disk_buffer_size;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* peer_connection::release_disk_receive_buffer()
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(is_single_thread());
|
|
||||||
if (!m_disk_recv_buffer) return 0;
|
|
||||||
|
|
||||||
TORRENT_ASSERT(m_disk_recv_buffer_size <= m_recv_end);
|
|
||||||
TORRENT_ASSERT(m_recv_start <= m_recv_end - m_disk_recv_buffer_size);
|
|
||||||
m_recv_end -= m_disk_recv_buffer_size;
|
|
||||||
m_disk_recv_buffer_size = 0;
|
|
||||||
return m_disk_recv_buffer.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
// size = the packet size to remove from the receive buffer
|
|
||||||
// packet_size = the next packet size to receive in the buffer
|
|
||||||
// offset = the offset into the receive buffer where to remove `size` bytes
|
|
||||||
void peer_connection::cut_receive_buffer(int size, int packet_size, int offset)
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(is_single_thread());
|
|
||||||
INVARIANT_CHECK;
|
|
||||||
|
|
||||||
TORRENT_ASSERT(packet_size > 0);
|
|
||||||
TORRENT_ASSERT(int(m_recv_buffer.size()) >= size);
|
|
||||||
TORRENT_ASSERT(int(m_recv_buffer.size()) >= m_recv_pos);
|
|
||||||
TORRENT_ASSERT(m_recv_pos >= size + offset);
|
|
||||||
TORRENT_ASSERT(offset >= 0);
|
|
||||||
TORRENT_ASSERT(m_recv_buffer.size() >= m_recv_end);
|
|
||||||
TORRENT_ASSERT(m_recv_start <= m_recv_end);
|
|
||||||
TORRENT_ASSERT(size >= 0);
|
|
||||||
|
|
||||||
if (offset > 0)
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(m_recv_start - size <= m_recv_end);
|
|
||||||
|
|
||||||
if (size > 0)
|
|
||||||
std::memmove(&m_recv_buffer[0] + m_recv_start + offset
|
|
||||||
, &m_recv_buffer[0] + m_recv_start + offset + size
|
|
||||||
, m_recv_end - m_recv_start - size - offset);
|
|
||||||
|
|
||||||
m_recv_pos -= size;
|
|
||||||
m_recv_end -= size;
|
|
||||||
|
|
||||||
#ifdef TORRENT_DEBUG
|
|
||||||
std::fill(m_recv_buffer.begin() + m_recv_end, m_recv_buffer.end(), 0xcc);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(m_recv_start + size <= m_recv_end);
|
|
||||||
m_recv_start += size;
|
|
||||||
m_recv_pos -= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_packet_size = packet_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the purpose of this function is to free up and cut off all messages
|
|
||||||
// in the receive buffer that have been parsed and processed.
|
|
||||||
void peer_connection::normalize_receive_buffer()
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(is_single_thread());
|
|
||||||
TORRENT_ASSERT(m_recv_end >= m_recv_start);
|
|
||||||
if (m_recv_start == 0) return;
|
|
||||||
|
|
||||||
if (m_recv_end > m_recv_start)
|
|
||||||
std::memmove(&m_recv_buffer[0], &m_recv_buffer[0] + m_recv_start, m_recv_end - m_recv_start);
|
|
||||||
|
|
||||||
m_recv_end -= m_recv_start;
|
|
||||||
m_recv_start = 0;
|
|
||||||
|
|
||||||
#ifdef TORRENT_DEBUG
|
|
||||||
std::fill(m_recv_buffer.begin() + m_recv_end, m_recv_buffer.end(), 0xcc);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void peer_connection::superseed_piece(int replace_piece, int new_piece)
|
void peer_connection::superseed_piece(int replace_piece, int new_piece)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
|
@ -5262,7 +5175,7 @@ namespace libtorrent
|
||||||
if (channel == download_channel)
|
if (channel == download_channel)
|
||||||
{
|
{
|
||||||
return (std::max)((std::max)(m_outstanding_bytes
|
return (std::max)((std::max)(m_outstanding_bytes
|
||||||
, m_packet_size - m_recv_pos) + 30
|
, m_recv_buffer.packet_bytes_remaining()) + 30
|
||||||
, int(boost::int64_t(m_statistics.download_rate()) * 2
|
, int(boost::int64_t(m_statistics.download_rate()) * 2
|
||||||
/ (1000 / m_settings.get_int(settings_pack::tick_interval))));
|
/ (1000 / m_settings.get_int(settings_pack::tick_interval))));
|
||||||
}
|
}
|
||||||
|
@ -5364,7 +5277,24 @@ namespace libtorrent
|
||||||
|
|
||||||
if (m_channel_state[upload_channel] & peer_info::bw_network) return;
|
if (m_channel_state[upload_channel] & peer_info::bw_network) return;
|
||||||
|
|
||||||
if (m_quota[upload_channel] == 0
|
if (m_send_barrier == 0)
|
||||||
|
{
|
||||||
|
std::vector<asio::mutable_buffer> vec;
|
||||||
|
m_send_buffer.build_mutable_iovec(m_send_buffer.size(), vec);
|
||||||
|
int next_barrier = hit_send_barrier(vec);
|
||||||
|
for (std::vector<asio::mutable_buffer>::reverse_iterator i = vec.rbegin();
|
||||||
|
i != vec.rend(); ++i)
|
||||||
|
{
|
||||||
|
m_send_buffer.prepend_buffer(asio::buffer_cast<char*>(*i)
|
||||||
|
, asio::buffer_size(*i)
|
||||||
|
, asio::buffer_size(*i)
|
||||||
|
, &nop
|
||||||
|
, NULL);
|
||||||
|
}
|
||||||
|
set_send_barrier(next_barrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_quota[upload_channel] == 0 || m_send_barrier == 0)
|
||||||
&& !m_send_buffer.empty()
|
&& !m_send_buffer.empty()
|
||||||
&& !m_connecting)
|
&& !m_connecting)
|
||||||
{
|
{
|
||||||
|
@ -5441,6 +5371,8 @@ namespace libtorrent
|
||||||
int amount_to_send = m_send_buffer.size();
|
int amount_to_send = m_send_buffer.size();
|
||||||
if (amount_to_send > quota_left)
|
if (amount_to_send > quota_left)
|
||||||
amount_to_send = quota_left;
|
amount_to_send = quota_left;
|
||||||
|
if (amount_to_send > m_send_barrier)
|
||||||
|
amount_to_send = m_send_barrier;
|
||||||
|
|
||||||
TORRENT_ASSERT(amount_to_send > 0);
|
TORRENT_ASSERT(amount_to_send > 0);
|
||||||
|
|
||||||
|
@ -5503,11 +5435,9 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
TORRENT_ASSERT(!m_disk_recv_buffer);
|
|
||||||
TORRENT_ASSERT(m_channel_state[download_channel] & peer_info::bw_disk);
|
TORRENT_ASSERT(m_channel_state[download_channel] & peer_info::bw_disk);
|
||||||
|
|
||||||
m_disk_recv_buffer.reset(buffer);
|
m_recv_buffer.assign_disk_buffer(buffer, buffer_size);
|
||||||
m_disk_recv_buffer_size = buffer_size;
|
|
||||||
|
|
||||||
m_counters.inc_stats_counter(counters::num_peers_down_disk, -1);
|
m_counters.inc_stats_counter(counters::num_peers_down_disk, -1);
|
||||||
m_channel_state[download_channel] &= ~peer_info::bw_disk;
|
m_channel_state[download_channel] &= ~peer_info::bw_disk;
|
||||||
|
@ -5572,7 +5502,7 @@ namespace libtorrent
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int max_receive = m_packet_size - m_recv_pos;
|
int max_receive = m_recv_buffer.max_receive();
|
||||||
|
|
||||||
boost::array<asio::mutable_buffer, 2> vec;
|
boost::array<asio::mutable_buffer, 2> vec;
|
||||||
int num_bufs = 0;
|
int num_bufs = 0;
|
||||||
|
@ -5580,7 +5510,7 @@ namespace libtorrent
|
||||||
// outstanding requests. When we're likely to receive pieces, we'll
|
// outstanding requests. When we're likely to receive pieces, we'll
|
||||||
// save more time from avoiding copying data from the socket
|
// save more time from avoiding copying data from the socket
|
||||||
if ((m_settings.get_bool(settings_pack::contiguous_recv_buffer)
|
if ((m_settings.get_bool(settings_pack::contiguous_recv_buffer)
|
||||||
|| m_download_queue.empty()) && !m_disk_recv_buffer)
|
|| m_download_queue.empty()) && !m_recv_buffer.has_disk_buffer())
|
||||||
{
|
{
|
||||||
if (s == read_sync)
|
if (s == read_sync)
|
||||||
{
|
{
|
||||||
|
@ -5602,12 +5532,8 @@ namespace libtorrent
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(m_packet_size > 0);
|
|
||||||
TORRENT_ASSERT(max_receive >= 0);
|
TORRENT_ASSERT(max_receive >= 0);
|
||||||
|
|
||||||
if (m_recv_pos >= m_soft_packet_size) m_soft_packet_size = 0;
|
|
||||||
if (m_soft_packet_size && max_receive > m_soft_packet_size - m_recv_pos)
|
|
||||||
max_receive = m_soft_packet_size - m_recv_pos;
|
|
||||||
int quota_left = m_quota[download_channel];
|
int quota_left = m_quota[download_channel];
|
||||||
if (max_receive > quota_left)
|
if (max_receive > quota_left)
|
||||||
max_receive = quota_left;
|
max_receive = quota_left;
|
||||||
|
@ -5618,43 +5544,7 @@ namespace libtorrent
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(m_recv_pos >= 0);
|
num_bufs = m_recv_buffer.reserve(vec, max_receive);
|
||||||
TORRENT_ASSERT(m_packet_size > 0);
|
|
||||||
|
|
||||||
int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size;
|
|
||||||
|
|
||||||
if (int(m_recv_buffer.size()) < regular_buffer_size)
|
|
||||||
m_recv_buffer.resize(round_up8(regular_buffer_size));
|
|
||||||
|
|
||||||
if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos + max_receive)
|
|
||||||
{
|
|
||||||
// only receive into regular buffer
|
|
||||||
TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size()));
|
|
||||||
vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos], max_receive);
|
|
||||||
num_bufs = 1;
|
|
||||||
}
|
|
||||||
else if (m_recv_pos >= regular_buffer_size)
|
|
||||||
{
|
|
||||||
// only receive into disk buffer
|
|
||||||
TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0);
|
|
||||||
TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size);
|
|
||||||
vec[0] = asio::buffer(m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size, max_receive);
|
|
||||||
num_bufs = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// receive into both regular and disk buffer
|
|
||||||
TORRENT_ASSERT(max_receive + m_recv_pos > regular_buffer_size);
|
|
||||||
TORRENT_ASSERT(m_recv_pos < regular_buffer_size);
|
|
||||||
TORRENT_ASSERT(max_receive - regular_buffer_size
|
|
||||||
+ m_recv_pos <= m_disk_recv_buffer_size);
|
|
||||||
|
|
||||||
vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos]
|
|
||||||
, regular_buffer_size - m_recv_pos);
|
|
||||||
vec[1] = asio::buffer(m_disk_recv_buffer.get()
|
|
||||||
, max_receive - regular_buffer_size + m_recv_pos);
|
|
||||||
num_bufs = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s == read_async)
|
if (s == read_async)
|
||||||
{
|
{
|
||||||
|
@ -5672,12 +5562,15 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
if (num_bufs == 1)
|
if (num_bufs == 1)
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(boost::asio::buffer_size(vec[0]) > 0);
|
||||||
m_socket->async_read_some(
|
m_socket->async_read_some(
|
||||||
asio::mutable_buffers_1(vec[0]), make_read_handler(
|
asio::mutable_buffers_1(vec[0]), make_read_handler(
|
||||||
boost::bind(&peer_connection::on_receive_data, self(), _1, _2)));
|
boost::bind(&peer_connection::on_receive_data, self(), _1, _2)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(boost::asio::buffer_size(vec[0])
|
||||||
|
+ boost::asio::buffer_size(vec[1])> 0);
|
||||||
m_socket->async_read_some(
|
m_socket->async_read_some(
|
||||||
vec, make_read_handler(
|
vec, make_read_handler(
|
||||||
boost::bind(&peer_connection::on_receive_data, self(), _1, _2)));
|
boost::bind(&peer_connection::on_receive_data, self(), _1, _2)));
|
||||||
|
@ -5690,11 +5583,14 @@ namespace libtorrent
|
||||||
j.peer = self();
|
j.peer = self();
|
||||||
if (num_bufs == 1)
|
if (num_bufs == 1)
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(boost::asio::buffer_size(vec[0]) > 0);
|
||||||
j.recv_buf = asio::buffer_cast<char*>(vec[0]);
|
j.recv_buf = asio::buffer_cast<char*>(vec[0]);
|
||||||
j.buf_size = asio::buffer_size(vec[0]);
|
j.buf_size = asio::buffer_size(vec[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(boost::asio::buffer_size(vec[0])
|
||||||
|
+ boost::asio::buffer_size(vec[1])> 0);
|
||||||
j.read_vec = vec;
|
j.read_vec = vec;
|
||||||
}
|
}
|
||||||
m_ses.post_socket_job(j);
|
m_ses.post_socket_job(j);
|
||||||
|
@ -5720,71 +5616,11 @@ namespace libtorrent
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
|
||||||
|
|
||||||
// returns the last 'bytes' from the receive buffer
|
|
||||||
std::pair<buffer::interval, buffer::interval> peer_connection::wr_recv_buffers(int bytes)
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(is_single_thread());
|
|
||||||
TORRENT_ASSERT(bytes <= m_recv_pos);
|
|
||||||
|
|
||||||
std::pair<buffer::interval, buffer::interval> vec;
|
|
||||||
int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size;
|
|
||||||
TORRENT_ASSERT(regular_buffer_size >= 0);
|
|
||||||
if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos)
|
|
||||||
{
|
|
||||||
vec.first = buffer::interval(&m_recv_buffer[0] + m_recv_start
|
|
||||||
+ m_recv_pos - bytes, &m_recv_buffer[0] + m_recv_start + m_recv_pos);
|
|
||||||
vec.second = buffer::interval(0,0);
|
|
||||||
}
|
|
||||||
else if (m_recv_pos - bytes >= regular_buffer_size)
|
|
||||||
{
|
|
||||||
vec.first = buffer::interval(m_disk_recv_buffer.get() + m_recv_pos
|
|
||||||
- regular_buffer_size - bytes, m_disk_recv_buffer.get() + m_recv_pos
|
|
||||||
- regular_buffer_size);
|
|
||||||
vec.second = buffer::interval(0,0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(m_recv_pos - bytes < regular_buffer_size);
|
|
||||||
TORRENT_ASSERT(m_recv_pos > regular_buffer_size);
|
|
||||||
vec.first = buffer::interval(&m_recv_buffer[0] + m_recv_start + m_recv_pos - bytes
|
|
||||||
, &m_recv_buffer[0] + m_recv_start + regular_buffer_size);
|
|
||||||
vec.second = buffer::interval(m_disk_recv_buffer.get()
|
|
||||||
, m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size);
|
|
||||||
}
|
|
||||||
TORRENT_ASSERT(vec.first.left() + vec.second.left() == bytes);
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void peer_connection::reset_recv_buffer(int packet_size)
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(is_single_thread());
|
|
||||||
TORRENT_ASSERT(m_recv_buffer.size() >= m_recv_end);
|
|
||||||
TORRENT_ASSERT(packet_size > 0);
|
|
||||||
if (m_recv_end > m_packet_size)
|
|
||||||
{
|
|
||||||
cut_receive_buffer(m_packet_size, packet_size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_recv_pos = 0;
|
|
||||||
m_recv_start = 0;
|
|
||||||
m_recv_end = 0;
|
|
||||||
m_packet_size = packet_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void peer_connection::append_send_buffer(char* buffer, int size
|
void peer_connection::append_send_buffer(char* buffer, int size
|
||||||
, chained_buffer::free_buffer_fun destructor, void* userdata
|
, chained_buffer::free_buffer_fun destructor, void* userdata
|
||||||
, block_cache_reference ref, bool encrypted)
|
, block_cache_reference ref)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
// bittorrent connections should never use this function, since
|
|
||||||
// they might be encrypted and this would circumvent the actual
|
|
||||||
// encryption. bt_peer_connection overrides this function with
|
|
||||||
// its own version.
|
|
||||||
TORRENT_ASSERT(encrypted || type() != bittorrent_connection);
|
|
||||||
m_send_buffer.append_buffer(buffer, size, size, destructor
|
m_send_buffer.append_buffer(buffer, size, size, destructor
|
||||||
, userdata, ref);
|
, userdata, ref);
|
||||||
}
|
}
|
||||||
|
@ -5804,8 +5640,7 @@ namespace libtorrent
|
||||||
ses->free_buffer(buffer);
|
ses->free_buffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void peer_connection::send_buffer(char const* buf, int size, int flags
|
void peer_connection::send_buffer(char const* buf, int size, int flags)
|
||||||
, void (*fun)(char*, int, void*), void* userdata)
|
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
int free_space = m_send_buffer.space_in_last_buffer();
|
int free_space = m_send_buffer.space_in_last_buffer();
|
||||||
|
@ -5814,7 +5649,6 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
char* dst = m_send_buffer.append(buf, free_space);
|
char* dst = m_send_buffer.append(buf, free_space);
|
||||||
TORRENT_ASSERT(dst != 0);
|
TORRENT_ASSERT(dst != 0);
|
||||||
if (fun) fun(dst, free_space, userdata);
|
|
||||||
size -= free_space;
|
size -= free_space;
|
||||||
buf += free_space;
|
buf += free_space;
|
||||||
}
|
}
|
||||||
|
@ -5833,7 +5667,6 @@ namespace libtorrent
|
||||||
const int alloc_buf_size = m_ses.send_buffer_size();
|
const int alloc_buf_size = m_ses.send_buffer_size();
|
||||||
int buf_size = (std::min)(alloc_buf_size, size);
|
int buf_size = (std::min)(alloc_buf_size, size);
|
||||||
memcpy(chain_buf, buf, buf_size);
|
memcpy(chain_buf, buf, buf_size);
|
||||||
if (fun) fun(chain_buf, buf_size, userdata);
|
|
||||||
buf += buf_size;
|
buf += buf_size;
|
||||||
size -= buf_size;
|
size -= buf_size;
|
||||||
m_send_buffer.append_buffer(chain_buf, alloc_buf_size, buf_size
|
m_send_buffer.append_buffer(chain_buf, alloc_buf_size, buf_size
|
||||||
|
@ -5914,14 +5747,13 @@ namespace libtorrent
|
||||||
|
|
||||||
if (buffer_size > 2097152) buffer_size = 2097152;
|
if (buffer_size > 2097152) buffer_size = 2097152;
|
||||||
|
|
||||||
m_recv_buffer.resize(m_recv_pos + buffer_size);
|
asio::mutable_buffer buffer = m_recv_buffer.reserve(buffer_size);
|
||||||
TORRENT_ASSERT(m_recv_start == 0);
|
TORRENT_ASSERT(m_recv_buffer.normalized());
|
||||||
|
|
||||||
// utp sockets aren't thread safe...
|
// utp sockets aren't thread safe...
|
||||||
if (is_utp(*m_socket))
|
if (is_utp(*m_socket))
|
||||||
{
|
{
|
||||||
bytes_transferred = m_socket->read_some(asio::buffer(&m_recv_buffer[m_recv_pos]
|
bytes_transferred = m_socket->read_some(asio::mutable_buffers_1(buffer), ec);
|
||||||
, buffer_size), ec);
|
|
||||||
|
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
|
@ -5945,8 +5777,8 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
socket_job j;
|
socket_job j;
|
||||||
j.type = socket_job::read_job;
|
j.type = socket_job::read_job;
|
||||||
j.recv_buf = &m_recv_buffer[m_recv_pos];
|
j.recv_buf = asio::buffer_cast<char*>(buffer);
|
||||||
j.buf_size = buffer_size;
|
j.buf_size = asio::buffer_size(buffer);
|
||||||
j.peer = self();
|
j.peer = self();
|
||||||
m_ses.post_socket_job(j);
|
m_ses.post_socket_job(j);
|
||||||
return;
|
return;
|
||||||
|
@ -5979,6 +5811,8 @@ namespace libtorrent
|
||||||
// function.
|
// function.
|
||||||
TORRENT_ASSERT(m_channel_state[download_channel] & peer_info::bw_network);
|
TORRENT_ASSERT(m_channel_state[download_channel] & peer_info::bw_network);
|
||||||
|
|
||||||
|
TORRENT_ASSERT(bytes_transferred > 0 || error);
|
||||||
|
|
||||||
receive_data_impl(error, bytes_transferred, 10);
|
receive_data_impl(error, bytes_transferred, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6019,6 +5853,8 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TORRENT_ASSERT(bytes_transferred > 0);
|
||||||
|
|
||||||
m_counters.inc_stats_counter(counters::on_read_counter);
|
m_counters.inc_stats_counter(counters::on_read_counter);
|
||||||
m_ses.received_buffer(bytes_transferred);
|
m_ses.received_buffer(bytes_transferred);
|
||||||
|
|
||||||
|
@ -6046,30 +5882,25 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(m_packet_size > 0);
|
|
||||||
TORRENT_ASSERT(bytes_transferred > 0);
|
TORRENT_ASSERT(bytes_transferred > 0);
|
||||||
|
m_recv_buffer.received(bytes_transferred);
|
||||||
m_recv_end += bytes_transferred;
|
|
||||||
TORRENT_ASSERT(m_recv_pos <= int(m_recv_buffer.size()
|
|
||||||
+ m_disk_recv_buffer_size));
|
|
||||||
|
|
||||||
int bytes = bytes_transferred;
|
int bytes = bytes_transferred;
|
||||||
int sub_transferred = 0;
|
int sub_transferred = 0;
|
||||||
do {
|
do {
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
#if TORRENT_USE_ASSERTS
|
// TODO: The stats checks can not be honored when authenticated encryption is in use
|
||||||
|
// because we may have encrypted data which we cannot authenticate yet
|
||||||
|
#if 0
|
||||||
size_type cur_payload_dl = m_statistics.last_payload_downloaded();
|
size_type cur_payload_dl = m_statistics.last_payload_downloaded();
|
||||||
size_type cur_protocol_dl = m_statistics.last_protocol_downloaded();
|
size_type cur_protocol_dl = m_statistics.last_protocol_downloaded();
|
||||||
#endif
|
#endif
|
||||||
int packet_size = m_soft_packet_size ? m_soft_packet_size : m_packet_size;
|
sub_transferred = m_recv_buffer.advance_pos(bytes);
|
||||||
int limit = packet_size > m_recv_pos ? packet_size - m_recv_pos : packet_size;
|
|
||||||
sub_transferred = (std::min)(bytes, limit);
|
|
||||||
m_recv_pos += sub_transferred;
|
|
||||||
on_receive(error, sub_transferred);
|
on_receive(error, sub_transferred);
|
||||||
bytes -= sub_transferred;
|
bytes -= sub_transferred;
|
||||||
TORRENT_ASSERT(sub_transferred > 0);
|
TORRENT_ASSERT(sub_transferred > 0);
|
||||||
|
|
||||||
#if TORRENT_USE_ASSERTS
|
#if 0
|
||||||
TORRENT_ASSERT(m_statistics.last_payload_downloaded() - cur_payload_dl >= 0);
|
TORRENT_ASSERT(m_statistics.last_payload_downloaded() - cur_payload_dl >= 0);
|
||||||
TORRENT_ASSERT(m_statistics.last_protocol_downloaded() - cur_protocol_dl >= 0);
|
TORRENT_ASSERT(m_statistics.last_protocol_downloaded() - cur_protocol_dl >= 0);
|
||||||
size_type stats_diff = m_statistics.last_payload_downloaded() - cur_payload_dl +
|
size_type stats_diff = m_statistics.last_payload_downloaded() - cur_payload_dl +
|
||||||
|
@ -6080,22 +5911,16 @@ namespace libtorrent
|
||||||
|
|
||||||
} while (bytes > 0 && sub_transferred > 0);
|
} while (bytes > 0 && sub_transferred > 0);
|
||||||
|
|
||||||
normalize_receive_buffer();
|
m_recv_buffer.normalize();
|
||||||
|
|
||||||
TORRENT_ASSERT(m_recv_pos == m_recv_end);
|
TORRENT_ASSERT(m_recv_buffer.pos_at_end());
|
||||||
|
TORRENT_ASSERT(m_recv_buffer.packet_size() > 0);
|
||||||
|
|
||||||
TORRENT_ASSERT(m_packet_size > 0);
|
if (m_peer_choked)
|
||||||
|
|
||||||
if (m_peer_choked
|
|
||||||
&& m_recv_pos == 0
|
|
||||||
&& (m_recv_buffer.capacity() - m_packet_size) > 128)
|
|
||||||
{
|
{
|
||||||
// round up to an even 8 bytes since that's the RC4 blocksize
|
m_recv_buffer.clamp_size();
|
||||||
buffer(round_up8(m_packet_size)).swap(m_recv_buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_recv_pos >= m_soft_packet_size) m_soft_packet_size = 0;
|
|
||||||
|
|
||||||
if (num_loops > read_loops) break;
|
if (num_loops > read_loops) break;
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
|
@ -6137,6 +5962,7 @@ namespace libtorrent
|
||||||
// we want to send data
|
// we want to send data
|
||||||
return !m_send_buffer.empty()
|
return !m_send_buffer.empty()
|
||||||
&& m_quota[upload_channel] > 0
|
&& m_quota[upload_channel] > 0
|
||||||
|
&& (m_send_barrier > 0)
|
||||||
&& !m_connecting;
|
&& !m_connecting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6388,6 +6214,9 @@ namespace libtorrent
|
||||||
|
|
||||||
trancieve_ip_packet(bytes_transferred, m_remote.address().is_v6());
|
trancieve_ip_packet(bytes_transferred, m_remote.address().is_v6());
|
||||||
|
|
||||||
|
if (m_send_barrier != INT_MAX)
|
||||||
|
m_send_barrier -= bytes_transferred;
|
||||||
|
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
peer_log(">>> wrote %d bytes", int(bytes_transferred));
|
peer_log(">>> wrote %d bytes", int(bytes_transferred));
|
||||||
#endif
|
#endif
|
||||||
|
@ -6405,7 +6234,7 @@ namespace libtorrent
|
||||||
// make sure we free up all send buffers that are owned
|
// make sure we free up all send buffers that are owned
|
||||||
// by the disk thread
|
// by the disk thread
|
||||||
m_send_buffer.clear();
|
m_send_buffer.clear();
|
||||||
m_disk_recv_buffer.reset();
|
m_recv_buffer.free_disk_buffer();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6448,10 +6277,9 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
TORRENT_ASSERT(m_in_use == 1337);
|
TORRENT_ASSERT(m_in_use == 1337);
|
||||||
TORRENT_ASSERT(m_queued_time_critical <= int(m_request_queue.size()));
|
TORRENT_ASSERT(m_queued_time_critical <= int(m_request_queue.size()));
|
||||||
TORRENT_ASSERT(m_recv_end >= m_recv_start);
|
|
||||||
TORRENT_ASSERT(m_accept_fast.size() == m_accept_fast_piece_cnt.size());
|
TORRENT_ASSERT(m_accept_fast.size() == m_accept_fast_piece_cnt.size());
|
||||||
|
|
||||||
TORRENT_ASSERT(bool(m_disk_recv_buffer) == (m_disk_recv_buffer_size > 0));
|
m_recv_buffer.check_invariant();
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -915,7 +915,7 @@ namespace libtorrent
|
||||||
|
|
||||||
if (m_round_robin >= iter - m_peers.begin()) ++m_round_robin;
|
if (m_round_robin >= iter - m_peers.begin()) ++m_round_robin;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
if (flags & flag_encryption) p->pe_support = true;
|
if (flags & flag_encryption) p->pe_support = true;
|
||||||
#endif
|
#endif
|
||||||
if (flags & flag_seed)
|
if (flags & flag_seed)
|
||||||
|
|
|
@ -0,0 +1,400 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Arvid Norberg, Steven Siloti
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the author nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libtorrent/receive_buffer.hpp>
|
||||||
|
|
||||||
|
namespace libtorrent {
|
||||||
|
|
||||||
|
int receive_buffer::max_receive()
|
||||||
|
{
|
||||||
|
int max = packet_bytes_remaining();
|
||||||
|
if (m_recv_pos >= m_soft_packet_size) m_soft_packet_size = 0;
|
||||||
|
if (m_soft_packet_size && max > m_soft_packet_size - m_recv_pos)
|
||||||
|
max = m_soft_packet_size - m_recv_pos;
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::asio::mutable_buffer receive_buffer::reserve(int size)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(size > 0);
|
||||||
|
TORRENT_ASSERT(!m_disk_recv_buffer);
|
||||||
|
m_recv_buffer.resize(m_recv_pos + size);
|
||||||
|
return boost::asio::buffer(&m_recv_buffer[m_recv_pos], size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int receive_buffer::reserve(boost::array<boost::asio::mutable_buffer, 2>& vec, int size)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(size > 0);
|
||||||
|
TORRENT_ASSERT(m_recv_pos >= 0);
|
||||||
|
TORRENT_ASSERT(m_packet_size > 0);
|
||||||
|
|
||||||
|
int num_bufs;
|
||||||
|
int regular_buf_size = regular_buffer_size();
|
||||||
|
|
||||||
|
if (int(m_recv_buffer.size()) < regular_buf_size)
|
||||||
|
m_recv_buffer.resize(round_up8(regular_buf_size));
|
||||||
|
|
||||||
|
if (!m_disk_recv_buffer || regular_buf_size >= m_recv_pos + size)
|
||||||
|
{
|
||||||
|
// only receive into regular buffer
|
||||||
|
TORRENT_ASSERT(m_recv_pos + size <= int(m_recv_buffer.size()));
|
||||||
|
vec[0] = boost::asio::buffer(&m_recv_buffer[m_recv_pos], size);
|
||||||
|
TORRENT_ASSERT(boost::asio::buffer_size(vec[0]) > 0);
|
||||||
|
num_bufs = 1;
|
||||||
|
}
|
||||||
|
else if (m_recv_pos >= regular_buf_size)
|
||||||
|
{
|
||||||
|
// only receive into disk buffer
|
||||||
|
TORRENT_ASSERT(m_recv_pos - regular_buf_size >= 0);
|
||||||
|
TORRENT_ASSERT(m_recv_pos - regular_buf_size + size <= m_disk_recv_buffer_size);
|
||||||
|
vec[0] = boost::asio::buffer(m_disk_recv_buffer.get() + m_recv_pos - regular_buf_size, size);
|
||||||
|
TORRENT_ASSERT(boost::asio::buffer_size(vec[0]) > 0);
|
||||||
|
num_bufs = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// receive into both regular and disk buffer
|
||||||
|
TORRENT_ASSERT(size + m_recv_pos > regular_buf_size);
|
||||||
|
TORRENT_ASSERT(m_recv_pos < regular_buf_size);
|
||||||
|
TORRENT_ASSERT(size - regular_buf_size
|
||||||
|
+ m_recv_pos <= m_disk_recv_buffer_size);
|
||||||
|
|
||||||
|
vec[0] = boost::asio::buffer(&m_recv_buffer[m_recv_pos]
|
||||||
|
, regular_buf_size - m_recv_pos);
|
||||||
|
vec[1] = boost::asio::buffer(m_disk_recv_buffer.get()
|
||||||
|
, size - regular_buf_size + m_recv_pos);
|
||||||
|
TORRENT_ASSERT(boost::asio::buffer_size(vec[0])
|
||||||
|
+ boost::asio::buffer_size(vec[1])> 0);
|
||||||
|
num_bufs = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_bufs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int receive_buffer::advance_pos(int bytes)
|
||||||
|
{
|
||||||
|
int packet_size = m_soft_packet_size ? m_soft_packet_size : m_packet_size;
|
||||||
|
int limit = packet_size > m_recv_pos ? packet_size - m_recv_pos : packet_size;
|
||||||
|
int sub_transferred = (std::min)(bytes, limit);
|
||||||
|
m_recv_pos += sub_transferred;
|
||||||
|
if (m_recv_pos >= m_soft_packet_size) m_soft_packet_size = 0;
|
||||||
|
return sub_transferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
void receive_buffer::clamp_size()
|
||||||
|
{
|
||||||
|
if (m_recv_pos == 0
|
||||||
|
&& (m_recv_buffer.capacity() - m_packet_size) > 128)
|
||||||
|
{
|
||||||
|
// round up to an even 8 bytes since that's the RC4 blocksize
|
||||||
|
buffer(round_up8(m_packet_size)).swap(m_recv_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// size = the packet size to remove from the receive buffer
|
||||||
|
// packet_size = the next packet size to receive in the buffer
|
||||||
|
// offset = the offset into the receive buffer where to remove `size` bytes
|
||||||
|
void receive_buffer::cut(int size, int packet_size, int offset)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(packet_size > 0);
|
||||||
|
TORRENT_ASSERT(int(m_recv_buffer.size()) >= size);
|
||||||
|
TORRENT_ASSERT(int(m_recv_buffer.size()) >= m_recv_pos);
|
||||||
|
TORRENT_ASSERT(m_recv_pos >= size + offset);
|
||||||
|
TORRENT_ASSERT(offset >= 0);
|
||||||
|
TORRENT_ASSERT(m_recv_buffer.size() >= m_recv_end);
|
||||||
|
TORRENT_ASSERT(m_recv_start <= m_recv_end);
|
||||||
|
TORRENT_ASSERT(size >= 0);
|
||||||
|
|
||||||
|
if (offset > 0)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(m_recv_start - size <= m_recv_end);
|
||||||
|
|
||||||
|
if (size > 0)
|
||||||
|
std::memmove(&m_recv_buffer[0] + m_recv_start + offset
|
||||||
|
, &m_recv_buffer[0] + m_recv_start + offset + size
|
||||||
|
, m_recv_end - m_recv_start - size - offset);
|
||||||
|
|
||||||
|
m_recv_pos -= size;
|
||||||
|
m_recv_end -= size;
|
||||||
|
|
||||||
|
#ifdef TORRENT_DEBUG
|
||||||
|
std::fill(m_recv_buffer.begin() + m_recv_end, m_recv_buffer.end(), 0xcc);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(m_recv_start + size <= m_recv_end);
|
||||||
|
m_recv_start += size;
|
||||||
|
m_recv_pos -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_packet_size = packet_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer::const_interval receive_buffer::get() const
|
||||||
|
{
|
||||||
|
if (m_recv_buffer.empty())
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(m_recv_pos == 0);
|
||||||
|
return buffer::interval(0,0);
|
||||||
|
}
|
||||||
|
int rcv_pos = (std::min)(m_recv_pos, int(m_recv_buffer.size()));
|
||||||
|
return buffer::const_interval(&m_recv_buffer[0] + m_recv_start
|
||||||
|
, &m_recv_buffer[0] + m_recv_start + rcv_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
buffer::interval receive_buffer::mutable_buffer()
|
||||||
|
{
|
||||||
|
if (m_recv_buffer.empty())
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(m_recv_pos == 0);
|
||||||
|
return buffer::interval(0,0);
|
||||||
|
}
|
||||||
|
TORRENT_ASSERT(!m_disk_recv_buffer);
|
||||||
|
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
|
||||||
|
int rcv_pos = (std::min)(m_recv_pos, int(m_recv_buffer.size()));
|
||||||
|
return buffer::interval(&m_recv_buffer[0] + m_recv_start
|
||||||
|
, &m_recv_buffer[0] + m_recv_start + rcv_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void receive_buffer::mutable_buffers(std::vector<boost::asio::mutable_buffer>& vec, int bytes)
|
||||||
|
{
|
||||||
|
using namespace boost;
|
||||||
|
TORRENT_ASSERT(bytes <= m_recv_pos);
|
||||||
|
|
||||||
|
int regular_buf_size = regular_buffer_size();
|
||||||
|
TORRENT_ASSERT(regular_buf_size >= 0);
|
||||||
|
if (!m_disk_recv_buffer || regular_buf_size >= m_recv_pos)
|
||||||
|
{
|
||||||
|
vec.push_back(asio::mutable_buffer(&m_recv_buffer[0] + m_recv_start
|
||||||
|
+ m_recv_pos - bytes, bytes));
|
||||||
|
}
|
||||||
|
else if (m_recv_pos - bytes >= regular_buf_size)
|
||||||
|
{
|
||||||
|
vec.push_back(asio::mutable_buffer(m_disk_recv_buffer.get() + m_recv_pos
|
||||||
|
- regular_buf_size - bytes, bytes));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(m_recv_pos - bytes < regular_buf_size);
|
||||||
|
TORRENT_ASSERT(m_recv_pos > regular_buf_size);
|
||||||
|
vec.push_back(asio::mutable_buffer(&m_recv_buffer[0] + m_recv_start + m_recv_pos - bytes
|
||||||
|
, regular_buf_size - (m_recv_start + m_recv_pos - bytes)));
|
||||||
|
vec.push_back(asio::mutable_buffer(m_disk_recv_buffer.get()
|
||||||
|
, m_recv_pos - regular_buf_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
|
||||||
|
int vec_bytes = 0;
|
||||||
|
for (std::vector<asio::mutable_buffer>::iterator i = vec.begin();
|
||||||
|
i != vec.end(); ++i)
|
||||||
|
vec_bytes += boost::asio::buffer_size(*i);
|
||||||
|
TORRENT_ASSERT(vec_bytes == bytes);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void receive_buffer::assign_disk_buffer(char* buffer, int size)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(m_packet_size > 0);
|
||||||
|
assert_no_disk_buffer();
|
||||||
|
m_disk_recv_buffer.reset(buffer);
|
||||||
|
if (m_disk_recv_buffer)
|
||||||
|
m_disk_recv_buffer_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* receive_buffer::release_disk_buffer()
|
||||||
|
{
|
||||||
|
if (!m_disk_recv_buffer) return 0;
|
||||||
|
|
||||||
|
TORRENT_ASSERT(m_disk_recv_buffer_size <= m_recv_end);
|
||||||
|
TORRENT_ASSERT(m_recv_start <= m_recv_end - m_disk_recv_buffer_size);
|
||||||
|
m_recv_end -= m_disk_recv_buffer_size;
|
||||||
|
m_disk_recv_buffer_size = 0;
|
||||||
|
return m_disk_recv_buffer.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// the purpose of this function is to free up and cut off all messages
|
||||||
|
// in the receive buffer that have been parsed and processed.
|
||||||
|
void receive_buffer::normalize()
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(m_recv_end >= m_recv_start);
|
||||||
|
if (m_recv_start == 0) return;
|
||||||
|
|
||||||
|
if (m_recv_end > m_recv_start)
|
||||||
|
std::memmove(&m_recv_buffer[0], &m_recv_buffer[0] + m_recv_start, m_recv_end - m_recv_start);
|
||||||
|
|
||||||
|
m_recv_end -= m_recv_start;
|
||||||
|
m_recv_start = 0;
|
||||||
|
|
||||||
|
#ifdef TORRENT_DEBUG
|
||||||
|
std::fill(m_recv_buffer.begin() + m_recv_end, m_recv_buffer.end(), 0xcc);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void receive_buffer::reset(int packet_size)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(m_recv_buffer.size() >= m_recv_end);
|
||||||
|
TORRENT_ASSERT(packet_size > 0);
|
||||||
|
if (m_recv_end > m_packet_size)
|
||||||
|
{
|
||||||
|
cut(m_packet_size, packet_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_recv_pos = 0;
|
||||||
|
m_recv_start = 0;
|
||||||
|
m_recv_end = 0;
|
||||||
|
m_packet_size = packet_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
bool crypto_receive_buffer::packet_finished() const
|
||||||
|
{
|
||||||
|
if (m_recv_pos == INT_MAX)
|
||||||
|
return m_connection_buffer.packet_finished();
|
||||||
|
else
|
||||||
|
return m_packet_size <= m_recv_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypto_receive_buffer::packet_size() const
|
||||||
|
{
|
||||||
|
if (m_recv_pos == INT_MAX)
|
||||||
|
return m_connection_buffer.packet_size();
|
||||||
|
else
|
||||||
|
return m_packet_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypto_receive_buffer::pos() const
|
||||||
|
{
|
||||||
|
if (m_recv_pos == INT_MAX)
|
||||||
|
return m_connection_buffer.pos();
|
||||||
|
else
|
||||||
|
return m_recv_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_receive_buffer::cut(int size, int packet_size, int offset)
|
||||||
|
{
|
||||||
|
if (m_recv_pos != INT_MAX)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(size <= m_recv_pos);
|
||||||
|
m_packet_size = packet_size;
|
||||||
|
packet_size = m_connection_buffer.packet_size() - size;
|
||||||
|
m_recv_pos -= size;
|
||||||
|
}
|
||||||
|
m_connection_buffer.cut(size, packet_size, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_receive_buffer::reset(int packet_size)
|
||||||
|
{
|
||||||
|
if (m_recv_pos != INT_MAX)
|
||||||
|
{
|
||||||
|
if (m_connection_buffer.m_recv_end > m_packet_size)
|
||||||
|
{
|
||||||
|
cut(m_packet_size, packet_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_packet_size = packet_size;
|
||||||
|
packet_size = m_connection_buffer.packet_size() - m_recv_pos;
|
||||||
|
m_recv_pos = 0;
|
||||||
|
}
|
||||||
|
m_connection_buffer.reset(packet_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_receive_buffer::crypto_reset(int packet_size)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(packet_finished());
|
||||||
|
TORRENT_ASSERT(crypto_packet_finished());
|
||||||
|
TORRENT_ASSERT(m_recv_pos == INT_MAX || m_recv_pos == m_connection_buffer.pos());
|
||||||
|
TORRENT_ASSERT(m_recv_pos == INT_MAX || m_connection_buffer.pos_at_end());
|
||||||
|
TORRENT_ASSERT(!m_connection_buffer.has_disk_buffer());
|
||||||
|
|
||||||
|
if (packet_size == 0)
|
||||||
|
{
|
||||||
|
if (m_recv_pos != INT_MAX)
|
||||||
|
m_connection_buffer.cut(0, m_packet_size);
|
||||||
|
m_recv_pos = INT_MAX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_recv_pos == INT_MAX)
|
||||||
|
m_packet_size = m_connection_buffer.packet_size();
|
||||||
|
m_recv_pos = m_connection_buffer.pos();
|
||||||
|
TORRENT_ASSERT(m_recv_pos >= 0);
|
||||||
|
m_connection_buffer.cut(0, m_recv_pos + packet_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_receive_buffer::set_soft_packet_size(int size)
|
||||||
|
{
|
||||||
|
if (m_recv_pos == INT_MAX)
|
||||||
|
m_connection_buffer.set_soft_packet_size(size);
|
||||||
|
else
|
||||||
|
m_soft_packet_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypto_receive_buffer::advance_pos(int bytes)
|
||||||
|
{
|
||||||
|
if (m_recv_pos == INT_MAX) return bytes;
|
||||||
|
|
||||||
|
int packet_size = m_soft_packet_size ? m_soft_packet_size : m_packet_size;
|
||||||
|
int limit = packet_size > m_recv_pos ? packet_size - m_recv_pos : packet_size;
|
||||||
|
int sub_transferred = (std::min)(bytes, limit);
|
||||||
|
m_recv_pos += sub_transferred;
|
||||||
|
m_connection_buffer.cut(0, m_connection_buffer.packet_size() + sub_transferred);
|
||||||
|
if (m_recv_pos >= m_soft_packet_size) m_soft_packet_size = 0;
|
||||||
|
return sub_transferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer::const_interval crypto_receive_buffer::get() const
|
||||||
|
{
|
||||||
|
buffer::const_interval recv_buffer = m_connection_buffer.get();
|
||||||
|
if (m_recv_pos < m_connection_buffer.pos())
|
||||||
|
recv_buffer.end = recv_buffer.begin + m_recv_pos;
|
||||||
|
return recv_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crypto_receive_buffer::mutable_buffers(
|
||||||
|
std::vector<boost::asio::mutable_buffer>& vec
|
||||||
|
, std::size_t bytes_transfered)
|
||||||
|
{
|
||||||
|
int pending_decryption = bytes_transfered;
|
||||||
|
if (m_recv_pos != INT_MAX)
|
||||||
|
{
|
||||||
|
pending_decryption = m_connection_buffer.packet_size() - m_recv_pos;
|
||||||
|
}
|
||||||
|
m_connection_buffer.mutable_buffers(vec, pending_decryption);
|
||||||
|
}
|
||||||
|
#endif // TORRENT_DISABLE_ENCRYPTION
|
||||||
|
|
||||||
|
} // namespace libtorrent
|
|
@ -4199,7 +4199,7 @@ retry:
|
||||||
trigger_auto_manage();
|
trigger_auto_manage();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
torrent const* session_impl::find_encrypted_torrent(sha1_hash const& info_hash
|
torrent const* session_impl::find_encrypted_torrent(sha1_hash const& info_hash
|
||||||
, sha1_hash const& xor_mask)
|
, sha1_hash const& xor_mask)
|
||||||
{
|
{
|
||||||
|
@ -4692,7 +4692,7 @@ retry:
|
||||||
|
|
||||||
TORRENT_ASSERT(m_torrents.size() >= m_torrent_lru.size());
|
TORRENT_ASSERT(m_torrents.size() >= m_torrent_lru.size());
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
hasher h;
|
hasher h;
|
||||||
h.update("req2", 4);
|
h.update("req2", 4);
|
||||||
h.update((char*)&(*ih)[0], 20);
|
h.update((char*)&(*ih)[0], 20);
|
||||||
|
@ -4904,7 +4904,7 @@ retry:
|
||||||
|
|
||||||
TORRENT_ASSERT(m_torrents.size() >= m_torrent_lru.size());
|
TORRENT_ASSERT(m_torrents.size() >= m_torrent_lru.size());
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
hasher h;
|
hasher h;
|
||||||
h.update("req2", 4);
|
h.update("req2", 4);
|
||||||
h.update((char*)&tptr->info_hash()[0], 20);
|
h.update((char*)&tptr->info_hash()[0], 20);
|
||||||
|
@ -5527,13 +5527,13 @@ retry:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
void session_impl::add_obfuscated_hash(sha1_hash const& obfuscated
|
void session_impl::add_obfuscated_hash(sha1_hash const& obfuscated
|
||||||
, boost::weak_ptr<torrent> const& t)
|
, boost::weak_ptr<torrent> const& t)
|
||||||
{
|
{
|
||||||
m_obfuscated_torrents.insert(std::make_pair(obfuscated, t.lock()));
|
m_obfuscated_torrents.insert(std::make_pair(obfuscated, t.lock()));
|
||||||
}
|
}
|
||||||
#endif // TORRENT_DISABLE_ENCRYPTION
|
#endif // !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
|
||||||
bool session_impl::is_listening() const
|
bool session_impl::is_listening() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -518,7 +518,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
m_trackers.swap(new_trackers);
|
m_trackers.swap(new_trackers);
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
hasher h;
|
hasher h;
|
||||||
h.update("req2", 4);
|
h.update("req2", 4);
|
||||||
h.update((char*)&m_torrent_file->info_hash()[0], 20);
|
h.update((char*)&m_torrent_file->info_hash()[0], 20);
|
||||||
|
@ -667,7 +667,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
m_trackers.swap(new_trackers);
|
m_trackers.swap(new_trackers);
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
hasher h;
|
hasher h;
|
||||||
h.update("req2", 4);
|
h.update("req2", 4);
|
||||||
h.update((char*)&m_torrent_file->info_hash()[0], 20);
|
h.update((char*)&m_torrent_file->info_hash()[0], 20);
|
||||||
|
|
|
@ -145,7 +145,7 @@ namespace libtorrent
|
||||||
, fast_reconnects(0)
|
, fast_reconnects(0)
|
||||||
, trust_points(0)
|
, trust_points(0)
|
||||||
, source(src)
|
, source(src)
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
// assume no support in order to
|
// assume no support in order to
|
||||||
// prefer opening non-encrypyed
|
// prefer opening non-encrypyed
|
||||||
// connections. If it fails, we'll
|
// connections. If it fails, we'll
|
||||||
|
|
|
@ -179,7 +179,7 @@ namespace libtorrent { namespace
|
||||||
// used as a rendezvous point in case direct
|
// used as a rendezvous point in case direct
|
||||||
// connections to the peer fail
|
// connections to the peer fail
|
||||||
int flags = p->is_seed() ? 2 : 0;
|
int flags = p->is_seed() ? 2 : 0;
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
flags |= p->supports_encryption() ? 1 : 0;
|
flags |= p->supports_encryption() ? 1 : 0;
|
||||||
#endif
|
#endif
|
||||||
flags |= is_utp(*p->get_socket()) ? 4 : 0;
|
flags |= is_utp(*p->get_socket()) ? 4 : 0;
|
||||||
|
@ -565,7 +565,7 @@ namespace libtorrent { namespace
|
||||||
// used as a rendezvous point in case direct
|
// used as a rendezvous point in case direct
|
||||||
// connections to the peer fail
|
// connections to the peer fail
|
||||||
int flags = p->is_seed() ? 2 : 0;
|
int flags = p->is_seed() ? 2 : 0;
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
flags |= p->supports_encryption() ? 1 : 0;
|
flags |= p->supports_encryption() ? 1 : 0;
|
||||||
#endif
|
#endif
|
||||||
flags |= is_utp(*p->get_socket()) ? 4 : 0;
|
flags |= is_utp(*p->get_socket()) ? 4 : 0;
|
||||||
|
|
|
@ -124,7 +124,7 @@ namespace libtorrent
|
||||||
// it is always possible to request pieces
|
// it is always possible to request pieces
|
||||||
incoming_unchoke();
|
incoming_unchoke();
|
||||||
|
|
||||||
reset_recv_buffer(t->block_size() + 1024);
|
m_recv_buffer.reset(t->block_size() + 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
void web_connection_base::add_headers(std::string& request
|
void web_connection_base::add_headers(std::string& request
|
||||||
|
|
|
@ -376,7 +376,7 @@ void web_peer_connection::write_request(peer_request const& r)
|
||||||
// in case the first file on this series of requests is a padfile
|
// in case the first file on this series of requests is a padfile
|
||||||
// we need to handle it right now, and pretend that we got a response
|
// we need to handle it right now, and pretend that we got a response
|
||||||
// with zeros.
|
// with zeros.
|
||||||
buffer::const_interval recv_buffer = receive_buffer();
|
buffer::const_interval recv_buffer = m_recv_buffer.get();
|
||||||
handle_padfile(recv_buffer);
|
handle_padfile(recv_buffer);
|
||||||
if (associated_torrent().expired()) return;
|
if (associated_torrent().expired()) return;
|
||||||
|
|
||||||
|
@ -412,16 +412,16 @@ bool web_peer_connection::maybe_harvest_block()
|
||||||
|
|
||||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||||
TORRENT_ASSERT(t);
|
TORRENT_ASSERT(t);
|
||||||
buffer::const_interval recv_buffer = receive_buffer();
|
buffer::const_interval recv_buffer = m_recv_buffer.get();
|
||||||
|
|
||||||
incoming_piece(front_request, &m_piece[0]);
|
incoming_piece(front_request, &m_piece[0]);
|
||||||
m_requests.pop_front();
|
m_requests.pop_front();
|
||||||
if (associated_torrent().expired()) return false;
|
if (associated_torrent().expired()) return false;
|
||||||
TORRENT_ASSERT(m_block_pos >= front_request.length);
|
TORRENT_ASSERT(m_block_pos >= front_request.length);
|
||||||
m_block_pos -= front_request.length;
|
m_block_pos -= front_request.length;
|
||||||
cut_receive_buffer(m_body_start, t->block_size() + request_size_overhead);
|
m_recv_buffer.cut(m_body_start, t->block_size() + request_size_overhead);
|
||||||
m_body_start = 0;
|
m_body_start = 0;
|
||||||
recv_buffer = receive_buffer();
|
recv_buffer = m_recv_buffer.get();
|
||||||
// TORRENT_ASSERT(m_received_body <= range_end - range_start);
|
// TORRENT_ASSERT(m_received_body <= range_end - range_start);
|
||||||
m_piece.clear();
|
m_piece.clear();
|
||||||
TORRENT_ASSERT(m_piece.empty());
|
TORRENT_ASSERT(m_piece.empty());
|
||||||
|
@ -510,7 +510,7 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
== dl_target);
|
== dl_target);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
buffer::const_interval recv_buffer = receive_buffer();
|
buffer::const_interval recv_buffer = m_recv_buffer.get();
|
||||||
|
|
||||||
int payload;
|
int payload;
|
||||||
int protocol;
|
int protocol;
|
||||||
|
@ -540,7 +540,7 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
|
|
||||||
TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
|
TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
|
||||||
|
|
||||||
TORRENT_ASSERT(recv_buffer.left() <= packet_size());
|
TORRENT_ASSERT(recv_buffer.left() <= m_recv_buffer.packet_size());
|
||||||
|
|
||||||
// this means the entire status line hasn't been received yet
|
// this means the entire status line hasn't been received yet
|
||||||
if (m_parser.status_code() == -1)
|
if (m_parser.status_code() == -1)
|
||||||
|
@ -800,8 +800,8 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
TORRENT_ASSERT(chunk_size != 0 || chunk_start.left() <= header_size || chunk_start.begin[header_size] == 'H');
|
TORRENT_ASSERT(chunk_size != 0 || chunk_start.left() <= header_size || chunk_start.begin[header_size] == 'H');
|
||||||
// cut out the chunk header from the receive buffer
|
// cut out the chunk header from the receive buffer
|
||||||
TORRENT_ASSERT(m_body_start + m_chunk_pos < INT_MAX);
|
TORRENT_ASSERT(m_body_start + m_chunk_pos < INT_MAX);
|
||||||
cut_receive_buffer(header_size, t->block_size() + request_size_overhead, int(m_body_start + m_chunk_pos));
|
m_recv_buffer.cut(header_size, t->block_size() + request_size_overhead, int(m_body_start + m_chunk_pos));
|
||||||
recv_buffer = receive_buffer();
|
recv_buffer = m_recv_buffer.get();
|
||||||
recv_buffer.begin += m_body_start;
|
recv_buffer.begin += m_body_start;
|
||||||
m_chunk_pos += chunk_size;
|
m_chunk_pos += chunk_size;
|
||||||
if (chunk_size == 0)
|
if (chunk_size == 0)
|
||||||
|
@ -925,7 +925,7 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maybe_harvest_block())
|
if (maybe_harvest_block())
|
||||||
recv_buffer = receive_buffer();
|
recv_buffer = m_recv_buffer.get();
|
||||||
if (associated_torrent().expired()) return;
|
if (associated_torrent().expired()) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -945,16 +945,16 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
TORRENT_ASSERT(m_block_pos >= r.length);
|
TORRENT_ASSERT(m_block_pos >= r.length);
|
||||||
m_block_pos -= r.length;
|
m_block_pos -= r.length;
|
||||||
m_received_body += r.length;
|
m_received_body += r.length;
|
||||||
TORRENT_ASSERT(receive_buffer().begin + m_body_start == recv_buffer.begin);
|
TORRENT_ASSERT(m_recv_buffer.get().begin + m_body_start == recv_buffer.begin);
|
||||||
TORRENT_ASSERT(m_received_body <= range_end - range_start);
|
TORRENT_ASSERT(m_received_body <= range_end - range_start);
|
||||||
cut_receive_buffer(m_body_start + r.length, t->block_size() + request_size_overhead);
|
m_recv_buffer.cut(m_body_start + r.length, t->block_size() + request_size_overhead);
|
||||||
if (m_chunk_pos > 0)
|
if (m_chunk_pos > 0)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_chunk_pos >= r.length);
|
TORRENT_ASSERT(m_chunk_pos >= r.length);
|
||||||
m_chunk_pos -= r.length;
|
m_chunk_pos -= r.length;
|
||||||
}
|
}
|
||||||
m_body_start = 0;
|
m_body_start = 0;
|
||||||
recv_buffer = receive_buffer();
|
recv_buffer = m_recv_buffer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_requests.empty())
|
if (!m_requests.empty())
|
||||||
|
@ -989,18 +989,18 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
if (m_received_body == range_end - range_start
|
if (m_received_body == range_end - range_start
|
||||||
&& (!m_parser.chunked_encoding() || m_chunk_pos == -1))
|
&& (!m_parser.chunked_encoding() || m_chunk_pos == -1))
|
||||||
{
|
{
|
||||||
int size_to_cut = recv_buffer.begin - receive_buffer().begin;
|
int size_to_cut = recv_buffer.begin - m_recv_buffer.get().begin;
|
||||||
|
|
||||||
TORRENT_ASSERT(receive_buffer().left() < size_to_cut + 1
|
TORRENT_ASSERT(m_recv_buffer.get().left() < size_to_cut + 1
|
||||||
|| receive_buffer()[size_to_cut] == 'H');
|
|| m_recv_buffer.get()[size_to_cut] == 'H');
|
||||||
|
|
||||||
cut_receive_buffer(size_to_cut, t->block_size() + request_size_overhead);
|
m_recv_buffer.cut(size_to_cut, t->block_size() + request_size_overhead);
|
||||||
if (m_chunk_pos > 0)
|
if (m_chunk_pos > 0)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_chunk_pos >= size_to_cut);
|
TORRENT_ASSERT(m_chunk_pos >= size_to_cut);
|
||||||
m_chunk_pos -= size_to_cut;
|
m_chunk_pos -= size_to_cut;
|
||||||
}
|
}
|
||||||
recv_buffer = receive_buffer();
|
recv_buffer = m_recv_buffer.get();
|
||||||
m_file_requests.pop_front();
|
m_file_requests.pop_front();
|
||||||
m_parser.reset();
|
m_parser.reset();
|
||||||
m_body_start = 0;
|
m_body_start = 0;
|
||||||
|
@ -1072,7 +1072,7 @@ void web_peer_connection::on_receive(error_code const& error
|
||||||
incoming_piece_fragment(pad_size);
|
incoming_piece_fragment(pad_size);
|
||||||
|
|
||||||
if (maybe_harvest_block())
|
if (maybe_harvest_block())
|
||||||
recv_buffer = receive_buffer();
|
recv_buffer = m_recv_buffer.get();
|
||||||
if (associated_torrent().expired()) return;
|
if (associated_torrent().expired()) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "setup_transfer.hpp"
|
#include "setup_transfer.hpp"
|
||||||
#include "test.hpp"
|
#include "test.hpp"
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
|
||||||
char const* pe_policy(boost::uint8_t policy)
|
char const* pe_policy(boost::uint8_t policy)
|
||||||
{
|
{
|
||||||
|
@ -137,7 +137,7 @@ void test_transfer(libtorrent::settings_pack::enc_policy policy
|
||||||
remove_all("tmp3_pe", ec);
|
remove_all("tmp3_pe", ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_enc_handler(libtorrent::encryption_handler* a, libtorrent::encryption_handler* b)
|
void test_enc_handler(libtorrent::crypto_plugin* a, libtorrent::crypto_plugin* b)
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_USE_VALGRIND
|
#ifdef TORRENT_USE_VALGRIND
|
||||||
const int repcount = 10;
|
const int repcount = 10;
|
||||||
|
@ -153,15 +153,37 @@ void test_enc_handler(libtorrent::encryption_handler* a, libtorrent::encryption_
|
||||||
std::generate(buf, buf + buf_len, &std::rand);
|
std::generate(buf, buf + buf_len, &std::rand);
|
||||||
std::memcpy(cmp_buf, buf, buf_len);
|
std::memcpy(cmp_buf, buf, buf_len);
|
||||||
|
|
||||||
a->encrypt(buf, buf_len);
|
using namespace boost::asio;
|
||||||
|
std::vector<mutable_buffer> iovec;
|
||||||
|
iovec.push_back(mutable_buffer(buf, buf_len));
|
||||||
|
a->encrypt(iovec);
|
||||||
TEST_CHECK(!std::equal(buf, buf + buf_len, cmp_buf));
|
TEST_CHECK(!std::equal(buf, buf + buf_len, cmp_buf));
|
||||||
b->decrypt(buf, buf_len);
|
TEST_CHECK(iovec.empty());
|
||||||
|
int consume = 0;
|
||||||
|
int produce = buf_len;
|
||||||
|
int packet_size = 0;
|
||||||
|
iovec.push_back(mutable_buffer(buf, buf_len));
|
||||||
|
b->decrypt(iovec, consume, produce, packet_size);
|
||||||
TEST_CHECK(std::equal(buf, buf + buf_len, cmp_buf));
|
TEST_CHECK(std::equal(buf, buf + buf_len, cmp_buf));
|
||||||
|
TEST_CHECK(iovec.empty());
|
||||||
|
TEST_EQUAL(consume, 0);
|
||||||
|
TEST_EQUAL(produce, buf_len);
|
||||||
|
TEST_EQUAL(packet_size, 0);
|
||||||
|
|
||||||
b->encrypt(buf, buf_len);
|
iovec.push_back(mutable_buffer(buf, buf_len));
|
||||||
|
b->encrypt(iovec);
|
||||||
TEST_CHECK(!std::equal(buf, buf + buf_len, cmp_buf));
|
TEST_CHECK(!std::equal(buf, buf + buf_len, cmp_buf));
|
||||||
a->decrypt(buf, buf_len);
|
TEST_CHECK(iovec.empty());
|
||||||
|
consume = 0;
|
||||||
|
produce = buf_len;
|
||||||
|
packet_size = 0;
|
||||||
|
iovec.push_back(mutable_buffer(buf, buf_len));
|
||||||
|
a->decrypt(iovec, consume, produce, packet_size);
|
||||||
TEST_CHECK(std::equal(buf, buf + buf_len, cmp_buf));
|
TEST_CHECK(std::equal(buf, buf + buf_len, cmp_buf));
|
||||||
|
TEST_CHECK(iovec.empty());
|
||||||
|
TEST_EQUAL(consume, 0);
|
||||||
|
TEST_EQUAL(produce, buf_len);
|
||||||
|
TEST_EQUAL(packet_size, 0);
|
||||||
|
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
delete[] cmp_buf;
|
delete[] cmp_buf;
|
||||||
|
@ -174,7 +196,7 @@ int test_main()
|
||||||
{
|
{
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
|
|
||||||
#ifdef TORRENT_USE_VALGRIND
|
#ifdef TORRENT_USE_VALGRIND
|
||||||
const int repcount = 10;
|
const int repcount = 10;
|
||||||
|
|
Loading…
Reference in New Issue