support web seeds that resolve to multiple IPs

This commit is contained in:
Arvid Norberg 2014-09-28 02:20:13 +00:00
parent 9a985d197f
commit 154cbeb5cf
6 changed files with 53 additions and 17 deletions

View File

@ -1,3 +1,4 @@
* support web seeds that resolve to multiple IPs
* added auto-sequential feature. download well-seeded torrents in-order * added auto-sequential feature. download well-seeded torrents in-order
* removed built-in GeoIP support (this functionality is orthogonal to libtorrent) * removed built-in GeoIP support (this functionality is orthogonal to libtorrent)
* deprecate proxy settings in favor of regular settings * deprecate proxy settings in favor of regular settings

View File

@ -261,8 +261,8 @@ namespace libtorrent
ptime retry; ptime retry;
// if the hostname of the web seed has been resolved, // if the hostname of the web seed has been resolved,
// this is its IP address // these are its IP addresses
tcp::endpoint endpoint; std::vector<tcp::endpoint> endpoints;
// this is the peer_info field used for the // this is the peer_info field used for the
// connection, just to count hash failures // connection, just to count hash failures

View File

@ -81,8 +81,20 @@ namespace libtorrent
#endif #endif
} }
void http_seed_connection::disconnect(error_code const& ec, peer_connection_interface::operation_t op, int error) void http_seed_connection::disconnect(error_code const& ec
, peer_connection_interface::operation_t op, int error)
{ {
if (is_disconnecting()) return;
if (op == peer_connection_interface::op_connect
&& m_web
&& !m_web->endpoints.empty())
{
// we failed to connect to this IP. remove it so that the next attempt
// uses the next IP in the list.
m_web->endpoints.erase(m_web->endpoints.begin());
}
boost::shared_ptr<torrent> t = associated_torrent().lock(); boost::shared_ptr<torrent> t = associated_torrent().lock();
peer_connection::disconnect(ec, op, error); peer_connection::disconnect(ec, op, error);
if (t) t->disconnect_web_seed(this); if (t) t->disconnect_web_seed(this);

View File

@ -3117,6 +3117,9 @@ namespace libtorrent
m_need_save_resume_data = true; m_need_save_resume_data = true;
} }
// TODO: 3 change the tracker_response interface to take a type capturing
// the response. Have multiple peer lists. IPv4, IPv6 and hostnames. That
// way we don't need to render addresses into strings
void torrent::tracker_response( void torrent::tracker_response(
tracker_request const& r tracker_request const& r
, address const& tracker_ip // this is the IP we connected to , address const& tracker_ip // this is the IP we connected to
@ -3464,6 +3467,7 @@ namespace libtorrent
if (e || host_list.empty() || m_ses.is_aborted()) return; if (e || host_list.empty() || m_ses.is_aborted()) return;
// TODO: add one peer per IP the hostname resolves to
tcp::endpoint host(host_list.front(), port); tcp::endpoint host(host_list.front(), port);
if (m_apply_ip_filter if (m_apply_ip_filter
@ -5851,7 +5855,6 @@ namespace libtorrent
peer->set_peer_info(0); peer->set_peer_info(0);
} }
if (has_picker()) picker().clear_peer(&web->peer_info); if (has_picker()) picker().clear_peer(&web->peer_info);
m_web_seeds.erase(web); m_web_seeds.erase(web);
update_want_tick(); update_want_tick();
@ -5965,9 +5968,9 @@ namespace libtorrent
return; return;
} }
if (web->endpoint.port() != 0) if (!web->endpoints.empty())
{ {
connect_web_seed(web, web->endpoint); connect_web_seed(web, web->endpoints.front());
return; return;
} }
@ -6131,16 +6134,22 @@ namespace libtorrent
return; return;
} }
tcp::endpoint a(host->endpoint()); while (host != tcp::resolver::iterator())
{
// fill in the peer struct's address field
web->endpoints.push_back(host->endpoint());
// fill in the peer struct's address field #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
web->endpoint = a; debug_log(" -> %s", print_endpoint(host->endpoint()).c_str());
#endif
++host;
}
if (int(m_connections.size()) >= m_max_connections if (int(m_connections.size()) >= m_max_connections
|| m_ses.num_connections() >= m_ses.settings().get_int(settings_pack::connections_limit)) || m_ses.num_connections() >= m_ses.settings().get_int(settings_pack::connections_limit))
return; return;
connect_web_seed(web, a); connect_web_seed(web, web->endpoints.front());
} }
void torrent::connect_web_seed(std::list<web_seed_entry>::iterator web, tcp::endpoint a) void torrent::connect_web_seed(std::list<web_seed_entry>::iterator web, tcp::endpoint a)
@ -6162,7 +6171,6 @@ namespace libtorrent
TORRENT_ASSERT(web->resolving == false); TORRENT_ASSERT(web->resolving == false);
TORRENT_ASSERT(web->peer_info.connection == 0); TORRENT_ASSERT(web->peer_info.connection == 0);
web->endpoint = a;
if (a.address().is_v4()) if (a.address().is_v4())
{ {
web->peer_info.addr = a.address().to_v4(); web->peer_info.addr = a.address().to_v4();
@ -6245,7 +6253,7 @@ namespace libtorrent
pack.ios = &m_ses.get_io_service(); pack.ios = &m_ses.get_io_service();
pack.tor = shared_from_this(); pack.tor = shared_from_this();
pack.s = s; pack.s = s;
pack.endp = &web->endpoint; pack.endp = &web->endpoints.front();
pack.peerinfo = &web->peer_info; pack.peerinfo = &web->peer_info;
if (web->type == web_seed_entry::url_seed) if (web->type == web_seed_entry::url_seed)
{ {
@ -6299,7 +6307,8 @@ namespace libtorrent
web->peer_info.prev_amount_download = 0; web->peer_info.prev_amount_download = 0;
web->peer_info.prev_amount_upload = 0; web->peer_info.prev_amount_upload = 0;
#if defined TORRENT_VERBOSE_LOGGING #if defined TORRENT_VERBOSE_LOGGING
debug_log("web seed connection started: %s", web->url.c_str()); debug_log("web seed connection started: [%s] %s"
, print_endpoint(a).c_str(), web->url.c_str());
#endif #endif
c->start(); c->start();
@ -10521,8 +10530,11 @@ namespace libtorrent
void torrent::disconnect_web_seed(peer_connection* p) void torrent::disconnect_web_seed(peer_connection* p)
{ {
std::list<web_seed_entry>::iterator i = std::find_if(m_web_seeds.begin(), m_web_seeds.end() std::list<web_seed_entry>::iterator i
, (boost::bind(&torrent_peer::connection, boost::bind(&web_seed_entry::peer_info, _1)) == p)); = std::find_if(m_web_seeds.begin(), m_web_seeds.end()
, (boost::bind(&torrent_peer::connection
, boost::bind(&web_seed_entry::peer_info, _1)) == p));
// this happens if the web server responded with a redirect // this happens if the web server responded with a redirect
// or with something incorrect, so that we removed the web seed // or with something incorrect, so that we removed the web seed
// immediately, before we disconnected // immediately, before we disconnected

View File

@ -63,7 +63,8 @@ namespace libtorrent
, m_body_start(0) , m_body_start(0)
{ {
TORRENT_ASSERT(&web.peer_info == pack.peerinfo); TORRENT_ASSERT(&web.peer_info == pack.peerinfo);
TORRENT_ASSERT(web.endpoint == *pack.endp); TORRENT_ASSERT(!web.endpoints.empty());
TORRENT_ASSERT(web.endpoints.front() == *pack.endp);
INVARIANT_CHECK; INVARIANT_CHECK;

View File

@ -114,10 +114,20 @@ void web_peer_connection::on_connected()
web_connection_base::on_connected(); web_connection_base::on_connected();
} }
void web_peer_connection::disconnect(error_code const& ec, peer_connection_interface::operation_t op, int error) void web_peer_connection::disconnect(error_code const& ec
, peer_connection_interface::operation_t op, int error)
{ {
if (is_disconnecting()) return; if (is_disconnecting()) return;
if (op == peer_connection_interface::op_connect
&& m_web
&& !m_web->endpoints.empty())
{
// we failed to connect to this IP. remove it so that the next attempt
// uses the next IP in the list.
m_web->endpoints.erase(m_web->endpoints.begin());
}
boost::shared_ptr<torrent> t = associated_torrent().lock(); boost::shared_ptr<torrent> t = associated_torrent().lock();
if (!m_requests.empty() && !m_file_requests.empty() if (!m_requests.empty() && !m_file_requests.empty()