diff --git a/docs/manual.rst b/docs/manual.rst index 33ccc07a4..0fce2d5cd 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -1641,6 +1641,7 @@ Its declaration looks like this:: void auto_managed(bool m) const; bool has_metadata() const; + bool set_metadata(char const* buf, int size) const; boost::filesystem::path save_path() const; void move_storage(boost::filesystem::path const& save_path) const; @@ -1980,17 +1981,26 @@ is_auto_managed() auto_managed() ``auto_managed()`` changes whether the torrent is auto managed or not. For more info, see queuing_. -has_metadata() --------------- +has_metadata() set_metadata() +----------------------------- :: bool has_metadata() const; + bool set_metadata(char const* buf, int size) const; + +``has_metadata`` returns true if this torrent has metadata (either it was started from a +.torrent file or the metadata has been downloaded). The only scenario where this can return +false is when the torrent was started torrent-less (i.e. with just an info-hash and tracker +ip). Note that if the torrent doesn't have metadata, the member `get_torrent_info()`_ will +throw. + +``set_metadata`` expects the *info* section of metadata. i.e. The buffer passed in will be +hashed and verified against the info-hash. If it fails, a ``metadata_failed_alert`` will be +generated. If it passes, a ``metadata_received_alert`` is generated. The function returns +true if the metadata is successfully set on the torrent, and false otherwise. If the torrent +already has metadata, this function will not affect the torrent, and false will be returned. -Returns true if this torrent has metadata (either it was started from a .torrent file or the -metadata has been downloaded). The only scenario where this can return false is when the torrent -was started torrent-less (i.e. with just an info-hash and tracker ip). Note that if the torrent -doesn't have metadata, the member `get_torrent_info()`_ will throw. set_tracker_login() ------------------- diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 168b10413..e2b0078c9 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -638,7 +638,7 @@ namespace libtorrent // to the checker thread for initial checking // of the storage. // a return value of false indicates an error - bool set_metadata(lazy_entry const& metadata, std::string& error); + bool set_metadata(char const* metadata_buf, int metadata_size); int sequence_number() const { return m_sequence_number; } diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 87b3e984a..b35628e15 100644 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -341,6 +341,7 @@ namespace libtorrent #endif bool has_metadata() const; + bool set_metadata(char const* metadata, int size) const; const torrent_info& get_torrent_info() const; bool is_valid() const; diff --git a/src/metadata_transfer.cpp b/src/metadata_transfer.cpp index fe47a88a6..99857f9bd 100644 --- a/src/metadata_transfer.cpp +++ b/src/metadata_transfer.cpp @@ -160,11 +160,7 @@ namespace libtorrent { namespace if (!have_all) return false; - hasher h; - h.update(&m_metadata[0], m_metadata_size); - sha1_hash info_hash = h.final(); - - if (info_hash != m_torrent.torrent_file().info_hash()) + if (!m_torrent.set_metadata(&m_metadata[0], m_metadata_size)) { std::fill( m_have_metadata.begin() @@ -172,26 +168,6 @@ namespace libtorrent { namespace , false); m_metadata_progress = 0; m_metadata_size = 0; - - if (m_torrent.alerts().should_post()) - { - m_torrent.alerts().post_alert(metadata_failed_alert( - m_torrent.get_handle())); - } - - return false; - } - - lazy_entry e; - lazy_bdecode(m_metadata.get(), m_metadata.get() + m_metadata_size, e); - std::string error; - if (!m_torrent.set_metadata(e, error)) - { - // this means the metadata is correct, since we - // verified it against the info-hash, but we - // failed to parse it. Pause the torrent - // TODO: Post an alert! - m_torrent.pause(); return false; } diff --git a/src/torrent.cpp b/src/torrent.cpp index 2fa35a0e4..bbe805beb 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -2953,14 +2953,39 @@ namespace libtorrent return true; } - bool torrent::set_metadata(lazy_entry const& metadata, std::string& error) + bool torrent::set_metadata(char const* metadata_buf, int metadata_size) { INVARIANT_CHECK; - TORRENT_ASSERT(!m_torrent_file->is_valid()); - if (!m_torrent_file->parse_info_section(metadata, error)) + if (m_torrent_file->is_valid()) return false; + + hasher h; + h.update(metadata_buf, metadata_size); + sha1_hash info_hash = h.final(); + + if (info_hash != m_torrent_file->info_hash()) { - // parse failed + if (alerts().should_post()) + { + alerts().post_alert(metadata_failed_alert(get_handle())); + } + return false; + } + + lazy_entry metadata; + std::string error = "parser error"; + int ret = lazy_bdecode(metadata_buf, metadata_buf + metadata_size, metadata); + if (ret != 0 || !m_torrent_file->parse_info_section(metadata, error)) + { + // this means the metadata is correct, since we + // verified it against the info-hash, but we + // failed to parse it. Pause the torrent + if (alerts().should_post()) + { + alerts().post_alert(metadata_failed_alert(get_handle())); + } + set_error("invalid metadata: " + error); + pause(); return false; } diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 80e266bc3..be47b6299 100644 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -235,6 +235,12 @@ namespace libtorrent TORRENT_FORWARD_RETURN(valid_metadata(), false); } + bool torrent_handle::set_metadata(char const* metadata, int size) const + { + INVARIANT_CHECK; + TORRENT_FORWARD_RETURN(set_metadata(metadata, size), false); + } + bool torrent_handle::is_seed() const { INVARIANT_CHECK; diff --git a/src/ut_metadata.cpp b/src/ut_metadata.cpp index 848c3795d..9699afe5e 100644 --- a/src/ut_metadata.cpp +++ b/src/ut_metadata.cpp @@ -131,33 +131,10 @@ namespace libtorrent { namespace if (!have_all) return false; - hasher h; - h.update(&m_metadata[0], m_metadata_size); - sha1_hash info_hash = h.final(); - - if (info_hash != m_torrent.torrent_file().info_hash()) + if (!m_torrent.set_metadata(&m_metadata[0], m_metadata_size)) { - std::fill(m_requested_metadata.begin(), m_requested_metadata.end(), 0); - - if (m_torrent.alerts().should_post()) - { - m_torrent.alerts().post_alert(metadata_failed_alert( - m_torrent.get_handle())); - } - - return false; - } - - lazy_entry metadata; - int ret = lazy_bdecode(m_metadata.get(), m_metadata.get() + m_metadata_size, metadata); - std::string error; - if (!m_torrent.set_metadata(metadata, error)) - { - // this means the metadata is correct, since we - // verified it against the info-hash, but we - // failed to parse it. Pause the torrent - // TODO: Post an alert! - m_torrent.pause(); + if (!m_torrent.valid_metadata()) + std::fill(m_requested_metadata.begin(), m_requested_metadata.end(), 0); return false; }