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:
parent
b2358666a1
commit
a9dbbdea37
|
@ -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]; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
// |
|
||||
|
|
Loading…
Reference in New Issue