improve support for loading torrents out of resume files

This commit is contained in:
Arvid Norberg 2012-11-08 02:07:10 +00:00
parent 5d21c6a1f4
commit 65e02c23e8
5 changed files with 99 additions and 70 deletions

View File

@ -6330,8 +6330,8 @@ The specific alerts are:
torrent_added_alert
-------------------
The ``torrent_added_alert`` is posted once every time a torrent is added.
It doesn't contain any members of its own, but inherits the torrent handle
The ``torrent_added_alert`` is posted once every time a torrent is successfully
added. It doesn't contain any members of its own, but inherits the torrent handle
from its base class.
It's posted when the ``status_notification`` bit is set in the alert mask.
@ -6346,9 +6346,10 @@ It's posted when the ``status_notification`` bit is set in the alert mask.
add_torrent_alert
-----------------
This alert is always posted when a torrent was added via ``async_add_torrent()``
This alert is always posted when a torrent was attempted to be added
and contains the return status of the add operation. The torrent handle of the new
torrent can be found in the base class' ``handle`` member.
torrent can be found in the base class' ``handle`` member. If adding
the torrent failed, ``error`` contains the error code.
::
@ -6362,7 +6363,7 @@ torrent can be found in the base class' ``handle`` member.
``params`` is a copy of the parameters used when adding the torrent, it can be used
to identify which invocation to ``async_add_torrent()`` caused this alert.
``error`` is set to the error, if any, adding the torrent.
``error`` is set to the error, if one occurred while adding the torrent.
torrent_removed_alert
@ -6373,6 +6374,14 @@ the torrent handle in its baseclass will always be invalid (since the torrent
is already removed) it has the info hash as a member, to identify it.
It's posted when the ``status_notification`` bit is set in the alert mask.
Even though the ``handle`` member doesn't point to an existing torrent anymore,
it is still useful for comparing to other handles, which may also no
longer point to existing torrents, but to the same non-existing torrents.
The ``torrent_handle`` acts as a ``weak_ptr``, even though its object no
longer exists, it can still compare equal to another weak pointer which
points to the same non-existent object.
::
struct torrent_removed_alert: torrent_alert

View File

@ -348,6 +348,7 @@ namespace libtorrent
bool is_listening() const;
torrent_handle add_torrent(add_torrent_params const&, error_code& ec);
torrent_handle add_torrent_impl(add_torrent_params const&, error_code& ec);
void async_add_torrent(add_torrent_params* params);
void remove_torrent(torrent_handle const& h, int options);

View File

@ -624,7 +624,12 @@ namespace libtorrent {
}
else
{
snprintf(msg, sizeof(msg), "added torrent: %s", !params.url.empty() ? params.url.c_str() : params.ti->name().c_str());
snprintf(msg, sizeof(msg), "added torrent: %s"
, !params.url.empty() ? params.url.c_str()
: params.ti ? params.ti->name().c_str()
: !params.name.empty() ? params.name.c_str()
: !params.uuid.empty() ? params.uuid.c_str()
: "");
}
return msg;
}

View File

@ -4916,13 +4916,20 @@ retry:
{
error_code ec;
torrent_handle handle = add_torrent(*params, ec);
m_alerts.post_alert(add_torrent_alert(handle, *params, ec));
delete params->resume_data;
delete params;
}
torrent_handle session_impl::add_torrent(add_torrent_params const& p
, error_code& ec)
{
torrent_handle h = add_torrent_impl(p, ec);
m_alerts.post_alert(add_torrent_alert(h, p, ec));
return h;
}
torrent_handle session_impl::add_torrent_impl(add_torrent_params const& p
, error_code& ec)
{
TORRENT_ASSERT(!p.save_path.empty());
@ -4978,6 +4985,76 @@ retry:
}
else ih = &params.info_hash;
// we don't have a torrent file. If the user provided
// resume data, there may be some metadata in there
if ((!params.ti || !params.ti->is_valid())
&& params.resume_data)
{
int pos;
error_code ec;
lazy_entry tmp;
lazy_entry const* info = 0;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
debug_log("adding magnet link with resume data");
#endif
if (lazy_bdecode(&(*params.resume_data)[0], &(*params.resume_data)[0]
+ params.resume_data->size(), tmp, ec, &pos) == 0
&& tmp.type() == lazy_entry::dict_t
&& (info = tmp.dict_find_dict("info")))
{
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
debug_log("found metadata in resume data");
#endif
// verify the info-hash of the metadata stored in the resume file matches
// the torrent we're loading
std::pair<char const*, int> buf = info->data_section();
sha1_hash resume_ih = hasher(buf.first, buf.second).final();
// if url is set, the info_hash is not actually the info-hash of the
// torrent, but the hash of the URL, until we have the full torrent
// only require the info-hash to match if we actually passed in one
if (resume_ih == params.info_hash
|| !params.url.empty()
|| params.info_hash.is_all_zeros())
{
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
debug_log("info-hash matched");
#endif
params.ti = new torrent_info(resume_ih);
if (params.ti->parse_info_section(*info, ec, 0))
{
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
debug_log("successfully loaded metadata from resume file");
#endif
// make the info-hash be the one in the resume file
params.info_hash = resume_ih;
ih = &params.info_hash;
}
else
{
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
debug_log("failed to load metadata from resume file: %s"
, ec.message().c_str());
#endif
}
}
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
else
{
debug_log("metadata info-hash failed");
}
#endif
}
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
else
{
debug_log("no metadata found");
}
#endif
}
// is the torrent already active?
boost::shared_ptr<torrent> torrent_ptr = find_torrent(*ih).lock();
if (!torrent_ptr && !params.uuid.empty()) torrent_ptr = find_torrent(params.uuid).lock();

View File

@ -446,69 +446,6 @@ namespace libtorrent
// extension. Make sure that when we save resume data for this
// torrent, we also save the metadata
m_magnet_link = true;
// did the user provide resume data?
// maybe the metadata is in there
if (p.resume_data)
{
int pos;
error_code ec;
lazy_entry tmp;
lazy_entry const* info = 0;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
debug_log("adding magnet link with resume data");
#endif
if (lazy_bdecode(&(*p.resume_data)[0], &(*p.resume_data)[0]
+ p.resume_data->size(), tmp, ec, &pos) == 0
&& tmp.type() == lazy_entry::dict_t
&& (info = tmp.dict_find_dict("info")))
{
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
debug_log("found metadata in resume data");
#endif
// verify the info-hash of the metadata stored in the resume file matches
// the torrent we're loading
std::pair<char const*, int> buf = info->data_section();
sha1_hash resume_ih = hasher(buf.first, buf.second).final();
// if url is set, the info_hash is not actually the info-hash of the
// torrent, but the hash of the URL, until we have the full torrent
if (resume_ih == info_hash || !p.url.empty())
{
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
debug_log("info-hash matched");
#endif
m_torrent_file = (p.ti ? p.ti : new torrent_info(resume_ih));
if (!m_torrent_file->parse_info_section(*info, ec, 0))
{
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
debug_log("failed to load metadata from resume file: %s"
, ec.message().c_str());
#endif
}
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
else
{
debug_log("successfully loaded metadata from resume file");
}
#endif
}
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
else
{
debug_log("metadata info-hash failed");
}
#endif
}
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
else
{
debug_log("no metadata found");
}
#endif
}
}
if (!m_torrent_file)