improve magnet link support. in RSS feeds for instance. Parsing of magnet links was factored out and moved to the proper place, in session_impl::add_torrent

This commit is contained in:
Arvid Norberg 2012-03-08 09:54:44 +00:00
parent 9bd40e950b
commit 341967dab7
10 changed files with 129 additions and 67 deletions

View File

@ -4,6 +4,8 @@
#include <list>
#include <string>
#include "Python.h"
#include <cctype>
#include <boost/python.hpp>
#include <libtorrent/session.hpp>
#include <libtorrent/settings.hpp> // for bencode_map_entry
@ -154,12 +156,6 @@ namespace
if (params.has_key("ti"))
p.ti = extract<intrusive_ptr<torrent_info> >(params["ti"]);
std::string url;
if (params.has_key("tracker_url"))
{
string_storage.push_back(extract<std::string>(params["tracker_url"]));
p.tracker_url = string_storage.back().c_str();
}
if (params.has_key("info_hash"))
p.info_hash = extract<sha1_hash>(params["info_hash"]);
if (params.has_key("name"))
@ -179,7 +175,28 @@ namespace
if (params.has_key("storage_mode"))
p.storage_mode = extract<storage_mode_t>(params["storage_mode"]);
if (params.has_key("tracker_url"))
{
list l = extract<list>(params["trackers"]);
int n = boost::python::len(l);
for(int i = 0; i < n; i++)
p.trackers.push_back(extract<std::string>(l[i]));
}
if (params.has_key("dht_nodes"))
{
list l = extract<list>(params["dht_nodes"]);
int n = boost::python::len(l);
for(int i = 0; i < n; i++)
p.dht_nodes.push_back(extract<std::pair<std::string, int> >(l[i]));
}
#ifndef TORRENT_NO_DEPRECATE
std::string url;
if (params.has_key("tracker_url"))
{
string_storage.push_back(extract<std::string>(params["tracker_url"]));
p.tracker_url = string_storage.back().c_str();
}
if (params.has_key("seed_mode"))
p.seed_mode = params["seed_mode"];
if (params.has_key("upload_mode"))

View File

@ -399,10 +399,14 @@ async_add_torrent() add_torrent()
int version;
boost::intrusive_ptr<torrent_info> ti;
#ifndef TORRENT_NO_DEPRECATE
char const* tracker_url;
#endif
std::vector<std::string> trackers;
std::vector<std::pair<std::string, int> > dht_nodes;
sha1_hash info_hash;
char const* name;
fs::path save_path;
std::string name;
std::string save_path;
std::vector<char>* resume_data;
storage_mode_t storage_mode;
storage_constructor_type storage;
@ -438,18 +442,22 @@ torrent file), the ``info_hash`` (the info hash of the torrent) or the ``url``
info-hash, the torrent file will be downloaded from peers, which requires them to
support the metadata extension. For the metadata extension to work, libtorrent must
be built with extensions enabled (``TORRENT_DISABLE_EXTENSIONS`` must not be
defined). It also takes an optional ``name`` argument. This may be 0 in case no
name should be assigned to the torrent. In case it's not 0, the name is used for
defined). It also takes an optional ``name`` argument. This may be left empty in case no
name should be assigned to the torrent. In case it's not, the name is used for
the torrent as long as it doesn't have metadata. See ``torrent_handle::name``.
If the torrent doesn't have a tracker, but relies on the DHT to find peers, the
``tracker_url`` can be 0, otherwise you might specify a tracker url that tracks this
torrent.
``trackers`` (or the deprecated ``tracker_url``) can specify tracker urls that
for the torrent.
If you specify a ``url``, the torrent will be set in ``downloading_metadata`` state
until the .torrent file has been downloaded. If there's any error while downloading,
the torrent will be stopped and the torrent error state (``torrent_status::error``)
will indicate what went wrong. The ``url`` may also refer to a magnet link.
will indicate what went wrong. The ``url`` may refer to a magnet link or a regular
http URL.
``dht_nodes`` is a list of hostname and port pairs, representing DHT nodes to be
added to the session (if DHT is enabled). The hostname may be an IP address.
If the torrent you are trying to add already exists in the session (is either queued
for checking, being checked or downloading) ``add_torrent()`` will throw
@ -6031,6 +6039,8 @@ it will throw libtorrent_exception_.
add_magnet_uri()
----------------
*deprecated*
::
torrent_handle add_magnet_uri(session& ses, std::string const& uri
@ -6052,6 +6062,16 @@ link through ``add_torrent_params::url`` argument to ``session::add_torrent()``.
For more information about magnet links, see `magnet links`_.
parse_magnet_uri()
------------------
::
void parse_magnet_uri(std::string const& uri, add_torrent_params& p, error_code& ec);
This function parses out information from the magnet link and populates the
``add_torrent_params`` object.
make_magnet_uri()
-----------------

View File

@ -49,8 +49,9 @@ namespace libtorrent
{
add_torrent_params(storage_constructor_type sc = default_storage_constructor)
: version(LIBTORRENT_VERSION_NUM)
#ifndef TORRENT_NO_DEPRECATE
, tracker_url(0)
, name(0)
#endif
, resume_data(0)
, storage_mode(storage_mode_sparse)
, storage(sc)
@ -114,9 +115,13 @@ namespace libtorrent
// libtorrent version. Used for forward binary compatibility
int version;
boost::intrusive_ptr<torrent_info> ti;
#ifndef TORRENT_NO_DEPRECATE
char const* tracker_url;
#endif
std::vector<std::string> trackers;
std::vector<std::pair<std::string, int> > dht_nodes;
sha1_hash info_hash;
char const* name;
std::string name;
std::string save_path;
std::vector<char>* resume_data;
storage_mode_t storage_mode;

View File

@ -46,23 +46,31 @@ namespace libtorrent
std::string TORRENT_EXPORT make_magnet_uri(torrent_handle const& handle);
std::string TORRENT_EXPORT make_magnet_uri(torrent_info const& info);
#ifndef BOOST_NO_EXCEPTIONS
#ifndef TORRENT_NO_DEPRECATE
#ifndef BOOST_NO_EXCEPTIONS
// deprecated in 0.14
TORRENT_DEPRECATED_PREFIX
torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::string const& uri
, std::string const& save_path
, storage_mode_t storage_mode = storage_mode_sparse
, bool paused = false
, storage_constructor_type sc = default_storage_constructor
, void* userdata = 0) TORRENT_DEPRECATED;
// deprecated in 0.16. Instead, pass in the magnet link as add_torrent_params::url
TORRENT_DEPRECATED_PREFIX
torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::string const& uri
, add_torrent_params p) TORRENT_DEPRECATED;
#endif
// deprecated in 0.16. Instead, pass in the magnet link as add_torrent_params::url
TORRENT_DEPRECATED_PREFIX
torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::string const& uri
, add_torrent_params p);
, add_torrent_params p, error_code& ec) TORRENT_DEPRECATED;
#endif
torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::string const& uri
, add_torrent_params p, error_code& ec);
TORRENT_EXPORT void parse_magnet_uri(std::string const& uri, add_torrent_params& p, error_code& ec);
}
#endif

