diff --git a/ChangeLog b/ChangeLog index eeb515c52f0..e9837b14112 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,10 +15,15 @@ 2.0.11 not released + * limit piece size in torrent creator + * fix file pre-allocation when changing file priority (HanabishiRecca) + * fix uTP issue where closing the connection could corrupt the payload + * apply DSCP/TOS to sockets before initiating the TCP connection * assume copy_file_range() exists on linux (unless old glibc) * fix issue where set_piece_deadline() did not correctly post read_piece_alert * fix integer overflow in piece picker * torrent_status::num_pieces counts pieces passed hash check, as documented + * check settings_pack::max_out_request_queue before performance alert 2.0.10 released @@ -182,7 +187,7 @@ 2.0 released * dropped dependency on iconv - * deprecate set_file_hash() in torrent creator, as it's superceded by v2 torrents + * deprecate set_file_hash() in torrent creator, as it's superseded by v2 torrents * deprecate mutable access to info_section in torrent_info * removed deprecated lazy_entry/lazy_bdecode * stats_alert deprecated diff --git a/Jamfile b/Jamfile index d28b2e7d81f..f2e680bd61b 100644 --- a/Jamfile +++ b/Jamfile @@ -191,7 +191,7 @@ rule linking ( properties * ) else if [ version.version-less $(jam-version) : 1990 0 ] { # the visibility feature was introduced in boost-1.69. This was close to - # when the verisoning scheme changed from year to (low) version numbers. + # when the versioning scheme changed from year to (low) version numbers. # in boost-1.70 result += hidden ; } diff --git a/bindings/python/Jamfile b/bindings/python/Jamfile index 2f27ab846c6..8b903920131 100644 --- a/bindings/python/Jamfile +++ b/bindings/python/Jamfile @@ -28,7 +28,7 @@ feature.compose on : -fPIC ; feature python-install-path : : free path ; # when not specifying a custom install path, this controls whether to install -# the python module in the system directory or user-specifc directory +# the python module in the system directory or user-specific directory feature python-install-scope : user system : ; feature auto-ptr : off on : composite propagated ; diff --git a/bindings/python/libtorrent/__init__.pyi b/bindings/python/libtorrent/__init__.pyi index a954c782830..ecd501ff367 100644 --- a/bindings/python/libtorrent/__init__.pyi +++ b/bindings/python/libtorrent/__init__.pyi @@ -854,21 +854,21 @@ class listen_on_flags_t(int): names: Mapping[str, listen_on_flags_t] values: Mapping[int, listen_on_flags_t] -class listen_succeded_alert_socket_type_t(int): - i2p: listen_succeded_alert_socket_type_t - names: Mapping[str, listen_succeded_alert_socket_type_t] - socks5: listen_succeded_alert_socket_type_t - tcp: listen_succeded_alert_socket_type_t - tcp_ssl: listen_succeded_alert_socket_type_t - udp: listen_succeded_alert_socket_type_t - utp_ssl: listen_succeded_alert_socket_type_t - values: Mapping[int, listen_succeded_alert_socket_type_t] +class listen_succeeded_alert_socket_type_t(int): + i2p: listen_succeeded_alert_socket_type_t + names: Mapping[str, listen_succeeded_alert_socket_type_t] + socks5: listen_succeeded_alert_socket_type_t + tcp: listen_succeeded_alert_socket_type_t + tcp_ssl: listen_succeeded_alert_socket_type_t + udp: listen_succeeded_alert_socket_type_t + utp_ssl: listen_succeeded_alert_socket_type_t + values: Mapping[int, listen_succeeded_alert_socket_type_t] class listen_succeeded_alert(alert): address: str endpoint: Tuple[str, int] port: int - sock_type: listen_succeded_alert_socket_type_t + sock_type: listen_succeeded_alert_socket_type_t socket_type: socket_type_t class log_alert(alert): diff --git a/bindings/python/src/alert.cpp b/bindings/python/src/alert.cpp index 24ae3c0f91e..737db1a8d03 100644 --- a/bindings/python/src/alert.cpp +++ b/bindings/python/src/alert.cpp @@ -635,7 +635,7 @@ void bind_alert() ; #if TORRENT_ABI_VERSION == 1 - enum_("listen_succeded_alert_socket_type_t") + enum_("listen_succeeded_alert_socket_type_t") .value("tcp", listen_succeeded_alert::socket_type_t::tcp) .value("tcp_ssl", listen_succeeded_alert::socket_type_t::tcp_ssl) .value("udp", listen_succeeded_alert::socket_type_t::udp) diff --git a/bindings/python/tests/alert_test.py b/bindings/python/tests/alert_test.py index bcf7b68474f..3cfff27fd38 100644 --- a/bindings/python/tests/alert_test.py +++ b/bindings/python/tests/alert_test.py @@ -144,35 +144,35 @@ def test_operation_name(self) -> None: continue self.assertIsInstance(lt.operation_name(value), str) - def test_listen_succeded_alert_socket_type_t(self) -> None: + def test_listen_succeeded_alert_socket_type_t(self) -> None: if lt.api_version < 2: - self.assertIsInstance(lt.listen_succeded_alert_socket_type_t.tcp, int) - self.assertIsInstance(lt.listen_succeded_alert_socket_type_t.tcp_ssl, int) - self.assertIsInstance(lt.listen_succeded_alert_socket_type_t.udp, int) - self.assertIsInstance(lt.listen_succeded_alert_socket_type_t.i2p, int) - self.assertIsInstance(lt.listen_succeded_alert_socket_type_t.socks5, int) - self.assertIsInstance(lt.listen_succeded_alert_socket_type_t.utp_ssl, int) + self.assertIsInstance(lt.listen_succeeded_alert_socket_type_t.tcp, int) + self.assertIsInstance(lt.listen_succeeded_alert_socket_type_t.tcp_ssl, int) + self.assertIsInstance(lt.listen_succeeded_alert_socket_type_t.udp, int) + self.assertIsInstance(lt.listen_succeeded_alert_socket_type_t.i2p, int) + self.assertIsInstance(lt.listen_succeeded_alert_socket_type_t.socks5, int) + self.assertIsInstance(lt.listen_succeeded_alert_socket_type_t.utp_ssl, int) @unittest.skip("https://github.com/arvidn/libtorrent/issues/5967") - def test_listen_succeded_alert_socket_type_t_deprecated(self) -> None: + def test_listen_succeeded_alert_socket_type_t_deprecated(self) -> None: if lt.api_version < 2: with self.assertWarns(DeprecationWarning): - self.assertIsInstance(lt.listen_succeded_alert_socket_type_t.tcp, int) + self.assertIsInstance(lt.listen_succeeded_alert_socket_type_t.tcp, int) with self.assertWarns(DeprecationWarning): self.assertIsInstance( - lt.listen_succeded_alert_socket_type_t.tcp_ssl, int + lt.listen_succeeded_alert_socket_type_t.tcp_ssl, int ) with self.assertWarns(DeprecationWarning): - self.assertIsInstance(lt.listen_succeded_alert_socket_type_t.udp, int) + self.assertIsInstance(lt.listen_succeeded_alert_socket_type_t.udp, int) with self.assertWarns(DeprecationWarning): - self.assertIsInstance(lt.listen_succeded_alert_socket_type_t.i2p, int) + self.assertIsInstance(lt.listen_succeeded_alert_socket_type_t.i2p, int) with self.assertWarns(DeprecationWarning): self.assertIsInstance( - lt.listen_succeded_alert_socket_type_t.socks5, int + lt.listen_succeeded_alert_socket_type_t.socks5, int ) with self.assertWarns(DeprecationWarning): self.assertIsInstance( - lt.listen_succeded_alert_socket_type_t.utp_ssl, int + lt.listen_succeeded_alert_socket_type_t.utp_ssl, int ) def test_listen_failed_alert_socket_type_t(self) -> None: @@ -1283,7 +1283,7 @@ def test_listen_succeeded_alert(self) -> None: if lt.api_version < 2: self.assertEqual(alert.endpoint, ("127.0.0.1", self.session.listen_port())) self.assertIsInstance( - alert.sock_type, lt.listen_succeded_alert_socket_type_t + alert.sock_type, lt.listen_succeeded_alert_socket_type_t ) self.assertEqual(alert.address, "127.0.0.1") self.assertEqual(alert.port, self.session.listen_port()) diff --git a/cmake/Modules/LibtorrentMacros.cmake b/cmake/Modules/LibtorrentMacros.cmake index e3500c7a71e..a49462c4267 100644 --- a/cmake/Modules/LibtorrentMacros.cmake +++ b/cmake/Modules/LibtorrentMacros.cmake @@ -15,7 +15,7 @@ endmacro() # target_optional_compile_definitions( [FEATURE] # NAME DESCRIPTION DEFAULT # [ENABLED [enabled_compile_definitions...]] -# [DISABLED [disabled_compile_defnitions...]] +# [DISABLED [disabled_compile_definitions...]] # ) # NAME, DESCRIPTION and DEFAULT are passed to option() call # if FEATURE is given, they are passed to add_feature_info() diff --git a/examples/connection_tester.cpp b/examples/connection_tester.cpp index 822a9880e51..774d113d346 100644 --- a/examples/connection_tester.cpp +++ b/examples/connection_tester.cpp @@ -55,7 +55,7 @@ void generate_block(span buffer, piece_index_t const piece for (auto& w : buffer) w = fill; } -// in order to circumvent the restricton of only +// in order to circumvent the restriction of only // one connection per IP that most clients implement // all sockets created by this tester are bound to // unique local IPs in the range (127.0.0.1 - 127.255.255.255) diff --git a/include/libtorrent/aux_/hash_picker.hpp b/include/libtorrent/aux_/hash_picker.hpp index 2d10ac2b980..4ad37b8441f 100644 --- a/include/libtorrent/aux_/hash_picker.hpp +++ b/include/libtorrent/aux_/hash_picker.hpp @@ -196,7 +196,7 @@ namespace libtorrent::aux // this is for a future per-block request feature #if 0 - // blocks are only added to this list if there is a time critial block which + // blocks are only added to this list if there is a time critical block which // has been downloaded but we don't have its hash or if the initial request // for the hash was rejected // this block hash will be requested from every peer possible until the hash diff --git a/include/libtorrent/aux_/merkle.hpp b/include/libtorrent/aux_/merkle.hpp index 427b5a7259e..f56cad0e807 100644 --- a/include/libtorrent/aux_/merkle.hpp +++ b/include/libtorrent/aux_/merkle.hpp @@ -101,7 +101,7 @@ namespace libtorrent { // if we're inserting the hash N, the uncle hashes provide proof of it being // valid by containing 0, 1 and two (as marked in the tree above) // Any non-zero hash encountered in target_tree is assumed to be valid, and - // will termiate the validation early, either successful (if there's a + // will terminate the validation early, either successful (if there's a // match) or unsuccessful (if there's a mismatch). TORRENT_EXTRA_EXPORT bool merkle_validate_and_insert_proofs(span target_tree diff --git a/include/libtorrent/aux_/peer_connection.hpp b/include/libtorrent/aux_/peer_connection.hpp index f4f8777b0b5..7bdaa0ddcb5 100644 --- a/include/libtorrent/aux_/peer_connection.hpp +++ b/include/libtorrent/aux_/peer_connection.hpp @@ -656,7 +656,7 @@ namespace libtorrent::aux { int max_out_request_queue() const; std::time_t last_seen_complete() const { return m_last_seen_complete; } - void set_last_seen_complete(int ago) { m_last_seen_complete = ::time(nullptr) - ago; } + void set_last_seen_complete(int ago) { m_last_seen_complete = aux::posix_time() - ago; } std::int64_t uploaded_in_last_round() const { return m_statistics.total_payload_upload() - m_uploaded_at_last_round; } diff --git a/include/libtorrent/aux_/posix_storage.hpp b/include/libtorrent/aux_/posix_storage.hpp index 8295c6c09cc..d5696da3b5c 100644 --- a/include/libtorrent/aux_/posix_storage.hpp +++ b/include/libtorrent/aux_/posix_storage.hpp @@ -45,7 +45,8 @@ namespace aux { , storage_error& error); bool has_any_file(storage_error& error); - void set_file_priority(aux::vector& prio + void set_file_priority(settings_interface const& + , aux::vector& prio , storage_error& ec); bool verify_resume_data(add_torrent_params const& rd , aux::vector const& links diff --git a/include/libtorrent/aux_/time.hpp b/include/libtorrent/aux_/time.hpp index d24539a2950..328aaf17e2e 100644 --- a/include/libtorrent/aux_/time.hpp +++ b/include/libtorrent/aux_/time.hpp @@ -25,6 +25,9 @@ namespace libtorrent { namespace aux { TORRENT_EXTRA_EXPORT std::time_t to_time_t(time_point32 tp); TORRENT_EXTRA_EXPORT time_point32 from_time_t(std::time_t t); + + // returns the current posix time (UTC) + TORRENT_EXTRA_EXPORT time_t posix_time(); } } #endif diff --git a/include/libtorrent/aux_/torrent.hpp b/include/libtorrent/aux_/torrent.hpp index 448cc9824f6..bda9b5861a6 100644 --- a/include/libtorrent/aux_/torrent.hpp +++ b/include/libtorrent/aux_/torrent.hpp @@ -1115,8 +1115,8 @@ namespace libtorrent::aux { void write_resume_data(resume_data_flags_t const flags, add_torrent_params& ret) const; - void seen_complete() { m_last_seen_complete = ::time(nullptr); } - int time_since_complete() const { return int(::time(nullptr) - m_last_seen_complete); } + void seen_complete() { m_last_seen_complete = aux::posix_time(); } + int time_since_complete() const { return int(aux::posix_time() - m_last_seen_complete); } time_t last_seen_complete() const { return m_last_seen_complete; } template diff --git a/include/libtorrent/create_torrent.hpp b/include/libtorrent/create_torrent.hpp index b37e9cc0436..b679a137762 100644 --- a/include/libtorrent/create_torrent.hpp +++ b/include/libtorrent/create_torrent.hpp @@ -213,6 +213,8 @@ TORRENT_VERSION_NAMESPACE_4 // The ``piece_size`` is the size of each piece in bytes. It must be a // power of 2 and a minimum of 16 kiB. If a piece size of 0 is // specified, a piece_size will be set automatically. + // Piece sizes greater than 128 MiB are considered unreasonable and will + // be rejected (with an lt::system_error exception). // // The ``flags`` arguments specifies options for the torrent creation. It can // be any combination of the flags defined by create_flags_t. diff --git a/simulation/setup_swarm.cpp b/simulation/setup_swarm.cpp index 82fbd72d51c..04e3b1dac58 100644 --- a/simulation/setup_swarm.cpp +++ b/simulation/setup_swarm.cpp @@ -33,6 +33,11 @@ using namespace sim; #define DEBUG_SWARM 0 +#if DEBUG_SWARM +#include +#include "libtorrent/aux_/file_pointer.hpp" +#endif + constexpr swarm_test_t swarm_test::download; constexpr swarm_test_t swarm_test::upload; constexpr swarm_test_t swarm_test::no_auto_stop; @@ -311,6 +316,12 @@ void setup_swarm(int num_nodes // line #if DEBUG_SWARM == 0 if (i != 0) return; +#else + char path[200]; + lt::error_code ignore; + lt::create_directory("logs", ignore); + std::snprintf(path, sizeof(path), "logs/node-%d.log", i); + lt::aux::file_pointer log_output(::fopen(path, "a")); #endif for (lt::alert* a : alerts) @@ -320,25 +331,27 @@ void setup_swarm(int num_nodes std::uint32_t const millis = std::uint32_t( lt::duration_cast(d).count()); +#if DEBUG_SWARM != 0 + std::fprintf(log_output.file(), + "%4u.%03u: %-25s %s\n" + , millis / 1000, millis % 1000 + , a->what() + , a->message().c_str()); + + // the behavior of the test itself should not be affected by + // whether we're printing logs for all nodes + if (i != 0) continue; +#endif + // when debugging, we print *all* alerts to the log if (should_print(a)) { std::printf( -#if DEBUG_SWARM != 0 - "[%d] " -#endif "%4u.%03u: %-25s %s\n" -#if DEBUG_SWARM != 0 - , i -#endif , millis / 1000, millis % 1000 , a->what() , a->message().c_str()); } -#if DEBUG_SWARM != 0 - if (i != 0) continue; -#endif - // if a torrent was added save the torrent handle if (lt::add_torrent_alert* at = lt::alert_cast(a)) { diff --git a/simulation/test_web_seed.cpp b/simulation/test_web_seed.cpp index fd4b46a2db8..34d9343d598 100644 --- a/simulation/test_web_seed.cpp +++ b/simulation/test_web_seed.cpp @@ -538,7 +538,7 @@ TORRENT_TEST(urlseed_timeout) // check for correct handle of unexpected http status response. // with disabled "close_redundant_connections" alive web server connection // may be closed in such manner. -TORRENT_TEST(no_close_redudant_webseed) +TORRENT_TEST(no_close_redundant_webseed) { using namespace lt; diff --git a/src/create_torrent.cpp b/src/create_torrent.cpp index 54b8926684e..b66b13b3741 100644 --- a/src/create_torrent.cpp +++ b/src/create_torrent.cpp @@ -23,6 +23,7 @@ see LICENSE file. #include "libtorrent/session.hpp" // for default_disk_io_constructor #include "libtorrent/aux_/directory.hpp" #include "libtorrent/aux_/bencoder.hpp" +#include "libtorrent/aux_/time.hpp" // for posix_time #include #include @@ -559,7 +560,7 @@ TORRENT_VERSION_NAMESPACE_4 , create_flags_t const flags) : m_files(std::move(files)) , m_total_size(compute_total_size(m_files)) - , m_creation_date(::time(nullptr)) + , m_creation_date(aux::posix_time()) , m_multifile(m_files.size() > 1) , m_private(false) , m_include_mtime(bool(flags & create_torrent::modification_time)) @@ -628,6 +629,12 @@ TORRENT_VERSION_NAMESPACE_4 aux::throw_ex(errors::invalid_piece_size); } + // this is an unreasonably large piece size. Some clients don't support + // pieces this large. + if (piece_size > 128 * 1024 * 1024) { + aux::throw_ex(errors::invalid_piece_size); + } + m_piece_length = piece_size; TORRENT_ASSERT(m_piece_length > 0); if (!(flags & v1_only) @@ -644,7 +651,7 @@ TORRENT_VERSION_NAMESPACE_4 , m_piece_length(ti.piece_length()) , m_num_pieces(ti.num_pieces()) , m_name(ti.name()) - , m_creation_date(::time(nullptr)) + , m_creation_date(aux::posix_time()) , m_multifile(ti.num_files() > 1) , m_private(ti.priv()) , m_include_mtime(false) diff --git a/src/hash_picker.cpp b/src/hash_picker.cpp index 631e33be2af..f2759e10440 100644 --- a/src/hash_picker.cpp +++ b/src/hash_picker.cpp @@ -40,7 +40,7 @@ bool validate_hash_request(hash_request const& hr, file_storage const& fs) { // limit the size of the base layer to something reasonable // Blocks are requested for an entire piece so this limit - // effectivly caps the piece size we can handle. A limit of 8192 + // effectively caps the piece size we can handle. A limit of 8192 // corresponds to a piece size of 128MB. if (hr.file < file_index_t{0} diff --git a/src/ip_notifier.cpp b/src/ip_notifier.cpp index a70b5dfa762..516594d4890 100644 --- a/src/ip_notifier.cpp +++ b/src/ip_notifier.cpp @@ -144,15 +144,6 @@ struct ip_change_notifier_impl final : ip_change_notifier netlink::socket m_socket; std::array m_buf; - struct local_address - { - int family; - std::array data; - }; - // maps if_index to the most recently advertised local address - // this is used to filter duplicate updates - std::unordered_map m_state; - void on_notify(int len, std::function cb) { bool pertinent = false; @@ -161,33 +152,10 @@ struct ip_change_notifier_impl final : ip_change_notifier nlmsg_ok (nh, len); nh = nlmsg_next(nh, len)) { - if (nh->nlmsg_type != RTM_NEWADDR) + if (nh->nlmsg_type != RTM_NEWADDR && + nh->nlmsg_type != RTM_DELADDR) continue; - - auto const* addr_msg = static_cast(nlmsg_data(nh)); - std::uint32_t const index = addr_msg->ifa_index; - int const family = addr_msg->ifa_family; - std::size_t attr_len = ifa_payload(nh); - auto const* rta_ptr = ifa_rta(addr_msg); - - for (; rta_ok(rta_ptr, attr_len); rta_ptr = rta_next(rta_ptr, attr_len)) - { - auto* const ptr = rta_data(rta_ptr); - if (rta_ptr->rta_type != IFA_LOCAL) - continue; - - auto& existing = m_state[index]; - std::size_t const address_len = family == AF_INET ? 4 : 16; - if (existing.family == family - && std::memcmp(&existing.data, ptr, address_len) == 0) - { - break; - } - - existing.family = family; - std::memcpy(existing.data.data(), ptr, address_len); - pertinent = true; - } + pertinent = true; } if (!pertinent) diff --git a/src/kademlia/routing_table.cpp b/src/kademlia/routing_table.cpp index d322452d383..e8d1d66d81f 100644 --- a/src/kademlia/routing_table.cpp +++ b/src/kademlia/routing_table.cpp @@ -645,7 +645,7 @@ routing_table::add_node_status_t routing_table::add_node_impl(node_entry e) existing->update_rtt(e.rtt); existing->last_queried = e.last_queried; } - // if this was a replacement node it may be elligible for + // if this was a replacement node it may be eligible for // promotion to the live bucket fill_from_replacements(existing_bucket); prune_empty_bucket(); diff --git a/src/mmap_storage.cpp b/src/mmap_storage.cpp index cfb83b95a6a..ffb1a276e3f 100644 --- a/src/mmap_storage.cpp +++ b/src/mmap_storage.cpp @@ -41,6 +41,7 @@ see LICENSE file. #include "libtorrent/aux_/stat_cache.hpp" #include "libtorrent/aux_/readwrite.hpp" #include "libtorrent/hex.hpp" // to_hex +#include "libtorrent/aux_/scope_end.hpp" #if TORRENT_HAVE_MMAP || TORRENT_HAVE_MAP_VIEW_OF_FILE @@ -139,15 +140,22 @@ error_code translate_error(std::error_code const& err, bool const write) download_priority_t const old_prio = m_file_priority[i]; download_priority_t new_prio = prio[i]; + + m_file_priority[i] = new_prio; + + // in case there's an error, we make sure m_file_priority is only + // updated for the successful files. By leaving failed files as + // priority 0, we allow re-trying them. + auto restore_prio = aux::scope_end([&] { + m_file_priority[i] = old_prio; + prio = m_file_priority; + }); + if (old_prio == dont_download && new_prio != dont_download) { // move stuff out of the part file std::shared_ptr f = open_file(sett, i, aux::open_mode::write, ec); - if (ec) - { - prio = m_file_priority; - return; - } + if (ec) return; if (m_part_file && use_partfile(i)) { @@ -174,7 +182,6 @@ error_code translate_error(std::error_code const& err, bool const write) { ec.file(i); ec.operation = operation_t::partfile_write; - prio = m_file_priority; return; } } @@ -206,7 +213,6 @@ error_code translate_error(std::error_code const& err, bool const write) { ec.file(i); ec.operation = operation_t::file_stat; - prio = m_file_priority; return; } use_partfile(i, !file_exists); @@ -214,11 +220,7 @@ error_code translate_error(std::error_code const& err, bool const write) auto f = open_file(sett, i, aux::open_mode::read_only, ec); if (ec.ec != boost::system::errc::no_such_file_or_directory) { - if (ec) - { - prio = m_file_priority; - return; - } + if (ec) return; need_partfile(); @@ -227,7 +229,6 @@ error_code translate_error(std::error_code const& err, bool const write) { ec.file(i); ec.operation = operation_t::partfile_read; - prio = m_file_priority; return; } // remove the file @@ -237,14 +238,13 @@ error_code translate_error(std::error_code const& err, bool const write) { ec.file(i); ec.operation = operation_t::file_remove; - prio = m_file_priority; return; } } */ } ec.ec.clear(); - m_file_priority[i] = new_prio; + restore_prio.disarm(); if (m_file_priority[i] == dont_download && use_partfile(i)) { diff --git a/src/part_file.cpp b/src/part_file.cpp index 016db7398b1..c615f0b250c 100644 --- a/src/part_file.cpp +++ b/src/part_file.cpp @@ -346,7 +346,6 @@ namespace libtorrent::aux { span v = {buf.get(), block_to_copy}; auto bytes_read = aux::pread_all(file.fd(), v, slot_offset(slot) + piece_offset, ec); v = v.first(static_cast(bytes_read)); - TORRENT_ASSERT(!ec); if (ec || v.empty()) return; f(file_offset, {buf.get(), block_to_copy}); diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 9e4742f355d..a4f95c1efa0 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -347,6 +347,20 @@ namespace { init(); } + if (m_settings.get_int(settings_pack::peer_dscp) != 0) + { + int const value = m_settings.get_int(settings_pack::peer_dscp); + error_code ec; + aux::set_traffic_class(m_socket, value, ec); +#ifndef TORRENT_DISABLE_LOGGING + if (ec && should_log(peer_log_alert::outgoing)) + { + peer_log(peer_log_alert::outgoing, "SET_DSCP", "value: %d e: %s" + , value, ec.message().c_str()); + } +#endif + } + // if this is an incoming connection, we're done here if (!m_connecting) { @@ -5078,7 +5092,7 @@ namespace { update_desired_queue_size(); - if (m_desired_queue_size == m_max_out_request_queue + if (m_desired_queue_size >= m_settings.get_int(settings_pack::max_out_request_queue) && t->alerts().should_post()) { t->alerts().emplace_alert(t->get_handle() @@ -6364,19 +6378,6 @@ namespace { return; } - if (m_settings.get_int(settings_pack::peer_dscp) != 0) - { - int const value = m_settings.get_int(settings_pack::peer_dscp); - aux::set_traffic_class(m_socket, value, ec); -#ifndef TORRENT_DISABLE_LOGGING - if (ec && should_log(peer_log_alert::outgoing)) - { - peer_log(peer_log_alert::outgoing, "SET_DSCP", "value: %d e: %s" - , value, ec.message().c_str()); - } -#endif - } - #ifndef TORRENT_DISABLE_EXTENSIONS for (auto const& ext : m_extensions) { diff --git a/src/posix_disk_io.cpp b/src/posix_disk_io.cpp index 2ee318dadc3..3922c2e1fa9 100644 --- a/src/posix_disk_io.cpp +++ b/src/posix_disk_io.cpp @@ -335,7 +335,7 @@ namespace { { posix_storage* st = m_torrents[storage].get(); storage_error error; - st->set_file_priority(prio, error); + st->set_file_priority(m_settings, prio, error); post(m_ios, [p = std::move(prio), h = std::move(handler), error] () mutable { h(error, std::move(p)); }); } diff --git a/src/posix_part_file.cpp b/src/posix_part_file.cpp index 9497bcdc59b..c62813765f8 100644 --- a/src/posix_part_file.cpp +++ b/src/posix_part_file.cpp @@ -383,7 +383,6 @@ namespace aux { if (int(bytes_read) != block_to_copy) ec.assign(errno, generic_category()); - TORRENT_ASSERT(!ec); if (ec) return; f(file_offset, {buf.get(), block_to_copy}); diff --git a/src/posix_storage.cpp b/src/posix_storage.cpp index 7e14c60322e..ad16d08d308 100644 --- a/src/posix_storage.cpp +++ b/src/posix_storage.cpp @@ -61,7 +61,8 @@ namespace aux { , files().num_pieces(), files().piece_length()); } - void posix_storage::set_file_priority(aux::vector& prio + void posix_storage::set_file_priority(settings_interface const& + , aux::vector& prio , storage_error& ec) { // extend our file priorities in case it's truncated diff --git a/src/puff.cpp b/src/puff.cpp index f0ce1d00765..9cf0c529e9e 100644 --- a/src/puff.cpp +++ b/src/puff.cpp @@ -43,7 +43,7 @@ * - Use pointers instead of long to specify source and * destination sizes to avoid arbitrary 4 GB limits * 1.2 17 Mar 2002 - Add faster version of decode(), doubles speed (!), - * but leave simple version for readabilty + * but leave simple version for readability * - Make sure invalid distances detected if pointers * are 16 bits * - Fix fixed codes table error diff --git a/src/time.cpp b/src/time.cpp index c80846acc97..38f346ef66b 100644 --- a/src/time.cpp +++ b/src/time.cpp @@ -48,4 +48,12 @@ namespace libtorrent { namespace aux { return std::chrono::time_point_cast(r + milliseconds(500)); } + time_t posix_time() + { +#ifdef TORRENT_BUILD_SIMULATOR + return 1722056360 + clock_type::now().time_since_epoch().count(); +#else + return ::time(nullptr); +#endif + } } } diff --git a/src/torrent.cpp b/src/torrent.cpp index 379843e8bae..ffef03db773 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -179,7 +179,7 @@ bool is_downloading_state(int const st) , m_trackerid(p.trackerid) , m_save_path(complete(p.save_path)) , m_stats_counters(ses.stats_counters()) - , m_added_time(p.added_time ? p.added_time : std::time(nullptr)) + , m_added_time(p.added_time ? p.added_time : aux::posix_time()) , m_completed_time(p.completed_time) , m_last_seen_complete(p.last_seen_complete) , m_swarm_last_seen_complete(p.last_seen_complete) diff --git a/src/utp_stream.cpp b/src/utp_stream.cpp index a30fbe687e8..74d5502e4ac 100644 --- a/src/utp_stream.cpp +++ b/src/utp_stream.cpp @@ -1478,7 +1478,7 @@ bool utp_socket_impl::send_pkt(int const flags) // for non MTU-probes, use the conservative packet size int const effective_mtu = mtu_probe ? m_mtu : m_mtu_floor; - auto const close_reason = static_cast(m_close_reason); + auto close_reason = static_cast(m_close_reason); int sack = 0; if (m_inbuf.size()) @@ -1580,7 +1580,7 @@ bool utp_socket_impl::send_pkt(int const flags) int const packet_size = header_size + payload_size; p->size = std::uint16_t(packet_size); - p->header_size = std::uint16_t(packet_size - payload_size); + p->header_size = std::uint16_t(header_size); p->num_transmissions = 0; #if TORRENT_USE_ASSERTS p->num_fast_resend = 0; @@ -1637,6 +1637,10 @@ bool utp_socket_impl::send_pkt(int const flags) else sack = 0; + // we should not add or update a close reason extension header on a + // nagle packet. It's a bit tricky to get all the cases right. + close_reason = 0; + std::int32_t const size_left = std::min({ p->allocated - p->size , m_write_buffer_size @@ -1680,6 +1684,7 @@ bool utp_socket_impl::send_pkt(int const flags) *ptr++ = utp_no_extension; *ptr++ = 4; aux::write_uint32(close_reason, ptr); + TORRENT_ASSERT(ptr <= p->buf + p->header_size); } if (m_bytes_in_flight > 0 diff --git a/test/main.cpp b/test/main.cpp index 1c7d33d560d..96bc7baa5b0 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -481,7 +481,7 @@ int EXPORT main(int argc, char const* argv[]) { #endif - std::srand(unsigned(std::hash{}(executable)) + unsigned(i)); + std::srand(0x82daf973); lt::aux::random_engine().seed(0x82daf973); ::unit_test::g_test_failures = 0; @@ -529,7 +529,7 @@ int EXPORT main(int argc, char const* argv[]) if (!tests_to_run.empty()) { - std::printf("\x1b[1mUNKONWN tests:\x1b[0m\n"); + std::printf("\x1b[1mUNKNOWN tests:\x1b[0m\n"); for (std::set::iterator i = tests_to_run.begin() , end(tests_to_run.end()); i != end; ++i) { diff --git a/test/socks.py b/test/socks.py index 7a294738f68..20dc559e1a6 100755 --- a/test/socks.py +++ b/test/socks.py @@ -106,7 +106,7 @@ def handle(self): sys.stdout.flush() def inner_handle(self): - # IMRPOVEMENT: Report who requests are from in logging + # IMPROVEMENT: Report who requests are from in logging # IMPROVEMENT: Timeout on client debug('Connection - authenticating') version = self.read(1) diff --git a/test/test_bdecode.cpp b/test/test_bdecode.cpp index b046a3f52ac..2ab37f16fee 100644 --- a/test/test_bdecode.cpp +++ b/test/test_bdecode.cpp @@ -489,7 +489,7 @@ TORRENT_TEST(item_limit) } // test unexpected EOF -TORRENT_TEST(unepected_eof) +TORRENT_TEST(unexpected_eof) { char b[] = "l2:.."; // expected terminating 'e' @@ -502,7 +502,7 @@ TORRENT_TEST(unepected_eof) } // test unexpected EOF in string length -TORRENT_TEST(unepected_eof2) +TORRENT_TEST(unexpected_eof2) { char b[] = "l2:..0"; // expected ':' delimiter instead of EOF diff --git a/test/test_copy_file.cpp b/test/test_copy_file.cpp index 789fce4eb16..aebcecab088 100644 --- a/test/test_copy_file.cpp +++ b/test/test_copy_file.cpp @@ -98,7 +98,7 @@ bool fs_supports_sparse_files() static fsword_t const ufs = 0x00011954; static const std::set sparse_filesystems{ EXT4_SUPER_MAGIC, EXT3_SUPER_MAGIC, XFS_SUPER_MAGIC, fsword_t(BTRFS_SUPER_MAGIC) - , ufs, REISERFS_SUPER_MAGIC, TMPFS_MAGIC + , ufs, REISERFS_SUPER_MAGIC, TMPFS_MAGIC, OVERLAYFS_SUPER_MAGIC }; printf("filesystem: %ld\n", long(st.f_type)); return sparse_filesystems.count(st.f_type); diff --git a/test/test_create_torrent.cpp b/test/test_create_torrent.cpp index d82995cfcd5..c1d503f7996 100644 --- a/test/test_create_torrent.cpp +++ b/test/test_create_torrent.cpp @@ -126,6 +126,7 @@ int test_piece_size(int const piece_size, lt::create_flags_t const f = {}) TORRENT_TEST(piece_size_restriction_16kB) { + // v2 torrents must have piece sizes of at least 16 kiB TEST_EQUAL(test_piece_size(15000), 16 * 1024); TEST_EQUAL(test_piece_size(500), 16 * 1024); TEST_THROW(test_piece_size(15000, lt::create_torrent::v1_only)); @@ -135,6 +136,7 @@ TORRENT_TEST(piece_size_restriction_16kB) TORRENT_TEST(piece_size_quanta) { + // v2 torrents must have power-of-two piece sizes TEST_EQUAL(test_piece_size(32 * 1024), 32 * 1024); TEST_EQUAL(test_piece_size(32 * 1024, lt::create_torrent::v1_only), 32 * 1024); TEST_THROW(test_piece_size(48 * 1024)); @@ -143,6 +145,14 @@ TORRENT_TEST(piece_size_quanta) TEST_THROW(test_piece_size(47 * 1024)); } +TORRENT_TEST(piece_size_limit) +{ + // the max piece size is determined by piece_picker::max_blocks_per_piece + TEST_EQUAL(test_piece_size(0x8000000), 0x8000000); + TEST_THROW(test_piece_size(0x8000001, lt::create_torrent::v1_only)); + TEST_THROW(test_piece_size(0x10000000)); +} + #if TORRENT_ABI_VERSION < 4 TORRENT_TEST(create_torrent_round_trip) { diff --git a/test/test_dht.cpp b/test/test_dht.cpp index 62eeb576801..d6699dd10eb 100644 --- a/test/test_dht.cpp +++ b/test/test_dht.cpp @@ -791,7 +791,7 @@ TORRENT_TEST(invalid_message) } } -TORRENT_TEST(node_id_testng) +TORRENT_TEST(node_id_testing) { node_id rnd = generate_secret_id(); TEST_CHECK(verify_secret_id(rnd)); diff --git a/test/test_file_storage.cpp b/test/test_file_storage.cpp index bf98c34fa68..ee9d071d403 100644 --- a/test/test_file_storage.cpp +++ b/test/test_file_storage.cpp @@ -1053,7 +1053,7 @@ TORRENT_TEST(file_first_piece_node) // the size of the merkle tree is implied by the size of the file. // 0x500000 / 0x10000 = 80 pieces // a merkle tree must have a power of 2 number of leaves, so that's 128, - // thats 7 layers + // that's 7 layers TEST_EQUAL(first_piece_node(0x10000, 0x500000), 127); TEST_EQUAL(first_piece_node(0x8000, 0x500000), 255); TEST_EQUAL(first_piece_node(0x4000, 0x500000), 511); diff --git a/test/test_piece_picker.cpp b/test/test_piece_picker.cpp index 1ab15aca365..ef67535583b 100644 --- a/test/test_piece_picker.cpp +++ b/test/test_piece_picker.cpp @@ -2472,7 +2472,7 @@ TORRENT_TEST(mark_as_pad_pick_short_last_piece) // there is no block 3 in this piece } -TORRENT_TEST(mark_as_pad_pick_short_last_piece_prefer_contiguos) +TORRENT_TEST(mark_as_pad_pick_short_last_piece_prefer_contiguous) { auto p = std::make_shared( 3 * default_piece_size - default_block_size, default_piece_size); diff --git a/test/test_storage.cpp b/test/test_storage.cpp index c51a81476b7..7e99246952f 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -514,6 +514,121 @@ void test_rename(std::string const& test_path) TEST_EQUAL(s->files().file_path(0_file), "new_filename"); } +namespace { +std::int64_t file_size_on_disk(std::string const& path) +{ +#ifdef TORRENT_WINDOWS + native_path_string f = convert_to_native_path_string(path); + // in order to open a directory, we need the FILE_FLAG_BACKUP_SEMANTICS + HANDLE h = CreateFileW(f.c_str(), 0, FILE_SHARE_DELETE | FILE_SHARE_READ + | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + TEST_CHECK(h != INVALID_HANDLE_VALUE); + FILE_STANDARD_INFO Standard; + TEST_CHECK(GetFileInformationByHandleEx(h, FILE_INFO_BY_HANDLE_CLASS::FileStandardInfo, &Standard, sizeof(FILE_STANDARD_INFO))); + CloseHandle(h); + return Standard.AllocationSize.QuadPart; +#else + struct ::stat st{}; + TEST_EQUAL(::stat(path.c_str(), &st), 0); + return std::int64_t(st.st_blocks) * 512; +#endif +} +} + +template +void test_pre_allocate() +{ + std::string const test_path = complete("pre_allocate_test_path"); + delete_dirs(combine_path(test_path, "temp_storage")); + + std::vector buf; + typename file_pool_type::type fp; + io_context ios; + + aux::session_settings set; + std::shared_ptr info = setup_torrent_info(buf); + file_storage const& fs = info->files(); + + aux::vector priorities{ + lt::dont_download, + lt::default_priority, + lt::default_priority, + lt::default_priority, + lt::default_priority, + }; + storage_params p{ + info->files(), + nullptr, + test_path, + storage_mode_allocate, + priorities, + sha1_hash{}, + info->v1(), + info->v2() + }; + auto s = make_storage(p, fp); + + // allocate the files and create the directories + storage_error se; + s->initialize(set, se); + if (se) + { + TEST_ERROR(se.ec.message().c_str()); + std::printf("storage::initialize %s: %d\n" + , se.ec.message().c_str(), static_cast(se.file())); + throw system_error(se.ec); + } + + std::vector piece1 = new_piece(0x4000); + span iov = span(piece1); + + // ensure all files, except the first one, have been allocated + for (auto i : fs.file_range()) + { + if (fs.file_size(i) > 0) + { + int ret = write(s, set, iov, fs.piece_index_at_file(i), 0, aux::open_mode::write, se); + TEST_EQUAL(ret, int(iov.size())); + TEST_CHECK(!se.ec); + } + + error_code ec; + file_status st; + std::string const path = fs.file_path(i, test_path); + stat_file(path, &st, ec); + if (i == file_index_t{0}) + { + // the first file has priority 0, and so should not be created + TEST_EQUAL(ec, boost::system::errc::no_such_file_or_directory); + } + else + { + TEST_CHECK(!ec); + std::cerr << "error: " << ec.message() << std::endl; + TEST_EQUAL(st.file_size, fs.file_size(i)); + TEST_CHECK(file_size_on_disk(path) >= fs.file_size(i)); + } + } + + std::cerr << "set file priority" << std::endl; + // set priority of file 0 to non-zero, and make sure we create the file now + priorities[0_file] = lt::default_priority; + s->set_file_priority(set, priorities, se); + TEST_CHECK(!se.ec); + + for (auto i : fs.file_range()) + { + error_code ec; + file_status st; + std::string const path = fs.file_path(i, test_path); + stat_file(path, &st, ec); + std::cerr<< "error: " << ec.message() << std::endl; + TEST_CHECK(!ec); + + TEST_CHECK(file_size_on_disk(path) >= fs.file_size(i)); + } +} + using lt::operator""_bit; using check_files_flag_t = lt::flags::bitfield_flag; @@ -683,11 +798,15 @@ TORRENT_TEST(check_files_oversized_mmap) test_check_files(sparse | test_oversized, lt::mmap_disk_io_constructor); } - TORRENT_TEST(check_files_allocate_mmap) { test_check_files(zero_prio, lt::mmap_disk_io_constructor); } + +TORRENT_TEST(test_pre_allocate_mmap) +{ + test_pre_allocate(); +} #endif TORRENT_TEST(check_files_sparse_posix) { @@ -710,6 +829,14 @@ TORRENT_TEST(check_files_allocate_posix) test_check_files(zero_prio, lt::posix_disk_io_constructor); } +// posix_storage doesn't support pre-allocating files on non-windows +/* +TORRENT_TEST(test_pre_allocate_posix) +{ + test_pre_allocate(); +} +*/ + #if TORRENT_HAVE_MMAP || TORRENT_HAVE_MAP_VIEW_OF_FILE TORRENT_TEST(rename_mmap_disk_io) { diff --git a/test/test_xml.cpp b/test/test_xml.cpp index d7520a630f0..86c1ecc455a 100644 --- a/test/test_xml.cpp +++ b/test/test_xml.cpp @@ -421,7 +421,7 @@ TORRENT_TEST(xml_tag_no_attribute_whitespace) test_parse("", "Dxml"); } -TORRENT_TEST(attribute_missing_qoute) +TORRENT_TEST(attribute_missing_quote) { test_parse("foo