diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index 3828c3df1..197d6be2b 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -221,6 +221,9 @@ namespace libtorrent void bt_peer_connection::on_metadata() { +#ifdef TORRENT_VERBOSE_LOGGING + peer_log("*** ON_METADATA"); +#endif // connections that are still in the handshake // will send their bitfield when the handshake // is done @@ -758,13 +761,13 @@ namespace libtorrent // in anonymous mode, every peer connection // has a unique peer-id for (int i = 0; i < 20; ++i) - *ptr++ = random(); + ptr[i] = random(); } else { memcpy(ptr, &m_ses.get_peer_id()[0], 20); -// ptr += 20; } +// ptr += 20; #ifdef TORRENT_VERBOSE_LOGGING peer_log("==> HANDSHAKE [ ih: %s ]", to_hex(ih.to_string()).c_str()); @@ -2020,7 +2023,7 @@ namespace libtorrent if (t->is_seed()) { - memset(ptr, 0xff, packet_size - 6); + memset(ptr, 0xff, packet_size - 5); // Clear trailing bits unsigned char *p = ((unsigned char *)msg) + packet_size - 1; diff --git a/src/metadata_transfer.cpp b/src/metadata_transfer.cpp index 6520286fd..674c298b1 100644 --- a/src/metadata_transfer.cpp +++ b/src/metadata_transfer.cpp @@ -289,8 +289,8 @@ namespace libtorrent { namespace if (m_message_index == 0) return; #ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " ==> METADATA_REQUEST [ start: " << start << " | size: " << size << " ]\n"; + m_pc.peer_log("==> METADATA_REQUEST [ start: %d | size: %d ]\n" + , start, size); #endif char msg[9]; @@ -327,12 +327,8 @@ namespace libtorrent { namespace char* ptr = msg; #ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " ==> METADATA [ start: " << req.first - << " | size: " << req.second - << " | offset: " << offset.first - << " | byte_size: " << offset.second - << " ]\n"; + m_pc.peer_log("==> METADATA [ start: %d | total_size: %d | offset: %d | data_size: %d ]" + , req.first, req.second, offset.first, offset.second); #endif // yes, we have metadata, send it detail::write_uint32(11 + offset.second, ptr); @@ -349,8 +345,7 @@ namespace libtorrent { namespace else { #ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " ==> DONT HAVE METADATA\n"; + m_pc.peer_log("==> DONT HAVE METADATA\n"); #endif char msg[4+3]; char* ptr = msg; @@ -391,10 +386,8 @@ namespace libtorrent { namespace int size = detail::read_uint8(body.begin) + 1; #ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " <== METADATA_REQUEST [ start: " << start - << " | size: " << size - << " ]\n"; + m_pc.peer_log("<== METADATA_REQUEST [ start: %d | size: %d ]\n" + , start, size); #endif if (length != 3) @@ -416,11 +409,8 @@ namespace libtorrent { namespace int data_size = length - 9; #ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " <== METADATA [ total_size: " << total_size - << " | offset: " << offset - << " | data_size: " << data_size - << " ]\n"; + m_pc.peer_log("<== METADATA [ total_size: %d | offset: %d | data_size: %d ]" + ,total_size, offset, data_size); #endif if (total_size > m_torrent.session().settings().max_metadata_size) @@ -462,8 +452,7 @@ namespace libtorrent { namespace m_tp.cancel_metadata_request(m_last_metadata_request); m_waiting_metadata_request = false; #ifdef TORRENT_VERBOSE_LOGGING - (*m_pc.m_logger) << time_now_string() - << " <== DONT HAVE METADATA\n"; + m_pc.peer_log("<== DONT HAVE METADATA\n"); #endif break; default: diff --git a/src/torrent.cpp b/src/torrent.cpp index 0ab37b0f3..975aa7552 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -6527,24 +6527,35 @@ namespace libtorrent } #endif - if (!m_connections_initialized) + m_connections_initialized = true; + m_files_checked = true; + + for (torrent::peer_iterator i = m_connections.begin(); + i != m_connections.end();) { - m_connections_initialized = true; + peer_connection* pc = *i; + ++i; + // all peer connections have to initialize themselves now that the metadata // is available - for (torrent::peer_iterator i = m_connections.begin(); - i != m_connections.end();) + if (!m_connections_initialized) { - peer_connection* pc = *i; - ++i; if (pc->is_disconnecting()) continue; pc->on_metadata_impl(); if (pc->is_disconnecting()) continue; pc->init(); } + +#ifdef TORRENT_VERBOSE_LOGGING + pc->peer_log("*** ON_FILES_CHECKED"); +#endif + if (pc->is_interesting() && !pc->has_peer_choked()) + { + request_a_block(*this, *pc); + pc->send_block_requests(); + } } - m_files_checked = true; start_announcing(); diff --git a/src/ut_metadata.cpp b/src/ut_metadata.cpp index 25c321def..0994b57cf 100644 --- a/src/ut_metadata.cpp +++ b/src/ut_metadata.cpp @@ -238,7 +238,10 @@ namespace libtorrent { namespace TORRENT_ASSERT(!m_pc.associated_torrent().expired()); #ifdef TORRENT_VERBOSE_LOGGING - m_pc.peer_log("==> UT_METADATA [ type: %d | piece: %d ]", type, piece); + char const* names[] = {"request", "data", "dont-have"}; + char const* n = ""; + if (type >= 0 && type < 3) n = names[type]; + m_pc.peer_log("==> UT_METADATA [ type: %d (%s) | piece: %d ]", type, n, piece); #endif // abort if the peer doesn't support the metadata extension diff --git a/test/test_metadata_extension.cpp b/test/test_metadata_extension.cpp index 6b1904dad..362d84d18 100644 --- a/test/test_metadata_extension.cpp +++ b/test/test_metadata_extension.cpp @@ -43,17 +43,33 @@ POSSIBILITY OF SUCH DAMAGE. using boost::tuples::ignore; -void test_transfer(bool clear_files, bool disconnect - , boost::shared_ptr (*constructor)(libtorrent::torrent*, void*)) +enum flags_t +{ + clear_files = 1, + disconnect = 2, + full_encryption = 4 +}; + +void test_transfer(int flags + , boost::shared_ptr (*constructor)(libtorrent::torrent*, void*) + , int timeout) { using namespace libtorrent; + fprintf(stderr, "test transfer: timeout=%d %s%s%s\n" + , timeout + , (flags & clear_files) ? "clear-files " : "" + , (flags & disconnect) ? "disconnect " : "" + , (flags & full_encryption) ? "encryption " : ""); + // these are declared before the session objects // so that they are destructed last. This enables // the sessions to destruct in parallel session_proxy p1; session_proxy p2; + // TODO: it would be nice to test reversing + // which session is making the connection as well session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48100, 49000), "0.0.0.0", 0); session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49100, 50000), "0.0.0.0", 0); ses1.add_extension(constructor); @@ -62,41 +78,45 @@ void test_transfer(bool clear_files, bool disconnect torrent_handle tor2; #ifndef TORRENT_DISABLE_ENCRYPTION pe_settings pes; + pes.prefer_rc4 = (flags & full_encryption); pes.out_enc_policy = pe_settings::forced; pes.in_enc_policy = pe_settings::forced; ses1.set_pe_settings(pes); ses2.set_pe_settings(pes); #endif - boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, NULL, clear_files, true, true, "_meta"); + boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, NULL, flags & clear_files, true, true, "_meta"); - for (int i = 0; i < 80; ++i) + for (int i = 0; i < timeout * 10; ++i) { // make sure this function can be called on // torrents without metadata - if (!disconnect) tor2.status(); + if ((flags & disconnect) == 0) tor2.status(); print_alerts(ses1, "ses1", false, true); print_alerts(ses2, "ses2", false, true); - if (disconnect && tor2.is_valid()) ses2.remove_torrent(tor2); - if (!disconnect + if ((flags & disconnect) && tor2.is_valid()) ses2.remove_torrent(tor2); + if ((flags & disconnect) == 0 && tor2.status().has_metadata) break; test_sleep(100); } - if (disconnect) goto done; + if (flags & disconnect) goto done; TEST_CHECK(tor2.status().has_metadata); std::cerr << "waiting for transfer to complete\n"; - for (int i = 0; i < 30; ++i) + for (int i = 0; i < 20; ++i) { torrent_status st1 = tor1.status(); torrent_status st2 = tor2.status(); - print_ses_rate(i, &st1, &st2); + print_alerts(ses1, "ses1", false, true); + print_alerts(ses2, "ses2", false, true); + + print_ses_rate(i / 10.f, &st1, &st2); if (st2.is_seeding) break; - test_sleep(1000); + test_sleep(100); } TEST_CHECK(tor2.status().is_seeding); @@ -117,19 +137,11 @@ int test_main() { using namespace libtorrent; - // test to disconnect one client prematurely - test_transfer(true, true, &create_metadata_plugin); - // test where one has data and one doesn't - test_transfer(true, false, &create_metadata_plugin); - // test where both have data (to trigger the file check) - test_transfer(false, false, &create_metadata_plugin); + for (int f = 0; f <= (clear_files | disconnect | full_encryption); ++f) + test_transfer(f, &create_metadata_plugin, 5); - // test to disconnect one client prematurely - test_transfer(true, true, &create_ut_metadata_plugin); - // test where one has data and one doesn't - test_transfer(true, false, &create_ut_metadata_plugin); - // test where both have data (to trigger the file check) - test_transfer(false, false, &create_ut_metadata_plugin); + for (int f = 0; f <= (clear_files | disconnect | full_encryption); ++f) + test_transfer(f, &create_ut_metadata_plugin, 2); error_code ec; remove_all("tmp1", ec);