View File

@ -137,8 +137,16 @@ namespace libtorrent
return ret;
}
#endif
torrent_handle add_magnet_uri(session& ses, std::string const& uri
, add_torrent_params p, error_code& ec)
{
parse_magnet_uri(uri, p, ec);
if (ec) return torrent_handle();
return ses.add_torrent(p, ec);
}
void parse_magnet_uri(std::string const& uri, add_torrent_params& p, error_code& ec)
{
std::string name;
std::string tracker;
@ -146,21 +154,32 @@ namespace libtorrent
error_code e;
std::string display_name = url_has_argument(uri, "dn");
if (!display_name.empty()) name = unescape_string(display_name.c_str(), e);
// parse trackers out of the magnet link
std::string::size_type pos = std::string::npos;
std::string tracker_string = url_has_argument(uri, "tr", &pos);
if (!tracker_string.empty()) tracker = unescape_string(tracker_string.c_str(), e);
do
{
pos = uri.find("&tr=", pos);
if (pos == std::string::npos) break;
pos += 4;
error_code e;
std::string url = unescape_string(uri.substr(pos, uri.find('&', pos) - pos), e);
if (e) continue;
p.trackers.push_back(url);
}
while (pos != std::string::npos);
std::string btih = url_has_argument(uri, "xt");
if (btih.empty())
{
ec = errors::missing_info_hash_in_uri;
return torrent_handle();
return;
}
if (btih.compare(0, 9, "urn:btih:") != 0)
{
ec = errors::missing_info_hash_in_uri;
return torrent_handle();
return;
}
#ifndef TORRENT_DISABLE_DHT
@ -173,7 +192,7 @@ namespace libtorrent
{
int port = atoi(node.c_str()+divider+1);
if (port != 0)
ses.add_dht_node(std::make_pair(node.substr(0, divider), port));
p.dht_nodes.push_back(std::make_pair(node.substr(0, divider), port));
}
node_pos = uri.find("&dht=", node_pos);
@ -187,26 +206,8 @@ namespace libtorrent
if (btih.size() == 40 + 9) from_hex(&btih[9], 40, (char*)&info_hash[0]);
else info_hash.assign(base32decode(btih.substr(9)));
if (!tracker.empty()) p.tracker_url = tracker.c_str();
p.info_hash = info_hash;
if (!name.empty()) p.name = name.c_str();
torrent_handle ret = ses.add_torrent(p, ec);
int tier = 1;
// there might be more trackers in the url
while (pos != std::string::npos)
{
pos = uri.find("&tr=", pos);
if (pos == std::string::npos) break;
pos += 4;
error_code e;
std::string url = unescape_string(uri.substr(pos, uri.find('&', pos) - pos), e);
if (e) continue;
announce_entry ae(url);
ae.tier = tier++;
ret.add_tracker(ae);
}
return ret;
if (!name.empty()) p.name = name;
}
}

View File

