forked from premiere/premiere-libtorrent
improved IPv6 support by announcing twice when necessary
This commit is contained in:
parent
ea671933ab
commit
437cb94fd0
|
@ -1,3 +1,4 @@
|
|||
* improved IPv6 support by announcing twice when necessary
|
||||
* added feature to set a separate global rate limit for local peers
|
||||
* added preset settings for low memory environments and seed machines
|
||||
min_memory_usage() and high_performance_seeder()
|
||||
|
|
|
@ -719,6 +719,7 @@ namespace libtorrent
|
|||
|
||||
void tracker_response(tracker_request const&
|
||||
, libtorrent::address const& tracker_ip
|
||||
, std::list<address> const& ip_list
|
||||
, std::vector<peer_entry>& peers
|
||||
, int interval
|
||||
, int complete
|
||||
|
@ -737,7 +738,7 @@ namespace libtorrent
|
|||
to_hex((const char*)&i->pid[0], 20, pid);
|
||||
if (i->pid.is_all_zeros()) pid[0] = 0;
|
||||
|
||||
snprintf(tmp, 200, " %16s %5d %s\n", i->ip.c_str(), i->port, pid);
|
||||
snprintf(tmp, 200, " %-16s %-5d %s\n", i->ip.c_str(), i->port, pid);
|
||||
s += tmp;
|
||||
}
|
||||
snprintf(tmp, 200, "external ip: %s\n", print_address(external_ip).c_str());
|
||||
|
|
|
@ -122,6 +122,8 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
|
|||
#else
|
||||
socket_type const& socket() const { return m_sock; }
|
||||
#endif
|
||||
|
||||
std::list<tcp::endpoint> const& endpoints() const { return m_endpoints; }
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -70,7 +70,6 @@ namespace libtorrent
|
|||
, connection_queue& cc
|
||||
, tracker_manager& man
|
||||
, tracker_request const& req
|
||||
, address bind_infc
|
||||
, boost::weak_ptr<request_callback> c
|
||||
, aux::session_impl const& ses
|
||||
, proxy_settings const& ps
|
||||
|
@ -97,7 +96,6 @@ namespace libtorrent
|
|||
tracker_manager& m_man;
|
||||
boost::shared_ptr<http_connection> m_tracker_connection;
|
||||
aux::session_impl const& m_ses;
|
||||
address m_bind_iface;
|
||||
address m_tracker_ip;
|
||||
proxy_settings const& m_ps;
|
||||
connection_queue& m_cc;
|
||||
|
|
|
@ -363,6 +363,7 @@ namespace libtorrent
|
|||
virtual void tracker_response(
|
||||
tracker_request const& r
|
||||
, address const& tracker_ip
|
||||
, std::list<address> const& ip_list
|
||||
, std::vector<peer_entry>& e, int interval
|
||||
, int complete, int incomplete, address const& external_ip);
|
||||
virtual void tracker_request_timed_out(
|
||||
|
@ -390,7 +391,8 @@ namespace libtorrent
|
|||
void force_tracker_request(ptime);
|
||||
void scrape_tracker();
|
||||
void announce_with_tracker(tracker_request::event_t e
|
||||
= tracker_request::none);
|
||||
= tracker_request::none
|
||||
, address const& bind_interface = address_v4::any());
|
||||
ptime const& last_scrape() const { return m_last_scrape; }
|
||||
|
||||
// sets the username and password that will be sent to
|
||||
|
|
|
@ -110,6 +110,7 @@ namespace libtorrent
|
|||
int num_want;
|
||||
std::string ipv6;
|
||||
std::string ipv4;
|
||||
address bind_ip;
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT request_callback
|
||||
|
@ -124,6 +125,7 @@ namespace libtorrent
|
|||
virtual void tracker_response(
|
||||
tracker_request const& req
|
||||
, address const& tracker_ip
|
||||
, std::list<address> const& ip_list
|
||||
, std::vector<peer_entry>& peers
|
||||
, int interval
|
||||
, int complete
|
||||
|
@ -187,7 +189,6 @@ namespace libtorrent
|
|||
tracker_connection(tracker_manager& man
|
||||
, tracker_request const& req
|
||||
, io_service& ios
|
||||
, address bind_interface
|
||||
, boost::weak_ptr<request_callback> r);
|
||||
|
||||
boost::shared_ptr<request_callback> requester();
|
||||
|
@ -199,14 +200,13 @@ namespace libtorrent
|
|||
void fail_timeout();
|
||||
virtual void start() = 0;
|
||||
virtual void close();
|
||||
address const& bind_interface() const { return m_bind_interface; }
|
||||
address const& bind_interface() const { return m_req.bind_ip; }
|
||||
void sent_bytes(int bytes);
|
||||
void received_bytes(int bytes);
|
||||
|
||||
protected:
|
||||
boost::weak_ptr<request_callback> m_requester;
|
||||
private:
|
||||
address m_bind_interface;
|
||||
tracker_manager& m_man;
|
||||
const tracker_request m_req;
|
||||
};
|
||||
|
@ -226,7 +226,6 @@ namespace libtorrent
|
|||
, connection_queue& cc
|
||||
, tracker_request r
|
||||
, std::string const& auth
|
||||
, address bind_infc
|
||||
, boost::weak_ptr<request_callback> c
|
||||
= boost::weak_ptr<request_callback>());
|
||||
void abort_all_requests(bool all = false);
|
||||
|
|
|
@ -71,7 +71,6 @@ namespace libtorrent
|
|||
, connection_queue& cc
|
||||
, tracker_manager& man
|
||||
, tracker_request const& req
|
||||
, address bind_infc
|
||||
, boost::weak_ptr<request_callback> c
|
||||
, aux::session_impl const& ses
|
||||
, proxy_settings const& ps);
|
||||
|
@ -112,6 +111,7 @@ namespace libtorrent
|
|||
udp::resolver m_name_lookup;
|
||||
udp_socket m_socket;
|
||||
udp::endpoint m_target;
|
||||
std::list<udp::endpoint> m_endpoints;
|
||||
|
||||
int m_transaction_id;
|
||||
boost::int64_t m_connection_id;
|
||||
|
|
|
@ -298,8 +298,10 @@ void http_connection::on_resolve(error_code const& e
|
|||
// sort the endpoints so that the ones with the same IP version as our
|
||||
// bound listen socket are first. So that when contacting a tracker,
|
||||
// we'll talk to it from the same IP that we're listening on
|
||||
std::partition(m_endpoints.begin(), m_endpoints.end()
|
||||
, boost::bind(&address::is_v4, boost::bind(&tcp::endpoint::address, _1)) == m_bind_addr.is_v4());
|
||||
if (m_bind_addr != address_v4::any())
|
||||
std::partition(m_endpoints.begin(), m_endpoints.end()
|
||||
, boost::bind(&address::is_v4, boost::bind(&tcp::endpoint::address, _1))
|
||||
== m_bind_addr.is_v4());
|
||||
#endif
|
||||
|
||||
queue_connect();
|
||||
|
|
|
@ -70,15 +70,13 @@ namespace libtorrent
|
|||
, connection_queue& cc
|
||||
, tracker_manager& man
|
||||
, tracker_request const& req
|
||||
, address bind_infc
|
||||
, boost::weak_ptr<request_callback> c
|
||||
, aux::session_impl const& ses
|
||||
, proxy_settings const& ps
|
||||
, std::string const& auth)
|
||||
: tracker_connection(man, req, ios, bind_infc, c)
|
||||
: tracker_connection(man, req, ios, c)
|
||||
, m_man(man)
|
||||
, m_ses(ses)
|
||||
, m_bind_iface(bind_infc)
|
||||
, m_ps(ps)
|
||||
, m_cc(cc)
|
||||
, m_ios(ios)
|
||||
|
@ -173,7 +171,7 @@ namespace libtorrent
|
|||
:settings.tracker_completion_timeout;
|
||||
|
||||
m_tracker_connection->get(url, seconds(timeout)
|
||||
, 1, &m_ps, 5, settings.user_agent, m_bind_iface);
|
||||
, 1, &m_ps, 5, settings.user_agent, bind_interface());
|
||||
|
||||
// the url + 100 estimated header size
|
||||
sent_bytes(url.size() + 100);
|
||||
|
@ -476,8 +474,14 @@ namespace libtorrent
|
|||
if (incomplete_ent && incomplete_ent->type() == entry::int_t)
|
||||
incomplete = int(incomplete_ent->integer());
|
||||
|
||||
cb->tracker_response(tracker_req(), m_tracker_ip, peer_list, interval->integer(), complete
|
||||
, incomplete, external_ip);
|
||||
std::list<address> ip_list;
|
||||
std::transform(m_tracker_connection->endpoints().begin()
|
||||
, m_tracker_connection->endpoints().end()
|
||||
, std::back_inserter(ip_list)
|
||||
, boost::bind(&tcp::endpoint::address, _1));
|
||||
|
||||
cb->tracker_response(tracker_req(), m_tracker_ip, ip_list, peer_list
|
||||
, interval->integer(), complete, incomplete, external_ip);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1054,7 +1054,8 @@ namespace libtorrent
|
|||
|
||||
#endif
|
||||
|
||||
void torrent::announce_with_tracker(tracker_request::event_t e)
|
||||
void torrent::announce_with_tracker(tracker_request::event_t e
|
||||
, address const& bind_interface)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
|
@ -1106,6 +1107,9 @@ namespace libtorrent
|
|||
if (!ae.complete_sent && is_seed()) req.event = tracker_request::completed;
|
||||
}
|
||||
|
||||
if (!is_any(bind_interface)) req.bind_ip = bind_interface;
|
||||
else req.bind_ip = m_ses.m_listen_interface.address();
|
||||
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
||||
(*m_ses.m_logger) << time_now_string() << " ==> TACKER REQUEST " << req.url
|
||||
<< " event=" << (req.event==tracker_request::stopped?"stopped"
|
||||
|
@ -1115,13 +1119,12 @@ namespace libtorrent
|
|||
{
|
||||
boost::shared_ptr<aux::tracker_logger> tl(new aux::tracker_logger(m_ses));
|
||||
m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
|
||||
, tracker_login(), m_ses.m_listen_interface.address(), tl);
|
||||
, tracker_login(), tl);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
|
||||
, tracker_login(), m_ses.m_listen_interface.address()
|
||||
, m_abort?boost::shared_ptr<torrent>():shared_from_this());
|
||||
, tracker_login() , m_abort?boost::shared_ptr<torrent>():shared_from_this());
|
||||
ae.updating = true;
|
||||
|
||||
if (m_ses.m_alerts.should_post<tracker_announce_alert>())
|
||||
|
@ -1146,8 +1149,9 @@ namespace libtorrent
|
|||
req.info_hash = m_torrent_file->info_hash();
|
||||
req.kind = tracker_request::scrape_request;
|
||||
req.url = m_trackers[i].url;
|
||||
req.bind_ip = m_ses.m_listen_interface.address();
|
||||
m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
|
||||
, tracker_login(), m_ses.m_listen_interface.address(), shared_from_this());
|
||||
, tracker_login(), shared_from_this());
|
||||
|
||||
m_last_scrape = time_now();
|
||||
}
|
||||
|
@ -1182,7 +1186,8 @@ namespace libtorrent
|
|||
|
||||
void torrent::tracker_response(
|
||||
tracker_request const& r
|
||||
, address const& tracker_ip
|
||||
, address const& tracker_ip // this is the IP we connected to
|
||||
, std::list<address> const& tracker_ips // these are all the IPs it resolved to
|
||||
, std::vector<peer_entry>& peer_list
|
||||
, int interval
|
||||
, int complete
|
||||
|
@ -1237,6 +1242,10 @@ namespace libtorrent
|
|||
s << "\n";
|
||||
}
|
||||
s << "external ip: " << external_ip << "\n";
|
||||
s << "tracker ips: ";
|
||||
std::copy(tracker_ips.begin(), tracker_ips.end(), std::ostream_iterator<address>(s, " "));
|
||||
s << "\n";
|
||||
s << "we connected to: " << tracker_ip << "\n";
|
||||
debug_log(s.str());
|
||||
#endif
|
||||
// for each of the peers we got from the tracker
|
||||
|
@ -1273,6 +1282,41 @@ namespace libtorrent
|
|||
get_handle(), peer_list.size(), r.url));
|
||||
}
|
||||
m_got_tracker_response = true;
|
||||
|
||||
// we're listening on an interface type that was not used
|
||||
// when talking to the tracker. If there is a matching interface
|
||||
// type in the tracker IP list, make another tracker request
|
||||
// using that interface
|
||||
// in order to avoid triggering this case over and over, don't
|
||||
// do it if the bind IP for the tracker request that just completed
|
||||
// matches one of the listen interfaces, since that means this
|
||||
// announce was the second one
|
||||
// don't connect twice just to tell it we're stopping
|
||||
|
||||
if (((!is_any(m_ses.m_ipv6_interface.address()) && tracker_ip.is_v4())
|
||||
|| (!is_any(m_ses.m_ipv4_interface.address()) && tracker_ip.is_v6()))
|
||||
&& r.bind_ip != m_ses.m_ipv4_interface.address()
|
||||
&& r.bind_ip != m_ses.m_ipv6_interface.address()
|
||||
&& r.event != tracker_request::stopped)
|
||||
{
|
||||
std::list<address>::const_iterator i = std::find_if(tracker_ips.begin()
|
||||
, tracker_ips.end(), boost::bind(&address::is_v4, _1) != tracker_ip.is_v4());
|
||||
if (i != tracker_ips.end())
|
||||
{
|
||||
// the tracker did resolve to a different type if address, so announce
|
||||
// to that as well
|
||||
|
||||
// tell the tracker to bind to the opposite protocol type
|
||||
address bind_interface = tracker_ip.is_v4()
|
||||
?m_ses.m_ipv6_interface.address()
|
||||
:m_ses.m_ipv4_interface.address();
|
||||
announce_with_tracker(r.event, bind_interface);
|
||||
#if (defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING) && TORRENT_USE_IOSTREAM
|
||||
debug_log("announce again using " + print_address(bind_interface)
|
||||
+ " as the bind interface");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::on_peer_name_lookup(error_code const& e, tcp::resolver::iterator host
|
||||
|
|
|
@ -133,11 +133,9 @@ namespace libtorrent
|
|||
tracker_manager& man
|
||||
, tracker_request const& req
|
||||
, io_service& ios
|
||||
, address bind_interface_
|
||||
, boost::weak_ptr<request_callback> r)
|
||||
: timeout_handler(ios)
|
||||
, m_requester(r)
|
||||
, m_bind_interface(bind_interface_)
|
||||
, m_man(man)
|
||||
, m_req(req)
|
||||
{}
|
||||
|
@ -211,7 +209,6 @@ namespace libtorrent
|
|||
, connection_queue& cc
|
||||
, tracker_request req
|
||||
, std::string const& auth
|
||||
, address bind_infc
|
||||
, boost::weak_ptr<request_callback> c)
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
@ -236,14 +233,14 @@ namespace libtorrent
|
|||
#endif
|
||||
{
|
||||
con = new http_tracker_connection(
|
||||
ios, cc, *this, req, bind_infc, c
|
||||
ios, cc, *this, req, c
|
||||
, m_ses, m_proxy, auth);
|
||||
}
|
||||
else if (protocol == "udp")
|
||||
{
|
||||
con = new udp_tracker_connection(
|
||||
ios, cc, *this, req, bind_infc
|
||||
, c, m_ses, m_proxy);
|
||||
ios, cc, *this, req , c, m_ses
|
||||
, m_proxy);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -75,11 +75,10 @@ namespace libtorrent
|
|||
, connection_queue& cc
|
||||
, tracker_manager& man
|
||||
, tracker_request const& req
|
||||
, address bind_infc
|
||||
, boost::weak_ptr<request_callback> c
|
||||
, aux::session_impl const& ses
|
||||
, proxy_settings const& proxy)
|
||||
: tracker_connection(man, req, ios, bind_infc, c)
|
||||
: tracker_connection(man, req, ios, c)
|
||||
, m_man(man)
|
||||
, m_name_lookup(ios)
|
||||
, m_socket(ios, boost::bind(&udp_tracker_connection::on_receive, self(), _1, _2, _3, _4), cc)
|
||||
|
@ -143,42 +142,69 @@ namespace libtorrent
|
|||
// look for an address that has the same kind as the one
|
||||
// we're listening on. To make sure the tracker get our
|
||||
// correct listening address.
|
||||
udp::resolver::iterator target = i;
|
||||
udp::resolver::iterator end;
|
||||
udp::endpoint target_address = *i;
|
||||
for (; target != end && target->endpoint().address().is_v4()
|
||||
!= bind_interface().is_v4(); ++target);
|
||||
if (target == end)
|
||||
|
||||
std::transform(i, udp::resolver::iterator(), std::back_inserter(m_endpoints)
|
||||
, boost::bind(&udp::resolver::iterator::value_type::endpoint, _1));
|
||||
|
||||
// remove endpoints that are filtered by the IP filter
|
||||
for (std::list<udp::endpoint>::iterator i = m_endpoints.begin();
|
||||
i != m_endpoints.end();)
|
||||
{
|
||||
TORRENT_ASSERT(target_address.address().is_v4() != bind_interface().is_v4());
|
||||
if (cb)
|
||||
{
|
||||
std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6";
|
||||
std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6";
|
||||
cb->tracker_warning(tracker_req(), "the tracker only resolves to an "
|
||||
+ tracker_address_type + " address, and you're listening on an "
|
||||
+ bind_address_type + " socket. This may prevent you from receiving incoming connections.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target_address = *target;
|
||||
if (m_ses.m_ip_filter.access(i->address()) == ip_filter::blocked)
|
||||
i = m_endpoints.erase(i);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
if (m_ses.m_ip_filter.access(target_address.address()) & ip_filter::blocked)
|
||||
if (m_endpoints.empty())
|
||||
{
|
||||
fail(-1, "blocked by IP filter");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cb) cb->m_tracker_address = tcp::endpoint(target_address.address(), target_address.port());
|
||||
m_target = target_address;
|
||||
error_code ec;
|
||||
m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
|
||||
if (ec)
|
||||
std::list<udp::endpoint>::iterator iter = m_endpoints.begin();
|
||||
m_target = *iter;
|
||||
|
||||
if (bind_interface() != address_v4::any())
|
||||
{
|
||||
fail(-1, ec.message().c_str());
|
||||
return;
|
||||
// find first endpoint that matches our bind interface type
|
||||
for (; iter != m_endpoints.end() && iter->address().is_v4()
|
||||
!= bind_interface().is_v4(); ++iter);
|
||||
|
||||
if (iter == m_endpoints.end())
|
||||
{
|
||||
TORRENT_ASSERT(m_target.address().is_v4() != bind_interface().is_v4());
|
||||
if (cb)
|
||||
{
|
||||
char const* tracker_address_type = m_target.address().is_v4() ? "IPv4" : "IPv6";
|
||||
char const* bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6";
|
||||
char msg[200];
|
||||
snprintf(msg, sizeof(msg)
|
||||
, "the tracker only resolves to an %s address, and you're "
|
||||
"listening on an %s socket. This may prevent you from receiving "
|
||||
"incoming connections."
|
||||
, tracker_address_type, bind_address_type);
|
||||
|
||||
cb->tracker_warning(tracker_req(), msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_target = *iter;
|
||||
}
|
||||
}
|
||||
|
||||
if (cb) cb->m_tracker_address = tcp::endpoint(m_target.address(), m_target.port());
|
||||
|
||||
if (bind_interface() != address_v4::any())
|
||||
{
|
||||
error_code ec;
|
||||
m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
|
||||
if (ec)
|
||||
{
|
||||
fail(-1, ec.message().c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
send_udp_connect();
|
||||
}
|
||||
|
@ -423,8 +449,14 @@ namespace libtorrent
|
|||
peer_list.push_back(e);
|
||||
}
|
||||
|
||||
cb->tracker_response(tracker_req(), m_target.address(), peer_list, interval
|
||||
, complete, incomplete, address());
|
||||
std::list<address> ip_list;
|
||||
std::transform(m_endpoints.begin()
|
||||
, m_endpoints.end()
|
||||
, std::back_inserter(ip_list)
|
||||
, boost::bind(&udp::endpoint::address, _1));
|
||||
|
||||
cb->tracker_response(tracker_req(), m_target.address(), ip_list
|
||||
, peer_list, interval, complete, incomplete, address());
|
||||
|
||||
m_man.remove_request(this);
|
||||
close();
|
||||
|
|
Loading…
Reference in New Issue