diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index 6281d5873..271e02c98 100644 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -2404,8 +2404,10 @@ namespace libtorrent private: std::reference_wrapper m_alloc; - int const m_num_peers; - aux::allocation_slot m_peers_idx; + int m_v4_num_peers = 0; + int m_v6_num_peers = 0; + aux::allocation_slot m_v4_peers_idx; + aux::allocation_slot m_v6_peers_idx; }; // This is posted exactly once for every call to session_handle::dht_direct_request. diff --git a/include/libtorrent/stack_allocator.hpp b/include/libtorrent/stack_allocator.hpp index 7771ca45b..2f3698137 100644 --- a/include/libtorrent/stack_allocator.hpp +++ b/include/libtorrent/stack_allocator.hpp @@ -125,7 +125,7 @@ namespace libtorrent { namespace aux allocation_slot allocate(int const bytes) { if (bytes < 1) return allocation_slot(); - int const ret = int(m_storage.size()); + int const ret = m_storage.end_index(); m_storage.resize(ret + bytes); return allocation_slot(ret); } diff --git a/src/alert.cpp b/src/alert.cpp index 07e8fdc84..011bc9816 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -1922,37 +1922,46 @@ namespace libtorrent , std::vector const& peers) : info_hash(ih) , m_alloc(alloc) - , m_num_peers(int(peers.size())) { - std::size_t total_size = peers.size(); // num bytes for sizes for (auto const& endp : peers) { - total_size += endp.size(); + if (endp.protocol() == tcp::v4()) + m_v4_num_peers++; +#if TORRENT_USE_IPV6 + else + m_v6_num_peers++; +#endif } - m_peers_idx = alloc.allocate(int(total_size)); + m_v4_peers_idx = alloc.allocate(m_v4_num_peers * 6); + m_v6_peers_idx = alloc.allocate(m_v6_num_peers * 18); - char *ptr = alloc.ptr(m_peers_idx); + char* v4_ptr = alloc.ptr(m_v4_peers_idx); +#if TORRENT_USE_IPV6 + char* v6_ptr = alloc.ptr(m_v6_peers_idx); +#endif for (auto const& endp : peers) { - std::size_t const size = endp.size(); - TORRENT_ASSERT(size < 0x100); - detail::write_uint8(size, ptr); - std::memcpy(ptr, endp.data(), size); - ptr += size; + if (endp.protocol() == tcp::v4()) + detail::write_endpoint(endp, v4_ptr); +#if TORRENT_USE_IPV6 + else + detail::write_endpoint(endp, v6_ptr); +#endif } } std::string dht_get_peers_reply_alert::message() const { char msg[200]; - std::snprintf(msg, sizeof(msg), "incoming dht get_peers reply: %s, peers %d", aux::to_hex(info_hash).c_str(), m_num_peers); + std::snprintf(msg, sizeof(msg), "incoming dht get_peers reply: %s, peers %d" + , aux::to_hex(info_hash).c_str(), num_peers()); return msg; } int dht_get_peers_reply_alert::num_peers() const { - return m_num_peers; + return m_v4_num_peers + m_v6_num_peers; } #ifndef TORRENT_NO_DEPRECATE @@ -1965,16 +1974,17 @@ namespace libtorrent #endif std::vector dht_get_peers_reply_alert::peers() const { - std::size_t const num_peers = aux::numeric_cast(m_num_peers); - std::vector peers(num_peers); + aux::vector peers; + peers.reserve(num_peers()); - const char *ptr = m_alloc.get().ptr(m_peers_idx); - for (std::size_t i = 0; i < num_peers; i++) - { - std::size_t const size = detail::read_uint8(ptr); - std::memcpy(peers[i].data(), ptr, size); - ptr += size; - } + char const* v4_ptr = m_alloc.get().ptr(m_v4_peers_idx); + for (int i = 0; i < m_v4_num_peers; i++) + peers.push_back(detail::read_v4_endpoint(v4_ptr)); +#if TORRENT_USE_IPV6 + char const* v6_ptr = m_alloc.get().ptr(m_v6_peers_idx); + for (int i = 0; i < m_v6_num_peers; i++) + peers.push_back(detail::read_v6_endpoint(v6_ptr)); +#endif return peers; } diff --git a/test/Jamfile b/test/Jamfile index c2036906f..1238793d1 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -169,6 +169,7 @@ test-suite libtorrent : [ run test_gzip.cpp ] [ run test_receive_buffer.cpp ] [ run test_alert_manager.cpp ] + [ run test_alert_types.cpp ] [ run test_magnet.cpp ] [ run test_storage.cpp ] [ run test_session.cpp ] diff --git a/test/Makefile.am b/test/Makefile.am index b46fd80b9..76e6afa34 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -152,6 +152,7 @@ test_primitives_SOURCES = \ test_identify_client.cpp \ test_merkle.cpp \ test_alert_manager.cpp \ + test_alert_types.cpp \ test_resolve_links.cpp \ test_crc32.cpp \ test_heterogeneous_queue.cpp \ diff --git a/test/setup_transfer.cpp b/test/setup_transfer.cpp index 8ba62c125..4d10af51f 100644 --- a/test/setup_transfer.cpp +++ b/test/setup_transfer.cpp @@ -121,11 +121,11 @@ address rand_v6() static std::uint16_t g_port = 0; -tcp::endpoint rand_tcp_ep() +tcp::endpoint rand_tcp_ep(libtorrent::address(&rand_addr)()) { - // make sure we don't procude the same "random" port twice + // make sure we don't produce the same "random" port twice g_port = (g_port + 1) % 14038; - return tcp::endpoint(rand_v4(), g_port + 1024); + return tcp::endpoint(rand_addr(), g_port + 1024); } udp::endpoint rand_udp_ep(libtorrent::address(&rand_addr)()) diff --git a/test/setup_transfer.hpp b/test/setup_transfer.hpp index d05ebae57..cbeec7fe9 100644 --- a/test/setup_transfer.hpp +++ b/test/setup_transfer.hpp @@ -58,7 +58,7 @@ EXPORT libtorrent::address rand_v4(); #if TORRENT_USE_IPV6 EXPORT libtorrent::address rand_v6(); #endif -EXPORT libtorrent::tcp::endpoint rand_tcp_ep(); +EXPORT libtorrent::tcp::endpoint rand_tcp_ep(libtorrent::address(&rand_addr)() = rand_v4); EXPORT libtorrent::udp::endpoint rand_udp_ep(libtorrent::address(&rand_addr)() = rand_v4); EXPORT libtorrent::sha1_hash rand_hash(); diff --git a/test/test_alert_types.cpp b/test/test_alert_types.cpp new file mode 100644 index 000000000..74cf77fb7 --- /dev/null +++ b/test/test_alert_types.cpp @@ -0,0 +1,73 @@ +/* + +Copyright (c) 2017, Arvid Norberg, Alden Torres +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/alert_manager.hpp" +#include "libtorrent/alert_types.hpp" +#include "test.hpp" +#include "setup_transfer.hpp" + +#include + +using namespace libtorrent; + +TORRENT_TEST(dht_get_peers_reply_alert) +{ + alert_manager mgr(1, dht_get_peers_reply_alert::static_category); + + TEST_EQUAL(mgr.should_post(), true); + + sha1_hash const ih = rand_hash(); + tcp::endpoint const ep1 = rand_tcp_ep(rand_v4); + tcp::endpoint const ep2 = rand_tcp_ep(rand_v4); + tcp::endpoint const ep3 = rand_tcp_ep(rand_v4); +#if TORRENT_USE_IPV6 + tcp::endpoint const ep4 = rand_tcp_ep(rand_v6); + tcp::endpoint const ep5 = rand_tcp_ep(rand_v6); +#else + tcp::endpoint const ep4 = rand_tcp_ep(rand_v4); + tcp::endpoint const ep5 = rand_tcp_ep(rand_v4); +#endif + std::vector v = {ep1, ep2, ep3, ep4, ep5}; + + mgr.emplace_alert(ih, v); + + auto const* a = alert_cast(mgr.wait_for_alert(seconds(0))); + TEST_CHECK(a != nullptr); + + TEST_EQUAL(a->info_hash, ih); + TEST_EQUAL(a->num_peers(), 5); + + std::vector peers = a->peers(); + std::sort(v.begin(), v.end()); + std::sort(peers.begin(), peers.end()); + TEST_CHECK(v == peers); +} diff --git a/tools/test_coverage.sh b/tools/test_coverage.sh index fa862cb42..5b10dd61b 100755 --- a/tools/test_coverage.sh +++ b/tools/test_coverage.sh @@ -46,6 +46,7 @@ run_test test_packet_buffer "*/packet_buffer.*" run_test test_ip_voter "*/ip_voter.*" run_test test_bitfield "*/bitfield.*" run_test test_alert_manager "*/alert_manager.*" +run_test test_alert_types "*/alert_types.*" run_test test_dht "*/kademlia/*" run_test test_bdecode "*/bdecode.*" run_test test_piece_picker "*/piece_picker.*"