@ -391,7 +391,6 @@ void feed::on_feed(error_code const& ec
p.name = i->title.c_str();
error_code e;
// #error session_impl::add_torrent doesn't support magnet links via url
torrent_handle h = m_ses.add_torrent(p, e);
m_ses.m_alerts.post_alert(add_torrent_alert(h, p, e));
m_added.insert(make_pair(i->url, now));

View File

@ -591,13 +591,6 @@ namespace libtorrent
#ifndef BOOST_NO_EXCEPTIONS
torrent_handle session::add_torrent(add_torrent_params const& params)
{
if (string_begins_no_case("magnet:", params.url.c_str()))
{
add_torrent_params p(params);
p.url.clear();
return add_magnet_uri(*this, params.url, p);
}
error_code ec;
TORRENT_SYNC_CALL_RET2(torrent_handle, add_torrent, params, boost::ref(ec));
if (ec) throw libtorrent_exception(ec);
@ -608,13 +601,6 @@ namespace libtorrent
torrent_handle session::add_torrent(add_torrent_params const& params, error_code& ec)
{
ec.clear();
if (string_begins_no_case("magnet:", params.url.c_str()))
{
add_torrent_params p(params);
p.url.clear();
return add_magnet_uri(*this, params.url, p, ec);
}
TORRENT_SYNC_CALL_RET2(torrent_handle, add_torrent, params, boost::ref(ec));
return r;
}
@ -623,8 +609,6 @@ namespace libtorrent
{
add_torrent_params* p = new add_torrent_params(params);
if (params.resume_data) p->resume_data = new std::vector<char>(*params.resume_data);
if (params.tracker_url) p->tracker_url = strdup(params.tracker_url);
if (params.name) p->name = strdup(params.name);
TORRENT_ASYNC_CALL1(async_add_torrent, p);
}

View File

@ -81,6 +81,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/build_config.hpp"
#include "libtorrent/extensions.hpp"
#include "libtorrent/random.hpp"
#include "libtorrent/magnet_uri.hpp"
#if defined TORRENT_STATS && defined __MACH__
#include <mach/task.h>
@ -4724,26 +4725,42 @@ namespace aux {
torrent_handle handle = add_torrent(*params, ec);
m_alerts.post_alert(add_torrent_alert(handle, *params, ec));
delete params->resume_data;
free((char*)params->tracker_url);
free((char*)params->name);
delete params;
}
torrent_handle session_impl::add_torrent(add_torrent_params const& params
torrent_handle session_impl::add_torrent(add_torrent_params const& p
, error_code& ec)
{
TORRENT_ASSERT(!params.save_path.empty());
TORRENT_ASSERT(!p.save_path.empty());
#ifndef TORRENT_NO_DEPRECATE
params.update_flags();
p.update_flags();
#endif
add_torrent_params params = p;
if (string_begins_no_case("magnet:", params.url.c_str()))
{
parse_magnet_uri(params.url, params, ec);
if (ec) return torrent_handle();
params.url.clear();
}
if (params.ti && params.ti->is_valid() && params.ti->num_files() == 0)
{
ec = errors::no_files_in_torrent;
return torrent_handle();
}
#ifndef TORRENT_DISABLE_DHT
// add p.dht_nodes to the DHT, if enabled
if (m_dht && !p.dht_nodes.empty())
{
for (std::vector<std::pair<std::string, int> >::const_iterator i = p.dht_nodes.begin()
, end(p.dht_nodes.end()); i != end; ++i)
m_dht->add_node(*i);
}
#endif
// INVARIANT_CHECK;
if (is_aborted())

View File

@ -520,7 +520,7 @@ namespace libtorrent
}
else
{
if (p.name) m_name.reset(new std::string(p.name));
if (!p.name.empty()) m_name.reset(new std::string(p.name));
}
if (!m_url.empty() && m_uuid.empty()) m_uuid = m_url;
@ -554,6 +554,7 @@ namespace libtorrent
if (!m_name && !m_url.empty()) m_name.reset(new std::string(m_url));
#ifndef TORRENT_NO_DEPRECATE
if (p.tracker_url && std::strlen(p.tracker_url) > 0)
{
m_trackers.push_back(announce_entry(p.tracker_url));
@ -561,6 +562,16 @@ namespace libtorrent
m_trackers.back().source = announce_entry::source_magnet_link;
m_torrent_file->add_tracker(p.tracker_url);
}
#endif
for (std::vector<std::string>::const_iterator i = p.trackers.begin()
, end(p.trackers.end()); i != end; ++i)
{
m_trackers.push_back(announce_entry(*i));
m_trackers.back().fail_limit = 0;
m_trackers.back().source = announce_entry::source_magnet_link;
m_torrent_file->add_tracker(*i);
}
if (settings().prefer_udp_trackers)
prioritize_udp_trackers();

View File

@ -1132,7 +1132,7 @@ int test_main()
TEST_CHECK(f.open("test_file", file::read_write, ec));
#endif
TEST_CHECK(!ec);
file::iovec_t b = {"test", 4};
file::iovec_t b = {(void*)"test", 4};
TEST_CHECK(f.writev(0, &b, 1, ec) == 4);
TEST_CHECK(!ec);
char test_buf[5] = {0};