forked from premiere/premiere-libtorrent
transition tracker_connections to use shared_ptr instead of intrusive_ptr. optimize udp tracker connection lookups by using unordered map instead of linear search.
This commit is contained in:
parent
22f054e2ff
commit
ffb66ec156
|
@ -1,3 +1,4 @@
|
||||||
|
* optimize UDP tracker packet handling
|
||||||
* support SSL over uTP connections
|
* support SSL over uTP connections
|
||||||
* support web seeds that resolve to multiple IPs
|
* 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
|
||||||
|
|
|
@ -83,8 +83,11 @@ namespace libtorrent
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::intrusive_ptr<http_tracker_connection> self()
|
boost::shared_ptr<http_tracker_connection> shared_from_this()
|
||||||
{ return boost::intrusive_ptr<http_tracker_connection>(this); }
|
{
|
||||||
|
return boost::static_pointer_cast<http_tracker_connection>(
|
||||||
|
tracker_connection::shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
void on_filter(http_connection& c, std::vector<tcp::endpoint>& endpoints);
|
void on_filter(http_connection& c, std::vector<tcp::endpoint>& endpoints);
|
||||||
void on_connect(http_connection& c);
|
void on_connect(http_connection& c);
|
||||||
|
|
|
@ -44,10 +44,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
#include <boost/weak_ptr.hpp>
|
#include <boost/weak_ptr.hpp>
|
||||||
#include <boost/intrusive_ptr.hpp>
|
|
||||||
#include <boost/tuple/tuple.hpp>
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
@ -59,7 +60,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/peer_id.hpp"
|
#include "libtorrent/peer_id.hpp"
|
||||||
#include "libtorrent/peer.hpp" // peer_entry
|
#include "libtorrent/peer.hpp" // peer_entry
|
||||||
#include "libtorrent/deadline_timer.hpp"
|
#include "libtorrent/deadline_timer.hpp"
|
||||||
#include "libtorrent/intrusive_ptr_base.hpp"
|
|
||||||
#include "libtorrent/size_type.hpp"
|
#include "libtorrent/size_type.hpp"
|
||||||
#include "libtorrent/union_endpoint.hpp"
|
#include "libtorrent/union_endpoint.hpp"
|
||||||
#include "libtorrent/udp_socket.hpp" // for udp_socket_observer
|
#include "libtorrent/udp_socket.hpp" // for udp_socket_observer
|
||||||
|
@ -73,6 +73,8 @@ namespace libtorrent
|
||||||
class tracker_manager;
|
class tracker_manager;
|
||||||
struct timeout_handler;
|
struct timeout_handler;
|
||||||
struct tracker_connection;
|
struct tracker_connection;
|
||||||
|
class udp_tracker_connection;
|
||||||
|
class http_tracker_connection;
|
||||||
namespace aux { struct session_impl; }
|
namespace aux { struct session_impl; }
|
||||||
|
|
||||||
// returns -1 if gzip header is invalid or the header size in bytes
|
// returns -1 if gzip header is invalid or the header size in bytes
|
||||||
|
@ -222,7 +224,7 @@ namespace libtorrent
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TORRENT_EXTRA_EXPORT timeout_handler
|
struct TORRENT_EXTRA_EXPORT timeout_handler
|
||||||
: intrusive_ptr_base<timeout_handler>
|
: boost::enable_shared_from_this<timeout_handler>
|
||||||
, boost::noncopyable
|
, boost::noncopyable
|
||||||
{
|
{
|
||||||
timeout_handler(io_service& str);
|
timeout_handler(io_service& str);
|
||||||
|
@ -241,9 +243,6 @@ namespace libtorrent
|
||||||
|
|
||||||
void timeout_callback(error_code const&);
|
void timeout_callback(error_code const&);
|
||||||
|
|
||||||
boost::intrusive_ptr<timeout_handler> self()
|
|
||||||
{ return boost::intrusive_ptr<timeout_handler>(this); }
|
|
||||||
|
|
||||||
int m_completion_timeout;
|
int m_completion_timeout;
|
||||||
|
|
||||||
typedef mutex mutex_t;
|
typedef mutex mutex_t;
|
||||||
|
@ -264,6 +263,7 @@ namespace libtorrent
|
||||||
bool m_abort;
|
bool m_abort;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: 2 this class probably doesn't need to have virtual functions.
|
||||||
struct TORRENT_EXTRA_EXPORT tracker_connection
|
struct TORRENT_EXTRA_EXPORT tracker_connection
|
||||||
: timeout_handler
|
: timeout_handler
|
||||||
{
|
{
|
||||||
|
@ -272,6 +272,9 @@ namespace libtorrent
|
||||||
, io_service& ios
|
, io_service& ios
|
||||||
, boost::weak_ptr<request_callback> r);
|
, boost::weak_ptr<request_callback> r);
|
||||||
|
|
||||||
|
void update_transaction_id(boost::shared_ptr<udp_tracker_connection> c
|
||||||
|
, boost::uint64_t tid);
|
||||||
|
|
||||||
boost::shared_ptr<request_callback> requester() const;
|
boost::shared_ptr<request_callback> requester() const;
|
||||||
virtual ~tracker_connection() {}
|
virtual ~tracker_connection() {}
|
||||||
|
|
||||||
|
@ -290,8 +293,11 @@ namespace libtorrent
|
||||||
, char const* /* hostname */
|
, char const* /* hostname */
|
||||||
, char const* /* buf */, int /* size */) { return false; }
|
, char const* /* buf */, int /* size */) { return false; }
|
||||||
|
|
||||||
boost::intrusive_ptr<tracker_connection> self()
|
boost::shared_ptr<tracker_connection> shared_from_this()
|
||||||
{ return boost::intrusive_ptr<tracker_connection>(this); }
|
{
|
||||||
|
return boost::static_pointer_cast<tracker_connection>(
|
||||||
|
timeout_handler::shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -307,7 +313,9 @@ namespace libtorrent
|
||||||
tracker_manager& m_man;
|
tracker_manager& m_man;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TORRENT_EXTRA_EXPORT tracker_manager: public udp_socket_observer, boost::noncopyable
|
class TORRENT_EXTRA_EXPORT tracker_manager
|
||||||
|
: public udp_socket_observer
|
||||||
|
, boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -339,14 +347,23 @@ namespace libtorrent
|
||||||
virtual bool incoming_packet(error_code const& e, char const* hostname
|
virtual bool incoming_packet(error_code const& e, char const* hostname
|
||||||
, char const* buf, int size);
|
, char const* buf, int size);
|
||||||
|
|
||||||
|
void update_transaction_id(
|
||||||
|
boost::shared_ptr<udp_tracker_connection> c
|
||||||
|
, boost::uint64_t tid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef mutex mutex_t;
|
typedef mutex mutex_t;
|
||||||
mutable mutex_t m_mutex;
|
mutable mutex_t m_mutex;
|
||||||
|
|
||||||
typedef std::list<boost::intrusive_ptr<tracker_connection> >
|
// maps transactionid to the udp_tracker_connection
|
||||||
tracker_connections_t;
|
// TODO: 2 this should be unique_ptr in the future
|
||||||
tracker_connections_t m_connections;
|
typedef boost::unordered_map<boost::uint32_t, boost::shared_ptr<udp_tracker_connection> > udp_conns_t;
|
||||||
|
udp_conns_t m_udp_conns;
|
||||||
|
|
||||||
|
typedef std::vector<boost::shared_ptr<http_tracker_connection> > http_conns_t;
|
||||||
|
http_conns_t m_http_conns;
|
||||||
|
|
||||||
aux::session_impl& m_ses;
|
aux::session_impl& m_ses;
|
||||||
bool m_abort;
|
bool m_abort;
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,6 +77,8 @@ namespace libtorrent
|
||||||
void start();
|
void start();
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
boost::uint32_t transaction_id() const { return m_transaction_id; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum action_t
|
enum action_t
|
||||||
|
@ -87,8 +89,13 @@ namespace libtorrent
|
||||||
action_error
|
action_error
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::intrusive_ptr<udp_tracker_connection> self()
|
boost::shared_ptr<udp_tracker_connection> shared_from_this()
|
||||||
{ return boost::intrusive_ptr<udp_tracker_connection>(this); }
|
{
|
||||||
|
return boost::static_pointer_cast<udp_tracker_connection>(
|
||||||
|
tracker_connection::shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_transaction_id();
|
||||||
|
|
||||||
void name_lookup(error_code const& error
|
void name_lookup(error_code const& error
|
||||||
, std::vector<address> const& addresses, int port);
|
, std::vector<address> const& addresses, int port);
|
||||||
|
@ -116,6 +123,7 @@ namespace libtorrent
|
||||||
udp::endpoint pick_target_endpoint() const;
|
udp::endpoint pick_target_endpoint() const;
|
||||||
|
|
||||||
std::string m_hostname;
|
std::string m_hostname;
|
||||||
|
// TODO: 3 this should be a vector
|
||||||
std::list<tcp::endpoint> m_endpoints;
|
std::list<tcp::endpoint> m_endpoints;
|
||||||
|
|
||||||
aux::session_impl& m_ses;
|
aux::session_impl& m_ses;
|
||||||
|
@ -133,7 +141,7 @@ namespace libtorrent
|
||||||
|
|
||||||
udp::endpoint m_target;
|
udp::endpoint m_target;
|
||||||
|
|
||||||
int m_transaction_id;
|
boost::uint32_t m_transaction_id;
|
||||||
int m_attempts;
|
int m_attempts;
|
||||||
|
|
||||||
// action_t
|
// action_t
|
||||||
|
|
|
@ -205,10 +205,10 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
m_tracker_connection.reset(new http_connection(m_ios, m_ses.m_host_resolver
|
m_tracker_connection.reset(new http_connection(m_ios, m_ses.m_host_resolver
|
||||||
, boost::bind(&http_tracker_connection::on_response, self(), _1, _2, _3, _4)
|
, boost::bind(&http_tracker_connection::on_response, shared_from_this(), _1, _2, _3, _4)
|
||||||
, true, settings.get_int(settings_pack::max_http_recv_buffer_size)
|
, true, settings.get_int(settings_pack::max_http_recv_buffer_size)
|
||||||
, boost::bind(&http_tracker_connection::on_connect, self(), _1)
|
, boost::bind(&http_tracker_connection::on_connect, shared_from_this(), _1)
|
||||||
, boost::bind(&http_tracker_connection::on_filter, self(), _1, _2)
|
, boost::bind(&http_tracker_connection::on_filter, shared_from_this(), _1, _2)
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
, tracker_req().ssl_ctx
|
, tracker_req().ssl_ctx
|
||||||
#endif
|
#endif
|
||||||
|
@ -296,7 +296,7 @@ namespace libtorrent
|
||||||
, http_parser const& parser, char const* data, int size)
|
, http_parser const& parser, char const* data, int size)
|
||||||
{
|
{
|
||||||
// keep this alive
|
// keep this alive
|
||||||
boost::intrusive_ptr<http_tracker_connection> me(this);
|
boost::shared_ptr<http_tracker_connection> me(shared_from_this());
|
||||||
|
|
||||||
if (ec && ec != asio::error::eof)
|
if (ec && ec != asio::error::eof)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
#include "libtorrent/tracker_manager.hpp"
|
#include "libtorrent/tracker_manager.hpp"
|
||||||
#include "libtorrent/http_tracker_connection.hpp"
|
#include "libtorrent/http_tracker_connection.hpp"
|
||||||
|
@ -89,7 +90,7 @@ namespace libtorrent
|
||||||
error_code ec;
|
error_code ec;
|
||||||
m_timeout.expires_at(m_read_time + seconds(timeout), ec);
|
m_timeout.expires_at(m_read_time + seconds(timeout), ec);
|
||||||
m_timeout.async_wait(boost::bind(
|
m_timeout.async_wait(boost::bind(
|
||||||
&timeout_handler::timeout_callback, self(), _1));
|
&timeout_handler::timeout_callback, shared_from_this(), _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void timeout_handler::restart_read_timeout()
|
void timeout_handler::restart_read_timeout()
|
||||||
|
@ -140,7 +141,7 @@ namespace libtorrent
|
||||||
error_code ec;
|
error_code ec;
|
||||||
m_timeout.expires_at(m_read_time + seconds(timeout), ec);
|
m_timeout.expires_at(m_read_time + seconds(timeout), ec);
|
||||||
m_timeout.async_wait(
|
m_timeout.async_wait(
|
||||||
boost::bind(&timeout_handler::timeout_callback, self(), _1));
|
boost::bind(&timeout_handler::timeout_callback, shared_from_this(), _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
tracker_connection::tracker_connection(
|
tracker_connection::tracker_connection(
|
||||||
|
@ -164,7 +165,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
// we need to post the error to avoid deadlock
|
// we need to post the error to avoid deadlock
|
||||||
get_io_service().post(boost::bind(&tracker_connection::fail_impl
|
get_io_service().post(boost::bind(&tracker_connection::fail_impl
|
||||||
, self(), ec, code, std::string(msg), interval, min_interval));
|
, shared_from_this(), ec, code, std::string(msg), interval, min_interval));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tracker_connection::fail_impl(error_code const& ec, int code
|
void tracker_connection::fail_impl(error_code const& ec, int code
|
||||||
|
@ -176,6 +177,7 @@ namespace libtorrent
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 3 replace this with performance counters. remove depedency on session
|
||||||
void tracker_connection::sent_bytes(int bytes)
|
void tracker_connection::sent_bytes(int bytes)
|
||||||
{
|
{
|
||||||
m_man.sent_bytes(bytes);
|
m_man.sent_bytes(bytes);
|
||||||
|
@ -214,11 +216,32 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
tracker_connections_t::iterator i = std::find(m_connections.begin()
|
http_conns_t::iterator i = std::find_if(m_http_conns.begin()
|
||||||
, m_connections.end(), boost::intrusive_ptr<const tracker_connection>(c));
|
, m_http_conns.end()
|
||||||
if (i == m_connections.end()) return;
|
, boost::bind(&boost::shared_ptr<http_tracker_connection>::get, _1) == c);
|
||||||
|
if (i != m_http_conns.end())
|
||||||
|
{
|
||||||
|
m_http_conns.erase(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_connections.erase(i);
|
udp_conns_t::iterator j = std::find_if(m_udp_conns.begin()
|
||||||
|
, m_udp_conns.end()
|
||||||
|
, boost::bind(&boost::shared_ptr<udp_tracker_connection>::get
|
||||||
|
, boost::bind(&udp_conns_t::value_type::second, _1)) == c);
|
||||||
|
if (j != m_udp_conns.end())
|
||||||
|
{
|
||||||
|
m_udp_conns.erase(j);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tracker_manager::update_transaction_id(
|
||||||
|
boost::shared_ptr<udp_tracker_connection> c
|
||||||
|
, boost::uint64_t tid)
|
||||||
|
{
|
||||||
|
m_udp_conns.erase(c->transaction_id());
|
||||||
|
m_udp_conns[tid] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tracker_manager::queue_request(
|
void tracker_manager::queue_request(
|
||||||
|
@ -240,91 +263,108 @@ namespace libtorrent
|
||||||
|
|
||||||
std::string protocol = req.url.substr(0, req.url.find(':'));
|
std::string protocol = req.url.substr(0, req.url.find(':'));
|
||||||
|
|
||||||
boost::intrusive_ptr<tracker_connection> con;
|
|
||||||
|
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
if (protocol == "http" || protocol == "https")
|
if (protocol == "http" || protocol == "https")
|
||||||
#else
|
#else
|
||||||
if (protocol == "http")
|
if (protocol == "http")
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
con = new http_tracker_connection(
|
boost::shared_ptr<http_tracker_connection> con
|
||||||
|
= boost::make_shared<http_tracker_connection>(
|
||||||
ios, *this, req, c
|
ios, *this, req, c
|
||||||
, m_ses, auth
|
, m_ses, auth
|
||||||
#if TORRENT_USE_I2P
|
#if TORRENT_USE_I2P
|
||||||
, &m_ses.m_i2p_conn
|
, &m_ses.m_i2p_conn
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
m_http_conns.push_back(con);
|
||||||
|
con->start();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (protocol == "udp")
|
else if (protocol == "udp")
|
||||||
{
|
{
|
||||||
con = new udp_tracker_connection(
|
boost::shared_ptr<udp_tracker_connection> con
|
||||||
ios, *this, req , c, m_ses, m_ses.proxy());
|
= boost::make_shared<udp_tracker_connection>(
|
||||||
}
|
ios, *this, req , c, m_ses, m_ses.proxy());
|
||||||
else
|
m_udp_conns[con->transaction_id()] = con;
|
||||||
{
|
con->start();
|
||||||
// we need to post the error to avoid deadlock
|
|
||||||
if (boost::shared_ptr<request_callback> r = c.lock())
|
|
||||||
ios.post(boost::bind(&request_callback::tracker_request_error, r, req
|
|
||||||
, -1, error_code(errors::unsupported_url_protocol)
|
|
||||||
, "", 0));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_connections.push_back(con);
|
// we need to post the error to avoid deadlock
|
||||||
|
if (boost::shared_ptr<request_callback> r = c.lock())
|
||||||
boost::shared_ptr<request_callback> cb = con->requester();
|
ios.post(boost::bind(&request_callback::tracker_request_error, r, req
|
||||||
con->start();
|
, -1, error_code(errors::unsupported_url_protocol)
|
||||||
|
, "", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tracker_manager::incoming_packet(error_code const& e
|
bool tracker_manager::incoming_packet(error_code const& e
|
||||||
, udp::endpoint const& ep, char const* buf, int size)
|
, udp::endpoint const& ep, char const* buf, int size)
|
||||||
{
|
{
|
||||||
// m_ses.m_stat.received_tracker_bytes(len + 28);
|
// ignore packets smaller than 8 bytes
|
||||||
for (tracker_connections_t::iterator i = m_connections.begin();
|
if (size < 8) return false;
|
||||||
i != m_connections.end();)
|
|
||||||
{
|
const char* ptr = buf + 4;
|
||||||
boost::intrusive_ptr<tracker_connection> p = *i;
|
boost::uint32_t transaction = detail::read_uint32(ptr);
|
||||||
++i;
|
udp_conns_t::iterator i = m_udp_conns.find(transaction);
|
||||||
// on_receive() may remove the tracker connection from the list
|
|
||||||
if (p->on_receive(e, ep, buf, size)) return true;
|
if (i == m_udp_conns.end()) return false;
|
||||||
}
|
|
||||||
return false;
|
boost::shared_ptr<tracker_connection> p = i->second;
|
||||||
|
// on_receive() may remove the tracker connection from the list
|
||||||
|
return p->on_receive(e, ep, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tracker_manager::incoming_packet(error_code const& e
|
bool tracker_manager::incoming_packet(error_code const& e
|
||||||
, char const* hostname, char const* buf, int size)
|
, char const* hostname, char const* buf, int size)
|
||||||
{
|
{
|
||||||
// m_ses.m_stat.received_tracker_bytes(len + 28);
|
// ignore packets smaller than 8 bytes
|
||||||
for (tracker_connections_t::iterator i = m_connections.begin();
|
if (size < 8) return false;
|
||||||
i != m_connections.end();)
|
|
||||||
{
|
const char* ptr = buf + 4;
|
||||||
boost::intrusive_ptr<tracker_connection> p = *i;
|
boost::uint32_t transaction = detail::read_uint32(ptr);
|
||||||
++i;
|
udp_conns_t::iterator i = m_udp_conns.find(transaction);
|
||||||
// on_receive() may remove the tracker connection from the list
|
|
||||||
if (p->on_receive_hostname(e, hostname, buf, size)) return true;
|
if (i == m_udp_conns.end()) return false;
|
||||||
}
|
|
||||||
return false;
|
boost::shared_ptr<tracker_connection> p = i->second;
|
||||||
|
// on_receive() may remove the tracker connection from the list
|
||||||
|
return p->on_receive_hostname(e, hostname, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tracker_manager::abort_all_requests(bool all)
|
void tracker_manager::abort_all_requests(bool all)
|
||||||
{
|
{
|
||||||
// removes all connections from m_connections
|
// removes all connections except 'event=stopped'-requests
|
||||||
// except 'event=stopped'-requests
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
m_abort = true;
|
m_abort = true;
|
||||||
tracker_connections_t close_connections;
|
http_conns_t close_http_connections;
|
||||||
|
std::vector<boost::shared_ptr<udp_tracker_connection> > close_udp_connections;
|
||||||
|
|
||||||
for (tracker_connections_t::iterator i = m_connections.begin()
|
for (http_conns_t::iterator i = m_http_conns.begin()
|
||||||
, end(m_connections.end()); i != end; ++i)
|
, end(m_http_conns.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
boost::intrusive_ptr<tracker_connection> c = *i;
|
http_tracker_connection* c = i->get();
|
||||||
tracker_request const& req = c->tracker_req();
|
tracker_request const& req = c->tracker_req();
|
||||||
if (req.event == tracker_request::stopped && !all)
|
if (req.event == tracker_request::stopped && !all)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
close_connections.push_back(c);
|
close_http_connections.push_back(*i);
|
||||||
|
|
||||||
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
|
boost::shared_ptr<request_callback> rc = c->requester();
|
||||||
|
if (rc) rc->debug_log("aborting: %s", req.url.c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
for (udp_conns_t::iterator i = m_udp_conns.begin()
|
||||||
|
, end(m_udp_conns.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<udp_tracker_connection> c = i->second;
|
||||||
|
tracker_request const& req = c->tracker_req();
|
||||||
|
if (req.event == tracker_request::stopped && !all)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
close_udp_connections.push_back(c);
|
||||||
|
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
boost::shared_ptr<request_callback> rc = c->requester();
|
boost::shared_ptr<request_callback> rc = c->requester();
|
||||||
|
@ -333,8 +373,15 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
l.unlock();
|
l.unlock();
|
||||||
|
|
||||||
for (tracker_connections_t::iterator i = close_connections.begin()
|
for (http_conns_t::iterator i = close_http_connections.begin()
|
||||||
, end(close_connections.end()); i != end; ++i)
|
, end(close_http_connections.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
(*i)->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<boost::shared_ptr<udp_tracker_connection> >::iterator i
|
||||||
|
= close_udp_connections.begin()
|
||||||
|
, end(close_udp_connections.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
(*i)->close();
|
(*i)->close();
|
||||||
}
|
}
|
||||||
|
@ -343,12 +390,12 @@ namespace libtorrent
|
||||||
bool tracker_manager::empty() const
|
bool tracker_manager::empty() const
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
return m_connections.empty();
|
return m_http_conns.empty() && m_udp_conns.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
int tracker_manager::num_requests() const
|
int tracker_manager::num_requests() const
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
return m_connections.size();
|
return m_http_conns.size() + m_udp_conns.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,7 @@ namespace libtorrent
|
||||||
, m_state(action_error)
|
, m_state(action_error)
|
||||||
, m_abort(false)
|
, m_abort(false)
|
||||||
{
|
{
|
||||||
|
update_transaction_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
void udp_tracker_connection::start()
|
void udp_tracker_connection::start()
|
||||||
|
@ -120,7 +121,7 @@ namespace libtorrent
|
||||||
? resolver_interface::prefer_cache
|
? resolver_interface::prefer_cache
|
||||||
: 0
|
: 0
|
||||||
, boost::bind(&udp_tracker_connection::name_lookup
|
, boost::bind(&udp_tracker_connection::name_lookup
|
||||||
, self(), _1, _2, port));
|
, shared_from_this(), _1, _2, port));
|
||||||
|
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
||||||
boost::shared_ptr<request_callback> cb = requester();
|
boost::shared_ptr<request_callback> cb = requester();
|
||||||
|
@ -165,7 +166,7 @@ namespace libtorrent
|
||||||
, m_hostname.c_str(), print_endpoint(m_target).c_str());
|
, m_hostname.c_str(), print_endpoint(m_target).c_str());
|
||||||
#endif
|
#endif
|
||||||
m_ses.m_io_service.post(boost::bind(
|
m_ses.m_io_service.post(boost::bind(
|
||||||
&udp_tracker_connection::start_announce, self()));
|
&udp_tracker_connection::start_announce, shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void udp_tracker_connection::name_lookup(error_code const& error
|
void udp_tracker_connection::name_lookup(error_code const& error
|
||||||
|
@ -221,7 +222,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if all endpoints were filtered by the IP filter, we can't connect
|
// ir all endpoints were filtered by the IP filter, we can't connect
|
||||||
if (m_endpoints.empty())
|
if (m_endpoints.empty())
|
||||||
{
|
{
|
||||||
fail(error_code(errors::banned_by_ip_filter));
|
fail(error_code(errors::banned_by_ip_filter));
|
||||||
|
@ -357,7 +358,7 @@ namespace libtorrent
|
||||||
|
|
||||||
const char* ptr = buf;
|
const char* ptr = buf;
|
||||||
int action = detail::read_int32(ptr);
|
int action = detail::read_int32(ptr);
|
||||||
int transaction = detail::read_int32(ptr);
|
boost::uint32_t transaction = detail::read_uint32(ptr);
|
||||||
|
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
||||||
if (cb)
|
if (cb)
|
||||||
|
@ -400,6 +401,20 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void udp_tracker_connection::update_transaction_id()
|
||||||
|
{
|
||||||
|
boost::uint32_t new_tid;
|
||||||
|
|
||||||
|
// don't use 0, because that has special meaning (unintialized)
|
||||||
|
do {
|
||||||
|
new_tid = random();
|
||||||
|
} while (new_tid == 0);
|
||||||
|
|
||||||
|
if (m_transaction_id != 0)
|
||||||
|
m_man.update_transaction_id(shared_from_this(), new_tid);
|
||||||
|
m_transaction_id = new_tid;
|
||||||
|
}
|
||||||
|
|
||||||
bool udp_tracker_connection::on_connect_response(char const* buf, int size)
|
bool udp_tracker_connection::on_connect_response(char const* buf, int size)
|
||||||
{
|
{
|
||||||
|
@ -410,8 +425,7 @@ namespace libtorrent
|
||||||
buf += 8; // skip header
|
buf += 8; // skip header
|
||||||
|
|
||||||
// reset transaction
|
// reset transaction
|
||||||
m_transaction_id = 0;
|
update_transaction_id();
|
||||||
m_attempts = 0;
|
|
||||||
boost::uint64_t connection_id = detail::read_int64(buf);
|
boost::uint64_t connection_id = detail::read_int64(buf);
|
||||||
|
|
||||||
mutex::scoped_lock l(m_cache_mutex);
|
mutex::scoped_lock l(m_cache_mutex);
|
||||||
|
@ -442,8 +456,7 @@ namespace libtorrent
|
||||||
char buf[16];
|
char buf[16];
|
||||||
char* ptr = buf;
|
char* ptr = buf;
|
||||||
|
|
||||||
if (m_transaction_id == 0)
|
TORRENT_ASSERT(m_transaction_id != 0);
|
||||||
m_transaction_id = random() ^ (random() << 16);
|
|
||||||
|
|
||||||
detail::write_uint32(0x417, ptr);
|
detail::write_uint32(0x417, ptr);
|
||||||
detail::write_uint32(0x27101980, ptr); // connection_id
|
detail::write_uint32(0x27101980, ptr); // connection_id
|
||||||
|
@ -472,9 +485,6 @@ namespace libtorrent
|
||||||
|
|
||||||
void udp_tracker_connection::send_udp_scrape()
|
void udp_tracker_connection::send_udp_scrape()
|
||||||
{
|
{
|
||||||
if (m_transaction_id == 0)
|
|
||||||
m_transaction_id = random() ^ (random() << 16);
|
|
||||||
|
|
||||||
if (m_abort) return;
|
if (m_abort) return;
|
||||||
|
|
||||||
std::map<address, connection_cache_entry>::iterator i
|
std::map<address, connection_cache_entry>::iterator i
|
||||||
|
@ -579,7 +589,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
restart_read_timeout();
|
restart_read_timeout();
|
||||||
int action = detail::read_int32(buf);
|
int action = detail::read_int32(buf);
|
||||||
int transaction = detail::read_int32(buf);
|
boost::uint32_t transaction = detail::read_uint32(buf);
|
||||||
|
|
||||||
if (transaction != m_transaction_id)
|
if (transaction != m_transaction_id)
|
||||||
{
|
{
|
||||||
|
@ -625,9 +635,6 @@ namespace libtorrent
|
||||||
|
|
||||||
void udp_tracker_connection::send_udp_announce()
|
void udp_tracker_connection::send_udp_announce()
|
||||||
{
|
{
|
||||||
if (m_transaction_id == 0)
|
|
||||||
m_transaction_id = random() ^ (random() << 16);
|
|
||||||
|
|
||||||
if (m_abort) return;
|
if (m_abort) return;
|
||||||
|
|
||||||
char buf[800];
|
char buf[800];
|
||||||
|
|
Loading…
Reference in New Issue