simplify and clean up some of torrent_info (#847)

simplify and clean up some of torrent_info
This commit is contained in:
Arvid Norberg 2016-06-23 11:34:26 -04:00 committed by GitHub
parent 21c1540ace
commit ce00ebf723
2 changed files with 67 additions and 148 deletions

View File

@ -400,17 +400,17 @@ namespace libtorrent
// returns true if this torrent_info object has a torrent loaded. // returns true if this torrent_info object has a torrent loaded.
// This is primarily used to determine if a magnet link has had its // This is primarily used to determine if a magnet link has had its
// metadata resolved yet or not. // 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 // returns true if this torrent is private. i.e., it should not be
// distributed on the trackerless network (the kademlia DHT). // 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 // 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 // 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 // torrents disable the DHT and local peer discovery as well as talking
// to peers over anything other than the i2p network. // 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 // ``hash_for_piece()`` takes a piece-index and returns the 20-bytes
// sha1-hash for that piece and ``info_hash()`` 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 // this is a pointer into the m_info_section buffer
// pointing to the first byte of the first sha-1 hash // 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 // if a comment is found in the torrent file
// this will be set to that comment // this will be set to that comment
@ -604,34 +604,40 @@ namespace libtorrent
// if a creation date is found in the torrent file // if a creation date is found in the torrent file
// this will be set to that, otherwise it'll be // this will be set to that, otherwise it'll be
// 1970, Jan 1 // 1970, Jan 1
time_t m_creation_date; time_t m_creation_date = 0;
// the hash that identifies this torrent // the hash that identifies this torrent
sha1_hash m_info_hash; sha1_hash m_info_hash;
// the number of bytes in m_info_section // 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 // the index to the first leaf. This is where the hash for the
// first piece is stored // 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 enum flags_t : std::uint8_t
// only one file there are cases where it's impossible {
// to know if it should be written as a multifile torrent // this is used when creating a torrent. If there's
// or not. e.g. test/test there's one file and one directory // only one file there are cases where it's impossible
// and they have the same name. // to know if it should be written as a multifile torrent
bool m_multifile:1; // 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 // this is true if the torrent is private. i.e., is should not
// be announced on the dht // be announced on the dht
bool m_private:1; private_torrent = 2,
// this is true if one of the trackers has an .i2p top // this is true if one of the trackers has an .i2p top
// domain in its hostname. This means the DHT and LSD // domain in its hostname. This means the DHT and LSD
// features are disabled for this torrent (unless the // features are disabled for this torrent (unless the
// settings allows mixing i2p peers with regular peers) // settings allows mixing i2p peers with regular peers)
bool m_i2p:1; i2p = 4
};
// any combination of values from flags_t enum
std::uint8_t m_flags = 0;
}; };
} }

View File

