[Libtorrent-commits] SF.net SVN: libtorrent:[10627] branches/mutable_torrents
Brought to you by:
arvidn
From: <ar...@us...> - 2014-12-19 12:32:41
|
Revision: 10627 http://sourceforge.net/p/libtorrent/code/10627 Author: arvidn Date: 2014-12-19 12:32:32 +0000 (Fri, 19 Dec 2014) Log Message: ----------- mutable torrent support in torrent_info and create_torrent Modified Paths: -------------- branches/mutable_torrents/include/libtorrent/create_torrent.hpp branches/mutable_torrents/include/libtorrent/torrent_info.hpp branches/mutable_torrents/src/create_torrent.cpp branches/mutable_torrents/src/torrent_info.cpp branches/mutable_torrents/test/test_torrent_info.cpp Modified: branches/mutable_torrents/include/libtorrent/create_torrent.hpp =================================================================== --- branches/mutable_torrents/include/libtorrent/create_torrent.hpp 2014-12-19 09:28:23 UTC (rev 10626) +++ branches/mutable_torrents/include/libtorrent/create_torrent.hpp 2014-12-19 12:32:32 UTC (rev 10627) @@ -279,6 +279,17 @@ // tree will be saved in the resume data. std::vector<sha1_hash> const& merkle_tree() const { return m_merkle_tree; } + // Add similar torrents (by info-hash) or collections of similar torrents. + // Similar torrents are expected to share some files with this torrent. + // Torrents sharing a collection name with this torrent are also expected + // to share files with this torrent. A torrent may have more than one + // collection and more than one similar torrents. For more information, + // see `BEP 38`_. + // + // .. _`BEP 38`: http://www.bittorrent.org/beps/bep_0038.html + void add_similar_torrent(sha1_hash ih); + void add_collection(std::string c); + private: file_storage& m_files; @@ -298,6 +309,9 @@ std::vector<sha1_hash> m_filehashes; + std::vector<sha1_hash> m_similar; + std::vector<std::string> m_collections; + // if we're generating a merkle torrent, this is the // merkle tree we got. This should be saved in fast-resume // in order to start seeding the torrent Modified: branches/mutable_torrents/include/libtorrent/torrent_info.hpp =================================================================== --- branches/mutable_torrents/include/libtorrent/torrent_info.hpp 2014-12-19 09:28:23 UTC (rev 10626) +++ branches/mutable_torrents/include/libtorrent/torrent_info.hpp 2014-12-19 12:32:32 UTC (rev 10627) @@ -443,6 +443,16 @@ void add_tracker(std::string const& url, int tier = 0); std::vector<announce_entry> const& trackers() const { return m_urls; } + // These two functions are related to BEP38_ (mutable torrents). The + // vectors returned from these correspond to the "similar" and + // "collections" keys in the .torrent file. Both info-hashes and + // collections from within the info-dict and from outside of it are + // included. + // + // .. _BEP38: http://www.bittorrent.org/beps/bep_0038.html + std::vector<sha1_hash> similar_torrents() const; + std::vector<std::string> collections() const; + #ifndef TORRENT_NO_DEPRECATE // deprecated in 0.16. Use web_seeds() instead TORRENT_DEPRECATED_PREFIX @@ -735,6 +745,27 @@ std::vector<web_seed_entry> m_web_seeds; nodes_t m_nodes; + // the info-hashes (20 bytes each) in the "similar" key. The pointers + // point directly into the info_section. When copied, these pointers must + // be corrected to point into the copied-to buffer + std::vector<char const*> m_similar_torrents; + + // these are similar torrents from outside of the info-dict. We can't + // have non-owning pointers to those, as we only keep the info-dict + // around. + std::vector<sha1_hash> m_owned_similar_torrents; + + // these or strings of the "collections" key from the torrent file. The + // pointers point directly into the info_section buffer and when copied, + // these pointers must be corrected to point into the new buffer. The + // int is the length of the string. Strings are not NULL-terminated. + std::vector<std::pair<char const*, int> > m_collections; + + // these are the collections from outside of the info-dict. These are + // owning strings, since we only keep the info-section around, these + // cannot be pointers into that buffer. + std::vector<std::string> m_owned_collections; + // if this is a merkle torrent, this is the merkle // tree. It has space for merkle_num_nodes(merkle_num_leafs(num_pieces)) // hashes Modified: branches/mutable_torrents/src/create_torrent.cpp =================================================================== --- branches/mutable_torrents/src/create_torrent.cpp 2014-12-19 09:28:23 UTC (rev 10626) +++ branches/mutable_torrents/src/create_torrent.cpp 2014-12-19 12:32:32 UTC (rev 10627) @@ -426,6 +426,26 @@ } } + if (!m_collections.empty()) + { + entry& list = dict["collections"]; + for (std::vector<std::string>::const_iterator i + = m_collections.begin(); i != m_collections.end(); ++i) + { + list.list().push_back(entry(*i)); + } + } + + if (!m_similar.empty()) + { + entry& list = dict["similar"]; + for (std::vector<sha1_hash>::const_iterator i + = m_similar.begin(); i != m_similar.end(); ++i) + { + list.list().push_back(entry(i->to_string())); + } + } + entry& info = dict["info"]; if (m_info_dict.type() == entry::dictionary_t) { @@ -587,6 +607,16 @@ m_root_cert = cert; } + void create_torrent::add_similar_torrent(sha1_hash ih) + { + m_similar.push_back(ih); + } + + void create_torrent::add_collection(std::string c) + { + m_collections.push_back(c); + } + void create_torrent::set_hash(int index, sha1_hash const& h) { TORRENT_ASSERT(index >= 0); Modified: branches/mutable_torrents/src/torrent_info.cpp =================================================================== --- branches/mutable_torrents/src/torrent_info.cpp 2014-12-19 09:28:23 UTC (rev 10626) +++ branches/mutable_torrents/src/torrent_info.cpp 2014-12-19 12:32:32 UTC (rev 10627) @@ -709,6 +709,12 @@ if (m_orig_files) const_cast<file_storage&>(*m_orig_files).apply_pointer_offset(offset); + for (int i = 0; i < m_collections.size(); ++i) + m_collections[i].first += offset; + + for (int i = 0; i < m_similar_torrents.size(); ++i) + m_similar_torrents[i] += offset; + #if TORRENT_USE_ASSERTS || !defined BOOST_NO_EXCEPTIONS int ret = #endif @@ -1149,7 +1155,6 @@ std::string name; sanitize_append_path_element(name, name_ent->string_ptr(), name_ent->string_length()); - if (name.empty()) name = to_hex(m_info_hash.to_string()); // extract file list @@ -1262,6 +1267,36 @@ m_private = info.dict_find_int_value("private", 0); + lazy_entry const* similar = info.dict_find_list("similar"); + if (similar) + { + for (int i = 0; i < similar->list_size(); ++i) + { + if (similar->list_at(i)->type() != lazy_entry::string_t) + continue; + + if (similar->list_at(i)->string_length() != 20) + continue; + + m_similar_torrents.push_back(similar->list_at(i)->string_ptr() + + info_ptr_diff); + } + } + + lazy_entry const* collections = info.dict_find_list("collections"); + if (collections) + { + for (int i = 0; i < collections->list_size(); ++i) + { + lazy_entry const* str = collections->list_at(i); + + if (str->type() != lazy_entry::string_t) continue; + + m_collections.push_back(std::make_pair(str->string_ptr() + + info_ptr_diff, str->string_length())); + } + } + // now, commit the files structure we just parsed out // into the torrent_info object. // if we already have an m_files that's populated, it @@ -1401,6 +1436,36 @@ if (!parse_info_section(*info, ec, flags)) return false; resolve_duplicate_filenames(); + lazy_entry const* similar = torrent_file.dict_find_list("similar"); + if (similar) + { + for (int i = 0; i < similar->list_size(); ++i) + { + if (similar->list_at(i)->type() != lazy_entry::string_t) + continue; + + if (similar->list_at(i)->string_length() != 20) + continue; + + m_owned_similar_torrents.push_back( + sha1_hash(similar->list_at(i)->string_ptr())); + } + } + + lazy_entry const* collections = torrent_file.dict_find_list("collections"); + if (collections) + { + for (int i = 0; i < collections->list_size(); ++i) + { + lazy_entry const* str = collections->list_at(i); + + if (str->type() != lazy_entry::string_t) continue; + + m_owned_collections.push_back(std::string(str->string_ptr() + , str->string_length())); + } + } + // extract the url of the tracker lazy_entry const* i = torrent_file.dict_find_list("announce-list"); if (i) @@ -1590,22 +1655,49 @@ #endif // TORRENT_NO_DEPRECATE void torrent_info::add_url_seed(std::string const& url - , std::string const& ext_auth - , web_seed_entry::headers_t const& ext_headers) + , std::string const& ext_auth + , web_seed_entry::headers_t const& ext_headers) { m_web_seeds.push_back(web_seed_entry(url, web_seed_entry::url_seed , ext_auth, ext_headers)); } void torrent_info::add_http_seed(std::string const& url - , std::string const& auth - , web_seed_entry::headers_t const& extra_headers) + , std::string const& auth + , web_seed_entry::headers_t const& extra_headers) { m_web_seeds.push_back(web_seed_entry(url, web_seed_entry::http_seed , auth, extra_headers)); } + std::vector<sha1_hash> torrent_info::similar_torrents() const + { + std::vector<sha1_hash> ret; + ret.reserve(m_similar_torrents.size() + m_owned_similar_torrents.size()); + for (int i = 0; i < m_similar_torrents.size(); ++i) + ret.push_back(sha1_hash(m_similar_torrents[i])); + + for (int i = 0; i < m_owned_similar_torrents.size(); ++i) + ret.push_back(m_owned_similar_torrents[i]); + + return ret; + } + + std::vector<std::string> torrent_info::collections() const + { + std::vector<std::string> ret; + ret.reserve(m_collections.size() + m_owned_collections.size()); + + for (int i = 0; i < m_collections.size(); ++i) + ret.push_back(std::string(m_collections[i].first, m_collections[i].second)); + + for (int i = 0; i < m_owned_collections.size(); ++i) + ret.push_back(m_owned_collections[i]); + + return ret; + } + #if !defined TORRENT_NO_DEPRECATE && TORRENT_USE_IOSTREAM // ------- start deprecation ------- Modified: branches/mutable_torrents/test/test_torrent_info.cpp =================================================================== --- branches/mutable_torrents/test/test_torrent_info.cpp 2014-12-19 09:28:23 UTC (rev 10626) +++ branches/mutable_torrents/test/test_torrent_info.cpp 2014-12-19 12:32:32 UTC (rev 10627) @@ -38,6 +38,46 @@ using namespace libtorrent; +void test_mutable_torrents() +{ + file_storage fs; + + fs.add_file("test/temporary.txt", 0x4000); + + libtorrent::create_torrent t(fs, 0x4000); + + // calculate the hash for all pieces + int num = t.num_pieces(); + sha1_hash ph; + for (int i = 0; i < num; ++i) + t.set_hash(i, ph); + + t.add_collection("collection1"); + t.add_collection("collection2"); + + t.add_similar_torrent(sha1_hash("abababababababababab")); + t.add_similar_torrent(sha1_hash("babababababababababa")); + + std::vector<char> tmp; + std::back_insert_iterator<std::vector<char> > out(tmp); + + entry tor = t.generate(); + bencode(out, tor); + + torrent_info ti(&tmp[0], tmp.size()); + + std::vector<sha1_hash> similar; + similar.push_back(sha1_hash("abababababababababab")); + similar.push_back(sha1_hash("babababababababababa")); + + std::vector<std::string> collections; + collections.push_back("collection1"); + collections.push_back("collection2"); + + TEST_CHECK(similar == ti.similar_torrents()); + TEST_CHECK(collections == ti.collections()); +} + void test_storage() { file_storage fs; @@ -138,5 +178,6 @@ { test_storage(); test_copy(); + test_mutable_torrents(); return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |