support web seeds in magnet links

This commit is contained in:
Arvid Norberg 2014-04-15 09:31:28 +00:00
parent 569fb6705e
commit 9e94a73ddd
4 changed files with 76 additions and 3 deletions

View File

@ -247,6 +247,9 @@ namespace libtorrent
// ``trackers`` can specify tracker URLs for the torrent.
std::vector<std::string> trackers;
// url seeds to be added to the torrent (`BEP 17`_).
std::vector<std::string> url_seeds;
// 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.
std::vector<std::pair<std::string, int> > dht_nodes;

View File

@ -50,7 +50,6 @@ namespace libtorrent
ret += to_hex(ih.to_string());
torrent_status st = handle.status(torrent_handle::query_name);
if (!st.name.empty())
{
ret += "&dn=";
@ -58,13 +57,20 @@ namespace libtorrent
}
std::vector<announce_entry> const& tr = handle.trackers();
for (std::vector<announce_entry>::const_iterator i = tr.begin(), end(tr.end()); i != end; ++i)
{
ret += "&tr=";
ret += escape_string(i->url.c_str(), i->url.length());
}
std::set<std::string> seeds = handle.url_seeds();
for (std::set<std::string>::iterator i = seeds.begin()
, end(seeds.end()); i != end; ++i)
{
ret += "&ws=";
ret += escape_string(i->c_str(), i->length());
}
return ret;
}
@ -91,6 +97,16 @@ namespace libtorrent
ret += escape_string(i->url.c_str(), i->url.length());
}
std::vector<web_seed_entry> const& seeds = info.web_seeds();
for (std::vector<web_seed_entry>::const_iterator i = seeds.begin()
, end(seeds.end()); i != end; ++i)
{
if (i->type != web_seed_entry::url_seed) continue;
ret += "&ws=";
ret += escape_string(i->url.c_str(), i->url.length());
}
return ret;
}
@ -170,7 +186,22 @@ namespace libtorrent
pos += 4;
url = uri.substr(pos, uri.find('&', pos) - pos);
}
// parse web seeds out of the magnet link
pos = std::string::npos;
url = url_has_argument(uri, "ws", &pos);
while (pos != std::string::npos)
{
error_code e;
url = unescape_string(url, e);
if (e) continue;
p.url_seeds.push_back(url);
pos = uri.find("&ws=", pos);
if (pos == std::string::npos) break;
pos += 4;
url = uri.substr(pos, uri.find('&', pos) - pos);
}
std::string btih = url_has_argument(uri, "xt");
if (btih.empty())
{

View File

@ -344,6 +344,13 @@ namespace libtorrent
if (!m_torrent_file)
m_torrent_file = (p.ti ? p.ti : new torrent_info(info_hash));
// add web seeds from add_torrent_params
for (std::vector<std::string>::const_iterator i = p.url_seeds.begin()
, end(p.url_seeds.end()); i != end; ++i)
{
m_web_seeds.push_back(web_seed_entry(*i, web_seed_entry::url_seed));
}
m_trackers = m_torrent_file->trackers();
if (m_torrent_file->is_valid())
{

View File

@ -161,6 +161,14 @@ int test_main()
TEST_CHECK(ec == error_code(errors::missing_info_hash_in_uri));
ec.clear();
// parse_magnet_uri
parse_magnet_uri("magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd&ws=http://foo.com/bar&ws=http://bar.com/foo", p, ec);
TEST_CHECK(!ec);
TEST_EQUAL(p.url_seeds.size(), 2);
TEST_EQUAL(p.url_seeds[0], "http://foo.com/bar");
TEST_EQUAL(p.url_seeds[1], "http://bar.com/foo");
ec.clear();
parse_magnet_uri("magnet:?xt=blah&dn=foo&dht=127.0.0.1:43", p, ec);
TEST_CHECK(ec == error_code(errors::missing_info_hash_in_uri));
ec.clear();
@ -263,6 +271,30 @@ int test_main()
printf("%s len: %d\n", magnet.c_str(), int(magnet.size()));
}
// make_magnet_uri
{
entry info;
info["pieces"] = "aaaaaaaaaaaaaaaaaaaa";
info["name"] = "test";
info["name.utf-8"] = "test";
info["piece length"] = 16 * 1024;
info["length"] = 3245;
entry torrent;
torrent["info"] = info;
torrent["url-list"] = "http://foo.com/bar";
std::vector<char> buf;
bencode(std::back_inserter(buf), torrent);
buf.push_back('\0');
printf("%s\n", &buf[0]);
error_code ec;
torrent_info ti(&buf[0], buf.size(), ec);
std::string magnet = make_magnet_uri(ti);
printf("%s len: %d\n", magnet.c_str(), int(magnet.size()));
TEST_CHECK(magnet.find("&ws=http%3a%2f%2ffoo.com%2fbar") != std::string::npos);
}
return 0;
}