@ -624,9 +624,7 @@ namespace libtorrent
, m_info_hash(t.m_info_hash) , m_info_hash(t.m_info_hash)
, m_info_section_size(t.m_info_section_size) , m_info_section_size(t.m_info_section_size)
, m_merkle_first_leaf(t.m_merkle_first_leaf) , m_merkle_first_leaf(t.m_merkle_first_leaf)
, m_multifile(t.m_multifile) , m_flags(t.m_flags)
, m_private(t.m_private)
, m_i2p(t.m_i2p)
{ {
#if TORRENT_USE_INVARIANT_CHECKS #if TORRENT_USE_INVARIANT_CHECKS
t.check_invariant(); t.check_invariant();
@ -761,14 +759,7 @@ namespace libtorrent
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
torrent_info::torrent_info(lazy_entry const& torrent_file, error_code& ec torrent_info::torrent_info(lazy_entry const& torrent_file, error_code& ec
, int flags) , int const 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_UNUSED(flags); TORRENT_UNUSED(flags);
std::pair<char const*, int> buf = torrent_file.data_section(); std::pair<char const*, int> buf = torrent_file.data_section();
@ -778,14 +769,7 @@ namespace libtorrent
parse_torrent_file(e, ec, 0); parse_torrent_file(e, ec, 0);
} }
torrent_info::torrent_info(lazy_entry const& torrent_file, int flags) torrent_info::torrent_info(lazy_entry const& torrent_file, int const 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_UNUSED(flags); TORRENT_UNUSED(flags);
std::pair<char const*, int> buf = torrent_file.data_section(); std::pair<char const*, int> buf = torrent_file.data_section();
@ -809,13 +793,6 @@ namespace libtorrent
// standard constructor that parses a torrent file // standard constructor that parses a torrent file
torrent_info::torrent_info(entry const& 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<char> tmp; std::vector<char> tmp;
std::back_insert_iterator<std::vector<char> > out(tmp); std::back_insert_iterator<std::vector<char> > out(tmp);
@ -842,14 +819,8 @@ namespace libtorrent
#endif #endif
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
torrent_info::torrent_info(bdecode_node const& torrent_file, int flags) torrent_info::torrent_info(bdecode_node const& torrent_file
: m_piece_hashes(0) , int const flags)
, m_creation_date(0)
, m_info_section_size(0)
, m_merkle_first_leaf(0)
, m_multifile(false)
, m_private(false)
, m_i2p(false)
{ {
error_code ec; error_code ec;
if (!parse_torrent_file(torrent_file, ec, flags)) if (!parse_torrent_file(torrent_file, ec, flags))
@ -858,14 +829,9 @@ namespace libtorrent
INVARIANT_CHECK; INVARIANT_CHECK;
} }
torrent_info::torrent_info(char const* buffer, int size, int flags) torrent_info::torrent_info(char const* buffer
: m_piece_hashes(0) , int const size
, m_creation_date(0) , int const flags)
, m_info_section_size(0)
, m_merkle_first_leaf(0)
, m_multifile(false)
, m_private(false)
, m_i2p(false)
{ {
error_code ec; error_code ec;
bdecode_node e; bdecode_node e;
@ -878,14 +844,8 @@ namespace libtorrent
INVARIANT_CHECK; INVARIANT_CHECK;
} }
torrent_info::torrent_info(std::string const& filename, int flags) torrent_info::torrent_info(std::string const& filename
: m_piece_hashes(0) , int const flags)
, 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<char> buf; std::vector<char> buf;
error_code ec; error_code ec;
@ -904,14 +864,8 @@ namespace libtorrent
#if TORRENT_USE_WSTRING #if TORRENT_USE_WSTRING
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
torrent_info::torrent_info(std::wstring const& filename, int flags) torrent_info::torrent_info(std::wstring const& filename
: m_piece_hashes(0) , int const flags)
, 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<char> buf; std::vector<char> buf;
std::string utf8; std::string utf8;
@ -940,29 +894,19 @@ namespace libtorrent
#endif // TORRENT_USE_WSTRING #endif // TORRENT_USE_WSTRING
#endif #endif
torrent_info::torrent_info(bdecode_node const& torrent_file, error_code& ec torrent_info::torrent_info(bdecode_node const& torrent_file
, int flags) , error_code& ec
: m_piece_hashes(0) , int const flags)
, m_creation_date(0)
, m_info_section_size(0)
, m_merkle_first_leaf(0)
, m_multifile(false)
, m_private(false)
, m_i2p(false)
{ {
parse_torrent_file(torrent_file, ec, flags); parse_torrent_file(torrent_file, ec, flags);
INVARIANT_CHECK; INVARIANT_CHECK;
} }
torrent_info::torrent_info(char const* buffer, int size, error_code& ec, int flags) torrent_info::torrent_info(char const* buffer
: m_piece_hashes(0) , int const size
, m_creation_date(0) , error_code& ec
, m_info_section_size(0) , int const flags)
, m_merkle_first_leaf(0)
, m_multifile(false)
, m_private(false)
, m_i2p(false)
{ {
bdecode_node e; bdecode_node e;
if (bdecode(buffer, buffer + size, e, ec) != 0) if (bdecode(buffer, buffer + size, e, ec) != 0)
@ -972,14 +916,8 @@ namespace libtorrent
INVARIANT_CHECK; INVARIANT_CHECK;
} }
torrent_info::torrent_info(std::string const& filename, error_code& ec, int flags) torrent_info::torrent_info(std::string const& filename, error_code& ec
: m_piece_hashes(0) , int const flags)
, 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<char> buf; std::vector<char> buf;
int ret = load_file(filename, buf, ec); int ret = load_file(filename, buf, ec);
@ -995,15 +933,9 @@ namespace libtorrent
#if TORRENT_USE_WSTRING #if TORRENT_USE_WSTRING
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
torrent_info::torrent_info(std::wstring const& filename, error_code& ec torrent_info::torrent_info(std::wstring const& filename
, int flags) , error_code& ec
: m_piece_hashes(0) , int const flags)
, 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<char> buf; std::vector<char> buf;
std::string utf8; std::string utf8;
@ -1025,15 +957,8 @@ namespace libtorrent
// will not contain any hashes, comments, creation date // will not contain any hashes, comments, creation date
// just the necessary to use it with piece manager // just the necessary to use it with piece manager
// used for torrents with no metadata // used for torrents with no metadata
torrent_info::torrent_info(sha1_hash const& info_hash, int flags) torrent_info::torrent_info(sha1_hash const& info_hash, int const flags)
: m_piece_hashes(0) : m_info_hash(info_hash)
, 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_UNUSED(flags); TORRENT_UNUSED(flags);
} }
@ -1084,11 +1009,6 @@ namespace libtorrent
m_orig_files.reset(new file_storage(m_files)); 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) void torrent_info::swap(torrent_info& ti)
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
@ -1107,19 +1027,11 @@ namespace libtorrent
swap(m_piece_hashes, ti.m_piece_hashes); swap(m_piece_hashes, ti.m_piece_hashes);
m_info_dict.swap(ti.m_info_dict); m_info_dict.swap(ti.m_info_dict);
swap(m_merkle_tree, ti.m_merkle_tree); swap(m_merkle_tree, ti.m_merkle_tree);
std::swap(m_info_section_size, ti.m_info_section_size); swap(m_info_section_size, ti.m_info_section_size);
swap(m_merkle_first_leaf, ti.m_merkle_first_leaf);
std::uint32_t tmp; swap(m_flags, ti.m_flags);
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);
} }
#undef SWAP
std::string torrent_info::ssl_cert() const std::string torrent_info::ssl_cert() const
{ {
// this is parsed lazily // this is parsed lazily
@ -1201,13 +1113,13 @@ namespace libtorrent
if (!extract_single_file(info, files, "", info_ptr_diff, true, ec)) if (!extract_single_file(info, files, "", info_ptr_diff, true, ec))
return false; return false;
m_multifile = false; m_flags &= ~multifile;
} }
else else
{ {
if (!extract_files(files_node, files, name, info_ptr_diff, ec)) if (!extract_files(files_node, files, name, info_ptr_diff, ec))
return false; return false;
m_multifile = true; m_flags |= multifile;
} }
TORRENT_ASSERT(!files.name().empty()); TORRENT_ASSERT(!files.name().empty());
@ -1246,20 +1158,21 @@ namespace libtorrent
ec = errors::torrent_invalid_hashes; ec = errors::torrent_invalid_hashes;
return false; return false;
} }
int num_leafs = merkle_num_leafs(files.num_pieces()); if (files.num_pieces() >= std::numeric_limits<int>::max()/2)
int num_nodes = merkle_num_nodes(num_leafs);
if (num_nodes - num_leafs >= (2<<24))
{ {
ec = errors::too_many_pieces_in_torrent; ec = errors::too_many_pieces_in_torrent;
return false; 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_first_leaf = num_nodes - num_leafs;
m_merkle_tree.resize(num_nodes); m_merkle_tree.resize(num_nodes);
std::memset(&m_merkle_tree[0], 0, num_nodes * 20); std::memset(&m_merkle_tree[0], 0, num_nodes * 20);
m_merkle_tree[0].assign(root_hash.string_ptr()); 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 #ifndef TORRENT_DISABLE_MUTABLE_TORRENTS
bdecode_node similar = info.dict_find_list("similar"); bdecode_node similar = info.dict_find_list("similar");
@ -1483,7 +1396,7 @@ namespace libtorrent
e.fail_limit = 0; e.fail_limit = 0;
e.source = announce_entry::source_torrent; e.source = announce_entry::source_torrent;
#if TORRENT_USE_I2P #if TORRENT_USE_I2P
if (is_i2p_url(e.url)) m_i2p = true; if (is_i2p_url(e.url)) m_flags |= i2p;
#endif #endif
m_urls.push_back(e); m_urls.push_back(e);
} }
@ -1515,7 +1428,7 @@ namespace libtorrent
e.source = announce_entry::source_torrent; e.source = announce_entry::source_torrent;
e.trim(); e.trim();
#if TORRENT_USE_I2P #if TORRENT_USE_I2P
if (is_i2p_url(e.url)) m_i2p = true; if (is_i2p_url(e.url)) m_flags |= i2p;
#endif #endif
if (!e.url.empty()) m_urls.push_back(e); 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 ent(maybe_url_encode(url_seeds.string_value())
, web_seed_entry::url_seed); , 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); m_web_seeds.push_back(ent);
} }
else if (url_seeds && url_seeds.type() == bdecode_node::list_t) else if (url_seeds && url_seeds.type() == bdecode_node::list_t)
@ -1565,7 +1478,7 @@ namespace libtorrent
if (url.string_length() == 0) continue; if (url.string_length() == 0) continue;
web_seed_entry ent(maybe_url_encode(url.string_value()) web_seed_entry ent(maybe_url_encode(url.string_value())
, web_seed_entry::url_seed); , 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; if (unique.count(ent.url)) continue;
unique.insert(ent.url); unique.insert(ent.url);
m_web_seeds.push_back(ent); m_web_seeds.push_back(ent);