From 77c0fa5872db38084e806bafe4abce1857985bd5 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Mon, 1 Mar 2010 06:46:57 +0000 Subject: [PATCH] support multiple trackers in magnet links --- ChangeLog | 1 + include/libtorrent/escape_string.hpp | 2 +- src/escape_string.cpp | 4 +++- src/magnet_uri.cpp | 18 +++++++++++++-- test/test_primitives.cpp | 33 +++++++++++++++++++++++++++- 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70c415bbc..2426970fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,7 @@ 0.15 release + * added support for multiple trackers in magnet links * added support for explicitly flushing the disk cache * added torrent priority to affect bandwidth allocation for its peers * reduced the number of floating point operations (to better support diff --git a/include/libtorrent/escape_string.hpp b/include/libtorrent/escape_string.hpp index 042626ce0..439be40e5 100644 --- a/include/libtorrent/escape_string.hpp +++ b/include/libtorrent/escape_string.hpp @@ -72,7 +72,7 @@ namespace libtorrent TORRENT_EXPORT std::string base32decode(std::string const& s); TORRENT_EXPORT std::string url_has_argument( - std::string const& url, std::string argument); + std::string const& url, std::string argument, int* out_pos = 0); // replaces \ with / TORRENT_EXPORT void convert_path_to_posix(std::string& path); diff --git a/src/escape_string.cpp b/src/escape_string.cpp index aae8c4349..49338f507 100644 --- a/src/escape_string.cpp +++ b/src/escape_string.cpp @@ -473,7 +473,7 @@ namespace libtorrent } std::string url_has_argument( - std::string const& url, std::string argument) + std::string const& url, std::string argument, int* out_pos) { size_t i = url.find('?'); if (i == std::string::npos) return std::string(); @@ -484,12 +484,14 @@ namespace libtorrent if (url.compare(i, argument.size(), argument) == 0) { size_t pos = i + argument.size(); + if (out_pos) *out_pos = pos; return url.substr(pos, url.find('&', pos) - pos); } argument.insert(0, "&"); i = url.find(argument, i); if (i == std::string::npos) return std::string(); size_t pos = i + argument.size(); + if (out_pos) *out_pos = pos; return url.substr(pos, url.find('&', pos) - pos); } diff --git a/src/magnet_uri.cpp b/src/magnet_uri.cpp index 793e03ef3..81982ca63 100644 --- a/src/magnet_uri.cpp +++ b/src/magnet_uri.cpp @@ -146,7 +146,8 @@ 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); - std::string tracker_string = url_has_argument(uri, "tr"); + int 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); std::string btih = url_has_argument(uri, "xt"); @@ -169,7 +170,20 @@ namespace libtorrent if (!tracker.empty()) p.tracker_url = tracker.c_str(); p.info_hash = info_hash; if (!name.empty()) p.name = name.c_str(); - return ses.add_torrent(p, ec); + 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; + announce_entry ae(uri.substr(pos, uri.find('&', pos) - pos)); + ae.tier = tier++; + ret.add_tracker(ae); + } + return ret; } } diff --git a/test/test_primitives.cpp b/test/test_primitives.cpp index 73fa9d71e..a7d197469 100644 --- a/test/test_primitives.cpp +++ b/test/test_primitives.cpp @@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. */ +#include "libtorrent/magnet_uri.hpp" #include "libtorrent/parse_url.hpp" #include "libtorrent/http_tracker_connection.hpp" #include "libtorrent/buffer.hpp" @@ -419,7 +420,37 @@ int test_main() */ entry session_state; s->save_state(session_state); - + + // test magnet link parsing + add_torrent_params p; + p.save_path = "."; + error_code ec; + const char* magnet_uri = "magnet:?xt=urn:btih:cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" + "&tr=http://1&tr=http://2&tr=http://3&dn=foo"; + torrent_handle t = add_magnet_uri(*s, magnet_uri, p, ec); + TEST_CHECK(!ec); + if (ec) fprintf(stderr, "%s\n", ec.message().c_str()); + + std::vector trackers = t.trackers(); + TEST_EQUAL(trackers.size(), 3); + if (trackers.size() > 0) + { + TEST_EQUAL(trackers[0].url, "http://1"); + fprintf(stderr, "1: %s\n", trackers[0].url.c_str()); + } + if (trackers.size() > 1) + { + TEST_EQUAL(trackers[1].url, "http://2"); + fprintf(stderr, "2: %s\n", trackers[1].url.c_str()); + } + if (trackers.size() > 2) + { + TEST_EQUAL(trackers[2].url, "http://3"); + fprintf(stderr, "3: %s\n", trackers[2].url.c_str()); + } + + TEST_EQUAL(to_hex(t.info_hash().to_string()), "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"); + delete s; s = new session(fingerprint("LT",0,0,0,0), 0);