diff --git a/ChangeLog b/ChangeLog index 973fa4f1b..ae963a191 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * added alert for block being sent to the send buffer * drop support for windows compilers without std::wstring * implemented support for DHT infohash indexing, BEP51 * removed deprecated support for file_base in file_storage diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index 6e78e788a..0c2a24ce2 100644 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -2663,11 +2663,31 @@ namespace libtorrent { aux::allocation_slot m_v6_nodes_idx; }; + // This alert is posted when a block intended to be sent to a peer is placed in the + // send buffer. Note that if the connection is closed before the send buffer is sent, + // the alert may be posted without the bytes having been sent to the peer. + // It belongs to the ``progress_notification`` category. + struct TORRENT_EXPORT block_uploaded_alert final : peer_alert + { + // internal + block_uploaded_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id, int block_num + , piece_index_t piece_num); + + TORRENT_DEFINE_ALERT(block_uploaded_alert, 94) + + static const int static_category = alert::progress_notification; + virtual std::string message() const override; + + int const block_index; + piece_index_t const piece_index; + }; + #undef TORRENT_DEFINE_ALERT_IMPL #undef TORRENT_DEFINE_ALERT #undef TORRENT_DEFINE_ALERT_PRIO - enum { num_alert_types = 94 }; // this enum represents "max_alert_index" + 1 + enum { num_alert_types = 95 }; // this enum represents "max_alert_index" + 1 } #endif diff --git a/simulation/test_swarm.cpp b/simulation/test_swarm.cpp index 559e94239..0f78afb4a 100644 --- a/simulation/test_swarm.cpp +++ b/simulation/test_swarm.cpp @@ -537,6 +537,51 @@ TORRENT_TEST(torrent_completed_alert) TEST_EQUAL(num_file_completed, 1); } +TORRENT_TEST(block_uploaded_alert) +{ + // blocks[piece count][number of blocks per piece] (each block's element will + // be set to true when a block_uploaded_alert alert is received for that block) + std::vector> blocks; + + setup_swarm(2, swarm_test::upload + // add session + , [](lt::settings_pack& pack) + { + pack.set_int(lt::settings_pack::alert_mask, + alert::progress_notification | alert::status_notification); + } + // add torrent + , [](lt::add_torrent_params&) {} + // on alert + , [&](lt::alert const* a, lt::session&) { + if (auto at = lt::alert_cast(a)) + { + // init blocks vector, MUST happen before any block_uploaded_alert alerts + int blocks_per_piece = at->handle.torrent_file()->piece_length() / 0x4000; + blocks.resize(at->handle.torrent_file()->num_pieces(), std::vector(blocks_per_piece, false)); + } + else if (auto at = lt::alert_cast(a)) + { + TEST_EQUAL(blocks[at->piece_index][at->block_index], false); + blocks[at->piece_index][at->block_index] = true; + } + } + // terminate + , [](int, lt::session&) -> bool + { return false; }); + + // ensure a block_uploaded_alert was received for each block in the torrent + TEST_CHECK(std::all_of(blocks.begin(), blocks.end(), + [](std::vector const& piece_row) { + return std::all_of(piece_row.begin(), piece_row.end(), + [](bool upload_alert_received) { + return upload_alert_received; + } + ); + } + )); +} + // template for testing running swarms with edge case settings template void test_settings(SettingsFun fun) diff --git a/src/alert.cpp b/src/alert.cpp index d672b0c35..052bbd210 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -2414,4 +2414,22 @@ namespace { , m_v6_num_nodes, m_v6_nodes_idx); } + block_uploaded_alert::block_uploaded_alert(aux::stack_allocator& alloc, torrent_handle h + , tcp::endpoint const& ep, peer_id const& peer_id, int block_num + , piece_index_t piece_num) + : peer_alert(alloc, h, ep, peer_id) + , block_index(block_num) + , piece_index(piece_num) + { + TORRENT_ASSERT(block_index >= 0 && piece_index >= piece_index_t{0}); + } + + std::string block_uploaded_alert::message() const + { + char ret[200]; + snprintf(ret, sizeof(ret), "%s block uploaded to a peer (piece: %u block: %u)" + , torrent_alert::message().c_str(), static_cast(piece_index), block_index); + return ret; + } + } // namespace libtorrent diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index b287445ee..ab8f695fd 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -67,6 +67,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/alloca.hpp" #include "libtorrent/socket_type.hpp" #include "libtorrent/performance_counters.hpp" // for counters +#include "libtorrent/alert_manager.hpp" // for alert_manager #if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS) #include "libtorrent/pe_crypto.hpp" @@ -2395,6 +2396,12 @@ namespace { setup_send(); stats_counters().inc_stats_counter(counters::num_outgoing_piece); + + if (t->alerts().should_post()) + { + t->alerts().emplace_alert(t->get_handle(), + remote(), pid(), r.start / t->block_size() , r.piece); + } } // -------------------------- diff --git a/test/test_alert_types.cpp b/test/test_alert_types.cpp index 8af5de1b6..00b055685 100644 --- a/test/test_alert_types.cpp +++ b/test/test_alert_types.cpp @@ -161,10 +161,11 @@ TORRENT_TEST(alerts_types) TEST_ALERT_TYPE(dht_live_nodes_alert, 91, 0, alert::dht_notification); TEST_ALERT_TYPE(session_stats_header_alert, 92, 0, alert::stats_notification); TEST_ALERT_TYPE(dht_sample_infohashes_alert, 93, 0, alert::dht_operation_notification); + TEST_ALERT_TYPE(block_uploaded_alert, 94, 0, alert::progress_notification); #undef TEST_ALERT_TYPE - TEST_EQUAL(num_alert_types, 94); + TEST_EQUAL(num_alert_types, 95); TEST_EQUAL(num_alert_types, count_alert_types); }