use array_view instead of std::vector in crypto_plugin interface (#835)

use array_view instead of std::vector in crypto_plugin interface. return a vector of const_buffers for prepending new buffers. use stack allocated (single buffer) iovecs for receives. general cleanup
This commit is contained in:
Arvid Norberg 2016-06-19 23:05:59 -04:00 committed by GitHub
parent b2358666a1
commit a9dbbdea37
13 changed files with 206 additions and 165 deletions

View File

@ -46,11 +46,12 @@ namespace libtorrent { namespace aux {
// T -> const T conversion constructor
template <typename U, typename
= std::enable_if<std::is_convertible<U, T>::value>
= std::enable_if<std::is_convertible<U*, T*>::value>
>
array_view(array_view<U> const& v)
: m_ptr(v.data()), m_len(v.size()) {}
array_view(T& p) : m_ptr(&p), m_len(1) {}
array_view(T* p, int l) : m_ptr(p), m_len(l)
{
TORRENT_ASSERT(l >= 0);
@ -69,8 +70,14 @@ namespace libtorrent { namespace aux {
size_t size() const { return m_len; }
T* data() const { return m_ptr; }
using iterator = T*;
using reverse_iterator = std::reverse_iterator<T*>;
T* begin() const { return m_ptr; }
T* end() const { return m_ptr + m_len; }
reverse_iterator rbegin() const { return reverse_iterator(end()); }
reverse_iterator rend() const { return reverse_iterator(begin()); }
T& front() const { TORRENT_ASSERT(m_len > 0); return m_ptr[0]; }
T& back() const { TORRENT_ASSERT(m_len > 0); return m_ptr[m_len-1]; }

View File

@ -159,7 +159,10 @@ namespace libtorrent
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<boost::asio::mutable_buffer>& iovec) override;
// next_barrier, buffers-to-prepend
virtual
std::tuple<int, aux::array_view<boost::asio::const_buffer>>
hit_send_barrier(aux::array_view<boost::asio::mutable_buffer> iovec) override;
#endif
virtual void get_specific_peer_info(peer_info& p) const override;

View File

@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
// TODO: 2 this type should probably be renamed to send_buffer
struct TORRENT_EXTRA_EXPORT chained_buffer : private single_threaded
{
chained_buffer(): m_bytes(0), m_capacity(0)
@ -67,6 +68,9 @@ namespace libtorrent
{
free_buffer_fun free_fun;
void* userdata;
// TODO: 2 the pointers here should probably be const, since
// they're not supposed to be mutated once inserted into the send
// buffer
char* buf; // the first byte of the buffer
char* start; // the first byte to send/receive in the buffer
int size; // the total size of the buffer

View File

@ -173,6 +173,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/sha1_hash.hpp" // for sha1_hash
#include "libtorrent/error_code.hpp"
#include "libtorrent/session_handle.hpp"
#include "libtorrent/aux_/array_view.hpp"
namespace libtorrent
{
@ -502,9 +503,13 @@ namespace libtorrent
// 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 retrieved 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;
// The additional data is returned as the second tupled value. Any
// returned buffer as well as the iovec itself, to be prepended to the
// send buffer, must be owned by the crypto plugin and guaranteed to stay
// alive until the crypto_plugin is destructed or this function is called
// again.
virtual std::tuple<int, aux::array_view<boost::asio::const_buffer>>
encrypt(aux::array_view<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
@ -515,7 +520,7 @@ namespace libtorrent
//
// 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*/
virtual void decrypt(aux::array_view<boost::asio::mutable_buffer> /*receive_vec*/
, int& /* consume */, int& /*produce*/, int& /*packet_size*/) = 0;
};
}

View File

@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/sha1_hash.hpp"
#include "libtorrent/extensions.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/aux_/array_view.hpp"
#include <list>
#include <array>
@ -98,8 +99,11 @@ namespace libtorrent
struct encryption_handler
{
int encrypt(std::vector<boost::asio::mutable_buffer>& iovec);
int decrypt(crypto_receive_buffer& recv_buffer, std::size_t& bytes_transferred);
std::tuple<int, aux::array_view<boost::asio::const_buffer>>
encrypt(aux::array_view<boost::asio::mutable_buffer> iovec);
int decrypt(crypto_receive_buffer& recv_buffer
, std::size_t& bytes_transferred);
bool switch_send_crypto(boost::shared_ptr<crypto_plugin> crypto
, int pending_encryption);
@ -140,8 +144,10 @@ namespace libtorrent
void set_incoming_key(unsigned char const* key, int len) override;
void set_outgoing_key(unsigned char const* key, int len) override;
int encrypt(std::vector<boost::asio::mutable_buffer>& buf) override;
void decrypt(std::vector<boost::asio::mutable_buffer>& buf
std::tuple<int, aux::array_view<boost::asio::const_buffer>>
encrypt(aux::array_view<boost::asio::mutable_buffer> buf) override;
void decrypt(aux::array_view<boost::asio::mutable_buffer> buf
, int& consume
, int& produce
, int& packet_size) override;

View File

@ -61,19 +61,21 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/receive_buffer.hpp"
#include "libtorrent/aux_/allocating_handler.hpp"
#include "libtorrent/debug.hpp"
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include "libtorrent/aux_/array_view.hpp"
#include <ctime>
#include <algorithm>
#include <vector>
#include <string>
#include <utility> // for std::forward
#include <tuple> // for make_tuple
#include <array>
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/smart_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <array>
#include <boost/optional.hpp>
#include <cstdint>
@ -747,8 +749,10 @@ namespace libtorrent
void send_piece_suggestions(int num);
virtual int hit_send_barrier(std::vector<boost::asio::mutable_buffer>&)
{ return INT_MAX; }
virtual
std::tuple<int, aux::array_view<boost::asio::const_buffer>>
hit_send_barrier(aux::array_view<boost::asio::mutable_buffer> /* iovec */)
{ return std::make_tuple(INT_MAX, aux::array_view<boost::asio::const_buffer>()); }
void attach_to_torrent(sha1_hash const& ih);

View File

@ -36,7 +36,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/buffer.hpp>
#include <libtorrent/disk_buffer_holder.hpp>
#include <boost/asio/buffer.hpp>
#include <vector>
namespace libtorrent {
@ -110,7 +109,7 @@ struct TORRENT_EXTRA_EXPORT receive_buffer
buffer::interval mutable_buffer();
// returns the last 'bytes' from the receive buffer
boost::asio::mutable_buffer mutable_buffers(int bytes);
boost::asio::mutable_buffer mutable_buffer(int bytes);
#endif
// the purpose of this function is to free up and cut off all messages
@ -226,7 +225,7 @@ struct crypto_receive_buffer
buffer::const_interval get() const;
boost::asio::mutable_buffer mutable_buffers(std::size_t bytes);
boost::asio::mutable_buffer mutable_buffer(std::size_t bytes);
private:
// explicitly disallow assignment, to silence msvc warning

View File

@ -515,7 +515,7 @@ namespace libtorrent
return;
}
int pad_size = random() % 512;
int const pad_size = random() % 512;
#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION", "pad size: %d", pad_size);
@ -523,7 +523,7 @@ namespace libtorrent
char msg[dh_key_len + 512];
char* ptr = msg;
int buf_size = dh_key_len + pad_size;
int const buf_size = dh_key_len + pad_size;
mp::export_bits(m_dh_key_exchange->get_local_key()
, reinterpret_cast<std::uint8_t*>(ptr), 8);
@ -610,8 +610,7 @@ namespace libtorrent
#endif
write_pe_vc_cryptofield(ptr, encrypt_size, crypto_provide, pad_size);
std::vector<boost::asio::mutable_buffer> vec;
vec.push_back(boost::asio::mutable_buffer(ptr, encrypt_size));
boost::asio::mutable_buffer vec(ptr, encrypt_size);
m_rc4->encrypt(vec);
send_buffer(msg, sizeof(msg) - 512 + pad_size);
}
@ -626,14 +625,13 @@ namespace libtorrent
TORRENT_ASSERT(crypto_select == 0x02 || crypto_select == 0x01);
TORRENT_ASSERT(!m_sent_handshake);
int pad_size = random() % 512;
int const pad_size = random() % 512;
const int buf_size = 8 + 4 + 2 + pad_size;
int const buf_size = 8 + 4 + 2 + pad_size;
char msg[512 + 8 + 4 + 2];
write_pe_vc_cryptofield(msg, sizeof(msg), crypto_select, pad_size);
std::vector<boost::asio::mutable_buffer> vec;
vec.push_back(boost::asio::mutable_buffer(msg, buf_size));
boost::asio::mutable_buffer vec(msg, buf_size);
m_rc4->encrypt(vec);
send_buffer(msg, buf_size);
@ -649,8 +647,10 @@ namespace libtorrent
#endif
}
void bt_peer_connection::write_pe_vc_cryptofield(char* write_buf, int len
, int crypto_field, int pad_size)
void bt_peer_connection::write_pe_vc_cryptofield(char* write_buf
, int const len
, int const crypto_field
, int const pad_size)
{
INVARIANT_CHECK;
#if !TORRENT_USE_ASSERTS
@ -682,15 +682,15 @@ namespace libtorrent
detail::write_uint16(handshake_len, write_buf); // len(IA)
}
int bt_peer_connection::get_syncoffset(char const* src, int src_size,
char const* target, int target_size) const
int bt_peer_connection::get_syncoffset(char const* src, int const src_size
, char const* target, int const target_size) const
{
TORRENT_ASSERT(target_size >= src_size);
TORRENT_ASSERT(src_size > 0);
TORRENT_ASSERT(src);
TORRENT_ASSERT(target);
int traverse_limit = target_size - src_size;
int const traverse_limit = target_size - src_size;
// TODO: this could be optimized using knuth morris pratt
for (int i = 0; i < traverse_limit; ++i)
@ -700,40 +700,16 @@ namespace libtorrent
return i;
}
// Partial sync
// for (int i = 0; i < target_size; ++i)
// {
// // first is iterator in src[] at which mismatch occurs
// // second is iterator in target[] at which mismatch occurs
// std::pair<const char*, const char*> ret;
// int src_sync_size;
// if (i > traverse_limit) // partial sync test
// {
// ret = std::mismatch(src, src + src_size - (i - traverse_limit), &target[i]);
// src_sync_size = ret.first - src;
// if (src_sync_size == (src_size - (i - traverse_limit)))
// return i;
// }
// else // complete sync test
// {
// ret = std::mismatch(src, src + src_size, &target[i]);
// src_sync_size = ret.first - src;
// if (src_sync_size == src_size)
// return i;
// }
// }
// no complete sync
return -1;
}
void bt_peer_connection::rc4_decrypt(char* pos, int len)
void bt_peer_connection::rc4_decrypt(char* const pos, int const len)
{
std::vector<boost::asio::mutable_buffer> vec;
vec.push_back(boost::asio::mutable_buffer(pos, len));
int consume = 0;
int produce = len;
int packet_size = 0;
boost::asio::mutable_buffer vec(pos, len);
m_rc4->decrypt(vec, consume, produce, packet_size);
}
@ -2172,9 +2148,8 @@ namespace libtorrent
// add predictive pieces to the bitfield as well, since we won't
// announce them again
for (std::vector<int>::const_iterator i = t->predictive_pieces().begin()
, end(t->predictive_pieces().end()); i != end; ++i)
msg[5 + *i / 8] |= (0x80 >> (*i & 7));
for (int p : t->predictive_pieces())
msg[5 + p / 8] |= (0x80 >> (p & 7));
#ifndef TORRENT_DISABLE_LOGGING
std::string bitfield_string;
@ -2531,7 +2506,7 @@ namespace libtorrent
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
if (!m_enc_handler.is_recv_plaintext())
{
int consumed = m_enc_handler.decrypt(m_recv_buffer, bytes_transferred);
int const consumed = m_enc_handler.decrypt(m_recv_buffer, bytes_transferred);
#ifndef TORRENT_DISABLE_LOGGING
if (consumed + bytes_transferred > 0)
peer_log(peer_log_alert::incoming_message, "ENCRYPTION"
@ -2974,7 +2949,7 @@ namespace libtorrent
bytes_transferred = 0;
if (!m_recv_buffer.packet_finished()) return;
int pad_size = is_outgoing() ? m_recv_buffer.packet_size() : m_recv_buffer.packet_size() - 2;
int const pad_size = is_outgoing() ? m_recv_buffer.packet_size() : m_recv_buffer.packet_size() - 2;
buffer::interval wr_buf = m_recv_buffer.mutable_buffer();
rc4_decrypt(wr_buf.begin, m_recv_buffer.packet_size());
@ -3480,8 +3455,8 @@ namespace libtorrent
return;
}
#if TORRENT_USE_ASSERTS
std::int64_t cur_payload_dl = statistics().last_payload_downloaded();
std::int64_t cur_protocol_dl = statistics().last_protocol_downloaded();
std::int64_t const cur_payload_dl = statistics().last_payload_downloaded();
std::int64_t const cur_protocol_dl = statistics().last_protocol_downloaded();
#endif
if (dispatch_message(int(bytes_transferred)))
{
@ -3492,7 +3467,7 @@ namespace libtorrent
#if TORRENT_USE_ASSERTS
TORRENT_ASSERT(statistics().last_payload_downloaded() - cur_payload_dl >= 0);
TORRENT_ASSERT(statistics().last_protocol_downloaded() - cur_protocol_dl >= 0);
std::int64_t stats_diff = statistics().last_payload_downloaded() - cur_payload_dl +
std::int64_t const stats_diff = statistics().last_payload_downloaded() - cur_payload_dl +
statistics().last_protocol_downloaded() - cur_protocol_dl;
TORRENT_ASSERT(stats_diff == std::int64_t(bytes_transferred));
TORRENT_ASSERT(!m_recv_buffer.packet_finished());
@ -3504,15 +3479,19 @@ namespace libtorrent
}
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
int bt_peer_connection::hit_send_barrier(std::vector<boost::asio::mutable_buffer>& iovec)
std::tuple<int, aux::array_view<boost::asio::const_buffer>>
bt_peer_connection::hit_send_barrier(
aux::array_view<boost::asio::mutable_buffer> iovec)
{
int next_barrier = m_enc_handler.encrypt(iovec);
int next_barrier;
aux::array_view<boost::asio::const_buffer> out_iovec;
std::tie(next_barrier, out_iovec) = m_enc_handler.encrypt(iovec);
#ifndef TORRENT_DISABLE_LOGGING
if (next_barrier != 0)
peer_log(peer_log_alert::outgoing, "SEND_BARRIER"
, "encrypted block s = %d", next_barrier);
#endif
return next_barrier;
return std::make_tuple(next_barrier, out_iovec);
}
#endif
@ -3585,7 +3564,8 @@ namespace libtorrent
TORRENT_ASSERT( (bool(m_state != read_pe_dhkey) || m_dh_key_exchange.get())
|| !is_outgoing());
TORRENT_ASSERT(!m_rc4_encrypted || (!m_encrypted && m_rc4) || (m_encrypted && !m_enc_handler.is_send_plaintext()));
TORRENT_ASSERT(!m_rc4_encrypted || (!m_encrypted && m_rc4)
|| (m_encrypted && !m_enc_handler.is_send_plaintext()));
#endif
if (!in_handshake())
{

View File

@ -50,9 +50,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include <random>
#include "libtorrent/random.hpp"
#include "libtorrent/alloca.hpp"
#include "libtorrent/pe_crypto.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/aux_/array_view.hpp"
namespace libtorrent
{
@ -101,47 +103,55 @@ namespace libtorrent
m_xor_mask = h.final();
}
int encryption_handler::encrypt(std::vector<boost::asio::mutable_buffer>& iovec)
std::tuple<int, aux::array_view<boost::asio::const_buffer>>
encryption_handler::encrypt(
aux::array_view<boost::asio::mutable_buffer> iovec)
{
using namespace boost::asio;
TORRENT_ASSERT(!m_send_barriers.empty());
TORRENT_ASSERT(m_send_barriers.front().enc_handler);
int to_process = m_send_barriers.front().next;
boost::asio::mutable_buffer* bufs;
int num_bufs;
bool need_destruct = false;
if (to_process != INT_MAX)
{
for (std::vector<boost::asio::mutable_buffer>::iterator i = iovec.begin();
to_process >= 0; ++i)
bufs = TORRENT_ALLOCA(mutable_buffer, iovec.size());
need_destruct = true;
num_bufs = 0;
for (int i = 0; to_process > 0; ++i)
{
if (to_process == 0)
++num_bufs;
int const size = buffer_size(iovec[i]);
if (to_process < size)
{
iovec.erase(i, iovec.end());
break;
}
else if (to_process < boost::asio::buffer_size(*i))
{
*i = boost::asio::mutable_buffer(boost::asio::buffer_cast<void*>(*i), to_process);
iovec.erase(++i, iovec.end());
new (&bufs[i]) mutable_buffer(
buffer_cast<void*>(iovec[i]), to_process);
to_process = 0;
break;
}
to_process -= int(boost::asio::buffer_size(*i));
else
{
new (&bufs[i]) mutable_buffer(iovec[i]);
to_process -= size;
}
}
TORRENT_ASSERT(to_process == 0);
}
else
{
bufs = iovec.data();
num_bufs = iovec.size();
}
#if TORRENT_USE_ASSERTS
to_process = 0;
for (std::vector<boost::asio::mutable_buffer>::iterator i = iovec.begin();
i != iovec.end(); ++i)
to_process += int(boost::asio::buffer_size(*i));
#endif
int next_barrier = 0;
bool process_barrier = iovec.empty();
aux::array_view<const_buffer> out_iovec;
bool process_barrier = num_bufs == 0;
if (!process_barrier)
{
next_barrier = m_send_barriers.front().enc_handler->encrypt(iovec);
std::tie(next_barrier, out_iovec)
= m_send_barriers.front().enc_handler->encrypt({bufs, num_bufs});
process_barrier = (next_barrier != 0);
}
if (process_barrier)
@ -149,37 +159,43 @@ namespace libtorrent
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 TORRENT_USE_ASSERTS
if (next_barrier != INT_MAX)
{
int payload = 0;
for (int i = 0; i < num_bufs; ++i)
payload += int(buffer_size(bufs[i]));
int overhead = 0;
for (std::vector<boost::asio::mutable_buffer>::iterator i = iovec.begin();
i != iovec.end(); ++i)
overhead += int(boost::asio::buffer_size(*i));
TORRENT_ASSERT(overhead + to_process == next_barrier);
for (auto buf : out_iovec)
overhead += int(buffer_size(buf));
TORRENT_ASSERT(overhead + payload == next_barrier);
}
#endif
}
else
if (need_destruct)
{
iovec.clear();
for (int i = 0; i < num_bufs; ++i)
bufs[i].~mutable_buffer();
}
return next_barrier;
return std::make_tuple(next_barrier, out_iovec);
}
int encryption_handler::decrypt(crypto_receive_buffer& recv_buffer, std::size_t& bytes_transferred)
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<boost::asio::mutable_buffer> wr_buf;
wr_buf.push_back(recv_buffer.mutable_buffers(bytes_transferred));
boost::asio::mutable_buffer wr_buf = recv_buffer.mutable_buffer(bytes_transferred);
int packet_size = 0;
int produce = int(bytes_transferred);
m_dec_handler->decrypt(wr_buf, consume, produce, packet_size);
@ -249,11 +265,11 @@ namespace libtorrent
m_decrypt = true;
rc4_init(key, len, &m_rc4_incoming);
// 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;
char buf[1024];
boost::asio::mutable_buffer vec(buf, sizeof(buf));
decrypt(vec, consume, produce, packet_size);
}
@ -263,21 +279,23 @@ namespace libtorrent
rc4_init(key, len, &m_rc4_outgoing);
// Discard first 1024 bytes
char buf[1024];
std::vector<boost::asio::mutable_buffer> vec(1, boost::asio::mutable_buffer(buf, 1024));
boost::asio::mutable_buffer vec(buf, sizeof(buf));
encrypt(vec);
}
int rc4_handler::encrypt(std::vector<boost::asio::mutable_buffer>& buf)
std::tuple<int, aux::array_view<boost::asio::const_buffer>>
rc4_handler::encrypt(aux::array_view<boost::asio::mutable_buffer> bufs)
{
if (!m_encrypt) return 0;
if (buf.empty()) return 0;
using namespace boost::asio;
aux::array_view<boost::asio::const_buffer> empty;
if (!m_encrypt) return std::make_tuple(0, empty);
if (bufs.size() == 0) return std::make_tuple(0, empty);
int bytes_processed = 0;
for (std::vector<boost::asio::mutable_buffer>::iterator i = buf.begin();
i != buf.end(); ++i)
for (auto& buf : bufs)
{
unsigned char* pos = boost::asio::buffer_cast<unsigned char*>(*i);
int len = int(boost::asio::buffer_size(*i));
unsigned char* const pos = buffer_cast<unsigned char*>(buf);
int const len = int(buffer_size(buf));
TORRENT_ASSERT(len >= 0);
TORRENT_ASSERT(pos);
@ -285,11 +303,10 @@ namespace libtorrent
bytes_processed += len;
rc4_encrypt(pos, len, &m_rc4_outgoing);
}
buf.clear();
return bytes_processed;
return std::make_tuple(bytes_processed, empty);
}
void rc4_handler::decrypt(std::vector<boost::asio::mutable_buffer>& buf
void rc4_handler::decrypt(aux::array_view<boost::asio::mutable_buffer> bufs
, int& consume
, int& produce
, int& packet_size)
@ -301,11 +318,10 @@ namespace libtorrent
if (!m_decrypt) return;
int bytes_processed = 0;
for (std::vector<boost::asio::mutable_buffer>::iterator i = buf.begin();
i != buf.end(); ++i)
for (auto& buf : bufs)
{
unsigned char* pos = boost::asio::buffer_cast<unsigned char*>(*i);
int len = int(boost::asio::buffer_size(*i));
unsigned char* const pos = boost::asio::buffer_cast<unsigned char*>(buf);
int const len = int(boost::asio::buffer_size(buf));
TORRENT_ASSERT(len >= 0);
TORRENT_ASSERT(pos);
@ -313,7 +329,6 @@ namespace libtorrent
bytes_processed += len;
rc4_encrypt(pos, len, &m_rc4_incoming);
}
buf.clear();
produce = bytes_processed;
}

View File

@ -5510,15 +5510,18 @@ namespace libtorrent
{
std::vector<boost::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<boost::asio::mutable_buffer>::reverse_iterator i = vec.rbegin();
i != vec.rend(); ++i)
int next_barrier;
aux::array_view<boost::asio::const_buffer> inject_vec;
std::tie(next_barrier, inject_vec) = hit_send_barrier(vec);
for (auto i = inject_vec.rbegin(); i != inject_vec.rend(); ++i)
{
m_send_buffer.prepend_buffer(boost::asio::buffer_cast<char*>(*i)
, int(boost::asio::buffer_size(*i))
, int(boost::asio::buffer_size(*i))
, &nop
, NULL);
int const size = boost::asio::buffer_size(*i);
// this const_cast is a here because chained_buffer need to be
// fixed.
char* ptr = const_cast<char*>(
boost::asio::buffer_cast<char const*>(*i));
m_send_buffer.prepend_buffer(ptr
, size, size, &nop, nullptr);
}
set_send_barrier(next_barrier);
}
@ -5530,7 +5533,7 @@ namespace libtorrent
return;
}
int quota_left = m_quota[upload_channel];
int const quota_left = m_quota[upload_channel];
if (m_send_buffer.empty()
&& m_reading_bytes > 0

View File

@ -151,7 +151,7 @@ buffer::interval receive_buffer::mutable_buffer()
, &m_recv_buffer[0] + m_recv_start + rcv_pos);
}
boost::asio::mutable_buffer receive_buffer::mutable_buffers(int const bytes)
boost::asio::mutable_buffer receive_buffer::mutable_buffer(int const bytes)
{
namespace asio = boost::asio;
@ -305,13 +305,13 @@ buffer::const_interval crypto_receive_buffer::get() const
return recv_buffer;
}
boost::asio::mutable_buffer crypto_receive_buffer::mutable_buffers(
boost::asio::mutable_buffer crypto_receive_buffer::mutable_buffer(
std::size_t const bytes)
{
int const pending_decryption = (m_recv_pos != INT_MAX)
? m_connection_buffer.packet_size() - m_recv_pos
: int(bytes);
return m_connection_buffer.mutable_buffers(pending_decryption);
return m_connection_buffer.mutable_buffer(pending_decryption);
}
#endif // TORRENT_DISABLE_ENCRYPTION

View File

@ -37,15 +37,18 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/pe_crypto.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/random.hpp"
#include "libtorrent/aux_/array_view.hpp"
#include "setup_transfer.hpp"
#include "test.hpp"
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
void test_enc_handler(libtorrent::crypto_plugin* a, libtorrent::crypto_plugin* b)
namespace lt = libtorrent;
void test_enc_handler(libtorrent::crypto_plugin& a, libtorrent::crypto_plugin& b)
{
const int repcount = 128;
int const repcount = 128;
for (int rep = 0; rep < repcount; ++rep)
{
int const buf_len = rand() % (512 * 1024);
@ -56,36 +59,48 @@ void test_enc_handler(libtorrent::crypto_plugin* a, libtorrent::crypto_plugin* b
std::copy(buf.begin(), buf.end(), cmp_buf.begin());
using namespace boost::asio;
std::vector<mutable_buffer> iovec;
iovec.push_back(mutable_buffer(&buf[0], buf_len));
a->encrypt(iovec);
TEST_CHECK(!std::equal(buf.begin(), buf.end(), cmp_buf.begin()));
TEST_CHECK(iovec.empty());
int consume = 0;
int produce = buf_len;
int packet_size = 0;
iovec.push_back(mutable_buffer(&buf[0], buf_len));
b->decrypt(iovec, consume, produce, packet_size);
TEST_CHECK(std::equal(buf.begin(), buf.end(), cmp_buf.begin()));
TEST_CHECK(iovec.empty());
TEST_EQUAL(consume, 0);
TEST_EQUAL(produce, buf_len);
TEST_EQUAL(packet_size, 0);
iovec.push_back(mutable_buffer(&buf[0], buf_len));
b->encrypt(iovec);
TEST_CHECK(!std::equal(buf.begin(), buf.end(), cmp_buf.begin()));
TEST_CHECK(iovec.empty());
consume = 0;
produce = buf_len;
packet_size = 0;
iovec.push_back(mutable_buffer(&buf[0], buf_len));
a->decrypt(iovec, consume, produce, packet_size);
TEST_CHECK(std::equal(buf.begin(), buf.end(), cmp_buf.begin()));
TEST_CHECK(iovec.empty());
TEST_EQUAL(consume, 0);
TEST_EQUAL(produce, buf_len);
TEST_EQUAL(packet_size, 0);
{
mutable_buffer iovec(&buf[0], buf_len);
int next_barrier;
lt::aux::array_view<const_buffer> iovec_out;
std::tie(next_barrier, iovec_out) = a.encrypt(iovec);
TEST_CHECK(buf != cmp_buf);
TEST_EQUAL(iovec_out.size(), 0);
TEST_EQUAL(next_barrier, buf_len);
}
{
int consume = 0;
int produce = buf_len;
int packet_size = 0;
mutable_buffer iovec(&buf[0], buf_len);
b.decrypt(iovec, consume, produce, packet_size);
TEST_CHECK(buf == cmp_buf);
TEST_EQUAL(consume, 0);
TEST_EQUAL(produce, buf_len);
TEST_EQUAL(packet_size, 0);
}
{
mutable_buffer iovec(&buf[0], buf_len);
int next_barrier;
lt::aux::array_view<const_buffer> iovec_out;
std::tie(next_barrier, iovec_out) = b.encrypt(iovec);
TEST_EQUAL(iovec_out.size(), 0);
TEST_CHECK(buf != cmp_buf);
TEST_EQUAL(next_barrier, buf_len);
int consume = 0;
int produce = buf_len;
int packet_size = 0;
mutable_buffer iovec2(&buf[0], buf_len);
a.decrypt(iovec2, consume, produce, packet_size);
TEST_CHECK(buf == cmp_buf);
TEST_EQUAL(consume, 0);
TEST_EQUAL(produce, buf_len);
TEST_EQUAL(packet_size, 0);
}
}
}
@ -134,7 +149,7 @@ TORRENT_TEST(rc4)
rc4_handler rc42;
rc42.set_incoming_key(&test1_key[0], 20);
rc42.set_outgoing_key(&test2_key[0], 20);
test_enc_handler(&rc41, &rc42);
test_enc_handler(rc41, rc42);
}
#else

View File

@ -107,7 +107,7 @@ TORRENT_TEST(recv_buffer_mutable_buffers)
b.cut(100, 1000); // packet size = 1000
packet_transferred = b.advance_pos(999);
TEST_EQUAL(packet_transferred, 999);
boost::asio::mutable_buffer vec = b.mutable_buffers(999);
boost::asio::mutable_buffer vec = b.mutable_buffer(999);
// previous packet
// |