From ce00ebf72357375551b88d8536835f47dbb33ad6 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 23 Jun 2016 11:34:26 -0400 Subject: [PATCH] simplify and clean up some of torrent_info (#847) simplify and clean up some of torrent_info --- include/libtorrent/torrent_info.hpp | 48 ++++---- src/torrent_info.cpp | 167 +++++++--------------------- 2 files changed, 67 insertions(+), 148 deletions(-) diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index 9b1b2a48a..df8b1c743 100644 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -400,17 +400,17 @@ namespace libtorrent // returns true if this torrent_info object has a torrent loaded. // This is primarily used to determine if a magnet link has had its // metadata resolved yet or not. - bool is_valid() const { return m_files.is_valid(); } + bool is_valid() const { return (m_files.is_valid()) != 0; } // returns true if this torrent is private. i.e., it should not be // distributed on the trackerless network (the kademlia DHT). - bool priv() const { return m_private; } + bool priv() const { return (m_flags & private_torrent) != 0; } // returns true if this is an i2p torrent. This is determined by whether // or not it has a tracker whose URL domain name ends with ".i2p". i2p // torrents disable the DHT and local peer discovery as well as talking // to peers over anything other than the i2p network. - bool is_i2p() const { return m_i2p; } + bool is_i2p() const { return (m_flags & i2p) != 0; } // ``hash_for_piece()`` takes a piece-index and returns the 20-bytes // sha1-hash for that piece and ``info_hash()`` returns the 20-bytes @@ -587,7 +587,7 @@ namespace libtorrent // this is a pointer into the m_info_section buffer // pointing to the first byte of the first sha-1 hash - char const* m_piece_hashes; + char const* m_piece_hashes = nullptr; // if a comment is found in the torrent file // this will be set to that comment @@ -604,34 +604,40 @@ namespace libtorrent // if a creation date is found in the torrent file // this will be set to that, otherwise it'll be // 1970, Jan 1 - time_t m_creation_date; + time_t m_creation_date = 0; // the hash that identifies this torrent sha1_hash m_info_hash; // the number of bytes in m_info_section - std::uint32_t m_info_section_size; + std::uint32_t m_info_section_size = 0; // the index to the first leaf. This is where the hash for the // first piece is stored - std::uint32_t m_merkle_first_leaf:24; + std::uint32_t m_merkle_first_leaf = 0; - // this is used when creating a torrent. If there's - // only one file there are cases where it's impossible - // to know if it should be written as a multifile torrent - // or not. e.g. test/test there's one file and one directory - // and they have the same name. - bool m_multifile:1; + enum flags_t : std::uint8_t + { + // this is used when creating a torrent. If there's + // only one file there are cases where it's impossible + // to know if it should be written as a multifile torrent + // or not. e.g. test/test there's one file and one directory + // and they have the same name. + multifile = 1, - // this is true if the torrent is private. i.e., is should not - // be announced on the dht - bool m_private:1; + // this is true if the torrent is private. i.e., is should not + // be announced on the dht + private_torrent = 2, - // this is true if one of the trackers has an .i2p top - // domain in its hostname. This means the DHT and LSD - // features are disabled for this torrent (unless the - // settings allows mixing i2p peers with regular peers) - bool m_i2p:1; + // this is true if one of the trackers has an .i2p top + // domain in its hostname. This means the DHT and LSD + // features are disabled for this torrent (unless the + // settings allows mixing i2p peers with regular peers) + i2p = 4 + }; + + // any combination of values from flags_t enum + std::uint8_t m_flags = 0; }; } diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 028cb3839..c0194b1f8 100644 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -624,9 +624,7 @@ namespace libtorrent , m_info_hash(t.m_info_hash) , m_info_section_size(t.m_info_section_size) , m_merkle_first_leaf(t.m_merkle_first_leaf) - , m_multifile(t.m_multifile) - , m_private(t.m_private) - , m_i2p(t.m_i2p) + , m_flags(t.m_flags) { #if TORRENT_USE_INVARIANT_CHECKS t.check_invariant(); @@ -761,14 +759,7 @@ namespace libtorrent #ifndef TORRENT_NO_DEPRECATE torrent_info::torrent_info(lazy_entry const& torrent_file, error_code& ec - , int flags) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + , int const flags) { TORRENT_UNUSED(flags); std::pair buf = torrent_file.data_section(); @@ -778,14 +769,7 @@ namespace libtorrent parse_torrent_file(e, ec, 0); } - torrent_info::torrent_info(lazy_entry const& torrent_file, int flags) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + torrent_info::torrent_info(lazy_entry const& torrent_file, int const flags) { TORRENT_UNUSED(flags); std::pair buf = torrent_file.data_section(); @@ -809,13 +793,6 @@ namespace libtorrent // standard constructor that parses a torrent file torrent_info::torrent_info(entry const& torrent_file) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) { std::vector tmp; std::back_insert_iterator > out(tmp); @@ -842,14 +819,8 @@ namespace libtorrent #endif #ifndef BOOST_NO_EXCEPTIONS - torrent_info::torrent_info(bdecode_node const& torrent_file, int flags) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + torrent_info::torrent_info(bdecode_node const& torrent_file + , int const flags) { error_code ec; if (!parse_torrent_file(torrent_file, ec, flags)) @@ -858,14 +829,9 @@ namespace libtorrent INVARIANT_CHECK; } - torrent_info::torrent_info(char const* buffer, int size, int flags) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + torrent_info::torrent_info(char const* buffer + , int const size + , int const flags) { error_code ec; bdecode_node e; @@ -878,14 +844,8 @@ namespace libtorrent INVARIANT_CHECK; } - torrent_info::torrent_info(std::string const& filename, int flags) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + torrent_info::torrent_info(std::string const& filename + , int const flags) { std::vector buf; error_code ec; @@ -904,14 +864,8 @@ namespace libtorrent #if TORRENT_USE_WSTRING #ifndef TORRENT_NO_DEPRECATE - torrent_info::torrent_info(std::wstring const& filename, int flags) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + torrent_info::torrent_info(std::wstring const& filename + , int const flags) { std::vector buf; std::string utf8; @@ -940,29 +894,19 @@ namespace libtorrent #endif // TORRENT_USE_WSTRING #endif - torrent_info::torrent_info(bdecode_node const& torrent_file, error_code& ec - , int flags) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + torrent_info::torrent_info(bdecode_node const& torrent_file + , error_code& ec + , int const flags) { parse_torrent_file(torrent_file, ec, flags); INVARIANT_CHECK; } - torrent_info::torrent_info(char const* buffer, int size, error_code& ec, int flags) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + torrent_info::torrent_info(char const* buffer + , int const size + , error_code& ec + , int const flags) { bdecode_node e; if (bdecode(buffer, buffer + size, e, ec) != 0) @@ -972,14 +916,8 @@ namespace libtorrent INVARIANT_CHECK; } - torrent_info::torrent_info(std::string const& filename, error_code& ec, int flags) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + torrent_info::torrent_info(std::string const& filename, error_code& ec + , int const flags) { std::vector buf; int ret = load_file(filename, buf, ec); @@ -995,15 +933,9 @@ namespace libtorrent #if TORRENT_USE_WSTRING #ifndef TORRENT_NO_DEPRECATE - torrent_info::torrent_info(std::wstring const& filename, error_code& ec - , int flags) - : m_piece_hashes(0) - , m_creation_date(0) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + torrent_info::torrent_info(std::wstring const& filename + , error_code& ec + , int const flags) { std::vector buf; std::string utf8; @@ -1025,15 +957,8 @@ namespace libtorrent // will not contain any hashes, comments, creation date // just the necessary to use it with piece manager // used for torrents with no metadata - torrent_info::torrent_info(sha1_hash const& info_hash, int flags) - : m_piece_hashes(0) - , m_creation_date(time(0)) - , m_info_hash(info_hash) - , m_info_section_size(0) - , m_merkle_first_leaf(0) - , m_multifile(false) - , m_private(false) - , m_i2p(false) + torrent_info::torrent_info(sha1_hash const& info_hash, int const flags) + : m_info_hash(info_hash) { TORRENT_UNUSED(flags); } @@ -1084,11 +1009,6 @@ namespace libtorrent m_orig_files.reset(new file_storage(m_files)); } -#define SWAP(tmp, a, b) \ - tmp = a; \ - a = b; \ - b = tmp; - void torrent_info::swap(torrent_info& ti) { INVARIANT_CHECK; @@ -1107,19 +1027,11 @@ namespace libtorrent swap(m_piece_hashes, ti.m_piece_hashes); m_info_dict.swap(ti.m_info_dict); swap(m_merkle_tree, ti.m_merkle_tree); - std::swap(m_info_section_size, ti.m_info_section_size); - - std::uint32_t tmp; - SWAP(tmp, m_merkle_first_leaf, ti.m_merkle_first_leaf); - - bool tmp2; - SWAP(tmp2, m_private, ti.m_private); - SWAP(tmp2, m_i2p, ti.m_i2p); - SWAP(tmp2, m_multifile, ti.m_multifile); + swap(m_info_section_size, ti.m_info_section_size); + swap(m_merkle_first_leaf, ti.m_merkle_first_leaf); + swap(m_flags, ti.m_flags); } -#undef SWAP - std::string torrent_info::ssl_cert() const { // this is parsed lazily @@ -1201,13 +1113,13 @@ namespace libtorrent if (!extract_single_file(info, files, "", info_ptr_diff, true, ec)) return false; - m_multifile = false; + m_flags &= ~multifile; } else { if (!extract_files(files_node, files, name, info_ptr_diff, ec)) return false; - m_multifile = true; + m_flags |= multifile; } TORRENT_ASSERT(!files.name().empty()); @@ -1246,20 +1158,21 @@ namespace libtorrent ec = errors::torrent_invalid_hashes; return false; } - int num_leafs = merkle_num_leafs(files.num_pieces()); - int num_nodes = merkle_num_nodes(num_leafs); - if (num_nodes - num_leafs >= (2<<24)) + if (files.num_pieces() >= std::numeric_limits::max()/2) { ec = errors::too_many_pieces_in_torrent; return false; } + int const num_leafs = merkle_num_leafs(files.num_pieces()); + int const num_nodes = merkle_num_nodes(num_leafs); m_merkle_first_leaf = num_nodes - num_leafs; m_merkle_tree.resize(num_nodes); std::memset(&m_merkle_tree[0], 0, num_nodes * 20); m_merkle_tree[0].assign(root_hash.string_ptr()); } - m_private = info.dict_find_int_value("private", 0) != 0; + m_flags |= (info.dict_find_int_value("private", 0) != 0) + ? private_torrent : 0; #ifndef TORRENT_DISABLE_MUTABLE_TORRENTS bdecode_node similar = info.dict_find_list("similar"); @@ -1483,7 +1396,7 @@ namespace libtorrent e.fail_limit = 0; e.source = announce_entry::source_torrent; #if TORRENT_USE_I2P - if (is_i2p_url(e.url)) m_i2p = true; + if (is_i2p_url(e.url)) m_flags |= i2p; #endif m_urls.push_back(e); } @@ -1515,7 +1428,7 @@ namespace libtorrent e.source = announce_entry::source_torrent; e.trim(); #if TORRENT_USE_I2P - if (is_i2p_url(e.url)) m_i2p = true; + if (is_i2p_url(e.url)) m_flags |= i2p; #endif if (!e.url.empty()) m_urls.push_back(e); } @@ -1551,7 +1464,7 @@ namespace libtorrent { web_seed_entry ent(maybe_url_encode(url_seeds.string_value()) , web_seed_entry::url_seed); - if (m_multifile && ent.url[ent.url.size()-1] != '/') ent.url += '/'; + if ((m_flags & multifile) && ent.url[ent.url.size()-1] != '/') ent.url += '/'; m_web_seeds.push_back(ent); } else if (url_seeds && url_seeds.type() == bdecode_node::list_t) @@ -1565,7 +1478,7 @@ namespace libtorrent if (url.string_length() == 0) continue; web_seed_entry ent(maybe_url_encode(url.string_value()) , web_seed_entry::url_seed); - if (m_multifile && ent.url[ent.url.size()-1] != '/') ent.url += '/'; + if ((m_flags & multifile) && ent.url[ent.url.size()-1] != '/') ent.url += '/'; if (unique.count(ent.url)) continue; unique.insert(ent.url); m_web_seeds.push_back(ent);