diff --git a/include/libtorrent/aux_/array_view.hpp b/include/libtorrent/aux_/array_view.hpp index 66c1cfcda..08ec5beb0 100644 --- a/include/libtorrent/aux_/array_view.hpp +++ b/include/libtorrent/aux_/array_view.hpp @@ -46,11 +46,12 @@ namespace libtorrent { namespace aux { // T -> const T conversion constructor template ::value> + = std::enable_if::value> > array_view(array_view 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* 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]; } diff --git a/include/libtorrent/bt_peer_connection.hpp b/include/libtorrent/bt_peer_connection.hpp index fa2ab936d..a5ca17b21 100644 --- a/include/libtorrent/bt_peer_connection.hpp +++ b/include/libtorrent/bt_peer_connection.hpp @@ -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& iovec) override; + // next_barrier, buffers-to-prepend + virtual + std::tuple> + hit_send_barrier(aux::array_view iovec) override; #endif virtual void get_specific_peer_info(peer_info& p) const override; diff --git a/include/libtorrent/chained_buffer.hpp b/include/libtorrent/chained_buffer.hpp index d68cf0de3..421aa0491 100644 --- a/include/libtorrent/chained_buffer.hpp +++ b/include/libtorrent/chained_buffer.hpp @@ -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 diff --git a/include/libtorrent/extensions.hpp b/include/libtorrent/extensions.hpp index 8e4029294..efa1ce3cd 100644 --- a/include/libtorrent/extensions.hpp +++ b/include/libtorrent/extensions.hpp @@ -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& /*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> + encrypt(aux::array_view /*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& /*receive_vec*/ + virtual void decrypt(aux::array_view /*receive_vec*/ , int& /* consume */, int& /*produce*/, int& /*packet_size*/) = 0; }; } diff --git a/include/libtorrent/pe_crypto.hpp b/include/libtorrent/pe_crypto.hpp index 463375b6c..021a9cdbd 100644 --- a/include/libtorrent/pe_crypto.hpp +++ b/include/libtorrent/pe_crypto.hpp @@ -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 #include @@ -98,8 +99,11 @@ namespace libtorrent struct encryption_handler { - int encrypt(std::vector& iovec); - int decrypt(crypto_receive_buffer& recv_buffer, std::size_t& bytes_transferred); + std::tuple> + encrypt(aux::array_view iovec); + + int decrypt(crypto_receive_buffer& recv_buffer + , std::size_t& bytes_transferred); bool switch_send_crypto(boost::shared_ptr 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& buf) override; - void decrypt(std::vector& buf + std::tuple> + encrypt(aux::array_view buf) override; + + void decrypt(aux::array_view buf , int& consume , int& produce , int& packet_size) override; diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index ffdd43272..33498ce5b 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -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 #include #include #include #include // for std::forward +#include // for make_tuple +#include + +#include "libtorrent/aux_/disable_warnings_push.hpp" #include #include #include -#include #include #include @@ -747,8 +749,10 @@ namespace libtorrent void send_piece_suggestions(int num); - virtual int hit_send_barrier(std::vector&) - { return INT_MAX; } + virtual + std::tuple> + hit_send_barrier(aux::array_view /* iovec */) + { return std::make_tuple(INT_MAX, aux::array_view()); } void attach_to_torrent(sha1_hash const& ih); diff --git a/include/libtorrent/receive_buffer.hpp b/include/libtorrent/receive_buffer.hpp index 2805d5426..a186171b3 100644 --- a/include/libtorrent/receive_buffer.hpp +++ b/include/libtorrent/receive_buffer.hpp @@ -36,7 +36,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include 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 diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index 7ec08ba0a..586024924 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -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(ptr), 8); @@ -610,8 +610,7 @@ namespace libtorrent #endif write_pe_vc_cryptofield(ptr, encrypt_size, crypto_provide, pad_size); - std::vector 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 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 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 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::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& iovec) + std::tuple> + bt_peer_connection::hit_send_barrier( + aux::array_view iovec) { - int next_barrier = m_enc_handler.encrypt(iovec); + int next_barrier; + aux::array_view 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()) { diff --git a/src/pe_crypto.cpp b/src/pe_crypto.cpp index 72bc3f41a..4f03571d8 100644 --- a/src/pe_crypto.cpp +++ b/src/pe_crypto.cpp @@ -50,9 +50,11 @@ POSSIBILITY OF SUCH DAMAGE. #include #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& iovec) + std::tuple> + encryption_handler::encrypt( + aux::array_view 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::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(*i), to_process); - iovec.erase(++i, iovec.end()); + new (&bufs[i]) mutable_buffer( + buffer_cast(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::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 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::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 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 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 vec(1, boost::asio::mutable_buffer(buf, 1024)); + boost::asio::mutable_buffer vec(buf, sizeof(buf)); encrypt(vec); } - int rc4_handler::encrypt(std::vector& buf) + std::tuple> + rc4_handler::encrypt(aux::array_view bufs) { - if (!m_encrypt) return 0; - if (buf.empty()) return 0; + using namespace boost::asio; + aux::array_view 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::iterator i = buf.begin(); - i != buf.end(); ++i) + for (auto& buf : bufs) { - unsigned char* pos = boost::asio::buffer_cast(*i); - int len = int(boost::asio::buffer_size(*i)); + unsigned char* const pos = buffer_cast(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& buf + void rc4_handler::decrypt(aux::array_view 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::iterator i = buf.begin(); - i != buf.end(); ++i) + for (auto& buf : bufs) { - unsigned char* pos = boost::asio::buffer_cast(*i); - int len = int(boost::asio::buffer_size(*i)); + unsigned char* const pos = boost::asio::buffer_cast(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; } diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index ac16f75cd..f192d0f30 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -5510,15 +5510,18 @@ namespace libtorrent { std::vector vec; m_send_buffer.build_mutable_iovec(m_send_buffer.size(), vec); - int next_barrier = hit_send_barrier(vec); - for (std::vector::reverse_iterator i = vec.rbegin(); - i != vec.rend(); ++i) + int next_barrier; + aux::array_view 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(*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( + boost::asio::buffer_cast(*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 diff --git a/src/receive_buffer.cpp b/src/receive_buffer.cpp index ef9eba15b..3ff1cb8ad 100644 --- a/src/receive_buffer.cpp +++ b/src/receive_buffer.cpp @@ -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 diff --git a/test/test_pe_crypto.cpp b/test/test_pe_crypto.cpp index 620ca217d..628399ca1 100644 --- a/test/test_pe_crypto.cpp +++ b/test/test_pe_crypto.cpp @@ -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 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 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 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 diff --git a/test/test_receive_buffer.cpp b/test/test_receive_buffer.cpp index 44268ed1c..5ec624122 100644 --- a/test/test_receive_buffer.cpp +++ b/test/test_receive_buffer.cpp @@ -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 // |