libtorrent sync 2347
This commit is contained in:
parent
576cae3b26
commit
b15608252c
|
@ -134,7 +134,7 @@ class Torrent:
|
|||
|
||||
def set_private_flag(self, private):
|
||||
self.private = private
|
||||
self.handle.get_torrent_info().set_priv(private)
|
||||
#self.handle.get_torrent_info().set_priv(private)
|
||||
|
||||
def set_prioritize_first_last(self, prioritize):
|
||||
self.prioritize_first_last = prioritize
|
||||
|
|
|
@ -28,17 +28,17 @@ namespace
|
|||
this->peer_plugin::add_handshake(e);
|
||||
}
|
||||
|
||||
bool on_handshake()
|
||||
bool on_handshake(char const* reserved_bits)
|
||||
{
|
||||
if (override f = this->get_override("on_handshake"))
|
||||
return f();
|
||||
else
|
||||
return peer_plugin::on_handshake();
|
||||
return peer_plugin::on_handshake(reserved_bits);
|
||||
}
|
||||
|
||||
bool default_on_handshake()
|
||||
bool default_on_handshake(char const* reserved_bits)
|
||||
{
|
||||
return this->peer_plugin::on_handshake();
|
||||
return this->peer_plugin::on_handshake(reserved_bits);
|
||||
}
|
||||
|
||||
bool on_extension_handshake(entry const& e)
|
||||
|
|
|
@ -74,13 +74,7 @@ void bind_torrent_info()
|
|||
.def(init<entry const&>())
|
||||
.def(init<sha1_hash const&>())
|
||||
|
||||
.def("create_torrent", &torrent_info::create_torrent)
|
||||
.def("set_comment", &torrent_info::set_comment)
|
||||
.def("set_piece_size", &torrent_info::set_piece_size)
|
||||
.def("set_creator", &torrent_info::set_creator)
|
||||
.def("set_hash", &torrent_info::set_hash)
|
||||
.def("add_tracker", &torrent_info::add_tracker, (arg("url"), arg("tier")=0))
|
||||
.def("add_file", &torrent_info::add_file)
|
||||
.def("add_url_seed", &torrent_info::add_url_seed)
|
||||
|
||||
.def("name", &torrent_info::name, copy)
|
||||
|
@ -91,7 +85,7 @@ void bind_torrent_info()
|
|||
.def("num_pieces", &torrent_info::num_pieces)
|
||||
.def("info_hash", &torrent_info::info_hash, copy)
|
||||
|
||||
.def("hash_for_piece", &torrent_info::hash_for_piece, copy)
|
||||
.def("hash_for_piece", &torrent_info::hash_for_piece)
|
||||
.def("piece_size", &torrent_info::piece_size)
|
||||
|
||||
.def("num_files", &torrent_info::num_files, (arg("storage")=false))
|
||||
|
@ -99,7 +93,6 @@ void bind_torrent_info()
|
|||
.def("files", &files, (arg("storage")=false))
|
||||
|
||||
.def("priv", &torrent_info::priv)
|
||||
.def("set_priv", &torrent_info::set_priv)
|
||||
.def("trackers", range(begin_trackers, end_trackers))
|
||||
|
||||
.def("creation_date", &torrent_info::creation_date)
|
||||
|
|
|
@ -173,10 +173,6 @@ GEOIP_API const char * GeoIP_region_name_by_code(const char *country_code, const
|
|||
/* Get timezone from country and region code */
|
||||
GEOIP_API const char * GeoIP_time_zone_by_country_and_region(const char *country_code, const char *region_code);
|
||||
|
||||
#ifdef BSD
|
||||
#define memcpy(dest, src, n) bcopy(src, dest, n)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -188,7 +188,7 @@ namespace libtorrent
|
|||
struct TORRENT_EXPORT peer_error_alert: alert
|
||||
{
|
||||
peer_error_alert(tcp::endpoint const& pip, peer_id const& pid_, std::string const& msg)
|
||||
: alert(alert::debug, msg)
|
||||
: alert(alert::info, msg)
|
||||
, ip(pip)
|
||||
, pid(pid_)
|
||||
{}
|
||||
|
@ -200,6 +200,21 @@ namespace libtorrent
|
|||
peer_id pid;
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT peer_disconnected_alert: alert
|
||||
{
|
||||
peer_disconnected_alert(tcp::endpoint const& pip, peer_id const& pid_, std::string const& msg)
|
||||
: alert(alert::debug, msg)
|
||||
, ip(pip)
|
||||
, pid(pid_)
|
||||
{}
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new peer_disconnected_alert(*this)); }
|
||||
|
||||
tcp::endpoint ip;
|
||||
peer_id pid;
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT invalid_request_alert: torrent_alert
|
||||
{
|
||||
invalid_request_alert(
|
||||
|
|
|
@ -151,7 +151,7 @@ namespace libtorrent
|
|||
|
||||
void async_accept(boost::shared_ptr<socket_acceptor> const& listener);
|
||||
void on_incoming_connection(boost::shared_ptr<socket_type> const& s
|
||||
, boost::weak_ptr<socket_acceptor> listener, asio::error_code const& e);
|
||||
, boost::weak_ptr<socket_acceptor> listener, error_code const& e);
|
||||
|
||||
// must be locked to access the data
|
||||
// in this struct
|
||||
|
@ -489,6 +489,11 @@ namespace libtorrent
|
|||
// from the torrent with the most peers
|
||||
int m_disconnect_time_scaler;
|
||||
|
||||
// when this scaler reaches zero, it will
|
||||
// scrape one of the auto managed, paused,
|
||||
// torrents.
|
||||
int m_auto_scrape_time_scaler;
|
||||
|
||||
// statistics gathered from all torrents.
|
||||
stat m_stat;
|
||||
|
||||
|
@ -498,7 +503,7 @@ namespace libtorrent
|
|||
// NAT or not.
|
||||
bool m_incoming_connection;
|
||||
|
||||
void second_tick(asio::error_code const& e);
|
||||
void second_tick(error_code const& e);
|
||||
void recalculate_auto_managed_torrents();
|
||||
void recalculate_unchoke_slots(int congested_torrents
|
||||
, int uncongested_torrents);
|
||||
|
@ -528,7 +533,7 @@ namespace libtorrent
|
|||
|
||||
udp_socket m_dht_socket;
|
||||
|
||||
void on_receive_udp(asio::error_code const& e
|
||||
void on_receive_udp(error_code const& e
|
||||
, udp::endpoint const& ep, char const* buf, int len);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -76,6 +76,8 @@ struct history_entry
|
|||
history_entry(intrusive_ptr<PeerConnection> p, weak_ptr<Torrent> t
|
||||
, int a, ptime exp)
|
||||
: expires_at(exp), amount(a), peer(p), tor(t) {}
|
||||
history_entry(int a, ptime exp)
|
||||
: expires_at(exp), amount(a), peer(), tor() {}
|
||||
ptime expires_at;
|
||||
int amount;
|
||||
intrusive_ptr<PeerConnection> peer;
|
||||
|
@ -111,6 +113,7 @@ struct bandwidth_manager
|
|||
: m_ios(ios)
|
||||
, m_history_timer(m_ios)
|
||||
, m_limit(bandwidth_limit::inf)
|
||||
, m_drain_quota(0)
|
||||
, m_current_quota(0)
|
||||
, m_channel(channel)
|
||||
, m_in_hand_out_bandwidth(false)
|
||||
|
@ -123,6 +126,14 @@ struct bandwidth_manager
|
|||
#endif
|
||||
}
|
||||
|
||||
void drain(int bytes)
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
TORRENT_ASSERT(bytes >= 0);
|
||||
m_drain_quota += bytes;
|
||||
if (m_drain_quota > m_limit * 5) m_drain_quota = m_limit * 5;
|
||||
}
|
||||
|
||||
void throttle(int limit)
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
@ -154,7 +165,6 @@ struct bandwidth_manager
|
|||
|
||||
bool is_queued(PeerConnection const* peer, boost::mutex::scoped_lock& l) const
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
for (typename queue_t::const_iterator i = m_queue.begin()
|
||||
, end(m_queue.end()); i != end; ++i)
|
||||
{
|
||||
|
@ -171,7 +181,6 @@ struct bandwidth_manager
|
|||
|
||||
bool is_in_history(PeerConnection const* peer, boost::mutex::scoped_lock& l) const
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
for (typename history_t::const_iterator i
|
||||
= m_history.begin(), end(m_history.end()); i != end; ++i)
|
||||
{
|
||||
|
@ -258,12 +267,12 @@ private:
|
|||
|
||||
if (m_abort) return;
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_history_timer.expires_at(e.expires_at, ec);
|
||||
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
|
||||
}
|
||||
|
||||
void on_history_expire(asio::error_code const& e)
|
||||
void on_history_expire(error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
|
@ -290,6 +299,7 @@ private:
|
|||
<< std::endl;
|
||||
#endif
|
||||
intrusive_ptr<PeerConnection> c = e.peer;
|
||||
if (!c) continue;
|
||||
shared_ptr<Torrent> t = e.tor.lock();
|
||||
l.unlock();
|
||||
if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount);
|
||||
|
@ -300,7 +310,7 @@ private:
|
|||
// now, wait for the next chunk to expire
|
||||
if (!m_history.empty() && !m_abort)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_history_timer.expires_at(m_history.back().expires_at, ec);
|
||||
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
|
||||
}
|
||||
|
@ -313,7 +323,6 @@ private:
|
|||
|
||||
void hand_out_bandwidth(boost::mutex::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
// if we're already handing out bandwidth, just return back
|
||||
// to the loop further down on the callstack
|
||||
if (m_in_hand_out_bandwidth) return;
|
||||
|
@ -332,6 +341,15 @@ private:
|
|||
|
||||
if (amount <= 0) return;
|
||||
|
||||
if (m_drain_quota > 0)
|
||||
{
|
||||
int drain_amount = (std::min)(m_drain_quota, amount);
|
||||
m_drain_quota -= drain_amount;
|
||||
amount -= drain_amount;
|
||||
add_history_entry(history_entry<PeerConnection, Torrent>(
|
||||
drain_amount, now + bw_window_size));
|
||||
}
|
||||
|
||||
queue_t tmp;
|
||||
while (!m_queue.empty() && amount > 0)
|
||||
{
|
||||
|
@ -436,6 +454,10 @@ private:
|
|||
// the rate limit (bytes per second)
|
||||
int m_limit;
|
||||
|
||||
// bytes to drain without handing out to a peer
|
||||
// used to deduct the IP overhead
|
||||
int m_drain_quota;
|
||||
|
||||
// the sum of all recently handed out bandwidth blocks
|
||||
int m_current_quota;
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace libtorrent
|
|||
int common_bits(unsigned char const* b1
|
||||
, unsigned char const* b2, int n);
|
||||
|
||||
TORRENT_EXPORT address guess_local_address(asio::io_service&);
|
||||
TORRENT_EXPORT address guess_local_address(io_service&);
|
||||
|
||||
typedef boost::function<void(udp::endpoint const& from
|
||||
, char* buffer, int size)> receive_handler_t;
|
||||
|
@ -59,11 +59,11 @@ namespace libtorrent
|
|||
class TORRENT_EXPORT broadcast_socket
|
||||
{
|
||||
public:
|
||||
broadcast_socket(asio::io_service& ios, udp::endpoint const& multicast_endpoint
|
||||
broadcast_socket(io_service& ios, udp::endpoint const& multicast_endpoint
|
||||
, receive_handler_t const& handler, bool loopback = true);
|
||||
~broadcast_socket() { close(); }
|
||||
|
||||
void send(char const* buffer, int size, asio::error_code& ec);
|
||||
void send(char const* buffer, int size, error_code& ec);
|
||||
void close();
|
||||
|
||||
private:
|
||||
|
@ -77,12 +77,12 @@ namespace libtorrent
|
|||
void close()
|
||||
{
|
||||
if (!socket) return;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
socket->close(ec);
|
||||
}
|
||||
};
|
||||
|
||||
void on_receive(socket_entry* s, asio::error_code const& ec
|
||||
void on_receive(socket_entry* s, error_code const& ec
|
||||
, std::size_t bytes_transferred);
|
||||
void open_unicast_socket(io_service& ios, address const& addr);
|
||||
void open_multicast_socket(io_service& ios, address const& addr
|
||||
|
|
|
@ -100,6 +100,7 @@ namespace libtorrent
|
|||
bt_peer_connection(
|
||||
aux::session_impl& ses
|
||||
, boost::shared_ptr<socket_type> s
|
||||
, tcp::endpoint const& remote
|
||||
, policy::peer* peerinfo);
|
||||
|
||||
void start();
|
||||
|
@ -141,9 +142,9 @@ namespace libtorrent
|
|||
// called from the main loop when this connection has any
|
||||
// work to do.
|
||||
|
||||
void on_sent(asio::error_code const& error
|
||||
void on_sent(error_code const& error
|
||||
, std::size_t bytes_transferred);
|
||||
void on_receive(asio::error_code const& error
|
||||
void on_receive(error_code const& error
|
||||
, std::size_t bytes_transferred);
|
||||
|
||||
virtual void get_specific_peer_info(peer_info& p) const;
|
||||
|
@ -363,6 +364,7 @@ private:
|
|||
// the peer indicated that it supports the
|
||||
// extension protocol
|
||||
bool m_supports_extensions;
|
||||
char m_reserved_bits[20];
|
||||
#endif
|
||||
bool m_supports_dht_port;
|
||||
bool m_supports_fast;
|
||||
|
|
|
@ -34,12 +34,19 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/buffer.hpp>
|
||||
#else
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#endif
|
||||
#include <list>
|
||||
#include <cstring>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
#if BOOST_VERSION >= 103500
|
||||
namespace asio = boost::asio;
|
||||
#endif
|
||||
struct chained_buffer
|
||||
{
|
||||
chained_buffer(): m_bytes(0), m_capacity(0) {}
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
private:
|
||||
|
||||
void try_connect();
|
||||
void on_timeout(asio::error_code const& e);
|
||||
void on_timeout(error_code const& e);
|
||||
|
||||
struct entry
|
||||
{
|
||||
|
|
|
@ -47,7 +47,13 @@ namespace libtorrent
|
|||
disk_buffer_holder(disk_io_thread& iothread, char* buf);
|
||||
~disk_buffer_holder();
|
||||
char* release();
|
||||
char* buffer() const { return m_buf; }
|
||||
char* get() const { return m_buf; }
|
||||
void reset(char* buf = 0);
|
||||
|
||||
typedef char* (disk_buffer_holder::*unspecified_bool_type)();
|
||||
operator unspecified_bool_type() const
|
||||
{ return m_buf == 0? 0: &disk_buffer_holder::release; }
|
||||
|
||||
private:
|
||||
disk_io_thread& m_iothread;
|
||||
char* m_buf;
|
||||
|
|
|
@ -149,7 +149,7 @@ namespace libtorrent
|
|||
// of disk io jobs
|
||||
struct disk_io_thread : boost::noncopyable
|
||||
{
|
||||
disk_io_thread(asio::io_service& ios, int block_size = 16 * 1024);
|
||||
disk_io_thread(io_service& ios, int block_size = 16 * 1024);
|
||||
~disk_io_thread();
|
||||
|
||||
#ifdef TORRENT_STATS
|
||||
|
@ -292,7 +292,7 @@ namespace libtorrent
|
|||
size_type m_writes;
|
||||
size_type m_blocks_written;
|
||||
|
||||
asio::io_service& m_ios;
|
||||
io_service& m_ios;
|
||||
|
||||
// thread for performing blocking disk io operations
|
||||
boost::thread m_disk_io_thread;
|
||||
|
|
|
@ -167,6 +167,8 @@ namespace libtorrent
|
|||
#endif
|
||||
entry* find_key(char const* key);
|
||||
entry const* find_key(char const* key) const;
|
||||
entry* find_key(std::string const& key);
|
||||
entry const* find_key(std::string const& key) const;
|
||||
|
||||
void print(std::ostream& os, int indent = 0) const;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace libtorrent
|
|||
{
|
||||
address interface_address;
|
||||
address netmask;
|
||||
char name[32];
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct ip_route
|
||||
|
@ -51,15 +51,15 @@ namespace libtorrent
|
|||
address destination;
|
||||
address netmask;
|
||||
address gateway;
|
||||
char name[32];
|
||||
char name[64];
|
||||
};
|
||||
|
||||
// returns a list of the configured IP interfaces
|
||||
// on the machine
|
||||
TORRENT_EXPORT std::vector<ip_interface> enum_net_interfaces(asio::io_service& ios
|
||||
, asio::error_code& ec);
|
||||
TORRENT_EXPORT std::vector<ip_interface> enum_net_interfaces(io_service& ios
|
||||
, error_code& ec);
|
||||
|
||||
TORRENT_EXPORT std::vector<ip_route> enum_routes(asio::io_service& ios, asio::error_code& ec);
|
||||
TORRENT_EXPORT std::vector<ip_route> enum_routes(io_service& ios, error_code& ec);
|
||||
|
||||
// returns true if the specified address is on the same
|
||||
// local network as the specified interface
|
||||
|
@ -67,11 +67,11 @@ namespace libtorrent
|
|||
|
||||
// returns true if the specified address is on the same
|
||||
// local network as us
|
||||
TORRENT_EXPORT bool in_local_network(asio::io_service& ios, address const& addr
|
||||
, asio::error_code& ec);
|
||||
TORRENT_EXPORT bool in_local_network(io_service& ios, address const& addr
|
||||
, error_code& ec);
|
||||
|
||||
TORRENT_EXPORT address get_default_gateway(asio::io_service& ios
|
||||
, asio::error_code& ec);
|
||||
TORRENT_EXPORT address get_default_gateway(io_service& ios
|
||||
, error_code& ec);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,6 +51,8 @@ namespace libtorrent
|
|||
|
||||
TORRENT_EXPORT boost::optional<std::string> url_has_argument(
|
||||
std::string const& url, std::string argument);
|
||||
|
||||
TORRENT_EXPORT std::string to_hex(std::string const& s);
|
||||
}
|
||||
|
||||
#endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace libtorrent
|
|||
// means that the other end doesn't support this extension and will remove
|
||||
// it from the list of plugins.
|
||||
// this is not called for web seeds
|
||||
virtual bool on_handshake() { return true; }
|
||||
virtual bool on_handshake(char const* reserved_bits) { return true; }
|
||||
|
||||
// called when the extension handshake from the other end is received
|
||||
// if this returns false, it means that this extension isn't
|
||||
|
|
|
@ -39,6 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "libtorrent/socket.hpp"
|
||||
|
@ -59,8 +60,8 @@ namespace libtorrent
|
|||
struct http_connection;
|
||||
class connection_queue;
|
||||
|
||||
typedef boost::function<void(asio::error_code const&
|
||||
, http_parser const&, char const* data, int size)> http_handler;
|
||||
typedef boost::function<void(error_code const&
|
||||
, http_parser const&, char const* data, int size, http_connection&)> http_handler;
|
||||
|
||||
typedef boost::function<void(http_connection&)> http_connect_handler;
|
||||
|
||||
|
@ -70,7 +71,7 @@ typedef boost::function<void(http_connection&)> http_connect_handler;
|
|||
// will always be 0
|
||||
struct http_connection : boost::enable_shared_from_this<http_connection>, boost::noncopyable
|
||||
{
|
||||
http_connection(asio::io_service& ios, connection_queue& cc
|
||||
http_connection(io_service& ios, connection_queue& cc
|
||||
, http_handler const& handler, bool bottled = true
|
||||
, http_connect_handler const& ch = http_connect_handler())
|
||||
: m_sock(ios)
|
||||
|
@ -91,6 +92,7 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
|
|||
, m_cc(cc)
|
||||
, m_ssl(false)
|
||||
, m_priority(0)
|
||||
, m_abort(false)
|
||||
{
|
||||
TORRENT_ASSERT(!m_handler.empty());
|
||||
}
|
||||
|
@ -121,19 +123,19 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
|
|||
|
||||
private:
|
||||
|
||||
void on_resolve(asio::error_code const& e
|
||||
void on_resolve(error_code const& e
|
||||
, tcp::resolver::iterator i);
|
||||
void queue_connect();
|
||||
void connect(int ticket, tcp::endpoint target_address);
|
||||
void on_connect_timeout();
|
||||
void on_connect(asio::error_code const& e
|
||||
/* , tcp::resolver::iterator i*/);
|
||||
void on_write(asio::error_code const& e);
|
||||
void on_read(asio::error_code const& e, std::size_t bytes_transferred);
|
||||
void on_connect(error_code const& e);
|
||||
void on_write(error_code const& e);
|
||||
void on_read(error_code const& e, std::size_t bytes_transferred);
|
||||
static void on_timeout(boost::weak_ptr<http_connection> p
|
||||
, asio::error_code const& e);
|
||||
void on_assign_bandwidth(asio::error_code const& e);
|
||||
, error_code const& e);
|
||||
void on_assign_bandwidth(error_code const& e);
|
||||
|
||||
void callback(asio::error_code const& e, char const* data = 0, int size = 0);
|
||||
void callback(error_code const& e, char const* data = 0, int size = 0);
|
||||
|
||||
std::vector<char> m_recvbuffer;
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
|
@ -158,6 +160,9 @@ private:
|
|||
bool m_called;
|
||||
std::string m_hostname;
|
||||
std::string m_port;
|
||||
std::string m_url;
|
||||
|
||||
std::list<tcp::endpoint> m_endpoints;
|
||||
|
||||
// the current download limit, in bytes per second
|
||||
// 0 is unlimited.
|
||||
|
@ -195,6 +200,8 @@ private:
|
|||
// the priority we have in the connection queue.
|
||||
// 0 is normal, 1 is high
|
||||
int m_priority;
|
||||
|
||||
bool m_abort;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ class http_stream : public proxy_base
|
|||
{
|
||||
public:
|
||||
|
||||
explicit http_stream(asio::io_service& io_service)
|
||||
explicit http_stream(io_service& io_service)
|
||||
: proxy_base(io_service)
|
||||
, m_no_connect(false)
|
||||
{}
|
||||
|
@ -55,7 +55,7 @@ public:
|
|||
m_password = password;
|
||||
}
|
||||
|
||||
typedef boost::function<void(asio::error_code const&)> handler_type;
|
||||
typedef boost::function<void(error_code const&)> handler_type;
|
||||
|
||||
template <class Handler>
|
||||
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
||||
|
@ -80,11 +80,11 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
||||
void name_lookup(error_code const& e, tcp::resolver::iterator i
|
||||
, boost::shared_ptr<handler_type> h);
|
||||
void connected(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
|
||||
// send and receive buffer
|
||||
std::vector<char> m_buffer;
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace libtorrent
|
|||
boost::intrusive_ptr<http_tracker_connection> self()
|
||||
{ return boost::intrusive_ptr<http_tracker_connection>(this); }
|
||||
|
||||
void on_response(asio::error_code const& ec, http_parser const& parser
|
||||
void on_response(error_code const& ec, http_parser const& parser
|
||||
, char const* data, int size);
|
||||
|
||||
virtual void on_timeout() {}
|
||||
|
|
|
@ -34,14 +34,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define TORRENT_INSTANTIATE_CONNECTION
|
||||
|
||||
#include "libtorrent/socket_type.hpp"
|
||||
#include <asio/io_service.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
struct proxy_settings;
|
||||
|
||||
bool instantiate_connection(asio::io_service& ios
|
||||
bool instantiate_connection(io_service& ios
|
||||
, proxy_settings const& ps, socket_type& s);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public:
|
|||
|
||||
private:
|
||||
void done();
|
||||
void invoke(node_id const& id, asio::ip::udp::endpoint addr);
|
||||
void invoke(node_id const& id, udp::endpoint addr);
|
||||
|
||||
closest_nodes(
|
||||
node_id target
|
||||
|
|
|
@ -53,6 +53,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/session_settings.hpp"
|
||||
#include "libtorrent/session_status.hpp"
|
||||
#include "libtorrent/udp_socket.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
|
||||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
@ -89,19 +90,20 @@ namespace libtorrent { namespace dht
|
|||
// translate bittorrent kademlia message into the generic kademlia message
|
||||
// used by the library
|
||||
void on_receive(udp::endpoint const& ep, char const* pkt, int size);
|
||||
void on_unreachable(udp::endpoint const& ep);
|
||||
|
||||
private:
|
||||
|
||||
boost::intrusive_ptr<dht_tracker> self()
|
||||
{ return boost::intrusive_ptr<dht_tracker>(this); }
|
||||
|
||||
void on_name_lookup(asio::error_code const& e
|
||||
void on_name_lookup(error_code const& e
|
||||
, udp::resolver::iterator host);
|
||||
void on_router_name_lookup(asio::error_code const& e
|
||||
void on_router_name_lookup(error_code const& e
|
||||
, udp::resolver::iterator host);
|
||||
void connection_timeout(asio::error_code const& e);
|
||||
void refresh_timeout(asio::error_code const& e);
|
||||
void tick(asio::error_code const& e);
|
||||
void connection_timeout(error_code const& e);
|
||||
void refresh_timeout(error_code const& e);
|
||||
void tick(error_code const& e);
|
||||
|
||||
void on_bootstrap();
|
||||
void send_packet(msg const& m);
|
||||
|
|
|
@ -48,8 +48,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
||||
using asio::ip::udp;
|
||||
|
||||
typedef std::vector<char> packet_t;
|
||||
|
||||
class rpc_manager;
|
||||
|
|
|
@ -36,15 +36,17 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <string>
|
||||
#include <libtorrent/kademlia/node_id.hpp>
|
||||
#include "libtorrent/entry.hpp"
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/ip/udp.hpp>
|
||||
#else
|
||||
#include <boost/asio/ip/udp.hpp>
|
||||
#endif
|
||||
|
||||
namespace libtorrent {
|
||||
namespace dht {
|
||||
|
||||
typedef std::vector<char> packet_t;
|
||||
|
||||
using asio::ip::udp;
|
||||
|
||||
namespace messages
|
||||
{
|
||||
enum { ping = 0, find_node = 1, get_peers = 2, announce_peer = 3, error = 4 };
|
||||
|
|
|
@ -56,8 +56,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
||||
using asio::ip::udp;
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_DECLARE_LOG(node);
|
||||
#endif
|
||||
|
@ -174,6 +172,7 @@ public:
|
|||
void(std::vector<node_entry> const&)> f);
|
||||
void add_router_node(udp::endpoint router);
|
||||
|
||||
void unreachable(udp::endpoint const& ep);
|
||||
void incoming(msg const& m);
|
||||
|
||||
void refresh();
|
||||
|
|
|
@ -41,20 +41,33 @@ namespace libtorrent { namespace dht
|
|||
|
||||
struct node_entry
|
||||
{
|
||||
node_entry(node_id const& id_, asio::ip::udp::endpoint addr_)
|
||||
node_entry(node_id const& id_, udp::endpoint addr_)
|
||||
: id(id_)
|
||||
, addr(addr_)
|
||||
, fail_count(0) {}
|
||||
node_entry(asio::ip::udp::endpoint addr_)
|
||||
, fail_count(0)
|
||||
{
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
first_seen = time_now();
|
||||
#endif
|
||||
}
|
||||
node_entry(udp::endpoint addr_)
|
||||
: id(0)
|
||||
, addr(addr_)
|
||||
, fail_count(0) {}
|
||||
, fail_count(0)
|
||||
{
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
first_seen = time_now();
|
||||
#endif
|
||||
}
|
||||
|
||||
node_id id;
|
||||
udp::endpoint addr;
|
||||
// the number of times this node has failed to
|
||||
// respond in a row
|
||||
int fail_count;
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
ptime first_seen;
|
||||
#endif
|
||||
};
|
||||
|
||||
} } // namespace libtorrent::dht
|
||||
|
|
|
@ -55,9 +55,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
||||
using asio::ip::udp;
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_DECLARE_LOG(table);
|
||||
#endif
|
||||
|
||||
//TORRENT_DECLARE_LOG(table);
|
||||
|
||||
typedef std::vector<node_entry> bucket_t;
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ namespace libtorrent { namespace dht
|
|||
|
||||
struct observer;
|
||||
|
||||
using asio::ip::udp;
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_DECLARE_LOG(rpc);
|
||||
#endif
|
||||
|
@ -82,6 +81,8 @@ public:
|
|||
, routing_table& table, send_fun const& sf);
|
||||
~rpc_manager();
|
||||
|
||||
void unreachable(udp::endpoint const& ep);
|
||||
|
||||
// returns true if the node needs a refresh
|
||||
bool incoming(msg const&);
|
||||
time_duration tick();
|
||||
|
|
|
@ -179,6 +179,15 @@ namespace libtorrent
|
|||
|
||||
void clear();
|
||||
|
||||
// releases ownership of any memory allocated
|
||||
void release()
|
||||
{
|
||||
m_data.start = 0;
|
||||
m_size = 0;
|
||||
m_capacity = 0;
|
||||
m_type = none_t;
|
||||
}
|
||||
|
||||
~lazy_entry()
|
||||
{ clear(); }
|
||||
|
||||
|
@ -186,6 +195,17 @@ namespace libtorrent
|
|||
// this entry has its bencoded data
|
||||
std::pair<char const*, int> data_section() const;
|
||||
|
||||
void swap(lazy_entry& e)
|
||||
{
|
||||
using std::swap;
|
||||
swap(m_type, e.m_type);
|
||||
swap(m_data.start, e.m_data.start);
|
||||
swap(m_size, e.m_size);
|
||||
swap(m_capacity, e.m_capacity);
|
||||
swap(m_begin, e.m_begin);
|
||||
swap(m_end, e.m_end);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
entry_type_t m_type;
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void resend_announce(asio::error_code const& e, std::string msg);
|
||||
void resend_announce(error_code const& e, std::string msg);
|
||||
void on_announce(udp::endpoint const& from, char* buffer
|
||||
, std::size_t bytes_transferred);
|
||||
// void setup_receive();
|
||||
|
|
|
@ -70,12 +70,12 @@ private:
|
|||
|
||||
void update_mapping(int i);
|
||||
void send_map_request(int i);
|
||||
void resend_request(int i, asio::error_code const& e);
|
||||
void on_reply(asio::error_code const& e
|
||||
void resend_request(int i, error_code const& e);
|
||||
void on_reply(error_code const& e
|
||||
, std::size_t bytes_transferred);
|
||||
void try_next_mapping(int i);
|
||||
void update_expiration_timer();
|
||||
void mapping_expired(asio::error_code const& e, int i);
|
||||
void mapping_expired(error_code const& e, int i);
|
||||
|
||||
void disable(char const* message);
|
||||
|
||||
|
|
|
@ -121,6 +121,7 @@ namespace libtorrent
|
|||
peer_connection(
|
||||
aux::session_impl& ses
|
||||
, boost::shared_ptr<socket_type> s
|
||||
, tcp::endpoint const& remote
|
||||
, policy::peer* peerinfo);
|
||||
|
||||
// this function is called after it has been constructed and properly
|
||||
|
@ -197,6 +198,9 @@ namespace libtorrent
|
|||
|
||||
bool is_seed() const;
|
||||
|
||||
void set_upload_only(bool u) { m_upload_only = u; }
|
||||
bool upload_only() const { return m_upload_only; }
|
||||
|
||||
bool has_timed_out() const;
|
||||
|
||||
// will send a keep-alive message to the peer
|
||||
|
@ -230,6 +234,8 @@ namespace libtorrent
|
|||
const stat& statistics() const { return m_statistics; }
|
||||
void add_stat(size_type downloaded, size_type uploaded);
|
||||
|
||||
void calc_ip_overhead();
|
||||
|
||||
// is called once every second by the main loop
|
||||
void second_tick(float tick_interval);
|
||||
|
||||
|
@ -240,15 +246,18 @@ namespace libtorrent
|
|||
std::vector<int> const& allowed_fast();
|
||||
std::vector<int> const& suggested_pieces() const { return m_suggested_pieces; }
|
||||
|
||||
ptime connected_time() const { return m_connect; }
|
||||
ptime last_received() const { return m_last_receive; }
|
||||
|
||||
void timed_out();
|
||||
// this will cause this peer_connection to be disconnected.
|
||||
void disconnect(char const* message);
|
||||
void disconnect(char const* message, int error = 0);
|
||||
bool is_disconnecting() const { return m_disconnecting; }
|
||||
|
||||
// this is called when the connection attempt has succeeded
|
||||
// and the peer_connection is supposed to set m_connecting
|
||||
// to false, and stop monitor writability
|
||||
void on_connection_complete(asio::error_code const& e);
|
||||
void on_connection_complete(error_code const& e);
|
||||
|
||||
// returns true if this connection is still waiting to
|
||||
// finish the connection attempt
|
||||
|
@ -288,7 +297,6 @@ namespace libtorrent
|
|||
bool ignore_bandwidth_limits() const
|
||||
{ return m_ignore_bandwidth_limits; }
|
||||
|
||||
void set_failed() { m_failed = true; }
|
||||
bool failed() const { return m_failed; }
|
||||
|
||||
int desired_queue_size() const { return m_desired_queue_size; }
|
||||
|
@ -449,15 +457,15 @@ namespace libtorrent
|
|||
virtual void on_connected() = 0;
|
||||
virtual void on_tick() {}
|
||||
|
||||
virtual void on_receive(asio::error_code const& error
|
||||
virtual void on_receive(error_code const& error
|
||||
, std::size_t bytes_transferred) = 0;
|
||||
virtual void on_sent(asio::error_code const& error
|
||||
virtual void on_sent(error_code const& error
|
||||
, std::size_t bytes_transferred) = 0;
|
||||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
buffer::interval wr_recv_buffer()
|
||||
{
|
||||
TORRENT_ASSERT(m_disk_recv_buffer == 0);
|
||||
TORRENT_ASSERT(!m_disk_recv_buffer);
|
||||
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
|
||||
if (m_recv_buffer.empty()) return buffer::interval(0,0);
|
||||
return buffer::interval(&m_recv_buffer[0]
|
||||
|
@ -501,9 +509,9 @@ namespace libtorrent
|
|||
|
||||
// called from the main loop when this connection has any
|
||||
// work to do.
|
||||
void on_send_data(asio::error_code const& error
|
||||
void on_send_data(error_code const& error
|
||||
, std::size_t bytes_transferred);
|
||||
void on_receive_data(asio::error_code const& error
|
||||
void on_receive_data(error_code const& error
|
||||
, std::size_t bytes_transferred);
|
||||
|
||||
// this is the limit on the number of outstanding requests
|
||||
|
@ -544,9 +552,6 @@ namespace libtorrent
|
|||
void on_disk_write_complete(int ret, disk_io_job const& j
|
||||
, peer_request r, boost::shared_ptr<torrent> t);
|
||||
|
||||
// the timeout in seconds
|
||||
int m_timeout;
|
||||
|
||||
// the time when we last got a part of a
|
||||
// piece packet from this peer
|
||||
ptime m_last_piece;
|
||||
|
@ -559,28 +564,54 @@ namespace libtorrent
|
|||
// the time when we unchoked this peer
|
||||
ptime m_last_unchoke;
|
||||
|
||||
int m_packet_size;
|
||||
int m_recv_pos;
|
||||
// timeouts
|
||||
ptime m_last_receive;
|
||||
ptime m_last_sent;
|
||||
|
||||
// a timestamp when the remote download rate
|
||||
// was last updated
|
||||
ptime m_remote_dl_update;
|
||||
|
||||
// the time when async_connect was called
|
||||
ptime m_connect;
|
||||
|
||||
// the time when this peer sent us a not_interested message
|
||||
// the last time.
|
||||
ptime m_became_uninterested;
|
||||
|
||||
// the time when we sent a not_interested message to
|
||||
// this peer the last time.
|
||||
ptime m_became_uninteresting;
|
||||
|
||||
// the amount of data this peer has been given
|
||||
// as free upload. This is distributed from
|
||||
// peers from which we get free download
|
||||
// this will be negative on a peer from which
|
||||
// we get free download, and positive on peers
|
||||
// that we give the free upload, to keep the balance.
|
||||
size_type m_free_upload;
|
||||
|
||||
// the total payload download bytes
|
||||
// at the last unchoke cycle. This is used to
|
||||
// measure the number of bytes transferred during
|
||||
// an unchoke cycle, to unchoke peers the more bytes
|
||||
// they sent us
|
||||
size_type m_downloaded_at_last_unchoke;
|
||||
|
||||
#ifndef TORRENT_DISABLE_GEO_IP
|
||||
std::string m_inet_as_name;
|
||||
#endif
|
||||
|
||||
buffer m_recv_buffer;
|
||||
|
||||
// if this peer is receiving a piece, this
|
||||
// points to a disk buffer that the data is
|
||||
// read into. This eliminates a memcopy from
|
||||
// the receive buffer into the disk buffer
|
||||
int m_disk_recv_buffer_size;
|
||||
char* m_disk_recv_buffer;
|
||||
disk_buffer_holder m_disk_recv_buffer;
|
||||
|
||||
chained_buffer m_send_buffer;
|
||||
|
||||
// the number of bytes we are currently reading
|
||||
// from disk, that will be added to the send
|
||||
// buffer as soon as they complete
|
||||
int m_reading_bytes;
|
||||
|
||||
// timeouts
|
||||
ptime m_last_receive;
|
||||
ptime m_last_sent;
|
||||
|
||||
boost::shared_ptr<socket_type> m_socket;
|
||||
// this is the peer we're actually talking to
|
||||
// it may not necessarily be the peer we're
|
||||
|
@ -593,51 +624,12 @@ namespace libtorrent
|
|||
// until the info_hash is received. Then it's
|
||||
// set to the torrent it belongs to.
|
||||
boost::weak_ptr<torrent> m_torrent;
|
||||
// is true if it was we that connected to the peer
|
||||
// and false if we got an incoming connection
|
||||
// could be considered: true = local, false = remote
|
||||
bool m_active;
|
||||
|
||||
// remote peer's id
|
||||
peer_id m_peer_id;
|
||||
|
||||
// other side says that it's interested in downloading
|
||||
// from us.
|
||||
bool m_peer_interested;
|
||||
|
||||
// the other side has told us that it won't send anymore
|
||||
// data to us for a while
|
||||
bool m_peer_choked;
|
||||
|
||||
// the peer has pieces we are interested in
|
||||
bool m_interesting;
|
||||
|
||||
// we have choked the upload to the peer
|
||||
bool m_choked;
|
||||
|
||||
// this is set to true if the connection timed
|
||||
// out or closed the connection. In that
|
||||
// case we will not try to reconnect to
|
||||
// this peer
|
||||
bool m_failed;
|
||||
|
||||
// if this is set to true, the peer will not
|
||||
// request bandwidth from the limiter, but instead
|
||||
// just send and receive as much as possible.
|
||||
bool m_ignore_bandwidth_limits;
|
||||
|
||||
// the pieces the other end have
|
||||
std::vector<bool> m_have_piece;
|
||||
// this is set to true when a have_all
|
||||
// message is received. This information
|
||||
// is used to fill the bitmask in init()
|
||||
bool m_have_all;
|
||||
|
||||
// the number of pieces this peer
|
||||
// has. Must be the same as
|
||||
// std::count(m_have_piece.begin(),
|
||||
// m_have_piece.end(), true)
|
||||
int m_num_pieces;
|
||||
|
||||
// the queue of requests we have got
|
||||
// from this peer
|
||||
|
@ -651,25 +643,42 @@ namespace libtorrent
|
|||
// from this peer
|
||||
std::deque<piece_block> m_download_queue;
|
||||
|
||||
// the number of request we should queue up
|
||||
// at the remote end.
|
||||
int m_desired_queue_size;
|
||||
// the pieces we will send to the peer
|
||||
// if requested (regardless of choke state)
|
||||
std::set<int> m_accept_fast;
|
||||
|
||||
// the amount of data this peer has been given
|
||||
// as free upload. This is distributed from
|
||||
// peers from which we get free download
|
||||
// this will be negative on a peer from which
|
||||
// we get free download, and positive on peers
|
||||
// that we give the free upload, to keep the balance.
|
||||
size_type m_free_upload;
|
||||
// the pieces the peer will send us if
|
||||
// requested (regardless of choke state)
|
||||
std::vector<int> m_allowed_fast;
|
||||
|
||||
// if this is true, this peer is assumed to handle all piece
|
||||
// requests in fifo order. All skipped blocks are re-requested
|
||||
// immediately instead of having a looser requirement
|
||||
// where blocks can be sent out of order. The default is to
|
||||
// allow non-fifo order.
|
||||
bool m_assume_fifo;
|
||||
// pieces that has been suggested to be
|
||||
// downloaded from this peer
|
||||
std::vector<int> m_suggested_pieces;
|
||||
|
||||
// the number of pieces this peer
|
||||
// has. Must be the same as
|
||||
// std::count(m_have_piece.begin(),
|
||||
// m_have_piece.end(), true)
|
||||
int m_num_pieces;
|
||||
|
||||
// the timeout in seconds
|
||||
int m_timeout;
|
||||
|
||||
// the size (in bytes) of the bittorrent message
|
||||
// we're currently receiving
|
||||
int m_packet_size;
|
||||
|
||||
// the number of bytes of the bittorrent payload
|
||||
// we've received so far
|
||||
int m_recv_pos;
|
||||
|
||||
int m_disk_recv_buffer_size;
|
||||
|
||||
// the number of bytes we are currently reading
|
||||
// from disk, that will be added to the send
|
||||
// buffer as soon as they complete
|
||||
int m_reading_bytes;
|
||||
|
||||
// the number of invalid piece-requests
|
||||
// we have got from this peer. If the request
|
||||
// queue gets empty, and there have been
|
||||
|
@ -679,49 +688,6 @@ namespace libtorrent
|
|||
// by sending choke, unchoke.
|
||||
int m_num_invalid_requests;
|
||||
|
||||
// this is true if this connection has been added
|
||||
// to the list of connections that will be closed.
|
||||
bool m_disconnecting;
|
||||
|
||||
// the time when this peer sent us a not_interested message
|
||||
// the last time.
|
||||
ptime m_became_uninterested;
|
||||
|
||||
// the time when we sent a not_interested message to
|
||||
// this peer the last time.
|
||||
ptime m_became_uninteresting;
|
||||
|
||||
// this is true until this socket has become
|
||||
// writable for the first time (i.e. the
|
||||
// connection completed). While connecting
|
||||
// the timeout will not be triggered. This is
|
||||
// because windows XP SP2 may delay connection
|
||||
// attempts, which means that the connection
|
||||
// may not even have been attempted when the
|
||||
// time out is reached.
|
||||
bool m_connecting;
|
||||
|
||||
// This is true until connect is called on the
|
||||
// peer_connection's socket. It is false on incoming
|
||||
// connections.
|
||||
bool m_queued;
|
||||
|
||||
// if set to non-zero, this peer will always prefer
|
||||
// to request entire n pieces, rather than blocks.
|
||||
// where n is the value of this variable.
|
||||
// if it is 0, the download rate limit setting
|
||||
// will be used to determine if whole pieces
|
||||
// are preferred.
|
||||
int m_prefer_whole_pieces;
|
||||
|
||||
// if this is true, the blocks picked by the piece
|
||||
// picker will be merged before passed to the
|
||||
// request function. i.e. subsequent blocks are
|
||||
// merged into larger blocks. This is used by
|
||||
// the http-downloader, to request whole pieces
|
||||
// at a time.
|
||||
bool m_request_large_blocks;
|
||||
|
||||
// this is the priority with which this peer gets
|
||||
// download bandwidth quota assigned to it.
|
||||
int m_priority;
|
||||
|
@ -753,60 +719,114 @@ namespace libtorrent
|
|||
// approximate peer download rate
|
||||
int m_remote_dl_rate;
|
||||
|
||||
// a timestamp when the remote download rate
|
||||
// was last updated
|
||||
ptime m_remote_dl_update;
|
||||
|
||||
// the pieces we will send to the peer
|
||||
// if requested (regardless of choke state)
|
||||
std::set<int> m_accept_fast;
|
||||
|
||||
// the pieces the peer will send us if
|
||||
// requested (regardless of choke state)
|
||||
std::vector<int> m_allowed_fast;
|
||||
|
||||
// pieces that has been suggested to be
|
||||
// downloaded from this peer
|
||||
std::vector<int> m_suggested_pieces;
|
||||
|
||||
// the number of bytes send to the disk-io
|
||||
// thread that hasn't yet been completely written.
|
||||
int m_outstanding_writing_bytes;
|
||||
|
||||
// max transfer rates seen on this peer
|
||||
int m_download_rate_peak;
|
||||
int m_upload_rate_peak;
|
||||
|
||||
// estimated round trip time to this peer
|
||||
// based on the time from when async_connect
|
||||
// was called to when on_connection_complete
|
||||
// was called. The rtt is specified in milliseconds
|
||||
boost::uint16_t m_rtt;
|
||||
|
||||
// if set to non-zero, this peer will always prefer
|
||||
// to request entire n pieces, rather than blocks.
|
||||
// where n is the value of this variable.
|
||||
// if it is 0, the download rate limit setting
|
||||
// will be used to determine if whole pieces
|
||||
// are preferred.
|
||||
boost::uint8_t m_prefer_whole_pieces;
|
||||
|
||||
// the number of request we should queue up
|
||||
// at the remote end.
|
||||
boost::uint8_t m_desired_queue_size;
|
||||
|
||||
// if this is true, the disconnection
|
||||
// timestamp is not updated when the connection
|
||||
// is closed. This means the time until we can
|
||||
// reconnect to this peer is shorter, and likely
|
||||
// immediate.
|
||||
bool m_fast_reconnect;
|
||||
bool m_fast_reconnect:1;
|
||||
|
||||
// the time when async_connect was called
|
||||
ptime m_connect;
|
||||
// is true if it was we that connected to the peer
|
||||
// and false if we got an incoming connection
|
||||
// could be considered: true = local, false = remote
|
||||
bool m_active:1;
|
||||
|
||||
// estimated round trip time to this peer
|
||||
// based on the time from when async_connect
|
||||
// was called to when on_connection_complete
|
||||
// was called. The rtt is specified in milliseconds
|
||||
int m_rtt;
|
||||
// other side says that it's interested in downloading
|
||||
// from us.
|
||||
bool m_peer_interested:1;
|
||||
|
||||
// the total payload download bytes
|
||||
// at the last unchoke cycle. This is used to
|
||||
// measure the number of bytes transferred during
|
||||
// an unchoke cycle, to unchoke peers the more bytes
|
||||
// they sent us
|
||||
size_type m_downloaded_at_last_unchoke;
|
||||
// the other side has told us that it won't send anymore
|
||||
// data to us for a while
|
||||
bool m_peer_choked:1;
|
||||
|
||||
#ifndef TORRENT_DISABLE_GEO_IP
|
||||
std::string m_inet_as_name;
|
||||
#endif
|
||||
// the peer has pieces we are interested in
|
||||
bool m_interesting:1;
|
||||
|
||||
// max transfer rates seen on this peer
|
||||
int m_download_rate_peak;
|
||||
int m_upload_rate_peak;
|
||||
// we have choked the upload to the peer
|
||||
bool m_choked:1;
|
||||
|
||||
// this is set to true if the connection timed
|
||||
// out or closed the connection. In that
|
||||
// case we will not try to reconnect to
|
||||
// this peer
|
||||
bool m_failed:1;
|
||||
|
||||
// if this is set to true, the peer will not
|
||||
// request bandwidth from the limiter, but instead
|
||||
// just send and receive as much as possible.
|
||||
bool m_ignore_bandwidth_limits:1;
|
||||
|
||||
// this is set to true when a have_all
|
||||
// message is received. This information
|
||||
// is used to fill the bitmask in init()
|
||||
bool m_have_all:1;
|
||||
|
||||
// if this is true, this peer is assumed to handle all piece
|
||||
// requests in fifo order. All skipped blocks are re-requested
|
||||
// immediately instead of having a looser requirement
|
||||
// where blocks can be sent out of order. The default is to
|
||||
// allow non-fifo order.
|
||||
bool m_assume_fifo:1;
|
||||
|
||||
// this is true if this connection has been added
|
||||
// to the list of connections that will be closed.
|
||||
bool m_disconnecting:1;
|
||||
|
||||
// this is true until this socket has become
|
||||
// writable for the first time (i.e. the
|
||||
// connection completed). While connecting
|
||||
// the timeout will not be triggered. This is
|
||||
// because windows XP SP2 may delay connection
|
||||
// attempts, which means that the connection
|
||||
// may not even have been attempted when the
|
||||
// time out is reached.
|
||||
bool m_connecting:1;
|
||||
|
||||
// This is true until connect is called on the
|
||||
// peer_connection's socket. It is false on incoming
|
||||
// connections.
|
||||
bool m_queued:1;
|
||||
|
||||
// if this is true, the blocks picked by the piece
|
||||
// picker will be merged before passed to the
|
||||
// request function. i.e. subsequent blocks are
|
||||
// merged into larger blocks. This is used by
|
||||
// the http-downloader, to request whole pieces
|
||||
// at a time.
|
||||
bool m_request_large_blocks:1;
|
||||
|
||||
// set to true when this peer is only uploading
|
||||
bool m_upload_only:1;
|
||||
|
||||
#ifndef NDEBUG
|
||||
public:
|
||||
bool m_in_constructor;
|
||||
bool m_in_constructor:1;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
|
|
@ -142,6 +142,9 @@ namespace libtorrent
|
|||
iterator begin() { return m_number; }
|
||||
iterator end() { return m_number+number_size; }
|
||||
|
||||
std::string to_string() const
|
||||
{ return std::string((char const*)&m_number[0], number_size); }
|
||||
|
||||
private:
|
||||
|
||||
unsigned char m_number[number_size];
|
||||
|
|
|
@ -248,7 +248,6 @@ namespace libtorrent
|
|||
const_iterator end_peer() const { return m_peers.end(); }
|
||||
|
||||
bool connect_one_peer();
|
||||
bool disconnect_one_peer();
|
||||
|
||||
bool has_peer(policy::peer const* p) const;
|
||||
|
||||
|
@ -267,7 +266,6 @@ namespace libtorrent
|
|||
bool compare_peer(policy::peer const& lhs, policy::peer const& rhs
|
||||
, address const& external_ip) const;
|
||||
|
||||
iterator find_disconnect_candidate();
|
||||
iterator find_connect_candidate();
|
||||
|
||||
bool is_connect_candidate(peer const& p, bool finished);
|
||||
|
|
|
@ -38,9 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/read.hpp>
|
||||
#include <asio/write.hpp>
|
||||
|
||||
#else
|
||||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#endif
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
|
@ -52,7 +56,7 @@ public:
|
|||
typedef stream_socket::endpoint_type endpoint_type;
|
||||
typedef stream_socket::protocol_type protocol_type;
|
||||
|
||||
explicit proxy_base(asio::io_service& io_service)
|
||||
explicit proxy_base(io_service& io_service)
|
||||
: m_sock(io_service)
|
||||
, m_resolver(io_service)
|
||||
{}
|
||||
|
@ -70,7 +74,7 @@ public:
|
|||
}
|
||||
|
||||
template <class Mutable_Buffers>
|
||||
std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
|
||||
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
|
||||
{
|
||||
return m_sock.read_some(buffers, ec);
|
||||
}
|
||||
|
@ -90,7 +94,7 @@ public:
|
|||
#endif
|
||||
|
||||
template <class IO_Control_Command>
|
||||
void io_control(IO_Control_Command& ioc, asio::error_code& ec)
|
||||
void io_control(IO_Control_Command& ioc, error_code& ec)
|
||||
{
|
||||
m_sock.io_control(ioc, ec);
|
||||
}
|
||||
|
@ -110,7 +114,7 @@ public:
|
|||
#endif
|
||||
|
||||
template <class SettableSocketOption>
|
||||
asio::error_code set_option(SettableSocketOption const& opt, asio::error_code& ec)
|
||||
error_code set_option(SettableSocketOption const& opt, error_code& ec)
|
||||
{
|
||||
return m_sock.set_option(opt, ec);
|
||||
}
|
||||
|
@ -122,7 +126,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
void bind(endpoint_type const& endpoint, asio::error_code& ec)
|
||||
void bind(endpoint_type const& endpoint, error_code& ec)
|
||||
{
|
||||
m_sock.bind(endpoint, ec);
|
||||
}
|
||||
|
@ -134,7 +138,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
void open(protocol_type const& p, asio::error_code& ec)
|
||||
void open(protocol_type const& p, error_code& ec)
|
||||
{
|
||||
m_sock.open(p, ec);
|
||||
}
|
||||
|
@ -148,7 +152,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
void close(asio::error_code& ec)
|
||||
void close(error_code& ec)
|
||||
{
|
||||
m_sock.close(ec);
|
||||
m_resolver.cancel();
|
||||
|
@ -161,7 +165,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
endpoint_type remote_endpoint(asio::error_code& ec) const
|
||||
endpoint_type remote_endpoint(error_code& ec) const
|
||||
{
|
||||
return m_remote_endpoint;
|
||||
}
|
||||
|
@ -173,14 +177,14 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
endpoint_type local_endpoint(asio::error_code& ec) const
|
||||
endpoint_type local_endpoint(error_code& ec) const
|
||||
{
|
||||
return m_sock.local_endpoint(ec);
|
||||
}
|
||||
|
||||
asio::io_service& io_service()
|
||||
io_service& get_io_service()
|
||||
{
|
||||
return m_sock.io_service();
|
||||
return m_sock.get_io_service();
|
||||
}
|
||||
|
||||
lowest_layer_type& lowest_layer()
|
||||
|
|
|
@ -129,7 +129,7 @@ namespace libtorrent
|
|||
, resume_data(0)
|
||||
, storage_mode(storage_mode_sparse)
|
||||
, paused(true)
|
||||
, auto_managed(false)
|
||||
, auto_managed(true)
|
||||
, duplicate_is_error(false)
|
||||
, storage(sc)
|
||||
, userdata(0)
|
||||
|
|
|
@ -102,11 +102,7 @@ namespace libtorrent
|
|||
, min_reconnect_time(60)
|
||||
, peer_connect_timeout(7)
|
||||
, ignore_limits_on_local_network(true)
|
||||
#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
|
||||
, connection_speed(2)
|
||||
#else
|
||||
, connection_speed(20)
|
||||
#endif
|
||||
, send_redundant_have(false)
|
||||
, lazy_bitfields(true)
|
||||
, inactivity_timeout(600)
|
||||
|
@ -134,6 +130,11 @@ namespace libtorrent
|
|||
, share_ratio_limit(2.f)
|
||||
, seed_time_ratio_limit(7.f)
|
||||
, seed_time_limit(24 * 60 * 60) // 24 hours
|
||||
, peer_turnover(1 / 50.f)
|
||||
, peer_turnover_cutoff(1.f)
|
||||
, close_redundant_connections(true)
|
||||
, auto_scrape_interval(1800)
|
||||
, auto_scrape_min_interval(300)
|
||||
{}
|
||||
|
||||
// this is the user agent that will be sent to the tracker
|
||||
|
@ -376,6 +377,31 @@ namespace libtorrent
|
|||
float share_ratio_limit;
|
||||
float seed_time_ratio_limit;
|
||||
int seed_time_limit;
|
||||
|
||||
// the percentage of peers to disconnect every
|
||||
// 90 seconds (if we're at the peer limit)
|
||||
// defaults to 1/50:th
|
||||
float peer_turnover;
|
||||
|
||||
// when we are connected to more than
|
||||
// limit * peer_turnover_enable peers
|
||||
// disconnect peer_turnover fraction
|
||||
// of the peers
|
||||
float peer_turnover_cutoff;
|
||||
|
||||
// if this is true (default) connections where both
|
||||
// ends have no utility in keeping the connection open
|
||||
// are closed. for instance if both ends have completed
|
||||
// their downloads
|
||||
bool close_redundant_connections;
|
||||
|
||||
// the number of seconds between scrapes of
|
||||
// queued torrents (auto managed and paused)
|
||||
int auto_scrape_interval;
|
||||
|
||||
// the minimum number of seconds between any
|
||||
// automatic scrape (regardless of torrent)
|
||||
int auto_scrape_min_interval;
|
||||
};
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
|
|
|
@ -45,13 +45,25 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define Protocol Protocol_
|
||||
#endif
|
||||
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/ip/tcp.hpp>
|
||||
#include <asio/ip/udp.hpp>
|
||||
#include <asio/io_service.hpp>
|
||||
#include <asio/deadline_timer.hpp>
|
||||
#include <asio/write.hpp>
|
||||
#include <asio/read.hpp>
|
||||
#include <asio/time_traits.hpp>
|
||||
#include <asio/basic_deadline_timer.hpp>
|
||||
#else
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ip/udp.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/time_traits.hpp>
|
||||
#include <boost/asio/basic_deadline_timer.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
#undef Protocol
|
||||
|
@ -67,24 +79,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace libtorrent
|
||||
{
|
||||
|
||||
/*
|
||||
namespace asio = boost::asio;
|
||||
|
||||
using boost::asio::ipv4::tcp;
|
||||
using boost::asio::ipv4::address;
|
||||
using boost::asio::stream_socket;
|
||||
using boost::asio::datagram_socket;
|
||||
using boost::asio::socket_acceptor;
|
||||
using boost::asio::io_service;
|
||||
using boost::asio::ipv4::host_resolver;
|
||||
using boost::asio::async_write;
|
||||
using boost::asio::ipv4::host;
|
||||
using boost::asio::deadline_timer;
|
||||
*/
|
||||
// namespace asio = ::asio;
|
||||
|
||||
#if BOOST_VERSION < 103500
|
||||
using asio::ip::tcp;
|
||||
using asio::ip::udp;
|
||||
using asio::async_write;
|
||||
using asio::async_read;
|
||||
|
||||
typedef asio::ip::tcp::socket stream_socket;
|
||||
typedef asio::ip::address address;
|
||||
typedef asio::ip::address_v4 address_v4;
|
||||
|
@ -92,14 +92,32 @@ namespace libtorrent
|
|||
typedef asio::ip::udp::socket datagram_socket;
|
||||
typedef asio::ip::tcp::acceptor socket_acceptor;
|
||||
typedef asio::io_service io_service;
|
||||
typedef asio::error_code error_code;
|
||||
|
||||
using asio::async_write;
|
||||
|
||||
namespace asio = ::asio;
|
||||
typedef asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
|
||||
#else
|
||||
using boost::system::error_code;
|
||||
using boost::asio::ip::tcp;
|
||||
using boost::asio::ip::udp;
|
||||
using boost::asio::async_write;
|
||||
using boost::asio::async_read;
|
||||
|
||||
typedef boost::asio::ip::tcp::socket stream_socket;
|
||||
typedef boost::asio::ip::address address;
|
||||
typedef boost::asio::ip::address_v4 address_v4;
|
||||
typedef boost::asio::ip::address_v6 address_v6;
|
||||
typedef boost::asio::ip::udp::socket datagram_socket;
|
||||
typedef boost::asio::ip::tcp::acceptor socket_acceptor;
|
||||
typedef boost::asio::io_service io_service;
|
||||
|
||||
namespace asio = boost::asio;
|
||||
typedef boost::asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
|
||||
#endif
|
||||
|
||||
inline std::ostream& print_address(std::ostream& os, address const& addr)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
std::string a = addr.to_string(ec);
|
||||
if (ec) return os;
|
||||
os << a;
|
||||
|
@ -109,7 +127,7 @@ namespace libtorrent
|
|||
inline std::ostream& print_endpoint(std::ostream& os, tcp::endpoint const& ep)
|
||||
{
|
||||
address const& addr = ep.address();
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
std::string a = addr.to_string(ec);
|
||||
if (ec) return os;
|
||||
|
||||
|
@ -132,7 +150,7 @@ namespace libtorrent
|
|||
}
|
||||
else if (a.is_v6())
|
||||
{
|
||||
asio::ip::address_v6::bytes_type bytes
|
||||
address_v6::bytes_type bytes
|
||||
= a.to_v6().to_bytes();
|
||||
std::copy(bytes.begin(), bytes.end(), out);
|
||||
}
|
||||
|
@ -142,18 +160,18 @@ namespace libtorrent
|
|||
address read_v4_address(InIt& in)
|
||||
{
|
||||
unsigned long ip = read_uint32(in);
|
||||
return asio::ip::address_v4(ip);
|
||||
return address_v4(ip);
|
||||
}
|
||||
|
||||
template<class InIt>
|
||||
address read_v6_address(InIt& in)
|
||||
{
|
||||
typedef asio::ip::address_v6::bytes_type bytes_t;
|
||||
typedef address_v6::bytes_type bytes_t;
|
||||
bytes_t bytes;
|
||||
for (bytes_t::iterator i = bytes.begin()
|
||||
, end(bytes.end()); i != end; ++i)
|
||||
*i = read_uint8(in);
|
||||
return asio::ip::address_v6(bytes);
|
||||
return address_v6(bytes);
|
||||
}
|
||||
|
||||
template<class Endpoint, class OutIt>
|
||||
|
|
|
@ -41,8 +41,8 @@ class socks4_stream : public proxy_base
|
|||
{
|
||||
public:
|
||||
|
||||
explicit socks4_stream(asio::io_service& io_service)
|
||||
: proxy_base(io_service)
|
||||
explicit socks4_stream(io_service& io_service_)
|
||||
: proxy_base(io_service_)
|
||||
{}
|
||||
|
||||
void set_username(std::string const& user)
|
||||
|
@ -50,7 +50,7 @@ public:
|
|||
m_user = user;
|
||||
}
|
||||
|
||||
typedef boost::function<void(asio::error_code const&)> handler_type;
|
||||
typedef boost::function<void(error_code const&)> handler_type;
|
||||
|
||||
template <class Handler>
|
||||
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
||||
|
@ -74,11 +74,11 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
||||
void name_lookup(error_code const& e, tcp::resolver::iterator i
|
||||
, boost::shared_ptr<handler_type> h);
|
||||
void connected(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
|
||||
// send and receive buffer
|
||||
std::vector<char> m_buffer;
|
||||
|
|
|
@ -41,7 +41,7 @@ class socks5_stream : public proxy_base
|
|||
{
|
||||
public:
|
||||
|
||||
explicit socks5_stream(asio::io_service& io_service)
|
||||
explicit socks5_stream(io_service& io_service)
|
||||
: proxy_base(io_service)
|
||||
{}
|
||||
|
||||
|
@ -52,7 +52,7 @@ public:
|
|||
m_password = password;
|
||||
}
|
||||
|
||||
typedef boost::function<void(asio::error_code const&)> handler_type;
|
||||
typedef boost::function<void(error_code const&)> handler_type;
|
||||
|
||||
template <class Handler>
|
||||
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
||||
|
@ -79,17 +79,17 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
||||
void name_lookup(error_code const& e, tcp::resolver::iterator i
|
||||
, boost::shared_ptr<handler_type> h);
|
||||
void connected(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake3(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake4(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake3(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void handshake4(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void socks_connect(boost::shared_ptr<handler_type> h);
|
||||
void connect1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void connect2(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void connect3(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void connect1(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void connect2(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
void connect3(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||
|
||||
// send and receive buffer
|
||||
std::vector<char> m_buffer;
|
||||
|
|
|
@ -34,8 +34,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define TORRENT_SSL_STREAM_HPP_INCLUDED
|
||||
|
||||
#include "libtorrent/socket.hpp"
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/ssl.hpp>
|
||||
|
||||
#else
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#endif
|
||||
// openssl seems to believe it owns
|
||||
// this name in every single scope
|
||||
#undef set_key
|
||||
|
@ -47,7 +50,7 @@ class ssl_stream
|
|||
{
|
||||
public:
|
||||
|
||||
explicit ssl_stream(asio::io_service& io_service)
|
||||
explicit ssl_stream(io_service& io_service)
|
||||
: m_context(io_service, asio::ssl::context::sslv23_client)
|
||||
, m_sock(io_service, m_context)
|
||||
{
|
||||
|
@ -60,7 +63,7 @@ public:
|
|||
typedef typename Stream::protocol_type protocol_type;
|
||||
typedef typename asio::ssl::stream<Stream> sock_type;
|
||||
|
||||
typedef boost::function<void(asio::error_code const&)> handler_type;
|
||||
typedef boost::function<void(error_code const&)> handler_type;
|
||||
|
||||
template <class Handler>
|
||||
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
||||
|
@ -70,7 +73,7 @@ public:
|
|||
// 2. perform SSL client handshake
|
||||
|
||||
// to avoid unnecessary copying of the handler,
|
||||
// store it in a shaed_ptr
|
||||
// store it in a shared_ptr
|
||||
boost::shared_ptr<handler_type> h(new handler_type(handler));
|
||||
|
||||
m_sock.next_layer().async_connect(endpoint
|
||||
|
@ -84,7 +87,7 @@ public:
|
|||
}
|
||||
|
||||
template <class Mutable_Buffers>
|
||||
std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
|
||||
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
|
||||
{
|
||||
return m_sock.read_some(buffers, ec);
|
||||
}
|
||||
|
@ -104,7 +107,7 @@ public:
|
|||
#endif
|
||||
|
||||
template <class IO_Control_Command>
|
||||
void io_control(IO_Control_Command& ioc, asio::error_code& ec)
|
||||
void io_control(IO_Control_Command& ioc, error_code& ec)
|
||||
{
|
||||
m_sock.next_layer().io_control(ioc, ec);
|
||||
}
|
||||
|
@ -122,7 +125,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
void bind(endpoint_type const& endpoint, asio::error_code& ec)
|
||||
void bind(endpoint_type const& endpoint, error_code& ec)
|
||||
{
|
||||
m_sock.next_layer().bind(endpoint, ec);
|
||||
}
|
||||
|
@ -134,7 +137,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
void open(protocol_type const& p, asio::error_code& ec)
|
||||
void open(protocol_type const& p, error_code& ec)
|
||||
{
|
||||
m_sock.next_layer().open(p, ec);
|
||||
}
|
||||
|
@ -151,7 +154,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
void close(asio::error_code& ec)
|
||||
void close(error_code& ec)
|
||||
{
|
||||
m_sock.next_layer().close(ec);
|
||||
}
|
||||
|
@ -163,7 +166,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
endpoint_type remote_endpoint(asio::error_code& ec) const
|
||||
endpoint_type remote_endpoint(error_code& ec) const
|
||||
{
|
||||
return const_cast<sock_type&>(m_sock).next_layer().remote_endpoint(ec);
|
||||
}
|
||||
|
@ -175,14 +178,14 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
endpoint_type local_endpoint(asio::error_code& ec) const
|
||||
endpoint_type local_endpoint(error_code& ec) const
|
||||
{
|
||||
return const_cast<sock_type&>(m_sock).next_layer().local_endpoint(ec);
|
||||
}
|
||||
|
||||
asio::io_service& io_service()
|
||||
io_service& get_io_service()
|
||||
{
|
||||
return m_sock.io_service();
|
||||
return m_sock.get_io_service();
|
||||
}
|
||||
|
||||
lowest_layer_type& lowest_layer()
|
||||
|
@ -197,7 +200,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void connected(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
|
@ -209,7 +212,7 @@ private:
|
|||
, boost::bind(&ssl_stream::handshake, this, _1, h));
|
||||
}
|
||||
|
||||
void handshake(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void handshake(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
(*h)(e);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
#include <cstring>
|
||||
|
||||
#include "libtorrent/size_type.hpp"
|
||||
#include "libtorrent/invariant_check.hpp"
|
||||
|
@ -44,88 +45,162 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
class TORRENT_EXPORT stat
|
||||
class TORRENT_EXPORT stat_channel
|
||||
{
|
||||
friend class invariant_access;
|
||||
public:
|
||||
enum { history = 10 };
|
||||
|
||||
stat()
|
||||
: m_downloaded_payload(0)
|
||||
, m_uploaded_payload(0)
|
||||
, m_downloaded_protocol(0)
|
||||
, m_uploaded_protocol(0)
|
||||
, m_total_download_payload(0)
|
||||
, m_total_upload_payload(0)
|
||||
, m_total_download_protocol(0)
|
||||
, m_total_upload_protocol(0)
|
||||
, m_mean_download_rate(0)
|
||||
, m_mean_upload_rate(0)
|
||||
, m_mean_download_payload_rate(0)
|
||||
, m_mean_upload_payload_rate(0)
|
||||
stat_channel()
|
||||
: m_counter(0)
|
||||
, m_total_counter(0)
|
||||
, m_rate_sum(0)
|
||||
{
|
||||
std::fill(m_download_rate_history, m_download_rate_history+history, 0.f);
|
||||
std::fill(m_upload_rate_history, m_upload_rate_history+history, 0.f);
|
||||
std::fill(m_download_payload_rate_history, m_download_payload_rate_history+history, 0.f);
|
||||
std::fill(m_upload_payload_rate_history, m_upload_payload_rate_history+history, 0.f);
|
||||
std::memset(m_rate_history, 0, sizeof(m_rate_history));
|
||||
}
|
||||
|
||||
void operator+=(const stat& s)
|
||||
void operator+=(stat_channel const& s)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_downloaded_payload += s.m_downloaded_payload;
|
||||
m_total_download_payload += s.m_downloaded_payload;
|
||||
m_downloaded_protocol += s.m_downloaded_protocol;
|
||||
m_total_download_protocol += s.m_downloaded_protocol;
|
||||
|
||||
m_uploaded_payload += s.m_uploaded_payload;
|
||||
m_total_upload_payload += s.m_uploaded_payload;
|
||||
m_uploaded_protocol += s.m_uploaded_protocol;
|
||||
m_total_upload_protocol += s.m_uploaded_protocol;
|
||||
m_counter += s.m_counter;
|
||||
m_total_counter += s.m_counter;
|
||||
}
|
||||
|
||||
void received_bytes(int bytes_payload, int bytes_protocol)
|
||||
void add(int count)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_ASSERT(count >= 0);
|
||||
|
||||
TORRENT_ASSERT(bytes_payload >= 0);
|
||||
TORRENT_ASSERT(bytes_protocol >= 0);
|
||||
|
||||
m_downloaded_payload += bytes_payload;
|
||||
m_total_download_payload += bytes_payload;
|
||||
m_downloaded_protocol += bytes_protocol;
|
||||
m_total_download_protocol += bytes_protocol;
|
||||
}
|
||||
|
||||
void sent_bytes(int bytes_payload, int bytes_protocol)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
TORRENT_ASSERT(bytes_payload >= 0);
|
||||
TORRENT_ASSERT(bytes_protocol >= 0);
|
||||
|
||||
m_uploaded_payload += bytes_payload;
|
||||
m_total_upload_payload += bytes_payload;
|
||||
m_uploaded_protocol += bytes_protocol;
|
||||
m_total_upload_protocol += bytes_protocol;
|
||||
m_counter += count;
|
||||
m_total_counter += count;
|
||||
}
|
||||
|
||||
// should be called once every second
|
||||
void second_tick(float tick_interval);
|
||||
float rate() const { return m_rate_sum / float(history); }
|
||||
size_type rate_sum() const { return m_rate_sum; }
|
||||
size_type total() const { return m_total_counter; }
|
||||
|
||||
float upload_rate() const { return m_mean_upload_rate; }
|
||||
float download_rate() const { return m_mean_download_rate; }
|
||||
void offset(size_type counter)
|
||||
{
|
||||
TORRENT_ASSERT(counter >= 0);
|
||||
m_total_counter += counter;
|
||||
}
|
||||
|
||||
float upload_payload_rate() const { return m_mean_upload_payload_rate; }
|
||||
float download_payload_rate() const { return m_mean_download_payload_rate; }
|
||||
size_type counter() const { return m_counter; }
|
||||
|
||||
size_type total_payload_upload() const { return m_total_upload_payload; }
|
||||
size_type total_payload_download() const { return m_total_download_payload; }
|
||||
private:
|
||||
|
||||
size_type total_protocol_upload() const { return m_total_upload_protocol; }
|
||||
size_type total_protocol_download() const { return m_total_download_protocol; }
|
||||
#ifndef NDEBUG
|
||||
void check_invariant() const
|
||||
{
|
||||
int sum = 0;
|
||||
for (int i = 0; i < history; ++i) sum += m_rate_history[i];
|
||||
TORRENT_ASSERT(m_rate_sum == sum);
|
||||
TORRENT_ASSERT(m_total_counter >= 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// history of rates a few seconds back
|
||||
int m_rate_history[history];
|
||||
|
||||
// the accumulator for this second.
|
||||
int m_counter;
|
||||
|
||||
// total counters
|
||||
size_type m_total_counter;
|
||||
|
||||
// sum of all elements in m_rate_history
|
||||
size_type m_rate_sum;
|
||||
};
|
||||
|
||||
class TORRENT_EXPORT stat
|
||||
{
|
||||
friend class invariant_access;
|
||||
public:
|
||||
void operator+=(const stat& s)
|
||||
{
|
||||
for (int i = 0; i < num_channels; ++i)
|
||||
m_stat[i] += s.m_stat[i];
|
||||
}
|
||||
|
||||
void received_bytes(int bytes_payload, int bytes_protocol)
|
||||
{
|
||||
TORRENT_ASSERT(bytes_payload >= 0);
|
||||
TORRENT_ASSERT(bytes_protocol >= 0);
|
||||
|
||||
m_stat[download_payload].add(bytes_payload);
|
||||
m_stat[download_protocol].add(bytes_protocol);
|
||||
}
|
||||
|
||||
void sent_bytes(int bytes_payload, int bytes_protocol)
|
||||
{
|
||||
TORRENT_ASSERT(bytes_payload >= 0);
|
||||
TORRENT_ASSERT(bytes_protocol >= 0);
|
||||
|
||||
m_stat[upload_payload].add(bytes_payload);
|
||||
m_stat[upload_protocol].add(bytes_protocol);
|
||||
}
|
||||
|
||||
// calculate ip protocol overhead
|
||||
void calc_ip_overhead()
|
||||
{
|
||||
int uploaded = m_stat[upload_protocol].counter()
|
||||
+ m_stat[upload_payload].counter();
|
||||
int downloaded = m_stat[download_protocol].counter()
|
||||
+ m_stat[download_payload].counter();
|
||||
|
||||
// IP + TCP headers are 40 bytes per MTU (1460)
|
||||
// bytes of payload, but at least 40 bytes
|
||||
m_stat[upload_ip_protocol].add((std::max)(uploaded / 1460, uploaded>0?40:0));
|
||||
m_stat[download_ip_protocol].add((std::max)(downloaded / 1460, downloaded>0?40:0));
|
||||
|
||||
// also account for ACK traffic. That adds to the transfers
|
||||
// in the opposite direction. Even on connections with symmetric
|
||||
// transfer rates, it seems to add a penalty.
|
||||
m_stat[upload_ip_protocol].add((std::max)(downloaded * 40 / 1460, downloaded>0?40:0));
|
||||
m_stat[download_ip_protocol].add((std::max)(uploaded * 40 / 1460, uploaded>0?40:0));
|
||||
}
|
||||
|
||||
int upload_ip_overhead() const { return m_stat[upload_ip_protocol].counter(); }
|
||||
int download_ip_overhead() const { return m_stat[download_ip_protocol].counter(); }
|
||||
|
||||
// should be called once every second
|
||||
void second_tick(float tick_interval)
|
||||
{
|
||||
for (int i = 0; i < num_channels; ++i)
|
||||
m_stat[i].second_tick(tick_interval);
|
||||
}
|
||||
|
||||
float upload_rate() const
|
||||
{
|
||||
return (m_stat[upload_payload].rate_sum()
|
||||
+ m_stat[upload_protocol].rate_sum()
|
||||
+ m_stat[upload_ip_protocol].rate_sum())
|
||||
/ float(stat_channel::history);
|
||||
}
|
||||
|
||||
float download_rate() const
|
||||
{
|
||||
return (m_stat[download_payload].rate_sum()
|
||||
+ m_stat[download_protocol].rate_sum()
|
||||
+ m_stat[download_ip_protocol].rate_sum())
|
||||
/ float(stat_channel::history);
|
||||
}
|
||||
|
||||
float upload_payload_rate() const
|
||||
{ return m_stat[upload_payload].rate(); }
|
||||
|
||||
float download_payload_rate() const
|
||||
{ return m_stat[download_payload].rate(); }
|
||||
|
||||
size_type total_payload_upload() const
|
||||
{ return m_stat[upload_payload].total(); }
|
||||
size_type total_payload_download() const
|
||||
{ return m_stat[download_payload].total(); }
|
||||
|
||||
size_type total_protocol_upload() const
|
||||
{ return m_stat[upload_protocol].total(); }
|
||||
size_type total_protocol_download() const
|
||||
{ return m_stat[download_protocol].total(); }
|
||||
|
||||
// this is used to offset the statistics when a
|
||||
// peer_connection is opened and have some previous
|
||||
|
@ -134,66 +209,33 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_ASSERT(downloaded >= 0);
|
||||
TORRENT_ASSERT(uploaded >= 0);
|
||||
m_total_download_payload += downloaded;
|
||||
m_total_upload_payload += uploaded;
|
||||
m_stat[download_payload].offset(downloaded);
|
||||
m_stat[upload_payload].offset(uploaded);
|
||||
}
|
||||
|
||||
size_type last_payload_downloaded() const { return m_downloaded_payload; }
|
||||
size_type last_payload_uploaded() const { return m_uploaded_payload; }
|
||||
size_type last_payload_downloaded() const
|
||||
{ return m_stat[download_payload].counter(); }
|
||||
size_type last_payload_uploaded() const
|
||||
{ return m_stat[upload_payload].counter(); }
|
||||
|
||||
private:
|
||||
|
||||
#ifndef NDEBUG
|
||||
void check_invariant() const
|
||||
// these are the channels we keep stats for
|
||||
enum
|
||||
{
|
||||
TORRENT_ASSERT(m_mean_upload_rate >= 0);
|
||||
TORRENT_ASSERT(m_mean_download_rate >= 0);
|
||||
TORRENT_ASSERT(m_mean_upload_payload_rate >= 0);
|
||||
TORRENT_ASSERT(m_mean_download_payload_rate >= 0);
|
||||
TORRENT_ASSERT(m_total_upload_payload >= 0);
|
||||
TORRENT_ASSERT(m_total_download_payload >= 0);
|
||||
TORRENT_ASSERT(m_total_upload_protocol >= 0);
|
||||
TORRENT_ASSERT(m_total_download_protocol >= 0);
|
||||
}
|
||||
#endif
|
||||
upload_payload,
|
||||
upload_protocol,
|
||||
upload_ip_protocol,
|
||||
download_payload,
|
||||
download_protocol,
|
||||
download_ip_protocol,
|
||||
num_channels
|
||||
};
|
||||
|
||||
// history of download/upload speeds a few seconds back
|
||||
float m_download_rate_history[history];
|
||||
float m_upload_rate_history[history];
|
||||
|
||||
float m_download_payload_rate_history[history];
|
||||
float m_upload_payload_rate_history[history];
|
||||
|
||||
// the accumulators we are adding the downloads/uploads
|
||||
// to this second. This only counts the actual payload
|
||||
// and ignores the bytes sent as protocol chatter.
|
||||
int m_downloaded_payload;
|
||||
int m_uploaded_payload;
|
||||
|
||||
// the accumulators we are adding the downloads/uploads
|
||||
// to this second. This only counts the protocol
|
||||
// chatter and ignores the actual payload
|
||||
int m_downloaded_protocol;
|
||||
int m_uploaded_protocol;
|
||||
|
||||
// total download/upload counters
|
||||
// only counting payload data
|
||||
size_type m_total_download_payload;
|
||||
size_type m_total_upload_payload;
|
||||
|
||||
// total download/upload counters
|
||||
// only counting protocol chatter
|
||||
size_type m_total_download_protocol;
|
||||
size_type m_total_upload_protocol;
|
||||
|
||||
// current mean download/upload rates
|
||||
float m_mean_download_rate;
|
||||
float m_mean_upload_rate;
|
||||
|
||||
float m_mean_download_payload_rate;
|
||||
float m_mean_upload_payload_rate;
|
||||
stat_channel m_stat[num_channels];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // TORRENT_STAT_HPP_INCLUDED
|
||||
|
||||
|
|
|
@ -86,7 +86,11 @@ namespace libtorrent
|
|||
|
||||
#else
|
||||
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/time_traits.hpp>
|
||||
#else
|
||||
#include <boost/asio/time_traits.hpp>
|
||||
#endif
|
||||
#include <boost/cstdint.hpp>
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
|
@ -152,6 +156,9 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
// asio time_traits
|
||||
#if BOOST_VERSION >= 103500
|
||||
namespace boost {
|
||||
#endif
|
||||
namespace asio
|
||||
{
|
||||
template<>
|
||||
|
@ -172,6 +179,9 @@ namespace asio
|
|||
{ return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
|
||||
};
|
||||
}
|
||||
#if BOOST_VERSION >= 103500
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__MACH__)
|
||||
|
||||
|
|
|
@ -151,8 +151,7 @@ namespace libtorrent
|
|||
void files_checked();
|
||||
void start_checking();
|
||||
|
||||
float seed_cycles(session_settings const& s) const;
|
||||
int seed_cycles_int(session_settings const& s) const { return int(seed_cycles(s)); }
|
||||
int seed_rank(session_settings const& s) const;
|
||||
|
||||
storage_mode_t storage_mode() const { return m_storage_mode; }
|
||||
// this will flag the torrent as aborted. The main
|
||||
|
@ -356,6 +355,7 @@ namespace libtorrent
|
|||
void force_tracker_request();
|
||||
void force_tracker_request(ptime);
|
||||
void scrape_tracker();
|
||||
ptime const& last_scrape() const { return m_last_scrape; }
|
||||
|
||||
// sets the username and password that will be sent to
|
||||
// the tracker
|
||||
|
@ -453,6 +453,7 @@ namespace libtorrent
|
|||
void announce_piece(int index);
|
||||
|
||||
void disconnect_all();
|
||||
int disconnect_peers(int num);
|
||||
|
||||
// this is called wheh the torrent has completed
|
||||
// the download. It will post an event, disconnect
|
||||
|
@ -461,17 +462,17 @@ namespace libtorrent
|
|||
|
||||
// this is the asio callback that is called when a name
|
||||
// lookup for a PEER is completed.
|
||||
void on_peer_name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
||||
void on_peer_name_lookup(error_code const& e, tcp::resolver::iterator i
|
||||
, peer_id pid);
|
||||
|
||||
// this is the asio callback that is called when a name
|
||||
// lookup for a WEB SEED is completed.
|
||||
void on_name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
||||
void on_name_lookup(error_code const& e, tcp::resolver::iterator i
|
||||
, std::string url, tcp::endpoint proxy);
|
||||
|
||||
// this is the asio callback that is called when a name
|
||||
// lookup for a proxy for a web seed is completed.
|
||||
void on_proxy_name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
||||
void on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator i
|
||||
, std::string url);
|
||||
|
||||
// this is called when the torrent has finished. i.e.
|
||||
|
@ -480,6 +481,11 @@ namespace libtorrent
|
|||
// completed() is called immediately after it.
|
||||
void finished();
|
||||
|
||||
// This is the opposite of finished. It is called if we used
|
||||
// to be finished but enabled some files for download so that
|
||||
// we wasn't finished anymore.
|
||||
void resume_download();
|
||||
|
||||
void async_verify_piece(int piece_index, boost::function<void(int)> const&);
|
||||
|
||||
// this is called from the peer_connection
|
||||
|
@ -570,7 +576,7 @@ namespace libtorrent
|
|||
// to the checker thread for initial checking
|
||||
// of the storage.
|
||||
// a return value of false indicates an error
|
||||
bool set_metadata(entry const& metadata, std::string& error);
|
||||
bool set_metadata(lazy_entry const& metadata, std::string& error);
|
||||
|
||||
int sequence_number() const { return m_sequence_number; }
|
||||
|
||||
|
@ -587,40 +593,43 @@ namespace libtorrent
|
|||
|
||||
void try_next_tracker();
|
||||
int prioritize_tracker(int tracker_index);
|
||||
void on_country_lookup(asio::error_code const& error, tcp::resolver::iterator i
|
||||
void on_country_lookup(error_code const& error, tcp::resolver::iterator i
|
||||
, boost::intrusive_ptr<peer_connection> p) const;
|
||||
bool request_bandwidth_from_session(int channel) const;
|
||||
|
||||
void update_peer_interest(bool was_finished);
|
||||
|
||||
policy m_policy;
|
||||
|
||||
// total time we've been available on this torrent
|
||||
// does not count when the torrent is stopped or paused
|
||||
time_duration m_active_time;
|
||||
|
||||
// total time we've been available as a seed on this torrent
|
||||
// does not count when the torrent is stopped or paused
|
||||
time_duration m_seeding_time;
|
||||
|
||||
// all time totals of uploaded and downloaded payload
|
||||
// stored in resume data
|
||||
size_type m_total_uploaded;
|
||||
size_type m_total_downloaded;
|
||||
|
||||
// if this torrent is running, this was the time
|
||||
// when it was started. This is used to have a
|
||||
// bias towards keeping seeding torrents that
|
||||
// recently was started, to avoid oscillation
|
||||
ptime m_started;
|
||||
|
||||
// the last time we initiated a scrape request to
|
||||
// one of the trackers in this torrent
|
||||
ptime m_last_scrape;
|
||||
|
||||
boost::intrusive_ptr<torrent_info> m_torrent_file;
|
||||
|
||||
// is set to true when the torrent has
|
||||
// been aborted.
|
||||
bool m_abort;
|
||||
|
||||
// is true if this torrent has been paused
|
||||
bool m_paused;
|
||||
// this is true from the time when the torrent was
|
||||
// paused to the time should_request() is called
|
||||
bool m_just_paused;
|
||||
|
||||
// if this is true, libtorrent may pause and resume
|
||||
// this torrent depending on queuing rules. Torrents
|
||||
// started with auto_managed flag set may be added in
|
||||
// a paused state in case there are no available
|
||||
// slots.
|
||||
bool m_auto_managed;
|
||||
|
||||
tracker_request::event_t m_event;
|
||||
|
||||
void parse_response(const entry& e, std::vector<peer_entry>& peer_list);
|
||||
|
||||
// the size of a request block
|
||||
// each piece is divided into these
|
||||
// blocks when requested
|
||||
int m_block_size;
|
||||
|
||||
// if this pointer is 0, the torrent is in
|
||||
// a state where the metadata hasn't been
|
||||
// received yet.
|
||||
|
@ -649,18 +658,6 @@ namespace libtorrent
|
|||
// the time of next tracker request
|
||||
ptime m_next_request;
|
||||
|
||||
// -----------------------------
|
||||
// DATA FROM TRACKER RESPONSE
|
||||
|
||||
// the number number of seconds between requests
|
||||
// from the tracker
|
||||
int m_duration;
|
||||
|
||||
// the scrape data from the tracker response, this
|
||||
// is optional and may be -1.
|
||||
int m_complete;
|
||||
int m_incomplete;
|
||||
|
||||
#ifndef NDEBUG
|
||||
public:
|
||||
#endif
|
||||
|
@ -681,28 +678,21 @@ namespace libtorrent
|
|||
// resolving the address for
|
||||
std::set<std::string> m_resolving_web_seeds;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;
|
||||
extension_list_t m_extensions;
|
||||
#endif
|
||||
|
||||
// used to resolve the names of web seeds
|
||||
mutable tcp::resolver m_host_resolver;
|
||||
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
// this is true while there is a country
|
||||
// resolution in progress. To avoid flodding
|
||||
// the DNS request queue, only one ip is resolved
|
||||
// at a time.
|
||||
mutable bool m_resolving_country;
|
||||
|
||||
// this is true if the user has enabled
|
||||
// country resolution in this torrent
|
||||
bool m_resolve_countries;
|
||||
#endif
|
||||
|
||||
// this announce timer is used both
|
||||
// by Local service discovery and
|
||||
// by the DHT.
|
||||
deadline_timer m_announce_timer;
|
||||
|
||||
static void on_announce_disp(boost::weak_ptr<torrent> p
|
||||
, asio::error_code const& e);
|
||||
, error_code const& e);
|
||||
|
||||
// this is called once per announce interval
|
||||
void on_announce();
|
||||
|
@ -737,41 +727,9 @@ namespace libtorrent
|
|||
std::vector<announce_entry> m_trackers;
|
||||
// this is an index into m_trackers
|
||||
|
||||
int m_last_working_tracker;
|
||||
int m_currently_trying_tracker;
|
||||
// the number of connection attempts that has
|
||||
// failed in a row, this is currently used to
|
||||
// determine the timeout until next try.
|
||||
int m_failed_trackers;
|
||||
|
||||
// this is a counter that is decreased every
|
||||
// second, and when it reaches 0, the policy::pulse()
|
||||
// is called and the time scaler is reset to 10.
|
||||
int m_time_scaler;
|
||||
|
||||
// the bitmask that says which pieces we have
|
||||
std::vector<bool> m_have_pieces;
|
||||
|
||||
// the number of pieces we have. The same as
|
||||
// std::accumulate(m_have_pieces.begin(),
|
||||
// m_have_pieces.end(), 0)
|
||||
int m_num_pieces;
|
||||
|
||||
// in case the piece picker hasn't been constructed
|
||||
// when this settings is set, this variable will keep
|
||||
// its value until the piece picker is created
|
||||
bool m_sequential_download;
|
||||
|
||||
// is false by default and set to
|
||||
// true when the first tracker reponse
|
||||
// is received
|
||||
bool m_got_tracker_response;
|
||||
|
||||
// the upload/download ratio that each peer
|
||||
// tries to maintain.
|
||||
// 0 is infinite
|
||||
float m_ratio;
|
||||
|
||||
// the number of bytes that has been
|
||||
// downloaded that failed the hash-test
|
||||
size_type m_total_failed_bytes;
|
||||
|
@ -791,25 +749,9 @@ namespace libtorrent
|
|||
|
||||
// the state of this torrent (queued, checking, downloading)
|
||||
torrent_status::state_t m_state;
|
||||
float m_progress;
|
||||
|
||||
entry m_resume_data;
|
||||
|
||||
// defaults to 16 kiB, but can be set by the user
|
||||
// when creating the torrent
|
||||
const int m_default_block_size;
|
||||
|
||||
// this is set to false as long as the connections
|
||||
// of this torrent hasn't been initialized. If we
|
||||
// have metadata from the start, connections are
|
||||
// initialized immediately, if we didn't have metadata,
|
||||
// they are initialized right after files_checked().
|
||||
// valid_resume_data() will return false as long as
|
||||
// the connections aren't initialized, to avoid
|
||||
// them from altering the piece-picker before it
|
||||
// has been initialized with files_checked().
|
||||
bool m_connections_initialized;
|
||||
|
||||
// if the torrent is started without metadata, it may
|
||||
// still be given a name until the metadata is received
|
||||
// once the metadata is received this field will no
|
||||
|
@ -820,6 +762,18 @@ namespace libtorrent
|
|||
|
||||
storage_constructor_type m_storage_constructor;
|
||||
|
||||
float m_progress;
|
||||
|
||||
// the number of pieces we have. The same as
|
||||
// std::accumulate(m_have_pieces.begin(),
|
||||
// m_have_pieces.end(), 0)
|
||||
int m_num_pieces;
|
||||
|
||||
// the upload/download ratio that each peer
|
||||
// tries to maintain.
|
||||
// 0 is infinite
|
||||
float m_ratio;
|
||||
|
||||
// the maximum number of uploads for this torrent
|
||||
int m_max_uploads;
|
||||
|
||||
|
@ -829,14 +783,18 @@ namespace libtorrent
|
|||
// the maximum number of connections for this torrent
|
||||
int m_max_connections;
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool m_files_checked;
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;
|
||||
extension_list_t m_extensions;
|
||||
#endif
|
||||
// the size of a request block
|
||||
// each piece is divided into these
|
||||
// blocks when requested
|
||||
int m_block_size;
|
||||
|
||||
// -----------------------------
|
||||
// DATA FROM TRACKER RESPONSE
|
||||
|
||||
// the scrape data from the tracker response, this
|
||||
// is optional and may be -1.
|
||||
int m_complete;
|
||||
int m_incomplete;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// this is the amount downloaded when this torrent
|
||||
|
@ -858,24 +816,84 @@ namespace libtorrent
|
|||
// torrent object, these points are called connect_points.
|
||||
int m_deficit_counter;
|
||||
|
||||
policy m_policy;
|
||||
// the number number of seconds between requests
|
||||
// from the tracker
|
||||
boost::int16_t m_duration;
|
||||
|
||||
// the sequence number for this torrent, this is a
|
||||
// monotonically increasing number for each added torrent
|
||||
int m_sequence_number;
|
||||
boost::int16_t m_sequence_number;
|
||||
|
||||
// total time we've been available on this torrent
|
||||
// does not count when the torrent is stopped or paused
|
||||
time_duration m_active_time;
|
||||
// the index to the last tracker that worked
|
||||
boost::int8_t m_last_working_tracker;
|
||||
|
||||
// total time we've been available as a seed on this torrent
|
||||
// does not count when the torrent is stopped or paused
|
||||
time_duration m_seeding_time;
|
||||
// the tracker that is currently (or was last)
|
||||
// tried
|
||||
boost::int8_t m_currently_trying_tracker;
|
||||
|
||||
// all time totals of uploaded and downloaded payload
|
||||
// stored in resume data
|
||||
size_type m_total_uploaded;
|
||||
size_type m_total_downloaded;
|
||||
// the number of connection attempts that has
|
||||
// failed in a row, this is currently used to
|
||||
// determine the timeout until next try.
|
||||
boost::int8_t m_failed_trackers;
|
||||
|
||||
// this is a counter that is decreased every
|
||||
// second, and when it reaches 0, the policy::pulse()
|
||||
// is called and the time scaler is reset to 10.
|
||||
boost::int8_t m_time_scaler;
|
||||
|
||||
// is set to true when the torrent has
|
||||
// been aborted.
|
||||
bool m_abort:1;
|
||||
|
||||
// is true if this torrent has been paused
|
||||
bool m_paused:1;
|
||||
// this is true from the time when the torrent was
|
||||
// paused to the time should_request() is called
|
||||
bool m_just_paused:1;
|
||||
|
||||
// if this is true, libtorrent may pause and resume
|
||||
// this torrent depending on queuing rules. Torrents
|
||||
// started with auto_managed flag set may be added in
|
||||
// a paused state in case there are no available
|
||||
// slots.
|
||||
bool m_auto_managed:1;
|
||||
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
// this is true while there is a country
|
||||
// resolution in progress. To avoid flodding
|
||||
// the DNS request queue, only one ip is resolved
|
||||
// at a time.
|
||||
mutable bool m_resolving_country:1;
|
||||
|
||||
// this is true if the user has enabled
|
||||
// country resolution in this torrent
|
||||
bool m_resolve_countries:1;
|
||||
#endif
|
||||
|
||||
// in case the piece picker hasn't been constructed
|
||||
// when this settings is set, this variable will keep
|
||||
// its value until the piece picker is created
|
||||
bool m_sequential_download:1;
|
||||
|
||||
// is false by default and set to
|
||||
// true when the first tracker reponse
|
||||
// is received
|
||||
bool m_got_tracker_response:1;
|
||||
|
||||
// this is set to false as long as the connections
|
||||
// of this torrent hasn't been initialized. If we
|
||||
// have metadata from the start, connections are
|
||||
// initialized immediately, if we didn't have metadata,
|
||||
// they are initialized right after files_checked().
|
||||
// valid_resume_data() will return false as long as
|
||||
// the connections aren't initialized, to avoid
|
||||
// them from altering the piece-picker before it
|
||||
// has been initialized with files_checked().
|
||||
bool m_connections_initialized:1;
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool m_files_checked:1;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline ptime torrent::next_announce() const
|
||||
|
|
|
@ -118,7 +118,8 @@ namespace libtorrent
|
|||
, all_time_download(0)
|
||||
, active_time(0)
|
||||
, seeding_time(0)
|
||||
, seed_cycles(0.f)
|
||||
, seed_rank(0)
|
||||
, last_scrape(0)
|
||||
{}
|
||||
|
||||
enum state_t
|
||||
|
@ -257,7 +258,12 @@ namespace libtorrent
|
|||
int active_time;
|
||||
int seeding_time;
|
||||
|
||||
float seed_cycles;
|
||||
// higher value means more important to seed
|
||||
int seed_rank;
|
||||
|
||||
// number of seconds since last scrape, or -1 if
|
||||
// there hasn't been a scrape
|
||||
int last_scrape;
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT block_info
|
||||
|
|
|
@ -45,12 +45,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/optional.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/shared_array.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include "libtorrent/entry.hpp"
|
||||
#include "libtorrent/lazy_entry.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/size_type.hpp"
|
||||
|
@ -110,18 +112,12 @@ namespace libtorrent
|
|||
|
||||
torrent_info();
|
||||
torrent_info(sha1_hash const& info_hash);
|
||||
torrent_info(entry const& torrent_file);
|
||||
torrent_info(lazy_entry const& torrent_file);
|
||||
torrent_info(char const* buffer, int size);
|
||||
torrent_info(char const* filename);
|
||||
~torrent_info();
|
||||
|
||||
entry create_torrent() const;
|
||||
entry create_info_metadata() const;
|
||||
void set_comment(char const* str);
|
||||
void set_creator(char const* str);
|
||||
void set_piece_size(int size);
|
||||
void set_hash(int index, sha1_hash const& h);
|
||||
void add_tracker(std::string const& url, int tier = 0);
|
||||
void add_file(fs::path file, size_type size);
|
||||
void add_url_seed(std::string const& url);
|
||||
|
||||
bool remap_files(std::vector<file_entry> const& map);
|
||||
|
||||
|
@ -131,10 +127,9 @@ namespace libtorrent
|
|||
, bool storage = false) const;
|
||||
|
||||
std::vector<std::string> const& url_seeds() const
|
||||
{
|
||||
TORRENT_ASSERT(!m_half_metadata);
|
||||
return m_url_seeds;
|
||||
}
|
||||
{ return m_url_seeds; }
|
||||
void add_url_seed(std::string const& url)
|
||||
{ m_url_seeds.push_back(url); }
|
||||
|
||||
typedef std::vector<file_entry>::const_iterator file_iterator;
|
||||
typedef std::vector<file_entry>::const_reverse_iterator reverse_file_iterator;
|
||||
|
@ -176,12 +171,12 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_ASSERT(m_piece_length > 0);
|
||||
if (!storage || m_remapped_files.empty())
|
||||
return (int)m_files.size();
|
||||
return int(m_files.size());
|
||||
else
|
||||
return (int)m_remapped_files.size();
|
||||
return int(m_remapped_files.size());
|
||||
}
|
||||
|
||||
const file_entry& file_at(int index, bool storage = false) const
|
||||
file_entry const& file_at(int index, bool storage = false) const
|
||||
{
|
||||
if (!storage || m_remapped_files.empty())
|
||||
{
|
||||
|
@ -195,7 +190,7 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
const std::vector<announce_entry>& trackers() const { return m_urls; }
|
||||
std::vector<announce_entry> const& trackers() const { return m_urls; }
|
||||
|
||||
size_type total_size() const { TORRENT_ASSERT(m_piece_length > 0); return m_total_size; }
|
||||
int piece_length() const { TORRENT_ASSERT(m_piece_length > 0); return m_piece_length; }
|
||||
|
@ -204,25 +199,30 @@ namespace libtorrent
|
|||
const std::string& name() const { TORRENT_ASSERT(m_piece_length > 0); return m_name; }
|
||||
|
||||
// ------- start deprecation -------
|
||||
// this functionaily will be removed in a future version
|
||||
// these functions will be removed in a future version
|
||||
torrent_info(entry const& torrent_file) TORRENT_DEPRECATED;
|
||||
void print(std::ostream& os) const TORRENT_DEPRECATED;
|
||||
// ------- end deprecation -------
|
||||
|
||||
bool is_valid() const { return m_piece_length > 0; }
|
||||
|
||||
bool priv() const { return m_private; }
|
||||
void set_priv(bool v) { m_private = v; }
|
||||
|
||||
void convert_file_names();
|
||||
|
||||
int piece_size(int index) const;
|
||||
|
||||
const sha1_hash& hash_for_piece(int index) const
|
||||
sha1_hash hash_for_piece(int index) const
|
||||
{
|
||||
return sha1_hash(hash_for_piece_ptr(index));
|
||||
}
|
||||
|
||||
char const* hash_for_piece_ptr(int index) const
|
||||
{
|
||||
TORRENT_ASSERT(index >= 0);
|
||||
TORRENT_ASSERT(index < (int)m_piece_hash.size());
|
||||
TORRENT_ASSERT(!m_half_metadata);
|
||||
return m_piece_hash[index];
|
||||
TORRENT_ASSERT(index < m_num_pieces);
|
||||
TORRENT_ASSERT(m_piece_hashes);
|
||||
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
|
||||
TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
|
||||
return &m_piece_hashes[index*20];
|
||||
}
|
||||
|
||||
boost::optional<pt::ptime> creation_date() const;
|
||||
|
@ -237,27 +237,30 @@ namespace libtorrent
|
|||
typedef std::vector<std::pair<std::string, int> > nodes_t;
|
||||
|
||||
nodes_t const& nodes() const
|
||||
{
|
||||
TORRENT_ASSERT(!m_half_metadata);
|
||||
return m_nodes;
|
||||
}
|
||||
{ return m_nodes; }
|
||||
void add_node(std::pair<std::string, int> const& node)
|
||||
{ m_nodes.push_back(node); }
|
||||
|
||||
void add_node(std::pair<std::string, int> const& node);
|
||||
bool parse_info_section(lazy_entry const& e, std::string& error);
|
||||
|
||||
bool parse_info_section(entry const& e, std::string& error);
|
||||
|
||||
entry const* extra(char const* key) const
|
||||
{ return m_extra_info.find_key(key); }
|
||||
|
||||
// frees parts of the metadata that isn't
|
||||
// used by seeds
|
||||
void seed_free();
|
||||
lazy_entry const* info(char const* key) const
|
||||
{
|
||||
if (m_info_dict.type() == lazy_entry::none_t)
|
||||
lazy_bdecode(m_info_section.get(), m_info_section.get()
|
||||
+ m_info_section_size, m_info_dict);
|
||||
return m_info_dict.dict_find(key);
|
||||
}
|
||||
|
||||
void swap(torrent_info& ti);
|
||||
|
||||
boost::shared_array<char> metadata() const
|
||||
{ return m_info_section; }
|
||||
|
||||
int metadata_size() const { return m_info_section_size; }
|
||||
|
||||
private:
|
||||
|
||||
bool read_torrent_info(const entry& libtorrent, std::string& error);
|
||||
bool parse_torrent_file(lazy_entry const& libtorrent, std::string& error);
|
||||
|
||||
// the urls to the trackers
|
||||
std::vector<announce_entry> m_urls;
|
||||
|
@ -269,9 +272,6 @@ namespace libtorrent
|
|||
// in an uninitialized state
|
||||
int m_piece_length;
|
||||
|
||||
// the sha-1 hashes of each piece
|
||||
std::vector<sha1_hash> m_piece_hash;
|
||||
|
||||
// the list of files that this torrent consists of
|
||||
std::vector<file_entry> m_files;
|
||||
|
||||
|
@ -293,7 +293,7 @@ namespace libtorrent
|
|||
// the hash that identifies this torrent
|
||||
// is mutable because it's calculated
|
||||
// lazily
|
||||
mutable sha1_hash m_info_hash;
|
||||
sha1_hash m_info_hash;
|
||||
|
||||
std::string m_name;
|
||||
|
||||
|
@ -321,18 +321,19 @@ namespace libtorrent
|
|||
// be announced on the dht
|
||||
bool m_private;
|
||||
|
||||
// contains any non-parsed entries from the info-section
|
||||
// these are kept in order to be able to accurately
|
||||
// reproduce the info-section when sending the metadata
|
||||
// to peers.
|
||||
entry m_extra_info;
|
||||
// this is a copy of the info section from the torrent.
|
||||
// it use maintained in this flat format in order to
|
||||
// make it available through the metadata extension
|
||||
boost::shared_array<char> m_info_section;
|
||||
int m_info_section_size;
|
||||
|
||||
#ifndef NDEBUG
|
||||
public:
|
||||
// this is set to true when seed_free() is called
|
||||
bool m_half_metadata;
|
||||
private:
|
||||
#endif
|
||||
// this is a pointer into the m_info_section buffer
|
||||
// pointing to the first byte of the first sha-1 hash
|
||||
char const* m_piece_hashes;
|
||||
|
||||
// the info section parsed. points into m_info_section
|
||||
// parsed lazily
|
||||
mutable lazy_entry m_info_dict;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -74,9 +74,6 @@ namespace libtorrent
|
|||
// returns -1 if gzip header is invalid or the header size in bytes
|
||||
TORRENT_EXPORT int gzip_header(const char* buf, int size);
|
||||
|
||||
TORRENT_EXPORT boost::tuple<std::string, std::string, std::string, int, std::string>
|
||||
parse_url_components(std::string url);
|
||||
|
||||
struct TORRENT_EXPORT tracker_request
|
||||
{
|
||||
tracker_request()
|
||||
|
@ -160,7 +157,7 @@ namespace libtorrent
|
|||
|
||||
private:
|
||||
|
||||
void timeout_callback(asio::error_code const&);
|
||||
void timeout_callback(error_code const&);
|
||||
|
||||
boost::intrusive_ptr<timeout_handler> self()
|
||||
{ return boost::intrusive_ptr<timeout_handler>(this); }
|
||||
|
|
|
@ -46,16 +46,16 @@ namespace libtorrent
|
|||
class udp_socket
|
||||
{
|
||||
public:
|
||||
typedef boost::function<void(asio::error_code const& ec
|
||||
typedef boost::function<void(error_code const& ec
|
||||
, udp::endpoint const&, char const* buf, int size)> callback_t;
|
||||
|
||||
udp_socket(asio::io_service& ios, callback_t const& c, connection_queue& cc);
|
||||
udp_socket(io_service& ios, callback_t const& c, connection_queue& cc);
|
||||
|
||||
bool is_open() const { return m_ipv4_sock.is_open() || m_ipv6_sock.is_open(); }
|
||||
asio::io_service& get_io_service() { return m_ipv4_sock.get_io_service(); }
|
||||
io_service& get_io_service() { return m_ipv4_sock.get_io_service(); }
|
||||
|
||||
void send(udp::endpoint const& ep, char const* p, int len, asio::error_code& ec);
|
||||
void bind(udp::endpoint const& ep, asio::error_code& ec);
|
||||
void send(udp::endpoint const& ep, char const* p, int len, error_code& ec);
|
||||
void bind(udp::endpoint const& ep, error_code& ec);
|
||||
void bind(int port);
|
||||
void close();
|
||||
int local_port() const { return m_bind_port; }
|
||||
|
@ -67,21 +67,21 @@ namespace libtorrent
|
|||
|
||||
callback_t m_callback;
|
||||
|
||||
void on_read(udp::socket* sock, asio::error_code const& e, std::size_t bytes_transferred);
|
||||
void on_name_lookup(asio::error_code const& e, tcp::resolver::iterator i);
|
||||
void on_read(udp::socket* sock, error_code const& e, std::size_t bytes_transferred);
|
||||
void on_name_lookup(error_code const& e, tcp::resolver::iterator i);
|
||||
void on_timeout();
|
||||
void on_connect(int ticket);
|
||||
void on_connected(asio::error_code const& ec);
|
||||
void handshake1(asio::error_code const& e);
|
||||
void handshake2(asio::error_code const& e);
|
||||
void handshake3(asio::error_code const& e);
|
||||
void handshake4(asio::error_code const& e);
|
||||
void on_connected(error_code const& ec);
|
||||
void handshake1(error_code const& e);
|
||||
void handshake2(error_code const& e);
|
||||
void handshake3(error_code const& e);
|
||||
void handshake4(error_code const& e);
|
||||
void socks_forward_udp();
|
||||
void connect1(asio::error_code const& e);
|
||||
void connect2(asio::error_code const& e);
|
||||
void connect1(error_code const& e);
|
||||
void connect2(error_code const& e);
|
||||
|
||||
void wrap(udp::endpoint const& ep, char const* p, int len, asio::error_code& ec);
|
||||
void unwrap(asio::error_code const& e, char const* buf, int size);
|
||||
void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec);
|
||||
void unwrap(error_code const& e, char const* buf, int size);
|
||||
|
||||
udp::socket m_ipv4_sock;
|
||||
udp::socket m_ipv6_sock;
|
||||
|
|
|
@ -89,10 +89,10 @@ namespace libtorrent
|
|||
boost::intrusive_ptr<udp_tracker_connection> self()
|
||||
{ return boost::intrusive_ptr<udp_tracker_connection>(this); }
|
||||
|
||||
void name_lookup(asio::error_code const& error, udp::resolver::iterator i);
|
||||
void timeout(asio::error_code const& error);
|
||||
void name_lookup(error_code const& error, udp::resolver::iterator i);
|
||||
void timeout(error_code const& error);
|
||||
|
||||
void on_receive(asio::error_code const& e, udp::endpoint const& ep
|
||||
void on_receive(error_code const& e, udp::endpoint const& ep
|
||||
, char const* buf, int size);
|
||||
void on_connect_response(char const* buf, int size);
|
||||
void on_announce_response(char const* buf, int size);
|
||||
|
|
|
@ -93,7 +93,7 @@ private:
|
|||
|
||||
enum { default_lease_time = 3600 };
|
||||
|
||||
void resend_request(asio::error_code const& e);
|
||||
void resend_request(error_code const& e);
|
||||
void on_reply(udp::endpoint const& from, char* buffer
|
||||
, std::size_t bytes_transferred);
|
||||
|
||||
|
@ -102,15 +102,16 @@ private:
|
|||
void update_map(rootdevice& d, int i);
|
||||
|
||||
|
||||
void on_upnp_xml(asio::error_code const& e
|
||||
, libtorrent::http_parser const& p, rootdevice& d);
|
||||
void on_upnp_map_response(asio::error_code const& e
|
||||
void on_upnp_xml(error_code const& e
|
||||
, libtorrent::http_parser const& p, rootdevice& d
|
||||
, int mapping);
|
||||
void on_upnp_unmap_response(asio::error_code const& e
|
||||
, http_connection& c);
|
||||
void on_upnp_map_response(error_code const& e
|
||||
, libtorrent::http_parser const& p, rootdevice& d
|
||||
, int mapping);
|
||||
void on_expire(asio::error_code const& e);
|
||||
, int mapping, http_connection& c);
|
||||
void on_upnp_unmap_response(error_code const& e
|
||||
, libtorrent::http_parser const& p, rootdevice& d
|
||||
, int mapping, http_connection& c);
|
||||
void on_expire(error_code const& e);
|
||||
|
||||
void disable(char const* msg);
|
||||
void return_error(int mapping, int code);
|
||||
|
@ -237,7 +238,7 @@ private:
|
|||
// current retry count
|
||||
int m_retry_count;
|
||||
|
||||
asio::io_service& m_io_service;
|
||||
io_service& m_io_service;
|
||||
|
||||
// the udp socket used to send and receive
|
||||
// multicast messages on the network
|
||||
|
@ -252,7 +253,7 @@ private:
|
|||
|
||||
bool m_disabled;
|
||||
bool m_closing;
|
||||
bool m_ignore_outside_network;
|
||||
bool m_ignore_non_routers;
|
||||
|
||||
connection_queue& m_cc;
|
||||
|
||||
|
|
|
@ -21,7 +21,11 @@
|
|||
# include <boost/type_traits/add_pointer.hpp>
|
||||
# include <boost/noncopyable.hpp>
|
||||
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/io_service.hpp>
|
||||
#else
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#endif
|
||||
|
||||
# define NETWORK_VARIANT_STREAM_LIMIT 5
|
||||
|
||||
|
@ -48,7 +52,7 @@ namespace aux
|
|||
template<class IO_Control_Command>
|
||||
struct io_control_visitor_ec: boost::static_visitor<>
|
||||
{
|
||||
io_control_visitor_ec(IO_Control_Command& ioc, asio::error_code& ec_)
|
||||
io_control_visitor_ec(IO_Control_Command& ioc, error_code& ec_)
|
||||
: ioc(ioc), ec(ec_) {}
|
||||
|
||||
template <class T>
|
||||
|
@ -61,7 +65,7 @@ namespace aux
|
|||
{}
|
||||
|
||||
IO_Control_Command& ioc;
|
||||
asio::error_code& ec;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
template<class IO_Control_Command>
|
||||
|
@ -112,7 +116,7 @@ namespace aux
|
|||
struct bind_visitor_ec
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
bind_visitor_ec(EndpointType const& ep, asio::error_code& ec_)
|
||||
bind_visitor_ec(EndpointType const& ep, error_code& ec_)
|
||||
: endpoint(ep)
|
||||
, ec(ec_)
|
||||
{}
|
||||
|
@ -124,7 +128,7 @@ namespace aux
|
|||
void operator()(boost::blank) const {}
|
||||
|
||||
EndpointType const& endpoint;
|
||||
asio::error_code& ec;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
template <class EndpointType>
|
||||
|
@ -150,7 +154,7 @@ namespace aux
|
|||
struct open_visitor_ec
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
open_visitor_ec(Protocol const& p, asio::error_code& ec_)
|
||||
open_visitor_ec(Protocol const& p, error_code& ec_)
|
||||
: proto(p)
|
||||
, ec(ec_)
|
||||
{}
|
||||
|
@ -162,7 +166,7 @@ namespace aux
|
|||
void operator()(boost::blank) const {}
|
||||
|
||||
Protocol const& proto;
|
||||
asio::error_code& ec;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
template <class Protocol>
|
||||
|
@ -201,7 +205,7 @@ namespace aux
|
|||
struct close_visitor_ec
|
||||
: boost::static_visitor<>
|
||||
{
|
||||
close_visitor_ec(asio::error_code& ec_)
|
||||
close_visitor_ec(error_code& ec_)
|
||||
: ec(ec_)
|
||||
{}
|
||||
|
||||
|
@ -211,7 +215,7 @@ namespace aux
|
|||
|
||||
void operator()(boost::blank) const {}
|
||||
|
||||
asio::error_code& ec;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
struct close_visitor
|
||||
|
@ -230,18 +234,18 @@ namespace aux
|
|||
struct remote_endpoint_visitor_ec
|
||||
: boost::static_visitor<EndpointType>
|
||||
{
|
||||
remote_endpoint_visitor_ec(asio::error_code& ec)
|
||||
: error_code(ec)
|
||||
remote_endpoint_visitor_ec(error_code& ec_)
|
||||
: ec(ec_)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
EndpointType operator()(T const* p) const
|
||||
{ return p->remote_endpoint(error_code); }
|
||||
{ return p->remote_endpoint(ec); }
|
||||
|
||||
EndpointType operator()(boost::blank) const
|
||||
{ return EndpointType(); }
|
||||
|
||||
asio::error_code& error_code;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
template <class EndpointType>
|
||||
|
@ -270,29 +274,29 @@ namespace aux
|
|||
void operator()(T* p) const
|
||||
{ p->set_option(opt_); }
|
||||
|
||||
void operator()(boost::blank) const {}
|
||||
void operator()(boost::blank) const {}
|
||||
|
||||
SettableSocketOption const& opt_;
|
||||
};
|
||||
|
||||
template <class SettableSocketOption>
|
||||
struct set_option_visitor_ec
|
||||
: boost::static_visitor<asio::error_code>
|
||||
: boost::static_visitor<error_code>
|
||||
{
|
||||
set_option_visitor_ec(SettableSocketOption const& opt, asio::error_code& ec)
|
||||
set_option_visitor_ec(SettableSocketOption const& opt, error_code& ec)
|
||||
: opt_(opt)
|
||||
, ec_(ec)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
asio::error_code operator()(T* p) const
|
||||
error_code operator()(T* p) const
|
||||
{ return p->set_option(opt_, ec_); }
|
||||
|
||||
asio::error_code operator()(boost::blank) const
|
||||
error_code operator()(boost::blank) const
|
||||
{ return ec_; }
|
||||
|
||||
SettableSocketOption const& opt_;
|
||||
asio::error_code& ec_;
|
||||
error_code& ec_;
|
||||
};
|
||||
|
||||
// -------------- local_endpoint -----------
|
||||
|
@ -301,14 +305,14 @@ namespace aux
|
|||
struct local_endpoint_visitor_ec
|
||||
: boost::static_visitor<EndpointType>
|
||||
{
|
||||
local_endpoint_visitor_ec(asio::error_code& ec)
|
||||
: error_code(ec)
|
||||
local_endpoint_visitor_ec(error_code& ec_)
|
||||
: ec(ec_)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
EndpointType operator()(T const* p) const
|
||||
{
|
||||
return p->local_endpoint(error_code);
|
||||
return p->local_endpoint(ec);
|
||||
}
|
||||
|
||||
EndpointType operator()(boost::blank) const
|
||||
|
@ -316,7 +320,7 @@ namespace aux
|
|||
return EndpointType();
|
||||
}
|
||||
|
||||
asio::error_code& error_code;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
template <class EndpointType>
|
||||
|
@ -372,7 +376,7 @@ namespace aux
|
|||
std::size_t operator()(T* p) const
|
||||
{ return p->read_some(buffers); }
|
||||
|
||||
std::size_t operator()(boost::blank) const
|
||||
std::size_t operator()(boost::blank) const
|
||||
{ return 0; }
|
||||
|
||||
Mutable_Buffers const& buffers;
|
||||
|
@ -382,7 +386,7 @@ namespace aux
|
|||
struct read_some_visitor_ec
|
||||
: boost::static_visitor<std::size_t>
|
||||
{
|
||||
read_some_visitor_ec(Mutable_Buffers const& buffers, asio::error_code& ec_)
|
||||
read_some_visitor_ec(Mutable_Buffers const& buffers, error_code& ec_)
|
||||
: buffers(buffers)
|
||||
, ec(ec_)
|
||||
{}
|
||||
|
@ -391,11 +395,11 @@ namespace aux
|
|||
std::size_t operator()(T* p) const
|
||||
{ return p->read_some(buffers, ec); }
|
||||
|
||||
std::size_t operator()(boost::blank) const
|
||||
std::size_t operator()(boost::blank) const
|
||||
{ return 0; }
|
||||
|
||||
Mutable_Buffers const& buffers;
|
||||
asio::error_code& ec;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
// -------------- async_write_some -----------
|
||||
|
@ -427,7 +431,7 @@ namespace aux
|
|||
struct in_avail_visitor_ec
|
||||
: boost::static_visitor<std::size_t>
|
||||
{
|
||||
in_avail_visitor_ec(asio::error_code& ec_)
|
||||
in_avail_visitor_ec(error_code& ec_)
|
||||
: ec(ec_)
|
||||
{}
|
||||
|
||||
|
@ -442,7 +446,7 @@ namespace aux
|
|||
return 0;
|
||||
}
|
||||
|
||||
asio::error_code& ec;
|
||||
error_code& ec;
|
||||
};
|
||||
|
||||
struct in_avail_visitor
|
||||
|
@ -524,11 +528,11 @@ public:
|
|||
typedef typename S0::endpoint_type endpoint_type;
|
||||
typedef typename S0::protocol_type protocol_type;
|
||||
|
||||
explicit variant_stream(asio::io_service& ios)
|
||||
explicit variant_stream(io_service& ios)
|
||||
: m_io_service(ios), m_variant(boost::blank()) {}
|
||||
|
||||
template <class S>
|
||||
void instantiate(asio::io_service& ios)
|
||||
void instantiate(io_service& ios)
|
||||
{
|
||||
TORRENT_ASSERT(&ios == &m_io_service);
|
||||
std::auto_ptr<S> owned(new S(ios));
|
||||
|
@ -540,7 +544,7 @@ public:
|
|||
template <class S>
|
||||
S& get()
|
||||
{
|
||||
return *boost::get<S*>(m_variant);
|
||||
return *boost::get<S*>(m_variant);
|
||||
}
|
||||
|
||||
bool instantiated() const
|
||||
|
@ -554,7 +558,7 @@ public:
|
|||
}
|
||||
|
||||
template <class Mutable_Buffers>
|
||||
std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
|
||||
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(
|
||||
|
@ -612,7 +616,7 @@ public:
|
|||
}
|
||||
|
||||
template <class IO_Control_Command>
|
||||
void io_control(IO_Control_Command& ioc, asio::error_code& ec)
|
||||
void io_control(IO_Control_Command& ioc, error_code& ec)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(
|
||||
|
@ -627,7 +631,7 @@ public:
|
|||
boost::apply_visitor(aux::bind_visitor<endpoint_type>(endpoint), m_variant);
|
||||
}
|
||||
|
||||
void bind(endpoint_type const& endpoint, asio::error_code& ec)
|
||||
void bind(endpoint_type const& endpoint, error_code& ec)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(
|
||||
|
@ -641,7 +645,7 @@ public:
|
|||
boost::apply_visitor(aux::open_visitor<protocol_type>(p), m_variant);
|
||||
}
|
||||
|
||||
void open(protocol_type const& p, asio::error_code& ec)
|
||||
void open(protocol_type const& p, error_code& ec)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
boost::apply_visitor(
|
||||
|
@ -660,7 +664,7 @@ public:
|
|||
boost::apply_visitor(aux::close_visitor(), m_variant);
|
||||
}
|
||||
|
||||
void close(asio::error_code& ec)
|
||||
void close(error_code& ec)
|
||||
{
|
||||
if (!instantiated()) return;
|
||||
boost::apply_visitor(
|
||||
|
@ -674,7 +678,7 @@ public:
|
|||
return boost::apply_visitor(aux::in_avail_visitor(), m_variant);
|
||||
}
|
||||
|
||||
std::size_t in_avail(asio::error_code& ec) const
|
||||
std::size_t in_avail(error_code& ec) const
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(
|
||||
|
@ -688,7 +692,7 @@ public:
|
|||
return boost::apply_visitor(aux::remote_endpoint_visitor<endpoint_type>(), m_variant);
|
||||
}
|
||||
|
||||
endpoint_type remote_endpoint(asio::error_code& ec) const
|
||||
endpoint_type remote_endpoint(error_code& ec) const
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(
|
||||
|
@ -705,20 +709,20 @@ public:
|
|||
}
|
||||
|
||||
template <class SettableSocketOption>
|
||||
asio::error_code set_option(SettableSocketOption const& opt, asio::error_code& ec)
|
||||
error_code set_option(SettableSocketOption const& opt, error_code& ec)
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(aux::set_option_visitor_ec<SettableSocketOption>(opt, ec)
|
||||
, m_variant);
|
||||
}
|
||||
|
||||
|
||||
endpoint_type local_endpoint() const
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_type>(), m_variant);
|
||||
}
|
||||
|
||||
endpoint_type local_endpoint(asio::error_code& ec) const
|
||||
endpoint_type local_endpoint(error_code& ec) const
|
||||
{
|
||||
TORRENT_ASSERT(instantiated());
|
||||
return boost::apply_visitor(
|
||||
|
@ -726,7 +730,7 @@ public:
|
|||
);
|
||||
}
|
||||
|
||||
asio::io_service& get_io_service()
|
||||
io_service& get_io_service()
|
||||
{
|
||||
return m_io_service;
|
||||
}
|
||||
|
@ -740,7 +744,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
asio::io_service& m_io_service;
|
||||
io_service& m_io_service;
|
||||
variant_type m_variant;
|
||||
};
|
||||
|
||||
|
|
|
@ -102,9 +102,9 @@ namespace libtorrent
|
|||
|
||||
// called from the main loop when this connection has any
|
||||
// work to do.
|
||||
void on_sent(asio::error_code const& error
|
||||
void on_sent(error_code const& error
|
||||
, std::size_t bytes_transferred);
|
||||
void on_receive(asio::error_code const& error
|
||||
void on_receive(error_code const& error
|
||||
, std::size_t bytes_transferred);
|
||||
|
||||
std::string const& url() const { return m_url; }
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "GeoIP.h"
|
||||
#include "libtorrent/GeoIP.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netdb.h>
|
||||
|
|
|
@ -30,8 +30,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
*/
|
||||
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/ip/host_name.hpp>
|
||||
#include <asio/ip/multicast.hpp>
|
||||
#else
|
||||
#include <boost/asio/ip/host_name.hpp>
|
||||
#include <boost/asio/ip/multicast.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "libtorrent/socket.hpp"
|
||||
|
@ -75,10 +81,10 @@ namespace libtorrent
|
|||
return addr.to_v6() == address_v6::any();
|
||||
}
|
||||
|
||||
address guess_local_address(asio::io_service& ios)
|
||||
address guess_local_address(io_service& ios)
|
||||
{
|
||||
// make a best guess of the interface we're using and its IP
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
std::vector<ip_interface> const& interfaces = enum_net_interfaces(ios, ec);
|
||||
address ret = address_v4::any();
|
||||
for (std::vector<ip_interface>::const_iterator i = interfaces.begin()
|
||||
|
@ -137,7 +143,7 @@ namespace libtorrent
|
|||
- common_bits(b1.c_array(), b2.c_array(), b1.size());
|
||||
}
|
||||
|
||||
broadcast_socket::broadcast_socket(asio::io_service& ios
|
||||
broadcast_socket::broadcast_socket(io_service& ios
|
||||
, udp::endpoint const& multicast_endpoint
|
||||
, receive_handler_t const& handler
|
||||
, bool loopback)
|
||||
|
@ -148,7 +154,7 @@ namespace libtorrent
|
|||
|
||||
using namespace asio::ip::multicast;
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
std::vector<ip_interface> interfaces = enum_net_interfaces(ios, ec);
|
||||
|
||||
if (multicast_endpoint.address().is_v4())
|
||||
|
@ -179,7 +185,7 @@ namespace libtorrent
|
|||
{
|
||||
using namespace asio::ip::multicast;
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
|
||||
if (addr.is_v4())
|
||||
s->open(udp::v4(), ec);
|
||||
|
@ -205,7 +211,7 @@ namespace libtorrent
|
|||
void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr)
|
||||
{
|
||||
using namespace asio::ip::multicast;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
|
||||
s->open(addr.is_v4() ? udp::v4() : udp::v6(), ec);
|
||||
if (ec) return;
|
||||
|
@ -220,13 +226,13 @@ namespace libtorrent
|
|||
, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
|
||||
}
|
||||
|
||||
void broadcast_socket::send(char const* buffer, int size, asio::error_code& ec)
|
||||
void broadcast_socket::send(char const* buffer, int size, error_code& ec)
|
||||
{
|
||||
for (std::list<socket_entry>::iterator i = m_unicast_sockets.begin()
|
||||
, end(m_unicast_sockets.end()); i != end; ++i)
|
||||
{
|
||||
if (!i->socket) continue;
|
||||
asio::error_code e;
|
||||
error_code e;
|
||||
i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
|
||||
#ifndef NDEBUG
|
||||
// std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << " to: " << m_multicast_endpoint << std::endl;
|
||||
|
@ -239,7 +245,7 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void broadcast_socket::on_receive(socket_entry* s, asio::error_code const& ec
|
||||
void broadcast_socket::on_receive(socket_entry* s, error_code const& ec
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
if (ec || bytes_transferred == 0 || !m_on_receive) return;
|
||||
|
|
|
@ -125,8 +125,9 @@ namespace libtorrent
|
|||
bt_peer_connection::bt_peer_connection(
|
||||
session_impl& ses
|
||||
, boost::shared_ptr<socket_type> s
|
||||
, tcp::endpoint const& remote
|
||||
, policy::peer* peerinfo)
|
||||
: peer_connection(ses, s, peerinfo)
|
||||
: peer_connection(ses, s, remote, peerinfo)
|
||||
, m_state(read_protocol_identifier)
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
, m_supports_extensions(false)
|
||||
|
@ -800,13 +801,14 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(received > 0);
|
||||
if (packet_size() != 1)
|
||||
{
|
||||
disconnect("'choke' message size != 1");
|
||||
disconnect("'choke' message size != 1", 2);
|
||||
return;
|
||||
}
|
||||
m_statistics.received_bytes(0, received);
|
||||
if (!packet_finished()) return;
|
||||
|
||||
incoming_choke();
|
||||
if (is_disconnecting()) return;
|
||||
if (!m_supports_fast)
|
||||
{
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
|
@ -834,7 +836,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(received > 0);
|
||||
if (packet_size() != 1)
|
||||
{
|
||||
disconnect("'unchoke' message size != 1");
|
||||
disconnect("'unchoke' message size != 1", 2);
|
||||
return;
|
||||
}
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -854,7 +856,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(received > 0);
|
||||
if (packet_size() != 1)
|
||||
{
|
||||
disconnect("'interested' message size != 1");
|
||||
disconnect("'interested' message size != 1", 2);
|
||||
return;
|
||||
}
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -874,7 +876,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(received > 0);
|
||||
if (packet_size() != 1)
|
||||
{
|
||||
disconnect("'not interested' message size != 1");
|
||||
disconnect("'not interested' message size != 1", 2);
|
||||
return;
|
||||
}
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -894,7 +896,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(received > 0);
|
||||
if (packet_size() != 5)
|
||||
{
|
||||
disconnect("'have' message size != 5");
|
||||
disconnect("'have' message size != 5", 2);
|
||||
return;
|
||||
}
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -926,7 +928,7 @@ namespace libtorrent
|
|||
if (t->valid_metadata()
|
||||
&& packet_size() - 1 != ((int)get_bitfield().size() + 7) / 8)
|
||||
{
|
||||
disconnect("bitfield with invalid size");
|
||||
disconnect("bitfield with invalid size", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -963,7 +965,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(received > 0);
|
||||
if (packet_size() != 13)
|
||||
{
|
||||
disconnect("'request' message size != 13");
|
||||
disconnect("'request' message size != 13", 2);
|
||||
return;
|
||||
}
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -1021,6 +1023,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
incoming_piece_fragment();
|
||||
if (is_disconnecting()) return;
|
||||
if (!packet_finished()) return;
|
||||
|
||||
const char* ptr = recv_buffer.begin + 1;
|
||||
|
@ -1044,7 +1047,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(received > 0);
|
||||
if (packet_size() != 13)
|
||||
{
|
||||
disconnect("'cancel' message size != 13");
|
||||
disconnect("'cancel' message size != 13", 2);
|
||||
return;
|
||||
}
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -1071,14 +1074,14 @@ namespace libtorrent
|
|||
|
||||
if (!m_supports_dht_port)
|
||||
{
|
||||
disconnect("got 'dht_port' message from peer that doesn't support it");
|
||||
disconnect("got 'dht_port' message from peer that doesn't support it", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(received > 0);
|
||||
if (packet_size() != 3)
|
||||
{
|
||||
disconnect("'dht_port' message size != 3");
|
||||
disconnect("'dht_port' message size != 3", 2);
|
||||
return;
|
||||
}
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -1098,7 +1101,7 @@ namespace libtorrent
|
|||
|
||||
if (!m_supports_fast)
|
||||
{
|
||||
disconnect("got 'suggest_piece' without FAST excension support");
|
||||
disconnect("got 'suggest_piece' without FAST excension support", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1118,7 +1121,7 @@ namespace libtorrent
|
|||
|
||||
if (!m_supports_fast)
|
||||
{
|
||||
disconnect("got 'have_all' without FAST extension support");
|
||||
disconnect("got 'have_all' without FAST extension support", 2);
|
||||
return;
|
||||
}
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -1131,7 +1134,7 @@ namespace libtorrent
|
|||
|
||||
if (!m_supports_fast)
|
||||
{
|
||||
disconnect("got 'have_none' without FAST extension support");
|
||||
disconnect("got 'have_none' without FAST extension support", 2);
|
||||
return;
|
||||
}
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -1144,7 +1147,7 @@ namespace libtorrent
|
|||
|
||||
if (!m_supports_fast)
|
||||
{
|
||||
disconnect("got 'reject_request' without FAST extension support");
|
||||
disconnect("got 'reject_request' without FAST extension support", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1168,7 +1171,7 @@ namespace libtorrent
|
|||
|
||||
if (!m_supports_fast)
|
||||
{
|
||||
disconnect("got 'allowed_fast' without FAST extension support");
|
||||
disconnect("got 'allowed_fast' without FAST extension support", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1193,13 +1196,13 @@ namespace libtorrent
|
|||
m_statistics.received_bytes(0, received);
|
||||
if (packet_size() < 2)
|
||||
{
|
||||
disconnect("'extended' message smaller than 2 bytes");
|
||||
disconnect("'extended' message smaller than 2 bytes", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (associated_torrent().expired())
|
||||
{
|
||||
disconnect("'extended' message sent before proper handshake");
|
||||
disconnect("'extended' message sent before proper handshake", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1229,7 +1232,7 @@ namespace libtorrent
|
|||
|
||||
std::stringstream msg;
|
||||
msg << "unknown extended message id: " << extended_id;
|
||||
disconnect(msg.str().c_str());
|
||||
disconnect(msg.str().c_str(), 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1298,6 +1301,12 @@ namespace libtorrent
|
|||
m_max_out_request_queue = 1;
|
||||
}
|
||||
|
||||
if (entry* upload_only = root.find_key("upload_only"))
|
||||
{
|
||||
if (upload_only->type() == entry::int_t && upload_only->integer() != 0)
|
||||
set_upload_only(true);
|
||||
}
|
||||
|
||||
if (entry* myip = root.find_key("yourip"))
|
||||
{
|
||||
// TODO: don't trust this blindly
|
||||
|
@ -1318,6 +1327,11 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we're finished and this peer is uploading only
|
||||
// disconnect it
|
||||
if (t->is_finished() && upload_only())
|
||||
disconnect("upload to upload connection, closing");
|
||||
}
|
||||
|
||||
bool bt_peer_connection::dispatch_message(int received)
|
||||
|
@ -1350,7 +1364,7 @@ namespace libtorrent
|
|||
|
||||
std::stringstream msg;
|
||||
msg << "unkown message id: " << packet_type << " size: " << packet_size();
|
||||
disconnect(msg.str().c_str());
|
||||
disconnect(msg.str().c_str(), 2);
|
||||
return packet_finished();
|
||||
}
|
||||
|
||||
|
@ -1553,6 +1567,9 @@ namespace libtorrent
|
|||
detail::write_address(remote().address(), out);
|
||||
handshake["yourip"] = remote_address;
|
||||
handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue;
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
TORRENT_ASSERT(t);
|
||||
if (t->is_finished()) handshake["upload_only"] = 1;
|
||||
|
||||
tcp::endpoint ep = m_ses.get_ipv6_interface();
|
||||
if (ep != tcp::endpoint())
|
||||
|
@ -1671,7 +1688,7 @@ namespace libtorrent
|
|||
detail::write_int32(r.start, ptr);
|
||||
send_buffer(msg, sizeof(msg));
|
||||
|
||||
append_send_buffer(buffer.buffer(), r.length
|
||||
append_send_buffer(buffer.get(), r.length
|
||||
, boost::bind(&session_impl::free_disk_buffer
|
||||
, boost::ref(m_ses), _1));
|
||||
buffer.release();
|
||||
|
@ -1707,7 +1724,7 @@ namespace libtorrent
|
|||
// --------------------------
|
||||
|
||||
// throws exception when the client should be disconnected
|
||||
void bt_peer_connection::on_receive(asio::error_code const& error
|
||||
void bt_peer_connection::on_receive(error_code const& error
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -1802,7 +1819,7 @@ namespace libtorrent
|
|||
if (recv_buffer.left() < 20)
|
||||
{
|
||||
if (packet_finished())
|
||||
disconnect("sync hash not found");
|
||||
disconnect("sync hash not found", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1828,7 +1845,7 @@ namespace libtorrent
|
|||
m_sync_bytes_read += bytes_processed;
|
||||
if (m_sync_bytes_read >= 512)
|
||||
{
|
||||
disconnect("sync hash not found within 532 bytes");
|
||||
disconnect("sync hash not found within 532 bytes", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1913,7 +1930,7 @@ namespace libtorrent
|
|||
|
||||
if (!m_RC4_handler.get())
|
||||
{
|
||||
disconnect("invalid streamkey identifier (info hash) in encrypted handshake");
|
||||
disconnect("invalid streamkey identifier (info hash) in encrypted handshake", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1925,7 +1942,7 @@ namespace libtorrent
|
|||
const char sh_vc[] = {0,0,0,0, 0,0,0,0};
|
||||
if (!std::equal(sh_vc, sh_vc+8, recv_buffer.begin + 20))
|
||||
{
|
||||
disconnect("unable to verify constant");
|
||||
disconnect("unable to verify constant", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1947,7 +1964,7 @@ namespace libtorrent
|
|||
if (recv_buffer.left() < 8)
|
||||
{
|
||||
if (packet_finished())
|
||||
disconnect("sync verification constant not found");
|
||||
disconnect("sync verification constant not found", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1972,7 +1989,7 @@ namespace libtorrent
|
|||
m_sync_bytes_read += bytes_processed;
|
||||
if (m_sync_bytes_read >= 512)
|
||||
{
|
||||
disconnect("sync verification constant not found within 520 bytes");
|
||||
disconnect("sync verification constant not found within 520 bytes", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2035,7 +2052,7 @@ namespace libtorrent
|
|||
case pe_settings::plaintext:
|
||||
if (!(crypto_field & 0x01))
|
||||
{
|
||||
disconnect("plaintext not provided");
|
||||
disconnect("plaintext not provided", 1);
|
||||
return;
|
||||
}
|
||||
crypto_select = 0x01;
|
||||
|
@ -2043,7 +2060,7 @@ namespace libtorrent
|
|||
case pe_settings::rc4:
|
||||
if (!(crypto_field & 0x02))
|
||||
{
|
||||
disconnect("rc4 not provided");
|
||||
disconnect("rc4 not provided", 1);
|
||||
return;
|
||||
}
|
||||
crypto_select = 0x02;
|
||||
|
@ -2065,7 +2082,7 @@ namespace libtorrent
|
|||
}
|
||||
if (!crypto_select)
|
||||
{
|
||||
disconnect("rc4/plaintext not provided");
|
||||
disconnect("rc4/plaintext not provided", 1);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -2083,7 +2100,7 @@ namespace libtorrent
|
|||
{
|
||||
if (allowed_enc_level == pe_settings::plaintext)
|
||||
{
|
||||
disconnect("rc4 selected by peer when not provided");
|
||||
disconnect("rc4 selected by peer when not provided", 2);
|
||||
return;
|
||||
}
|
||||
m_rc4_encrypted = true;
|
||||
|
@ -2092,14 +2109,14 @@ namespace libtorrent
|
|||
{
|
||||
if (allowed_enc_level == pe_settings::rc4)
|
||||
{
|
||||
disconnect("plaintext selected by peer when not provided");
|
||||
disconnect("plaintext selected by peer when not provided", 2);
|
||||
return;
|
||||
}
|
||||
m_rc4_encrypted = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect("unsupported crypto method selected by peer");
|
||||
disconnect("unsupported crypto method selected by peer", 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2107,7 +2124,7 @@ namespace libtorrent
|
|||
int len_pad = detail::read_int16(recv_buffer.begin);
|
||||
if (len_pad < 0 || len_pad > 512)
|
||||
{
|
||||
disconnect("invalid pad length");
|
||||
disconnect("invalid pad length", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2145,7 +2162,7 @@ namespace libtorrent
|
|||
|
||||
if (len_ia < 0)
|
||||
{
|
||||
disconnect("invalid len_ia in handshake");
|
||||
disconnect("invalid len_ia in handshake", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2277,7 +2294,7 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT((!is_local() && m_encrypted) || is_local());
|
||||
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
disconnect("incorrect protocol identifier");
|
||||
disconnect("incorrect protocol identifier", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2329,6 +2346,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
#ifndef DISABLE_EXTENSIONS
|
||||
std::memcpy(m_reserved_bits, recv_buffer.begin, 20);
|
||||
if ((recv_buffer[5] & 0x10))
|
||||
m_supports_extensions = true;
|
||||
#endif
|
||||
|
@ -2360,7 +2378,7 @@ namespace libtorrent
|
|||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << " received invalid info_hash\n";
|
||||
#endif
|
||||
disconnect("invalid info-hash in handshake");
|
||||
disconnect("invalid info-hash in handshake", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2449,8 +2467,7 @@ namespace libtorrent
|
|||
|
||||
if (pid == m_ses.get_peer_id())
|
||||
{
|
||||
set_failed();
|
||||
disconnect("closing connection to ourself");
|
||||
disconnect("closing connection to ourself", 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2466,8 +2483,7 @@ namespace libtorrent
|
|||
// since it most likely is ourself then
|
||||
if (pid == m_ses.get_peer_id())
|
||||
{
|
||||
set_failed();
|
||||
disconnect("closing connection to ourself");
|
||||
disconnect("closing connection to ourself", 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2475,7 +2491,7 @@ namespace libtorrent
|
|||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end;)
|
||||
{
|
||||
if (!(*i)->on_handshake())
|
||||
if (!(*i)->on_handshake(m_reserved_bits))
|
||||
{
|
||||
i = m_extensions.erase(i);
|
||||
}
|
||||
|
@ -2484,6 +2500,7 @@ namespace libtorrent
|
|||
++i;
|
||||
}
|
||||
}
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
if (m_supports_extensions) write_extensions();
|
||||
#endif
|
||||
|
@ -2542,13 +2559,14 @@ namespace libtorrent
|
|||
// packet too large
|
||||
std::stringstream msg;
|
||||
msg << "packet > 1 MB (" << (unsigned int)packet_size << " bytes)";
|
||||
disconnect(msg.str().c_str());
|
||||
disconnect(msg.str().c_str(), 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_size == 0)
|
||||
{
|
||||
incoming_keepalive();
|
||||
if (is_disconnecting()) return;
|
||||
// keepalive message
|
||||
m_state = read_packet_size;
|
||||
cut_receive_buffer(4, 4);
|
||||
|
@ -2586,8 +2604,7 @@ namespace libtorrent
|
|||
// SEND DATA
|
||||
// --------------------------
|
||||
|
||||
// throws exception when the client should be disconnected
|
||||
void bt_peer_connection::on_sent(asio::error_code const& error
|
||||
void bt_peer_connection::on_sent(error_code const& error
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
|
|
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/bind.hpp>
|
||||
#include "libtorrent/invariant_check.hpp"
|
||||
#include "libtorrent/connection_queue.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -112,7 +113,7 @@ namespace libtorrent
|
|||
|
||||
void connection_queue::close()
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timer.cancel(ec);
|
||||
}
|
||||
|
||||
|
@ -153,7 +154,7 @@ namespace libtorrent
|
|||
|
||||
if (m_queue.empty())
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timer.cancel(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -166,7 +167,7 @@ namespace libtorrent
|
|||
ptime expire = time_now() + i->timeout;
|
||||
if (m_num_connecting == 0)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timer.expires_at(expire, ec);
|
||||
m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
|
||||
}
|
||||
|
@ -206,7 +207,7 @@ namespace libtorrent
|
|||
};
|
||||
#endif
|
||||
|
||||
void connection_queue::on_timeout(asio::error_code const& e)
|
||||
void connection_queue::on_timeout(error_code const& e)
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
||||
|
@ -251,7 +252,7 @@ namespace libtorrent
|
|||
|
||||
if (next_expire < max_time())
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timer.expires_at(next_expire, ec);
|
||||
m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
|
||||
}
|
||||
|
|
|
@ -49,6 +49,12 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(buf == 0 || m_iothread.is_disk_buffer(buf));
|
||||
}
|
||||
|
||||
void disk_buffer_holder::reset(char* buf)
|
||||
{
|
||||
if (m_buf) m_iothread.free_buffer(m_buf);
|
||||
m_buf = buf;
|
||||
}
|
||||
|
||||
char* disk_buffer_holder::release()
|
||||
{
|
||||
char* ret = m_buf;
|
||||
|
|
|
@ -182,7 +182,6 @@ namespace libtorrent
|
|||
disk_io_thread::cache_t& cache
|
||||
, disk_io_job const& j, mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
for (cache_t::iterator i = cache.begin()
|
||||
, end(cache.end()); i != end; ++i)
|
||||
{
|
||||
|
@ -196,7 +195,6 @@ namespace libtorrent
|
|||
{
|
||||
ptime now = time_now();
|
||||
|
||||
TORRENT_ASSERT(l.locked());
|
||||
INVARIANT_CHECK;
|
||||
for (;;)
|
||||
{
|
||||
|
@ -213,7 +211,6 @@ namespace libtorrent
|
|||
|
||||
void disk_io_thread::free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
int piece_size = p.storage->info()->piece_size(p.piece);
|
||||
int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size;
|
||||
|
||||
|
@ -251,7 +248,6 @@ namespace libtorrent
|
|||
|
||||
void disk_io_thread::flush_oldest_piece(mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
INVARIANT_CHECK;
|
||||
// first look if there are any read cache entries that can
|
||||
// be cleared
|
||||
|
@ -275,7 +271,6 @@ namespace libtorrent
|
|||
void disk_io_thread::flush(disk_io_thread::cache_t::iterator e
|
||||
, mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
INVARIANT_CHECK;
|
||||
cached_piece_entry& p = *e;
|
||||
int piece_size = p.storage->info()->piece_size(p.piece);
|
||||
|
@ -340,7 +335,6 @@ namespace libtorrent
|
|||
|
||||
void disk_io_thread::cache_block(disk_io_job& j, mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_ASSERT(find_cached_piece(m_pieces, j, l) == m_pieces.end());
|
||||
cached_piece_entry p;
|
||||
|
@ -365,8 +359,6 @@ namespace libtorrent
|
|||
// read or -1 if there was an error
|
||||
int disk_io_thread::read_into_piece(cached_piece_entry& p, int start_block, mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
|
||||
int piece_size = p.storage->info()->piece_size(p.piece);
|
||||
int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size;
|
||||
|
||||
|
@ -436,8 +428,6 @@ namespace libtorrent
|
|||
, cache_t::iterator ignore
|
||||
, mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
|
||||
if (m_cache_size - m_cache_stats.cache_size < num_blocks)
|
||||
{
|
||||
// there's not enough room in the cache, clear a piece
|
||||
|
@ -452,8 +442,6 @@ namespace libtorrent
|
|||
// or the number of bytes read
|
||||
int disk_io_thread::cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
int piece_size = j.storage->info()->piece_size(j.piece);
|
||||
|
@ -543,7 +531,6 @@ namespace libtorrent
|
|||
|
||||
int disk_io_thread::try_read_from_cache(disk_io_job const& j, mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
TORRENT_ASSERT(j.buffer);
|
||||
|
||||
if (!m_use_read_cache) return -2;
|
||||
|
@ -707,7 +694,6 @@ namespace libtorrent
|
|||
|
||||
char* disk_io_thread::allocate_buffer(mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
#ifdef TORRENT_STATS
|
||||
++m_allocations;
|
||||
#endif
|
||||
|
@ -720,7 +706,6 @@ namespace libtorrent
|
|||
|
||||
void disk_io_thread::free_buffer(char* buf, mutex_t::scoped_lock& l)
|
||||
{
|
||||
TORRENT_ASSERT(l.locked());
|
||||
#ifdef TORRENT_STATS
|
||||
--m_allocations;
|
||||
#endif
|
||||
|
|
|
@ -35,8 +35,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <boost/bind.hpp>
|
||||
#include "libtorrent/entry.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/escape_string.hpp"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
namespace std
|
||||
|
@ -54,19 +56,6 @@ namespace
|
|||
TORRENT_ASSERT(o);
|
||||
o->~T();
|
||||
}
|
||||
|
||||
struct compare_string
|
||||
{
|
||||
compare_string(char const* s): m_str(s) {}
|
||||
|
||||
bool operator()(
|
||||
std::pair<std::string
|
||||
, libtorrent::entry> const& e) const
|
||||
{
|
||||
return m_str && e.first == m_str;
|
||||
}
|
||||
char const* m_str;
|
||||
};
|
||||
}
|
||||
|
||||
namespace libtorrent
|
||||
|
@ -94,6 +83,16 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
entry& entry::operator[](char const* key)
|
||||
{
|
||||
dictionary_type::iterator i = dict().find(key);
|
||||
if (i != dict().end()) return i->second;
|
||||
dictionary_type::iterator ret = dict().insert(
|
||||
dict().begin()
|
||||
, std::make_pair(key, entry()));
|
||||
return ret->second;
|
||||
}
|
||||
|
||||
entry& entry::operator[](std::string const& key)
|
||||
{
|
||||
dictionary_type::iterator i = dict().find(key);
|
||||
if (i != dict().end()) return i->second;
|
||||
|
@ -103,21 +102,11 @@ namespace libtorrent
|
|||
return ret->second;
|
||||
}
|
||||
|
||||
|
||||
entry& entry::operator[](std::string const& key)
|
||||
{
|
||||
return (*this)[key.c_str()];
|
||||
}
|
||||
|
||||
entry* entry::find_key(char const* key)
|
||||
{
|
||||
dictionary_type::iterator i = std::find_if(
|
||||
dict().begin()
|
||||
, dict().end()
|
||||
, compare_string(key));
|
||||
dictionary_type::iterator i = dict().find(key);
|
||||
if (i == dict().end()) return 0;
|
||||
return &i->second;
|
||||
|
||||
}
|
||||
|
||||
entry const* entry::find_key(char const* key) const
|
||||
|
@ -127,6 +116,20 @@ namespace libtorrent
|
|||
return &i->second;
|
||||
}
|
||||
|
||||
entry* entry::find_key(std::string const& key)
|
||||
{
|
||||
dictionary_type::iterator i = dict().find(key);
|
||||
if (i == dict().end()) return 0;
|
||||
return &i->second;
|
||||
}
|
||||
|
||||
entry const* entry::find_key(std::string const& key) const
|
||||
{
|
||||
dictionary_type::const_iterator i = dict().find(key);
|
||||
if (i == dict().end()) return 0;
|
||||
return &i->second;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
const entry& entry::operator[](char const* key) const
|
||||
{
|
||||
|
@ -370,21 +373,8 @@ namespace libtorrent
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (binary_string)
|
||||
{
|
||||
os.unsetf(std::ios_base::dec);
|
||||
os.setf(std::ios_base::hex);
|
||||
for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
|
||||
os << std::setfill('0') << std::setw(2)
|
||||
<< static_cast<unsigned int>((unsigned char)*i);
|
||||
os.unsetf(std::ios_base::hex);
|
||||
os.setf(std::ios_base::dec);
|
||||
os << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << string() << "\n";
|
||||
}
|
||||
if (binary_string) os << to_hex(string()) << "\n";
|
||||
else os << string() << "\n";
|
||||
} break;
|
||||
case list_t:
|
||||
{
|
||||
|
@ -399,8 +389,21 @@ namespace libtorrent
|
|||
os << "dictionary\n";
|
||||
for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
|
||||
{
|
||||
bool binary_string = false;
|
||||
for (std::string::const_iterator k = i->first.begin(); k != i->first.end(); ++k)
|
||||
{
|
||||
if (!std::isprint(static_cast<unsigned char>(*k)))
|
||||
{
|
||||
binary_string = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < indent+1; ++j) os << " ";
|
||||
os << "[" << i->first << "]";
|
||||
os << "[";
|
||||
if (binary_string) os << to_hex(i->first);
|
||||
else os << i->first;
|
||||
os << "]";
|
||||
|
||||
if (i->second.type() != entry::string_t
|
||||
&& i->second.type() != entry::int_t)
|
||||
os << "\n";
|
||||
|
|
|
@ -35,8 +35,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <vector>
|
||||
#include "libtorrent/enum_net.hpp"
|
||||
#include "libtorrent/broadcast_socket.hpp"
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/ip/host_name.hpp>
|
||||
|
||||
#else
|
||||
#include <boost/asio/ip/host_name.hpp>
|
||||
#endif
|
||||
|
||||
#if defined TORRENT_BSD
|
||||
#include <sys/ioctl.h>
|
||||
|
@ -225,7 +228,7 @@ namespace libtorrent
|
|||
== (iface.interface_address.to_v4().to_ulong() & iface.netmask.to_v4().to_ulong());
|
||||
}
|
||||
|
||||
bool in_local_network(asio::io_service& ios, address const& addr, asio::error_code& ec)
|
||||
bool in_local_network(io_service& ios, address const& addr, error_code& ec)
|
||||
{
|
||||
std::vector<ip_interface> const& net = enum_net_interfaces(ios, ec);
|
||||
if (ec) return false;
|
||||
|
@ -237,7 +240,7 @@ namespace libtorrent
|
|||
return false;
|
||||
}
|
||||
|
||||
std::vector<ip_interface> enum_net_interfaces(asio::io_service& ios, asio::error_code& ec)
|
||||
std::vector<ip_interface> enum_net_interfaces(io_service& ios, error_code& ec)
|
||||
{
|
||||
std::vector<ip_interface> ret;
|
||||
// covers linux, MacOS X and BSD distributions
|
||||
|
@ -254,7 +257,7 @@ namespace libtorrent
|
|||
ifc.ifc_buf = buf;
|
||||
if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
|
||||
{
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
close(s);
|
||||
return ret;
|
||||
}
|
||||
|
@ -283,7 +286,7 @@ namespace libtorrent
|
|||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
close(s);
|
||||
return ret;
|
||||
}
|
||||
|
@ -310,7 +313,7 @@ namespace libtorrent
|
|||
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s == SOCKET_ERROR)
|
||||
{
|
||||
ec = asio::error_code(WSAGetLastError(), asio::error::system_category);
|
||||
ec = error_code(WSAGetLastError(), asio::error::system_category);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -320,7 +323,7 @@ namespace libtorrent
|
|||
if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, 0, 0, buffer,
|
||||
sizeof(buffer), &size, 0, 0) != 0)
|
||||
{
|
||||
ec = asio::error_code(WSAGetLastError(), asio::error::system_category);
|
||||
ec = error_code(WSAGetLastError(), asio::error::system_category);
|
||||
closesocket(s);
|
||||
return ret;
|
||||
}
|
||||
|
@ -356,16 +359,21 @@ namespace libtorrent
|
|||
return ret;
|
||||
}
|
||||
|
||||
address get_default_gateway(asio::io_service& ios, asio::error_code& ec)
|
||||
address get_default_gateway(io_service& ios, error_code& ec)
|
||||
{
|
||||
std::vector<ip_route> ret = enum_routes(ios, ec);
|
||||
#ifdef TORRENT_WINDOWS
|
||||
std::vector<ip_route>::iterator i = std::find_if(ret.begin(), ret.end()
|
||||
, boost::bind(&is_loopback, boost::bind(&ip_route::destination, _1)));
|
||||
#else
|
||||
std::vector<ip_route>::iterator i = std::find_if(ret.begin(), ret.end()
|
||||
, boost::bind(&ip_route::destination, _1) == address());
|
||||
#endif
|
||||
if (i == ret.end()) return address();
|
||||
return i->gateway;
|
||||
}
|
||||
|
||||
std::vector<ip_route> enum_routes(asio::io_service& ios, asio::error_code& ec)
|
||||
std::vector<ip_route> enum_routes(io_service& ios, error_code& ec)
|
||||
{
|
||||
std::vector<ip_route> ret;
|
||||
|
||||
|
@ -390,14 +398,14 @@ namespace libtorrent
|
|||
int s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
|
||||
if (s == -1)
|
||||
{
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
||||
int n = write(s, &m, len);
|
||||
if (n == -1)
|
||||
{
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
close(s);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
@ -412,7 +420,7 @@ namespace libtorrent
|
|||
n = read(s, &m, len);
|
||||
if (n == -1)
|
||||
{
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
close(s);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
@ -423,7 +431,7 @@ namespace libtorrent
|
|||
std::cout << " rtm_type: " << ptr->rtm_type << std::endl;
|
||||
if (ptr->rtm_errno)
|
||||
{
|
||||
ec = asio::error_code(ptr->rtm_errno, asio::error::system_category);
|
||||
ec = error_code(ptr->rtm_errno, asio::error::system_category);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
if (m.m_rtm.rtm_flags & RTF_UP == 0
|
||||
|
@ -475,7 +483,7 @@ namespace libtorrent
|
|||
size_t needed = 0;
|
||||
if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
|
||||
{
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
||||
|
@ -493,7 +501,7 @@ namespace libtorrent
|
|||
|
||||
if (sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0)
|
||||
{
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
||||
|
@ -547,7 +555,6 @@ namespace libtorrent
|
|||
return std::vector<ip_route>();
|
||||
}
|
||||
|
||||
address ret;
|
||||
if (GetAdaptersInfo(adapter_info, &out_buf_size) == NO_ERROR)
|
||||
{
|
||||
for (PIP_ADAPTER_INFO adapter = adapter_info;
|
||||
|
@ -555,14 +562,14 @@ namespace libtorrent
|
|||
{
|
||||
|
||||
ip_route r;
|
||||
r.source = address::from_string(adapter->IpAddressList.IpAddress.String, ec);
|
||||
r.destination = address::from_string(adapter->IpAddressList.IpAddress.String, ec);
|
||||
r.gateway = address::from_string(adapter->GatewayList.IpAddress.String, ec);
|
||||
r.netmask = address::from_string(adapter->IpAddressList.IpMask.String, ec);
|
||||
strcpy(r.name, adapter->AdapterName);
|
||||
strncpy(r.name, adapter->AdapterName, sizeof(r.name));
|
||||
|
||||
if (ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
ec = error_code();
|
||||
continue;
|
||||
}
|
||||
ret.push_back(r);
|
||||
|
@ -573,8 +580,6 @@ namespace libtorrent
|
|||
free(adapter_info);
|
||||
FreeLibrary(iphlp);
|
||||
|
||||
return ret;
|
||||
|
||||
#elif defined TORRENT_LINUX
|
||||
|
||||
enum { BUFSIZE = 8192 };
|
||||
|
@ -582,7 +587,7 @@ namespace libtorrent
|
|||
int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE);
|
||||
if (sock < 0)
|
||||
{
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
||||
|
@ -600,7 +605,7 @@ namespace libtorrent
|
|||
|
||||
if (send(sock, nl_msg, nl_msg->nlmsg_len, 0) < 0)
|
||||
{
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
close(sock);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
@ -608,7 +613,7 @@ namespace libtorrent
|
|||
int len = read_nl_sock(sock, msg, BUFSIZE, seq, getpid());
|
||||
if (len < 0)
|
||||
{
|
||||
ec = asio::error_code(errno, asio::error::system_category);
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
close(sock);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
|
|
@ -352,5 +352,17 @@ namespace libtorrent
|
|||
return url.substr(pos, url.find('&', pos) - pos);
|
||||
}
|
||||
|
||||
TORRENT_EXPORT std::string to_hex(std::string const& s)
|
||||
{
|
||||
std::string ret;
|
||||
char* digits = "0123456789abcdef";
|
||||
for (std::string::const_iterator i = s.begin(); i != s.end(); ++i)
|
||||
{
|
||||
ret += digits[((unsigned char)*i) >> 4];
|
||||
ret += digits[((unsigned char)*i) & 0xf];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -34,12 +34,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/escape_string.hpp"
|
||||
#include "libtorrent/instantiate_connection.hpp"
|
||||
#include "libtorrent/gzip.hpp"
|
||||
#include "libtorrent/tracker_manager.hpp"
|
||||
#include "libtorrent/parse_url.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/connection_queue.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <asio/ip/tcp.hpp>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
using boost::bind;
|
||||
|
||||
|
@ -56,8 +58,17 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri
|
|||
std::string auth;
|
||||
std::string hostname;
|
||||
std::string path;
|
||||
char const* error;
|
||||
int port;
|
||||
boost::tie(protocol, auth, hostname, port, path) = parse_url_components(url);
|
||||
|
||||
boost::tie(protocol, auth, hostname, port, path, error)
|
||||
= parse_url_components(url);
|
||||
|
||||
if (error)
|
||||
{
|
||||
callback(asio::error::socket_type_not_supported);
|
||||
return;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(prio >= 0 && prio < 2);
|
||||
|
||||
|
@ -104,6 +115,7 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri
|
|||
"\r\n";
|
||||
|
||||
sendbuffer = headers.str();
|
||||
m_url = url;
|
||||
start(hostname, boost::lexical_cast<std::string>(port), timeout, prio
|
||||
, ps, ssl, handle_redirects, bind_addr);
|
||||
}
|
||||
|
@ -118,7 +130,7 @@ void http_connection::start(std::string const& hostname, std::string const& port
|
|||
if (ps) m_proxy = *ps;
|
||||
|
||||
m_timeout = timeout;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timer.expires_from_now(m_timeout, ec);
|
||||
m_timer.async_wait(bind(&http_connection::on_timeout
|
||||
, boost::weak_ptr<http_connection>(shared_from_this()), _1));
|
||||
|
@ -137,14 +149,14 @@ void http_connection::start(std::string const& hostname, std::string const& port
|
|||
if (m_sock.is_open() && m_hostname == hostname && m_port == port
|
||||
&& m_ssl == ssl && m_bind_addr == bind_addr)
|
||||
{
|
||||
asio::async_write(m_sock, asio::buffer(sendbuffer)
|
||||
async_write(m_sock, asio::buffer(sendbuffer)
|
||||
, bind(&http_connection::on_write, shared_from_this(), _1));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ssl = ssl;
|
||||
m_bind_addr = bind_addr;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_sock.close(ec);
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
|
@ -168,7 +180,7 @@ void http_connection::start(std::string const& hostname, std::string const& port
|
|||
#endif
|
||||
if (m_bind_addr != address_v4::any())
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_sock.bind(tcp::endpoint(m_bind_addr, 0), ec);
|
||||
if (ec)
|
||||
{
|
||||
|
@ -187,52 +199,65 @@ void http_connection::start(std::string const& hostname, std::string const& port
|
|||
|
||||
void http_connection::on_connect_timeout()
|
||||
{
|
||||
TORRENT_ASSERT(m_connection_ticket >= 0);
|
||||
if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
|
||||
m_connection_ticket = -1;
|
||||
|
||||
callback(asio::error::timed_out);
|
||||
close();
|
||||
if (!m_endpoints.empty())
|
||||
{
|
||||
m_sock.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
callback(asio::error::timed_out);
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void http_connection::on_timeout(boost::weak_ptr<http_connection> p
|
||||
, asio::error_code const& e)
|
||||
, error_code const& e)
|
||||
{
|
||||
boost::shared_ptr<http_connection> c = p.lock();
|
||||
if (!c) return;
|
||||
if (c->m_connection_ticket > -1) c->m_cc.done(c->m_connection_ticket);
|
||||
c->m_connection_ticket = -1;
|
||||
|
||||
if (e == asio::error::operation_aborted) return;
|
||||
|
||||
if (c->m_last_receive + c->m_timeout < time_now())
|
||||
{
|
||||
c->callback(asio::error::timed_out);
|
||||
c->close();
|
||||
if (c->m_connection_ticket > -1 && !c->m_endpoints.empty())
|
||||
{
|
||||
c->m_sock.close();
|
||||
error_code ec;
|
||||
c->m_timer.expires_at(c->m_last_receive + c->m_timeout, ec);
|
||||
c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1));
|
||||
}
|
||||
else
|
||||
{
|
||||
c->callback(asio::error::timed_out);
|
||||
c->close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c->m_sock.is_open()) return;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
c->m_timer.expires_at(c->m_last_receive + c->m_timeout, ec);
|
||||
c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1));
|
||||
}
|
||||
|
||||
void http_connection::close()
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timer.cancel(ec);
|
||||
m_limiter_timer.cancel(ec);
|
||||
m_sock.close(ec);
|
||||
m_hostname.clear();
|
||||
m_port.clear();
|
||||
|
||||
if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
|
||||
m_connection_ticket = -1;
|
||||
|
||||
m_handler.clear();
|
||||
m_abort = true;
|
||||
}
|
||||
|
||||
void http_connection::on_resolve(asio::error_code const& e
|
||||
void http_connection::on_resolve(error_code const& e
|
||||
, tcp::resolver::iterator i)
|
||||
{
|
||||
if (e)
|
||||
|
@ -243,21 +268,26 @@ void http_connection::on_resolve(asio::error_code const& e
|
|||
}
|
||||
TORRENT_ASSERT(i != tcp::resolver::iterator());
|
||||
|
||||
// look for an address that has the same kind as the one
|
||||
// we're binding to. To make sure a tracker get our
|
||||
// correct listening address.
|
||||
tcp::resolver::iterator target = i;
|
||||
tcp::resolver::iterator end;
|
||||
tcp::endpoint target_address = *i;
|
||||
for (; target != end && target->endpoint().address().is_v4()
|
||||
!= m_bind_addr.is_v4(); ++target);
|
||||
std::transform(i, tcp::resolver::iterator(), std::back_inserter(m_endpoints)
|
||||
, boost::bind(&tcp::resolver::iterator::value_type::endpoint, _1));
|
||||
|
||||
if (target != end)
|
||||
{
|
||||
target_address = *target;
|
||||
}
|
||||
|
||||
m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, target_address)
|
||||
// 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
|
||||
m_endpoints.sort(
|
||||
(bind(&address::is_v4, bind(&tcp::endpoint::address, _1)) == m_bind_addr.is_v4())
|
||||
> (bind(&address::is_v4, bind(&tcp::endpoint::address, _2)) == m_bind_addr.is_v4()));
|
||||
|
||||
queue_connect();
|
||||
}
|
||||
|
||||
void http_connection::queue_connect()
|
||||
{
|
||||
TORRENT_ASSERT(!m_endpoints.empty());
|
||||
tcp::endpoint target = m_endpoints.front();
|
||||
m_endpoints.pop_front();
|
||||
|
||||
m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, target)
|
||||
, bind(&http_connection::on_connect_timeout, shared_from_this())
|
||||
, m_timeout, m_priority);
|
||||
}
|
||||
|
@ -266,35 +296,35 @@ void http_connection::connect(int ticket, tcp::endpoint target_address)
|
|||
{
|
||||
m_connection_ticket = ticket;
|
||||
m_sock.async_connect(target_address, boost::bind(&http_connection::on_connect
|
||||
, shared_from_this(), _1/*, ++i*/));
|
||||
, shared_from_this(), _1));
|
||||
}
|
||||
|
||||
void http_connection::on_connect(asio::error_code const& e
|
||||
/*, tcp::resolver::iterator i*/)
|
||||
void http_connection::on_connect(error_code const& e)
|
||||
{
|
||||
TORRENT_ASSERT(m_connection_ticket >= 0);
|
||||
m_cc.done(m_connection_ticket);
|
||||
|
||||
m_last_receive = time_now();
|
||||
if (!e)
|
||||
{
|
||||
m_last_receive = time_now();
|
||||
if (m_connect_handler) m_connect_handler(*this);
|
||||
asio::async_write(m_sock, asio::buffer(sendbuffer)
|
||||
async_write(m_sock, asio::buffer(sendbuffer)
|
||||
, bind(&http_connection::on_write, shared_from_this(), _1));
|
||||
}
|
||||
/* else if (i != tcp::resolver::iterator())
|
||||
else if (!m_endpoints.empty() && !m_abort)
|
||||
{
|
||||
// The connection failed. Try the next endpoint in the list.
|
||||
m_sock.close();
|
||||
m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i)
|
||||
, bind(&http_connection::on_connect_timeout, shared_from_this())
|
||||
, m_timeout, m_priority);
|
||||
queue_connect();
|
||||
}
|
||||
*/ else
|
||||
else
|
||||
{
|
||||
callback(e);
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void http_connection::callback(asio::error_code const& e, char const* data, int size)
|
||||
void http_connection::callback(error_code const& e, char const* data, int size)
|
||||
{
|
||||
if (!m_bottled || !m_called)
|
||||
{
|
||||
|
@ -307,7 +337,7 @@ void http_connection::callback(asio::error_code const& e, char const* data, int
|
|||
std::string error;
|
||||
if (inflate_gzip(data, size, buf, max_bottled_buffer, error))
|
||||
{
|
||||
callback(asio::error::fault, data, size);
|
||||
if (m_handler) m_handler(asio::error::fault, m_parser, data, size, *this);
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
@ -317,11 +347,11 @@ void http_connection::callback(asio::error_code const& e, char const* data, int
|
|||
}
|
||||
m_called = true;
|
||||
m_timer.cancel();
|
||||
if (m_handler) m_handler(e, m_parser, data, size);
|
||||
if (m_handler) m_handler(e, m_parser, data, size, *this);
|
||||
}
|
||||
}
|
||||
|
||||
void http_connection::on_write(asio::error_code const& e)
|
||||
void http_connection::on_write(error_code const& e)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
|
@ -340,7 +370,7 @@ void http_connection::on_write(asio::error_code const& e)
|
|||
if (m_download_quota == 0)
|
||||
{
|
||||
if (!m_limiter_timer_active)
|
||||
on_assign_bandwidth(asio::error_code());
|
||||
on_assign_bandwidth(error_code());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -350,7 +380,7 @@ void http_connection::on_write(asio::error_code const& e)
|
|||
, shared_from_this(), _1, _2));
|
||||
}
|
||||
|
||||
void http_connection::on_read(asio::error_code const& e
|
||||
void http_connection::on_read(error_code const& e
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
if (m_rate_limit)
|
||||
|
@ -394,7 +424,7 @@ void http_connection::on_read(asio::error_code const& e
|
|||
if (error)
|
||||
{
|
||||
// HTTP parse error
|
||||
asio::error_code ec = asio::error::fault;
|
||||
error_code ec = asio::error::fault;
|
||||
callback(ec, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
@ -407,17 +437,44 @@ void http_connection::on_read(asio::error_code const& e
|
|||
if (code >= 300 && code < 400)
|
||||
{
|
||||
// attempt a redirect
|
||||
std::string const& url = m_parser.header("location");
|
||||
if (url.empty())
|
||||
std::string const& location = m_parser.header("location");
|
||||
if (location.empty())
|
||||
{
|
||||
// missing location header
|
||||
callback(e);
|
||||
callback(asio::error::fault);
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_sock.close(ec);
|
||||
get(url, m_timeout, m_priority, &m_proxy, m_redirects - 1);
|
||||
using boost::tuples::ignore;
|
||||
char const* error;
|
||||
boost::tie(ignore, ignore, ignore, ignore, ignore, error)
|
||||
= parse_url_components(location);
|
||||
if (error == 0)
|
||||
{
|
||||
get(location, m_timeout, m_priority, &m_proxy, m_redirects - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// some broken web servers send out relative paths
|
||||
// in the location header.
|
||||
std::string url = m_url;
|
||||
// remove the leaf filename
|
||||
std::size_t i = url.find_last_of('/');
|
||||
if (i == std::string::npos)
|
||||
{
|
||||
url += '/';
|
||||
}
|
||||
else
|
||||
{
|
||||
url.resize(i + 1);
|
||||
}
|
||||
url += location;
|
||||
|
||||
get(url, m_timeout, m_priority, &m_proxy, m_redirects - 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -434,7 +491,7 @@ void http_connection::on_read(asio::error_code const& e
|
|||
}
|
||||
else if (m_bottled && m_parser.finished())
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timer.cancel(ec);
|
||||
callback(e, m_parser.get_body().begin, m_parser.get_body().left());
|
||||
}
|
||||
|
@ -462,7 +519,7 @@ void http_connection::on_read(asio::error_code const& e
|
|||
if (m_download_quota == 0)
|
||||
{
|
||||
if (!m_limiter_timer_active)
|
||||
on_assign_bandwidth(asio::error_code());
|
||||
on_assign_bandwidth(error_code());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -472,7 +529,7 @@ void http_connection::on_read(asio::error_code const& e
|
|||
, shared_from_this(), _1, _2));
|
||||
}
|
||||
|
||||
void http_connection::on_assign_bandwidth(asio::error_code const& e)
|
||||
void http_connection::on_assign_bandwidth(error_code const& e)
|
||||
{
|
||||
if ((e == asio::error::operation_aborted
|
||||
&& m_limiter_timer_active)
|
||||
|
@ -499,7 +556,7 @@ void http_connection::on_assign_bandwidth(asio::error_code const& e)
|
|||
, bind(&http_connection::on_read
|
||||
, shared_from_this(), _1, _2));
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_limiter_timer_active = true;
|
||||
m_limiter_timer.expires_from_now(milliseconds(250), ec);
|
||||
m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth
|
||||
|
@ -512,7 +569,7 @@ void http_connection::rate_limit(int limit)
|
|||
|
||||
if (!m_limiter_timer_active)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_limiter_timer_active = true;
|
||||
m_limiter_timer.expires_from_now(milliseconds(250), ec);
|
||||
m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth
|
||||
|
|
|
@ -38,13 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace libtorrent
|
||||
{
|
||||
|
||||
void http_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
||||
void http_stream::name_lookup(error_code const& e, tcp::resolver::iterator i
|
||||
, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e || i == tcp::resolver::iterator())
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -53,12 +53,12 @@ namespace libtorrent
|
|||
&http_stream::connected, this, _1, h));
|
||||
}
|
||||
|
||||
void http_stream::connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void http_stream::connected(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -82,32 +82,32 @@ namespace libtorrent
|
|||
m_user + ":" + m_password) + "\r\n", p);
|
||||
}
|
||||
write_string("\r\n", p);
|
||||
asio::async_write(m_sock, asio::buffer(m_buffer)
|
||||
async_write(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&http_stream::handshake1, this, _1, h));
|
||||
}
|
||||
|
||||
void http_stream::handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void http_stream::handshake1(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
// read one byte from the socket
|
||||
m_buffer.resize(1);
|
||||
asio::async_read(m_sock, asio::buffer(m_buffer)
|
||||
async_read(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&http_stream::handshake2, this, _1, h));
|
||||
}
|
||||
|
||||
void http_stream::handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void http_stream::handshake2(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ namespace libtorrent
|
|||
if (status == 0)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ namespace libtorrent
|
|||
if (code != 200)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ namespace libtorrent
|
|||
|
||||
// read another byte from the socket
|
||||
m_buffer.resize(read_pos + 1);
|
||||
asio::async_read(m_sock, asio::buffer(&m_buffer[0] + read_pos, 1)
|
||||
async_read(m_sock, asio::buffer(&m_buffer[0] + read_pos, 1)
|
||||
, boost::bind(&http_stream::handshake2, this, _1, h));
|
||||
}
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ namespace libtorrent
|
|||
tracker_connection::close();
|
||||
}
|
||||
|
||||
void http_tracker_connection::on_response(asio::error_code const& ec
|
||||
void http_tracker_connection::on_response(error_code const& ec
|
||||
, http_parser const& parser, char const* data, int size)
|
||||
{
|
||||
// keep this alive
|
||||
|
@ -313,9 +313,7 @@ namespace libtorrent
|
|||
|
||||
if (tracker_req().kind == tracker_request::scrape_request)
|
||||
{
|
||||
std::string ih;
|
||||
std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end()
|
||||
, std::back_inserter(ih));
|
||||
std::string ih = tracker_req().info_hash.to_string();
|
||||
|
||||
entry const* files = e.find_key("files");
|
||||
if (files == 0 || files->type() != entry::dictionary_t)
|
||||
|
@ -324,7 +322,7 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
entry const* scrape_data = e.find_key(ih.c_str());
|
||||
entry const* scrape_data = files->find_key(ih);
|
||||
if (scrape_data == 0 || scrape_data->type() != entry::dictionary_t)
|
||||
{
|
||||
fail(-1, "missing or invalid info-hash entry in scrape response");
|
||||
|
|
|
@ -37,12 +37,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/socket_type.hpp"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <stdexcept>
|
||||
#include <asio/io_service.hpp>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
bool instantiate_connection(asio::io_service& ios
|
||||
bool instantiate_connection(io_service& ios
|
||||
, proxy_settings const& ps, socket_type& s)
|
||||
{
|
||||
if (ps.type == proxy_settings::none)
|
||||
|
|
|
@ -40,8 +40,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
||||
using asio::ip::udp;
|
||||
|
||||
closest_nodes_observer::~closest_nodes_observer()
|
||||
{
|
||||
if (m_algorithm) m_algorithm->failed(m_self, true);
|
||||
|
|
|
@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/bencode.hpp"
|
||||
#include "libtorrent/io.hpp"
|
||||
#include "libtorrent/version.hpp"
|
||||
#include "libtorrent/escape_string.hpp"
|
||||
|
||||
using boost::ref;
|
||||
using boost::lexical_cast;
|
||||
|
@ -66,9 +67,6 @@ enum
|
|||
key_refresh = 5 // generate a new write token key every 5 minutes
|
||||
};
|
||||
|
||||
using asio::ip::udp;
|
||||
typedef asio::ip::address_v4 address;
|
||||
|
||||
namespace
|
||||
{
|
||||
const int tick_period = 1; // minutes
|
||||
|
@ -228,7 +226,7 @@ namespace libtorrent { namespace dht
|
|||
s.dht_global_nodes = m_dht.num_global_nodes();
|
||||
}
|
||||
|
||||
void dht_tracker::connection_timeout(asio::error_code const& e)
|
||||
void dht_tracker::connection_timeout(error_code const& e)
|
||||
try
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
@ -247,7 +245,7 @@ namespace libtorrent { namespace dht
|
|||
#endif
|
||||
};
|
||||
|
||||
void dht_tracker::refresh_timeout(asio::error_code const& e)
|
||||
void dht_tracker::refresh_timeout(error_code const& e)
|
||||
try
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
@ -263,7 +261,7 @@ namespace libtorrent { namespace dht
|
|||
TORRENT_ASSERT(false);
|
||||
};
|
||||
|
||||
void dht_tracker::tick(asio::error_code const& e)
|
||||
void dht_tracker::tick(error_code const& e)
|
||||
try
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
@ -375,6 +373,12 @@ namespace libtorrent { namespace dht
|
|||
m_dht.announce(ih, listen_port, f);
|
||||
}
|
||||
|
||||
|
||||
void dht_tracker::on_unreachable(udp::endpoint const& ep)
|
||||
{
|
||||
m_dht.unreachable(ep);
|
||||
}
|
||||
|
||||
// translate bittorrent kademlia message into the generice kademlia message
|
||||
// used by the library
|
||||
void dht_tracker::on_receive(udp::endpoint const& ep, char const* buf, int bytes_transferred)
|
||||
|
@ -404,8 +408,8 @@ namespace libtorrent { namespace dht
|
|||
if (match->count == 20)
|
||||
{
|
||||
TORRENT_LOG(dht_tracker) << time_now_string() << " BANNING PEER [ ip: "
|
||||
<< ep << " | time: " << total_milliseconds((now - match->limit) + seconds(5)) / 1000.f
|
||||
<< " | count: " << match->count << " ]";
|
||||
<< ep << " time: " << total_milliseconds((now - match->limit) + seconds(5)) / 1000.f
|
||||
<< " count: " << match->count << " ]";
|
||||
}
|
||||
#endif
|
||||
// we've received 20 messages in less than 5 seconds from
|
||||
|
@ -442,8 +446,9 @@ namespace libtorrent { namespace dht
|
|||
entry e = bdecode(buf, buf + bytes_transferred);
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << time_now_string() << " RECEIVED ["
|
||||
<< ep << "]:";
|
||||
std::stringstream log_line;
|
||||
log_line << time_now_string() << " RECEIVED ["
|
||||
" ip: " << ep;
|
||||
#endif
|
||||
|
||||
libtorrent::dht::msg m;
|
||||
|
@ -461,36 +466,36 @@ namespace libtorrent { namespace dht
|
|||
if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "UT"))
|
||||
{
|
||||
++m_ut_message_input;
|
||||
TORRENT_LOG(dht_tracker) << " client: uTorrent";
|
||||
log_line << " c: uTorrent";
|
||||
}
|
||||
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "LT"))
|
||||
{
|
||||
++m_lt_message_input;
|
||||
TORRENT_LOG(dht_tracker) << " client: libtorrent";
|
||||
log_line << " c: libtorrent";
|
||||
}
|
||||
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MP"))
|
||||
{
|
||||
++m_mp_message_input;
|
||||
TORRENT_LOG(dht_tracker) << " client: MooPolice";
|
||||
log_line << " c: MooPolice";
|
||||
}
|
||||
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "GR"))
|
||||
{
|
||||
++m_gr_message_input;
|
||||
TORRENT_LOG(dht_tracker) << " client: GetRight";
|
||||
log_line << " c: GetRight";
|
||||
}
|
||||
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MO"))
|
||||
{
|
||||
++m_mo_message_input;
|
||||
TORRENT_LOG(dht_tracker) << " client: Mono Torrent";
|
||||
log_line << " c: Mono Torrent";
|
||||
}
|
||||
else
|
||||
{
|
||||
TORRENT_LOG(dht_tracker) << " client: " << client;
|
||||
log_line << " c: " << client;
|
||||
}
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
TORRENT_LOG(dht_tracker) << " client: generic";
|
||||
log_line << " c: generic";
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -499,8 +504,8 @@ namespace libtorrent { namespace dht
|
|||
if (msg_type == "r")
|
||||
{
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " reply: transaction: "
|
||||
<< m.transaction_id;
|
||||
log_line << " r: " << messages::ids[m.message_id]
|
||||
<< " t: " << to_hex(m.transaction_id);
|
||||
#endif
|
||||
|
||||
m.reply = true;
|
||||
|
@ -528,7 +533,7 @@ namespace libtorrent { namespace dht
|
|||
read_endpoint_list<tcp::endpoint>(n, m.peers);
|
||||
}
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size();
|
||||
log_line << " p: " << m.peers.size();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -548,7 +553,7 @@ namespace libtorrent { namespace dht
|
|||
id, read_v4_endpoint<udp::endpoint>(i)));
|
||||
}
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " nodes: " << m.nodes.size();
|
||||
log_line << " n: " << m.nodes.size();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -573,7 +578,7 @@ namespace libtorrent { namespace dht
|
|||
id, read_v6_endpoint<udp::endpoint>(in)));
|
||||
}
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " nodes2 + nodes: " << m.nodes.size();
|
||||
log_line << " n2: " << m.nodes.size();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -590,7 +595,7 @@ namespace libtorrent { namespace dht
|
|||
|
||||
std::string request_kind(e["q"].string());
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " query: " << request_kind;
|
||||
log_line << " q: " << request_kind;
|
||||
#endif
|
||||
|
||||
if (request_kind == "ping")
|
||||
|
@ -603,8 +608,7 @@ namespace libtorrent { namespace dht
|
|||
if (target.size() != 20) throw std::runtime_error("invalid size of target id");
|
||||
std::copy(target.begin(), target.end(), m.info_hash.begin());
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " target: "
|
||||
<< boost::lexical_cast<std::string>(m.info_hash);
|
||||
log_line << " t: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||
#endif
|
||||
|
||||
m.message_id = libtorrent::dht::messages::find_node;
|
||||
|
@ -616,8 +620,7 @@ namespace libtorrent { namespace dht
|
|||
std::copy(info_hash.begin(), info_hash.end(), m.info_hash.begin());
|
||||
m.message_id = libtorrent::dht::messages::get_peers;
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " info_hash: "
|
||||
<< boost::lexical_cast<std::string>(m.info_hash);
|
||||
log_line << " ih: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||
#endif
|
||||
}
|
||||
else if (request_kind == "announce_peer")
|
||||
|
@ -633,9 +636,8 @@ namespace libtorrent { namespace dht
|
|||
m.write_token = a["token"];
|
||||
m.message_id = libtorrent::dht::messages::announce_peer;
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " info_hash: "
|
||||
<< boost::lexical_cast<std::string>(m.info_hash);
|
||||
TORRENT_LOG(dht_tracker) << " port: " << m.port;
|
||||
log_line << " ih: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||
log_line << " p: " << m.port;
|
||||
|
||||
if (!m_dht.verify_token(m))
|
||||
++m_failed_announces;
|
||||
|
@ -657,8 +659,8 @@ namespace libtorrent { namespace dht
|
|||
m.error_msg = list.back().string();
|
||||
m.error_code = list.front().integer();
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " incoming error: " << m.error_code << " "
|
||||
<< m.error_msg;
|
||||
log_line << " incoming error: " << m.error_code
|
||||
<< " " << m.error_msg;
|
||||
#endif
|
||||
throw std::runtime_error("DHT error message");
|
||||
}
|
||||
|
@ -677,7 +679,7 @@ namespace libtorrent { namespace dht
|
|||
++m_queries_received[m.message_id];
|
||||
m_queries_bytes_received[m.message_id] += int(bytes_transferred);
|
||||
}
|
||||
TORRENT_LOG(dht_tracker) << e;
|
||||
TORRENT_LOG(dht_tracker) << log_line.str() << " ]";
|
||||
#endif
|
||||
TORRENT_ASSERT(m.message_id != messages::error);
|
||||
m_dht.incoming(m);
|
||||
|
@ -739,7 +741,7 @@ namespace libtorrent { namespace dht
|
|||
bind(&dht_tracker::on_name_lookup, self(), _1, _2));
|
||||
}
|
||||
|
||||
void dht_tracker::on_name_lookup(asio::error_code const& e
|
||||
void dht_tracker::on_name_lookup(error_code const& e
|
||||
, udp::resolver::iterator host) try
|
||||
{
|
||||
if (e || host == udp::resolver::iterator()) return;
|
||||
|
@ -757,7 +759,7 @@ namespace libtorrent { namespace dht
|
|||
bind(&dht_tracker::on_router_name_lookup, self(), _1, _2));
|
||||
}
|
||||
|
||||
void dht_tracker::on_router_name_lookup(asio::error_code const& e
|
||||
void dht_tracker::on_router_name_lookup(error_code const& e
|
||||
, udp::resolver::iterator host) try
|
||||
{
|
||||
if (e || host == udp::resolver::iterator()) return;
|
||||
|
@ -809,9 +811,6 @@ namespace libtorrent { namespace dht
|
|||
p.list().push_back(entry(endpoint));
|
||||
}
|
||||
}
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " nodes: " << m.nodes.size();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -828,9 +827,10 @@ namespace libtorrent { namespace dht
|
|||
e["v"] = std::string(version_str, version_str + 4);
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << time_now_string()
|
||||
<< " SENDING [" << m.addr << "]:";
|
||||
TORRENT_LOG(dht_tracker) << " transaction: " << m.transaction_id;
|
||||
std::stringstream log_line;
|
||||
log_line << time_now_string()
|
||||
<< " SENDING [ ip: " << m.addr
|
||||
<< " t: " << to_hex(m.transaction_id);
|
||||
#endif
|
||||
|
||||
if (m.message_id == messages::error)
|
||||
|
@ -843,8 +843,8 @@ namespace libtorrent { namespace dht
|
|||
error_list.list().push_back(entry(m.error_msg));
|
||||
e["e"] = error_list;
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << time_now_string()
|
||||
<< " outgoing error: " << m.error_code << " " << m.error_msg;
|
||||
log_line << " err: " << m.error_code
|
||||
<< " msg: " << m.error_msg;
|
||||
#endif
|
||||
}
|
||||
else if (m.reply)
|
||||
|
@ -855,8 +855,7 @@ namespace libtorrent { namespace dht
|
|||
r["id"] = std::string(m.id.begin(), m.id.end());
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << time_now_string()
|
||||
<< " reply: " << messages::ids[m.message_id];
|
||||
log_line << " r: " << messages::ids[m.message_id];
|
||||
#endif
|
||||
|
||||
if (m.write_token.type() != entry::undefined_t)
|
||||
|
@ -892,7 +891,7 @@ namespace libtorrent { namespace dht
|
|||
p.list().push_back(entry(endpoint));
|
||||
}
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size();
|
||||
log_line << " p: " << m.peers.size();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -916,8 +915,7 @@ namespace libtorrent { namespace dht
|
|||
e["q"] = messages::ids[m.message_id];
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " query: "
|
||||
<< messages::ids[m.message_id];
|
||||
log_line << " q: " << messages::ids[m.message_id];
|
||||
#endif
|
||||
|
||||
switch (m.message_id)
|
||||
|
@ -926,8 +924,7 @@ namespace libtorrent { namespace dht
|
|||
{
|
||||
a["target"] = std::string(m.info_hash.begin(), m.info_hash.end());
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " target: "
|
||||
<< boost::lexical_cast<std::string>(m.info_hash);
|
||||
log_line << " target: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -935,8 +932,7 @@ namespace libtorrent { namespace dht
|
|||
{
|
||||
a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end());
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker) << " info_hash: "
|
||||
<< boost::lexical_cast<std::string>(m.info_hash);
|
||||
log_line << " ih: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -945,9 +941,8 @@ namespace libtorrent { namespace dht
|
|||
a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end());
|
||||
a["token"] = m.write_token;
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(dht_tracker)
|
||||
<< " port: " << m.port
|
||||
<< " info_hash: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||
log_line << " p: " << m.port
|
||||
<< " ih: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||
#endif
|
||||
break;
|
||||
default: break;
|
||||
|
@ -957,7 +952,7 @@ namespace libtorrent { namespace dht
|
|||
|
||||
m_send_buf.clear();
|
||||
bencode(std::back_inserter(m_send_buf), e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_sock.send(m.addr, &m_send_buf[0], (int)m_send_buf.size(), ec);
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
|
@ -972,7 +967,7 @@ namespace libtorrent { namespace dht
|
|||
{
|
||||
m_queries_out_bytes += m_send_buf.size();
|
||||
}
|
||||
TORRENT_LOG(dht_tracker) << e;
|
||||
TORRENT_LOG(dht_tracker) << log_line.str() << " ]";
|
||||
#endif
|
||||
|
||||
if (!m.piggy_backed_ping) return;
|
||||
|
|
|
@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <libtorrent/kademlia/routing_table.hpp>
|
||||
#include <libtorrent/kademlia/rpc_manager.hpp>
|
||||
#include <libtorrent/io.hpp>
|
||||
#include <libtorrent/socket.hpp>
|
||||
|
||||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
@ -101,7 +102,7 @@ find_data::find_data(
|
|||
add_requests();
|
||||
}
|
||||
|
||||
void find_data::invoke(node_id const& id, asio::ip::udp::endpoint addr)
|
||||
void find_data::invoke(node_id const& id, udp::endpoint addr)
|
||||
{
|
||||
if (m_done)
|
||||
{
|
||||
|
|
|
@ -65,8 +65,6 @@ namespace
|
|||
// TODO: configurable?
|
||||
enum { announce_interval = 30 };
|
||||
|
||||
using asio::ip::udp;
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_DEFINE_LOG(node)
|
||||
#endif
|
||||
|
@ -245,6 +243,11 @@ void node_impl::refresh_bucket(int bucket) try
|
|||
}
|
||||
catch (std::exception&) {}
|
||||
|
||||
void node_impl::unreachable(udp::endpoint const& ep)
|
||||
{
|
||||
m_rpc.unreachable(ep);
|
||||
}
|
||||
|
||||
void node_impl::incoming(msg const& m)
|
||||
{
|
||||
if (m_rpc.incoming(m))
|
||||
|
@ -269,6 +272,9 @@ namespace
|
|||
for (std::vector<node_entry>::const_iterator i = v.begin()
|
||||
, end(v.end()); i != end; ++i)
|
||||
{
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(node) << " distance: " << (160 - distance_exp(ih, i->id));
|
||||
#endif
|
||||
observer_ptr o(new (rpc.allocator().malloc()) get_peers_observer(ih, listen_port, rpc, f));
|
||||
#ifndef NDEBUG
|
||||
o->m_in_constructor = false;
|
||||
|
|
|
@ -47,8 +47,6 @@ using boost::bind;
|
|||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
||||
using asio::ip::udp;
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_DEFINE_LOG(refresh)
|
||||
#endif
|
||||
|
|
|
@ -50,8 +50,9 @@ using boost::uint8_t;
|
|||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
||||
using asio::ip::udp;
|
||||
typedef asio::ip::address_v4 address;
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_DEFINE_LOG(table)
|
||||
#endif
|
||||
|
||||
routing_table::routing_table(node_id const& id, int bucket_size
|
||||
, dht_settings const& settings)
|
||||
|
@ -225,6 +226,15 @@ void routing_table::node_failed(node_id const& id)
|
|||
if (rb.empty())
|
||||
{
|
||||
++i->fail_count;
|
||||
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(table) << " NODE FAILED"
|
||||
" id: " << id <<
|
||||
" ip: " << i->addr <<
|
||||
" fails: " << i->fail_count <<
|
||||
" up-time: " << total_seconds(time_now() - i->first_seen);
|
||||
#endif
|
||||
|
||||
if (i->fail_count >= m_settings.max_fail_count)
|
||||
{
|
||||
b.erase(i);
|
||||
|
|
|
@ -159,6 +159,39 @@ void rpc_manager::check_invariant() const
|
|||
}
|
||||
#endif
|
||||
|
||||
void rpc_manager::unreachable(udp::endpoint const& ep)
|
||||
{
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(rpc) << time_now_string() << " PORT_UNREACHABLE [ ip: " << ep << " ]";
|
||||
#endif
|
||||
int num_active = m_oldest_transaction_id < m_next_transaction_id
|
||||
? m_next_transaction_id - m_oldest_transaction_id
|
||||
: max_transactions - m_next_transaction_id + m_oldest_transaction_id;
|
||||
TORRENT_ASSERT((m_oldest_transaction_id + num_active) % max_transactions
|
||||
== m_next_transaction_id);
|
||||
int tid = m_oldest_transaction_id;
|
||||
for (int i = 0; i < num_active; ++i, ++tid)
|
||||
{
|
||||
if (tid >= max_transactions) tid = 0;
|
||||
observer_ptr const& o = m_transactions[tid];
|
||||
if (!o) continue;
|
||||
if (o->target_addr != ep) continue;
|
||||
observer_ptr ptr = m_transactions[tid];
|
||||
m_transactions[tid] = 0;
|
||||
if (tid == m_oldest_transaction_id)
|
||||
{
|
||||
++m_oldest_transaction_id;
|
||||
if (m_oldest_transaction_id >= max_transactions)
|
||||
m_oldest_transaction_id = 0;
|
||||
}
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(rpc) << " found transaction [ tid: " << tid << " ]";
|
||||
#endif
|
||||
ptr->timeout();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool rpc_manager::incoming(msg const& m)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
|
|
@ -39,7 +39,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/bind.hpp>
|
||||
|
||||
using boost::bind;
|
||||
using asio::ip::udp;
|
||||
|
||||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
@ -89,7 +88,8 @@ boost::pool<>& traversal_algorithm::allocator() const
|
|||
void traversal_algorithm::traverse(node_id const& id, udp::endpoint addr)
|
||||
{
|
||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||
TORRENT_LOG(traversal) << "node returned a list which included a node with id 0";
|
||||
if (id.is_all_zeros())
|
||||
TORRENT_LOG(traversal) << time_now_string() << " WARNING: node returned a list which included a node with id 0";
|
||||
#endif
|
||||
add_entry(id, addr, 0);
|
||||
}
|
||||
|
|
|
@ -187,6 +187,7 @@ namespace libtorrent
|
|||
std::pair<char const*, lazy_entry>* tmp = new (std::nothrow) std::pair<char const*, lazy_entry>[capacity];
|
||||
if (tmp == 0) return 0;
|
||||
std::memcpy(tmp, m_data.dict, sizeof(std::pair<char const*, lazy_entry>) * m_size);
|
||||
for (int i = 0; i < m_size; ++i) m_data.dict[i].second.release();
|
||||
delete[] m_data.dict;
|
||||
m_data.dict = tmp;
|
||||
m_capacity = capacity;
|
||||
|
@ -299,6 +300,7 @@ namespace libtorrent
|
|||
lazy_entry* tmp = new (std::nothrow) lazy_entry[capacity];
|
||||
if (tmp == 0) return 0;
|
||||
std::memcpy(tmp, m_data.list, sizeof(lazy_entry) * m_size);
|
||||
for (int i = 0; i < m_size; ++i) m_data.list[i].release();
|
||||
delete[] m_data.list;
|
||||
m_data.list = tmp;
|
||||
m_capacity = capacity;
|
||||
|
@ -330,6 +332,7 @@ namespace libtorrent
|
|||
case dict_t: delete[] m_data.dict; break;
|
||||
default: break;
|
||||
}
|
||||
m_data.start = 0;
|
||||
m_size = 0;
|
||||
m_capacity = 0;
|
||||
m_type = none_t;
|
||||
|
@ -370,7 +373,8 @@ namespace libtorrent
|
|||
bool one_liner = (e.list_size() == 0
|
||||
|| e.list_at(0)->type() == lazy_entry::int_t
|
||||
|| (e.list_at(0)->type() == lazy_entry::string_t
|
||||
&& e.list_at(0)->string_length() < 10))
|
||||
&& (e.list_at(0)->string_length() < 10
|
||||
|| e.list_size() < 2)))
|
||||
&& e.list_size() < 5;
|
||||
if (!one_liner) os << "\n";
|
||||
for (int i = 0; i < e.list_size(); ++i)
|
||||
|
@ -388,7 +392,7 @@ namespace libtorrent
|
|||
bool one_liner = (e.dict_size() == 0
|
||||
|| e.dict_at(0).second->type() == lazy_entry::int_t
|
||||
|| (e.dict_at(0).second->type() == lazy_entry::string_t
|
||||
&& e.dict_at(0).second->string_length() < 10)
|
||||
&& e.dict_at(0).second->string_length() < 30)
|
||||
|| e.dict_at(0).first.size() < 10)
|
||||
&& e.dict_size() < 5;
|
||||
|
||||
|
|
|
@ -40,8 +40,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/ip/host_name.hpp>
|
||||
#include <asio/ip/multicast.hpp>
|
||||
#else
|
||||
#include <boost/asio/ip/host_name.hpp>
|
||||
#include <boost/asio/ip/multicast.hpp>
|
||||
#endif
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <cstdlib>
|
||||
#include <boost/config.hpp>
|
||||
|
@ -52,7 +57,7 @@ using namespace libtorrent;
|
|||
namespace libtorrent
|
||||
{
|
||||
// defined in broadcast_socket.cpp
|
||||
address guess_local_address(asio::io_service&);
|
||||
address guess_local_address(io_service&);
|
||||
}
|
||||
|
||||
lsd::lsd(io_service& ios, address const& listen_interface
|
||||
|
@ -84,7 +89,7 @@ void lsd::announce(sha1_hash const& ih, int listen_port)
|
|||
std::string const& msg = btsearch.str();
|
||||
|
||||
m_retry_count = 1;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket.send(msg.c_str(), int(msg.size()), ec);
|
||||
if (ec)
|
||||
{
|
||||
|
@ -101,11 +106,11 @@ void lsd::announce(sha1_hash const& ih, int listen_port)
|
|||
m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
|
||||
}
|
||||
|
||||
void lsd::resend_announce(asio::error_code const& e, std::string msg)
|
||||
void lsd::resend_announce(error_code const& e, std::string msg)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket.send(msg.c_str(), int(msg.size()), ec);
|
||||
|
||||
++m_retry_count;
|
||||
|
@ -192,7 +197,7 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
|
|||
void lsd::close()
|
||||
{
|
||||
m_socket.close();
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_broadcast_timer.cancel(ec);
|
||||
m_disabled = true;
|
||||
m_callback.clear();
|
||||
|
|
|
@ -47,6 +47,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/utility.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#if BOOST_VERSION >= 103500
|
||||
#include <boost/system/error_code.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
|
@ -57,8 +62,10 @@ using boost::iostreams::mapped_file_params;
|
|||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
#if BOOST_VERSION >= 103500
|
||||
using boost::system::error_code;
|
||||
#endif
|
||||
|
||||
struct mapped_file_pool
|
||||
{
|
||||
|
@ -78,7 +85,7 @@ namespace libtorrent
|
|||
#ifndef NDEBUG
|
||||
if (file_size > 0)
|
||||
{
|
||||
fs::system_error_type ec;
|
||||
error_code ec;
|
||||
fs::file_status st = fs::status(path, ec);
|
||||
TORRENT_ASSERT(!fs::exists(st));
|
||||
}
|
||||
|
@ -197,7 +204,11 @@ namespace libtorrent
|
|||
size_type start = (offset / view_size) * view_size;
|
||||
TORRENT_ASSERT(start + view_size >= offset + length);
|
||||
|
||||
#if BOOST_VERSION < 103500
|
||||
fs::system_error_type ec;
|
||||
#else
|
||||
error_code ec;
|
||||
#endif
|
||||
fs::file_status st = fs::status(p, ec);
|
||||
|
||||
m_files.push_back(file_entry());
|
||||
|
|
|
@ -55,6 +55,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/extensions.hpp"
|
||||
#include "libtorrent/extensions/metadata_transfer.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/buffer.hpp"
|
||||
|
||||
namespace libtorrent { namespace
|
||||
{
|
||||
|
@ -107,40 +108,37 @@ namespace libtorrent { namespace
|
|||
|
||||
virtual void on_files_checked()
|
||||
{
|
||||
// if the torrent is a seed, copy the metadata from
|
||||
// the torrent before it is deallocated
|
||||
if (m_torrent.is_seed())
|
||||
metadata();
|
||||
// if the torrent is a seed, make a reference to
|
||||
// the metadata from the torrent before it is deallocated
|
||||
if (m_torrent.is_seed()) metadata();
|
||||
}
|
||||
|
||||
virtual boost::shared_ptr<peer_plugin> new_connection(
|
||||
peer_connection* pc);
|
||||
|
||||
std::vector<char> const& metadata() const
|
||||
buffer::const_interval metadata() const
|
||||
{
|
||||
if (m_metadata.empty())
|
||||
if (!m_metadata)
|
||||
{
|
||||
bencode(std::back_inserter(m_metadata)
|
||||
, m_torrent.torrent_file().create_info_metadata());
|
||||
|
||||
TORRENT_ASSERT(hasher(&m_metadata[0], m_metadata.size()).final()
|
||||
m_metadata = m_torrent.torrent_file().metadata();
|
||||
m_metadata_size = m_torrent.torrent_file().metadata_size();
|
||||
TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final()
|
||||
== m_torrent.torrent_file().info_hash());
|
||||
}
|
||||
TORRENT_ASSERT(!m_metadata.empty());
|
||||
return m_metadata;
|
||||
return buffer::const_interval(m_metadata.get(), m_metadata.get()
|
||||
+ m_metadata_size);
|
||||
}
|
||||
|
||||
bool received_metadata(char const* buf, int size, int offset, int total_size)
|
||||
{
|
||||
if (m_torrent.valid_metadata()) return false;
|
||||
|
||||
if ((int)m_metadata.size() < total_size)
|
||||
m_metadata.resize(total_size);
|
||||
|
||||
std::copy(
|
||||
buf
|
||||
, buf + size
|
||||
, &m_metadata[offset]);
|
||||
if (!m_metadata || m_metadata_size < total_size)
|
||||
{
|
||||
m_metadata.reset(new char[total_size]);
|
||||
m_metadata_size = total_size;
|
||||
}
|
||||
std::copy(buf, buf + size, &m_metadata[offset]);
|
||||
|
||||
if (m_have_metadata.empty())
|
||||
m_have_metadata.resize(256, false);
|
||||
|
@ -163,7 +161,7 @@ namespace libtorrent { namespace
|
|||
if (!have_all) return false;
|
||||
|
||||
hasher h;
|
||||
h.update(&m_metadata[0], (int)m_metadata.size());
|
||||
h.update(&m_metadata[0], m_metadata_size);
|
||||
sha1_hash info_hash = h.final();
|
||||
|
||||
if (info_hash != m_torrent.torrent_file().info_hash())
|
||||
|
@ -184,9 +182,10 @@ namespace libtorrent { namespace
|
|||
return false;
|
||||
}
|
||||
|
||||
entry metadata = bdecode(m_metadata.begin(), m_metadata.end());
|
||||
lazy_entry e;
|
||||
lazy_bdecode(m_metadata.get(), m_metadata.get() + m_metadata_size, e);
|
||||
std::string error;
|
||||
if (!m_torrent.set_metadata(metadata, error))
|
||||
if (!m_torrent.set_metadata(e, error))
|
||||
{
|
||||
// this means the metadata is correct, since we
|
||||
// verified it against the info-hash, but we
|
||||
|
@ -240,10 +239,10 @@ namespace libtorrent { namespace
|
|||
// the metadata file while downloading it from
|
||||
// peers, and while sending it.
|
||||
// it is mutable because it's generated lazily
|
||||
mutable std::vector<char> m_metadata;
|
||||
mutable boost::shared_array<char> m_metadata;
|
||||
|
||||
int m_metadata_progress;
|
||||
int m_metadata_size;
|
||||
mutable int m_metadata_size;
|
||||
|
||||
// this is a bitfield of size 256, each bit represents
|
||||
// a piece of the metadata. It is set to one if we
|
||||
|
@ -333,7 +332,7 @@ namespace libtorrent { namespace
|
|||
if (m_torrent.valid_metadata() && !m_torrent.torrent_file().priv())
|
||||
{
|
||||
std::pair<int, int> offset
|
||||
= req_to_offset(req, (int)m_tp.metadata().size());
|
||||
= req_to_offset(req, (int)m_tp.metadata().left());
|
||||
|
||||
buffer::interval i = m_pc.allocate_send_buffer(15 + offset.second);
|
||||
|
||||
|
@ -343,11 +342,11 @@ namespace libtorrent { namespace
|
|||
detail::write_uint8(m_message_index, i.begin);
|
||||
// means 'data packet'
|
||||
detail::write_uint8(1, i.begin);
|
||||
detail::write_uint32((int)m_tp.metadata().size(), i.begin);
|
||||
detail::write_uint32((int)m_tp.metadata().left(), i.begin);
|
||||
detail::write_uint32(offset.first, i.begin);
|
||||
std::vector<char> const& metadata = m_tp.metadata();
|
||||
std::copy(metadata.begin() + offset.first
|
||||
, metadata.begin() + offset.first + offset.second, i.begin);
|
||||
char const* metadata = m_tp.metadata().begin;
|
||||
std::copy(metadata + offset.first
|
||||
, metadata + offset.first + offset.second, i.begin);
|
||||
i.begin += offset.second;
|
||||
TORRENT_ASSERT(i.begin == i.end);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/pch.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/ip/host_name.hpp>
|
||||
#else
|
||||
#include <boost/asio/ip/host_name.hpp>
|
||||
#endif
|
||||
|
||||
#include "libtorrent/natpmp.hpp"
|
||||
#include "libtorrent/io.hpp"
|
||||
|
@ -63,7 +67,7 @@ void natpmp::rebind(address const& listen_interface)
|
|||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
address gateway = get_default_gateway(m_socket.get_io_service(), ec);
|
||||
if (ec)
|
||||
{
|
||||
|
@ -198,7 +202,7 @@ void natpmp::try_next_mapping(int i)
|
|||
{
|
||||
if (m_abort)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_send_timer.cancel(ec);
|
||||
m_socket.close(ec);
|
||||
}
|
||||
|
@ -264,7 +268,7 @@ void natpmp::send_map_request(int i)
|
|||
<< " ttl: " << ttl << " ]" << std::endl;
|
||||
#endif
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint, 0, ec);
|
||||
// linear back-off instead of exponential
|
||||
++m_retry_count;
|
||||
|
@ -272,7 +276,7 @@ void natpmp::send_map_request(int i)
|
|||
m_send_timer.async_wait(bind(&natpmp::resend_request, self(), i, _1));
|
||||
}
|
||||
|
||||
void natpmp::resend_request(int i, asio::error_code const& e)
|
||||
void natpmp::resend_request(int i, error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
|
@ -290,7 +294,7 @@ void natpmp::resend_request(int i, asio::error_code const& e)
|
|||
send_map_request(i);
|
||||
}
|
||||
|
||||
void natpmp::on_reply(asio::error_code const& e
|
||||
void natpmp::on_reply(error_code const& e
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
using namespace libtorrent::detail;
|
||||
|
@ -305,7 +309,7 @@ void natpmp::on_reply(asio::error_code const& e
|
|||
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_send_timer.cancel(ec);
|
||||
|
||||
TORRENT_ASSERT(m_currently_mapping >= 0);
|
||||
|
@ -439,7 +443,7 @@ void natpmp::update_expiration_timer()
|
|||
<< " ttl: " << total_seconds(min_expire - time_now())
|
||||
<< " ]" << std::endl;
|
||||
#endif
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
if (m_next_refresh >= 0) m_refresh_timer.cancel(ec);
|
||||
m_refresh_timer.expires_from_now(min_expire - now, ec);
|
||||
m_refresh_timer.async_wait(bind(&natpmp::mapping_expired, self(), _1, min_index));
|
||||
|
@ -447,7 +451,7 @@ void natpmp::update_expiration_timer()
|
|||
}
|
||||
}
|
||||
|
||||
void natpmp::mapping_expired(asio::error_code const& e, int i)
|
||||
void natpmp::mapping_expired(error_code const& e, int i)
|
||||
{
|
||||
if (e) return;
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
@ -463,7 +467,7 @@ void natpmp::close()
|
|||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
m_abort = true;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string() << " close" << std::endl;
|
||||
#endif
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace libtorrent
|
|||
session_impl& ses
|
||||
, boost::weak_ptr<torrent> tor
|
||||
, shared_ptr<socket_type> s
|
||||
, tcp::endpoint const& remote
|
||||
, tcp::endpoint const& endp
|
||||
, policy::peer* peerinfo)
|
||||
:
|
||||
#ifndef NDEBUG
|
||||
|
@ -73,41 +73,28 @@ namespace libtorrent
|
|||
#endif
|
||||
m_ses(ses)
|
||||
, m_max_out_request_queue(m_ses.settings().max_out_request_queue)
|
||||
, m_timeout(m_ses.settings().peer_timeout)
|
||||
, m_last_piece(time_now())
|
||||
, m_last_request(time_now())
|
||||
, m_last_incoming_request(min_time())
|
||||
, m_last_unchoke(min_time())
|
||||
, m_last_receive(time_now())
|
||||
, m_last_sent(time_now())
|
||||
, m_remote_dl_update(time_now())
|
||||
, m_became_uninterested(time_now())
|
||||
, m_became_uninteresting(time_now())
|
||||
, m_free_upload(0)
|
||||
, m_downloaded_at_last_unchoke(0)
|
||||
, m_disk_recv_buffer(ses, 0)
|
||||
, m_socket(s)
|
||||
, m_remote(endp)
|
||||
, m_torrent(tor)
|
||||
, m_num_pieces(0)
|
||||
, m_timeout(m_ses.settings().peer_timeout)
|
||||
, m_packet_size(0)
|
||||
, m_recv_pos(0)
|
||||
, m_disk_recv_buffer_size(0)
|
||||
, m_disk_recv_buffer(0)
|
||||
, m_reading_bytes(0)
|
||||
, m_last_receive(time_now())
|
||||
, m_last_sent(time_now())
|
||||
, m_socket(s)
|
||||
, m_remote(remote)
|
||||
, m_torrent(tor)
|
||||
, m_active(true)
|
||||
, m_peer_interested(false)
|
||||
, m_peer_choked(true)
|
||||
, m_interesting(false)
|
||||
, m_choked(true)
|
||||
, m_failed(false)
|
||||
, m_ignore_bandwidth_limits(false)
|
||||
, m_have_all(false)
|
||||
, m_num_pieces(0)
|
||||
, m_desired_queue_size(2)
|
||||
, m_free_upload(0)
|
||||
, m_assume_fifo(false)
|
||||
, m_num_invalid_requests(0)
|
||||
, m_disconnecting(false)
|
||||
, m_became_uninterested(time_now())
|
||||
, m_became_uninteresting(time_now())
|
||||
, m_connecting(true)
|
||||
, m_queued(true)
|
||||
, m_prefer_whole_pieces(false)
|
||||
, m_request_large_blocks(false)
|
||||
, m_priority(1)
|
||||
, m_upload_limit(bandwidth_limit::inf)
|
||||
, m_download_limit(bandwidth_limit::inf)
|
||||
|
@ -116,13 +103,27 @@ namespace libtorrent
|
|||
, m_connection_ticket(-1)
|
||||
, m_remote_bytes_dled(0)
|
||||
, m_remote_dl_rate(0)
|
||||
, m_remote_dl_update(time_now())
|
||||
, m_outstanding_writing_bytes(0)
|
||||
, m_fast_reconnect(false)
|
||||
, m_rtt(0)
|
||||
, m_downloaded_at_last_unchoke(0)
|
||||
, m_download_rate_peak(0)
|
||||
, m_upload_rate_peak(0)
|
||||
, m_rtt(0)
|
||||
, m_prefer_whole_pieces(0)
|
||||
, m_desired_queue_size(2)
|
||||
, m_fast_reconnect(false)
|
||||
, m_active(true)
|
||||
, m_peer_interested(false)
|
||||
, m_peer_choked(true)
|
||||
, m_interesting(false)
|
||||
, m_choked(true)
|
||||
, m_failed(false)
|
||||
, m_ignore_bandwidth_limits(false)
|
||||
, m_have_all(false)
|
||||
, m_assume_fifo(false)
|
||||
, m_disconnecting(false)
|
||||
, m_connecting(true)
|
||||
, m_queued(true)
|
||||
, m_request_large_blocks(false)
|
||||
, m_upload_only(false)
|
||||
#ifndef NDEBUG
|
||||
, m_in_constructor(true)
|
||||
#endif
|
||||
|
@ -164,6 +165,7 @@ namespace libtorrent
|
|||
peer_connection::peer_connection(
|
||||
session_impl& ses
|
||||
, boost::shared_ptr<socket_type> s
|
||||
, tcp::endpoint const& endp
|
||||
, policy::peer* peerinfo)
|
||||
:
|
||||
#ifndef NDEBUG
|
||||
|
@ -172,39 +174,27 @@ namespace libtorrent
|
|||
#endif
|
||||
m_ses(ses)
|
||||
, m_max_out_request_queue(m_ses.settings().max_out_request_queue)
|
||||
, m_timeout(m_ses.settings().peer_timeout)
|
||||
, m_last_piece(time_now())
|
||||
, m_last_request(time_now())
|
||||
, m_last_incoming_request(min_time())
|
||||
, m_last_unchoke(min_time())
|
||||
, m_last_receive(time_now())
|
||||
, m_last_sent(time_now())
|
||||
, m_remote_dl_update(time_now())
|
||||
, m_became_uninterested(time_now())
|
||||
, m_became_uninteresting(time_now())
|
||||
, m_free_upload(0)
|
||||
, m_downloaded_at_last_unchoke(0)
|
||||
, m_disk_recv_buffer(ses, 0)
|
||||
, m_socket(s)
|
||||
, m_remote(endp)
|
||||
, m_num_pieces(0)
|
||||
, m_timeout(m_ses.settings().peer_timeout)
|
||||
, m_packet_size(0)
|
||||
, m_recv_pos(0)
|
||||
, m_disk_recv_buffer_size(0)
|
||||
, m_disk_recv_buffer(0)
|
||||
, m_reading_bytes(0)
|
||||
, m_last_receive(time_now())
|
||||
, m_last_sent(time_now())
|
||||
, m_socket(s)
|
||||
, m_active(false)
|
||||
, m_peer_interested(false)
|
||||
, m_peer_choked(true)
|
||||
, m_interesting(false)
|
||||
, m_choked(true)
|
||||
, m_failed(false)
|
||||
, m_ignore_bandwidth_limits(false)
|
||||
, m_have_all(false)
|
||||
, m_num_pieces(0)
|
||||
, m_desired_queue_size(2)
|
||||
, m_free_upload(0)
|
||||
, m_assume_fifo(false)
|
||||
, m_num_invalid_requests(0)
|
||||
, m_disconnecting(false)
|
||||
, m_became_uninterested(time_now())
|
||||
, m_became_uninteresting(time_now())
|
||||
, m_connecting(false)
|
||||
, m_queued(false)
|
||||
, m_prefer_whole_pieces(false)
|
||||
, m_request_large_blocks(false)
|
||||
, m_priority(1)
|
||||
, m_upload_limit(bandwidth_limit::inf)
|
||||
, m_download_limit(bandwidth_limit::inf)
|
||||
|
@ -213,13 +203,27 @@ namespace libtorrent
|
|||
, m_connection_ticket(-1)
|
||||
, m_remote_bytes_dled(0)
|
||||
, m_remote_dl_rate(0)
|
||||
, m_remote_dl_update(time_now())
|
||||
, m_outstanding_writing_bytes(0)
|
||||
, m_fast_reconnect(false)
|
||||
, m_rtt(0)
|
||||
, m_downloaded_at_last_unchoke(0)
|
||||
, m_download_rate_peak(0)
|
||||
, m_upload_rate_peak(0)
|
||||
, m_rtt(0)
|
||||
, m_prefer_whole_pieces(0)
|
||||
, m_desired_queue_size(2)
|
||||
, m_fast_reconnect(false)
|
||||
, m_active(false)
|
||||
, m_peer_interested(false)
|
||||
, m_peer_choked(true)
|
||||
, m_interesting(false)
|
||||
, m_choked(true)
|
||||
, m_failed(false)
|
||||
, m_ignore_bandwidth_limits(false)
|
||||
, m_have_all(false)
|
||||
, m_assume_fifo(false)
|
||||
, m_disconnecting(false)
|
||||
, m_connecting(false)
|
||||
, m_queued(false)
|
||||
, m_request_large_blocks(false)
|
||||
, m_upload_only(false)
|
||||
#ifndef NDEBUG
|
||||
, m_in_constructor(true)
|
||||
#endif
|
||||
|
@ -243,8 +247,8 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
asio::error_code ec;
|
||||
TORRENT_ASSERT(m_socket->remote_endpoint() == remote() || ec);
|
||||
error_code ec;
|
||||
TORRENT_ASSERT(m_socket->remote_endpoint(ec) == m_remote || ec);
|
||||
m_logger = m_ses.create_log(remote().address().to_string(ec) + "_"
|
||||
+ boost::lexical_cast<std::string>(remote().port()), m_ses.listen_port());
|
||||
(*m_logger) << "*** INCOMING CONNECTION\n";
|
||||
|
@ -286,12 +290,13 @@ namespace libtorrent
|
|||
|
||||
void peer_connection::start()
|
||||
{
|
||||
TORRENT_ASSERT(m_peer_info == 0 || m_peer_info->connection == this);
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
|
||||
if (!t)
|
||||
{
|
||||
tcp::socket::non_blocking_io ioc(true);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket->io_control(ioc, ec);
|
||||
if (ec)
|
||||
{
|
||||
|
@ -439,7 +444,7 @@ namespace libtorrent
|
|||
// if this is a web seed. we don't have a peer_info struct
|
||||
if (m_peer_info) m_peer_info->seed = true;
|
||||
// if we're a seed too, disconnect
|
||||
if (t->is_finished())
|
||||
if (t->is_finished() && m_ses.settings().close_redundant_connections)
|
||||
{
|
||||
disconnect("seed to seed connection redundant");
|
||||
return;
|
||||
|
@ -476,12 +481,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(!m_in_constructor);
|
||||
TORRENT_ASSERT(m_disconnecting);
|
||||
|
||||
if (m_disk_recv_buffer)
|
||||
{
|
||||
m_ses.free_disk_buffer(m_disk_recv_buffer);
|
||||
m_disk_recv_buffer = 0;
|
||||
m_disk_recv_buffer_size = 0;
|
||||
}
|
||||
m_disk_recv_buffer_size = 0;
|
||||
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
if (m_logger)
|
||||
|
@ -616,6 +616,7 @@ namespace libtorrent
|
|||
#endif
|
||||
}
|
||||
#endif
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
if (peer_info_struct())
|
||||
{
|
||||
|
@ -701,7 +702,7 @@ namespace libtorrent
|
|||
(*m_logger) << " " << i->second->torrent_file().info_hash() << "\n";
|
||||
}
|
||||
#endif
|
||||
disconnect("got invalid info-hash");
|
||||
disconnect("got invalid info-hash", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -785,6 +786,7 @@ namespace libtorrent
|
|||
if ((*i)->on_choke()) return;
|
||||
}
|
||||
#endif
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " <== CHOKE\n";
|
||||
|
@ -838,6 +840,8 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
std::deque<piece_block>::iterator i = std::find_if(
|
||||
m_download_queue.begin(), m_download_queue.end()
|
||||
, bind(match_request, boost::cref(r), _1, t->block_size()));
|
||||
|
@ -921,6 +925,7 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
if (is_disconnecting()) return;
|
||||
if (t->have_piece(index)) return;
|
||||
|
||||
if (m_suggested_pieces.size() > 9)
|
||||
|
@ -956,6 +961,8 @@ namespace libtorrent
|
|||
(*m_logger) << time_now_string() << " <== UNCHOKE\n";
|
||||
#endif
|
||||
m_peer_choked = false;
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
t->get_policy().unchoked(*this);
|
||||
}
|
||||
|
||||
|
@ -982,6 +989,7 @@ namespace libtorrent
|
|||
(*m_logger) << time_now_string() << " <== INTERESTED\n";
|
||||
#endif
|
||||
m_peer_interested = true;
|
||||
if (is_disconnecting()) return;
|
||||
t->get_policy().interested(*this);
|
||||
}
|
||||
|
||||
|
@ -1006,11 +1014,12 @@ namespace libtorrent
|
|||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " <== NOT_INTERESTED\n";
|
||||
#endif
|
||||
m_peer_interested = false;
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
TORRENT_ASSERT(t);
|
||||
|
||||
m_peer_interested = false;
|
||||
t->get_policy().not_interested(*this);
|
||||
}
|
||||
|
||||
|
@ -1033,6 +1042,8 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " <== HAVE [ piece: " << index << "]\n";
|
||||
|
@ -1059,7 +1070,7 @@ namespace libtorrent
|
|||
// if we got an invalid message, abort
|
||||
if (index >= int(m_have_piece.size()) || index < 0)
|
||||
{
|
||||
disconnect("got 'have'-message with higher index than the number of pieces");
|
||||
disconnect("got 'have'-message with higher index than the number of pieces", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1099,11 +1110,11 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
if (is_seed())
|
||||
if (upload_only())
|
||||
{
|
||||
TORRENT_ASSERT(m_peer_info);
|
||||
m_peer_info->seed = true;
|
||||
if (t->is_finished())
|
||||
if (is_seed()) m_peer_info->seed = true;
|
||||
if (t->is_finished() && m_ses.settings().close_redundant_connections)
|
||||
{
|
||||
disconnect("seed to seed connection redundant");
|
||||
return;
|
||||
|
@ -1131,6 +1142,8 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " <== BITFIELD ";
|
||||
|
||||
|
@ -1151,7 +1164,7 @@ namespace libtorrent
|
|||
msg << "got bitfield with invalid size: " << (bitfield.size() / 8)
|
||||
<< "bytes. expected: " << (m_have_piece.size() / 8)
|
||||
<< " bytes";
|
||||
disconnect(msg.str().c_str());
|
||||
disconnect(msg.str().c_str(), 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1178,7 +1191,7 @@ namespace libtorrent
|
|||
// if this is a web seed. we don't have a peer_info struct
|
||||
if (m_peer_info) m_peer_info->seed = true;
|
||||
// if we're a seed too, disconnect
|
||||
if (t->is_finished())
|
||||
if (t->is_finished() && m_ses.settings().close_redundant_connections)
|
||||
{
|
||||
disconnect("seed to seed connection redundant, disconnecting");
|
||||
return;
|
||||
|
@ -1220,6 +1233,7 @@ namespace libtorrent
|
|||
m_num_pieces = num_pieces;
|
||||
|
||||
if (interesting) t->get_policy().peer_is_interesting(*this);
|
||||
else if (upload_only()) disconnect("upload to upload connections");
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
|
@ -1240,6 +1254,7 @@ namespace libtorrent
|
|||
if ((*i)->on_request(r)) return;
|
||||
}
|
||||
#endif
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
if (!t->valid_metadata())
|
||||
{
|
||||
|
@ -1426,7 +1441,7 @@ namespace libtorrent
|
|||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
TORRENT_ASSERT(t);
|
||||
|
||||
TORRENT_ASSERT(m_disk_recv_buffer == 0);
|
||||
TORRENT_ASSERT(!m_disk_recv_buffer);
|
||||
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
|
@ -1436,6 +1451,7 @@ namespace libtorrent
|
|||
if ((*i)->on_piece(p, data)) return;
|
||||
}
|
||||
#endif
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
#ifndef NDEBUG
|
||||
check_postcondition post_checker_(t);
|
||||
|
@ -1461,7 +1477,7 @@ namespace libtorrent
|
|||
"start: " << p.start << " | "
|
||||
"length: " << p.length << " ]\n";
|
||||
#endif
|
||||
disconnect("got invalid piece packet");
|
||||
disconnect("got invalid piece packet", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1648,6 +1664,7 @@ namespace libtorrent
|
|||
if ((*i)->on_cancel(r)) return;
|
||||
}
|
||||
#endif
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
|
@ -1717,6 +1734,7 @@ namespace libtorrent
|
|||
if ((*i)->on_have_all()) return;
|
||||
}
|
||||
#endif
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
m_have_all = true;
|
||||
|
||||
|
@ -1739,7 +1757,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
// if we're a seed too, disconnect
|
||||
if (t->is_finished())
|
||||
if (t->is_finished() && m_ses.settings().close_redundant_connections)
|
||||
{
|
||||
disconnect("seed to seed connection redundant, disconnecting");
|
||||
return;
|
||||
|
@ -1762,13 +1780,13 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
TORRENT_ASSERT(t);
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " <== HAVE_NONE\n";
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
TORRENT_ASSERT(t);
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
|
@ -1776,8 +1794,9 @@ namespace libtorrent
|
|||
if ((*i)->on_have_none()) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is_disconnecting()) return;
|
||||
if (m_peer_info) m_peer_info->seed = false;
|
||||
|
||||
TORRENT_ASSERT(!m_have_piece.empty() || !t->ready_for_connections());
|
||||
}
|
||||
|
||||
|
@ -1803,6 +1822,7 @@ namespace libtorrent
|
|||
if ((*i)->on_allowed_fast(index)) return;
|
||||
}
|
||||
#endif
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
if (index < 0 || index >= int(m_have_piece.size()))
|
||||
{
|
||||
|
@ -2109,6 +2129,7 @@ namespace libtorrent
|
|||
{
|
||||
if (handled = (*i)->write_request(r)) break;
|
||||
}
|
||||
if (is_disconnecting()) return;
|
||||
if (!handled)
|
||||
{
|
||||
write_request(r);
|
||||
|
@ -2141,24 +2162,38 @@ namespace libtorrent
|
|||
(*m_ses.m_logger) << time_now_string() << " CONNECTION TIMED OUT: " << m_remote.address().to_string()
|
||||
<< "\n";
|
||||
#endif
|
||||
set_failed();
|
||||
disconnect("timed out");
|
||||
disconnect("timed out: connect", 1);
|
||||
}
|
||||
|
||||
void peer_connection::disconnect(char const* message)
|
||||
// the error argument defaults to 0, which means deliberate disconnect
|
||||
// 1 means unexpected disconnect/error
|
||||
// 2 protocol error (client sent something invalid)
|
||||
void peer_connection::disconnect(char const* message, int error)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
(*m_logger) << "*** CONNECTION FAILED " << message << "\n";
|
||||
switch (error)
|
||||
{
|
||||
case 0:
|
||||
(*m_logger) << "*** CONNECTION CLOSED " << message << "\n";
|
||||
break;
|
||||
case 1:
|
||||
(*m_logger) << "*** CONNECTION FAILED " << message << "\n";
|
||||
break;
|
||||
case 2:
|
||||
(*m_logger) << "*** PEER ERROR " << message << "\n";
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
// we cannot do this in a constructor
|
||||
TORRENT_ASSERT(m_in_constructor == false);
|
||||
if (error > 0) m_failed = true;
|
||||
if (m_disconnecting) return;
|
||||
boost::intrusive_ptr<peer_connection> me(this);
|
||||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_disconnecting) return;
|
||||
if (m_connecting && m_connection_ticket >= 0)
|
||||
{
|
||||
m_ses.m_half_open.done(m_connection_ticket);
|
||||
|
@ -2167,13 +2202,18 @@ namespace libtorrent
|
|||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
|
||||
if (message && m_ses.m_alerts.should_post(alert::debug))
|
||||
if (message)
|
||||
{
|
||||
m_ses.m_alerts.post_alert(
|
||||
peer_error_alert(
|
||||
remote()
|
||||
, pid()
|
||||
, message));
|
||||
if (error > 1 && m_ses.m_alerts.should_post(alert::info))
|
||||
{
|
||||
m_ses.m_alerts.post_alert(
|
||||
peer_error_alert(remote(), pid(), message));
|
||||
}
|
||||
else if (error <= 1 && m_ses.m_alerts.should_post(alert::debug))
|
||||
{
|
||||
m_ses.m_alerts.post_alert(
|
||||
peer_disconnected_alert(remote(), pid(), message));
|
||||
}
|
||||
}
|
||||
|
||||
if (t)
|
||||
|
@ -2207,7 +2247,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
m_disconnecting = true;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket->close(ec);
|
||||
m_ses.close_connection(this, message);
|
||||
}
|
||||
|
@ -2372,17 +2412,17 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(m_packet_size > 0);
|
||||
TORRENT_ASSERT(m_recv_pos <= m_packet_size - disk_buffer_size);
|
||||
TORRENT_ASSERT(m_disk_recv_buffer == 0);
|
||||
TORRENT_ASSERT(!m_disk_recv_buffer);
|
||||
TORRENT_ASSERT(disk_buffer_size <= 16 * 1024);
|
||||
|
||||
if (disk_buffer_size > 16 * 1024)
|
||||
{
|
||||
disconnect("invalid piece size");
|
||||
disconnect("invalid piece size", 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_disk_recv_buffer = m_ses.allocate_disk_buffer();
|
||||
if (m_disk_recv_buffer == 0)
|
||||
m_disk_recv_buffer.reset(m_ses.allocate_disk_buffer());
|
||||
if (!m_disk_recv_buffer)
|
||||
{
|
||||
disconnect("out of memory");
|
||||
return false;
|
||||
|
@ -2393,10 +2433,8 @@ namespace libtorrent
|
|||
|
||||
char* peer_connection::release_disk_receive_buffer()
|
||||
{
|
||||
char* ret = m_disk_recv_buffer;
|
||||
m_disk_recv_buffer = 0;
|
||||
m_disk_recv_buffer_size = 0;
|
||||
return ret;
|
||||
return m_disk_recv_buffer.release();
|
||||
}
|
||||
|
||||
void peer_connection::cut_receive_buffer(int size, int packet_size)
|
||||
|
@ -2420,11 +2458,17 @@ namespace libtorrent
|
|||
m_packet_size = packet_size;
|
||||
}
|
||||
|
||||
void peer_connection::calc_ip_overhead()
|
||||
{
|
||||
m_statistics.calc_ip_overhead();
|
||||
}
|
||||
|
||||
void peer_connection::second_tick(float tick_interval)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
ptime now(time_now());
|
||||
boost::intrusive_ptr<peer_connection> me(self());
|
||||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
if (!t || m_disconnecting)
|
||||
|
@ -2466,6 +2510,7 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
}
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
if (!t->valid_metadata()) return;
|
||||
|
||||
|
@ -2829,7 +2874,7 @@ namespace libtorrent
|
|||
if (int(m_recv_buffer.size()) < regular_buffer_size)
|
||||
m_recv_buffer.resize(regular_buffer_size);
|
||||
|
||||
if (m_disk_recv_buffer == 0 || regular_buffer_size >= m_recv_pos + max_receive)
|
||||
if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos + max_receive)
|
||||
{
|
||||
// only receive into regular buffer
|
||||
TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size()));
|
||||
|
@ -2841,7 +2886,7 @@ namespace libtorrent
|
|||
// only receive into disk buffer
|
||||
TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0);
|
||||
TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size);
|
||||
m_socket->async_read_some(asio::buffer(m_disk_recv_buffer + m_recv_pos - regular_buffer_size
|
||||
m_socket->async_read_some(asio::buffer(m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size
|
||||
, max_receive)
|
||||
, bind(&peer_connection::on_receive_data, self(), _1, _2));
|
||||
}
|
||||
|
@ -2856,7 +2901,7 @@ namespace libtorrent
|
|||
boost::array<asio::mutable_buffer, 2> vec;
|
||||
vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos]
|
||||
, regular_buffer_size - m_recv_pos);
|
||||
vec[1] = asio::buffer(m_disk_recv_buffer
|
||||
vec[1] = asio::buffer(m_disk_recv_buffer.get()
|
||||
, max_receive - regular_buffer_size + m_recv_pos);
|
||||
m_socket->async_read_some(vec, bind(&peer_connection::on_receive_data
|
||||
, self(), _1, _2));
|
||||
|
@ -2874,7 +2919,7 @@ namespace libtorrent
|
|||
std::pair<buffer::interval, buffer::interval> vec;
|
||||
int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size;
|
||||
TORRENT_ASSERT(regular_buffer_size >= 0);
|
||||
if (m_disk_recv_buffer == 0 || regular_buffer_size >= m_recv_pos)
|
||||
if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos)
|
||||
{
|
||||
vec.first = buffer::interval(&m_recv_buffer[0]
|
||||
+ m_recv_pos - bytes, &m_recv_buffer[0] + m_recv_pos);
|
||||
|
@ -2882,8 +2927,8 @@ namespace libtorrent
|
|||
}
|
||||
else if (m_recv_pos - bytes >= regular_buffer_size)
|
||||
{
|
||||
vec.first = buffer::interval(m_disk_recv_buffer + m_recv_pos
|
||||
- regular_buffer_size - bytes, m_disk_recv_buffer + m_recv_pos
|
||||
vec.first = buffer::interval(m_disk_recv_buffer.get() + m_recv_pos
|
||||
- regular_buffer_size - bytes, m_disk_recv_buffer.get() + m_recv_pos
|
||||
- regular_buffer_size);
|
||||
vec.second = buffer::interval(0,0);
|
||||
}
|
||||
|
@ -2893,8 +2938,8 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(m_recv_pos > regular_buffer_size);
|
||||
vec.first = buffer::interval(&m_recv_buffer[0] + m_recv_pos - bytes
|
||||
, &m_recv_buffer[0] + regular_buffer_size);
|
||||
vec.second = buffer::interval(m_disk_recv_buffer
|
||||
, m_disk_recv_buffer + m_recv_pos - regular_buffer_size);
|
||||
vec.second = buffer::interval(m_disk_recv_buffer.get()
|
||||
, m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size);
|
||||
}
|
||||
TORRENT_ASSERT(vec.first.left() + vec.second.left() == bytes);
|
||||
return vec;
|
||||
|
@ -2998,7 +3043,7 @@ namespace libtorrent
|
|||
// --------------------------
|
||||
|
||||
// throws exception when the client should be disconnected
|
||||
void peer_connection::on_receive_data(const asio::error_code& error
|
||||
void peer_connection::on_receive_data(const error_code& error
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
@ -3014,7 +3059,6 @@ namespace libtorrent
|
|||
(*m_logger) << time_now_string() << " **ERROR**: "
|
||||
<< error.message() << "[in peer_connection::on_receive_data]\n";
|
||||
#endif
|
||||
set_failed();
|
||||
on_receive(error, bytes_transferred);
|
||||
disconnect(error.message().c_str());
|
||||
return;
|
||||
|
@ -3063,8 +3107,8 @@ namespace libtorrent
|
|||
if (int(m_recv_buffer.size()) < regular_buffer_size)
|
||||
m_recv_buffer.resize(regular_buffer_size);
|
||||
|
||||
asio::error_code ec;
|
||||
if (m_disk_recv_buffer == 0 || regular_buffer_size >= m_recv_pos + max_receive)
|
||||
error_code ec;
|
||||
if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos + max_receive)
|
||||
{
|
||||
// only receive into regular buffer
|
||||
TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size()));
|
||||
|
@ -3076,7 +3120,7 @@ namespace libtorrent
|
|||
// only receive into disk buffer
|
||||
TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0);
|
||||
TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size);
|
||||
bytes_transferred = m_socket->read_some(asio::buffer(m_disk_recv_buffer
|
||||
bytes_transferred = m_socket->read_some(asio::buffer(m_disk_recv_buffer.get()
|
||||
+ m_recv_pos - regular_buffer_size, (std::min)(m_packet_size
|
||||
- m_recv_pos, max_receive)), ec);
|
||||
}
|
||||
|
@ -3091,7 +3135,7 @@ namespace libtorrent
|
|||
boost::array<asio::mutable_buffer, 2> vec;
|
||||
vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos]
|
||||
, regular_buffer_size - m_recv_pos);
|
||||
vec[1] = asio::buffer(m_disk_recv_buffer
|
||||
vec[1] = asio::buffer(m_disk_recv_buffer.get()
|
||||
, (std::min)(m_disk_recv_buffer_size
|
||||
, max_receive - regular_buffer_size + m_recv_pos));
|
||||
bytes_transferred = m_socket->read_some(vec, ec);
|
||||
|
@ -3107,27 +3151,6 @@ namespace libtorrent
|
|||
|
||||
setup_receive();
|
||||
}
|
||||
/*
|
||||
catch (file_error& e)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
if (!t)
|
||||
{
|
||||
disconnect(e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
if (t->alerts().should_post(alert::fatal))
|
||||
{
|
||||
t->alerts().post_alert(
|
||||
file_error_alert(t->get_handle()
|
||||
, std::string("torrent paused: ") + e.what()));
|
||||
}
|
||||
t->pause();
|
||||
}
|
||||
*/
|
||||
|
||||
bool peer_connection::can_write() const
|
||||
{
|
||||
|
@ -3158,7 +3181,7 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
(*m_ses.m_logger) << time_now_string() << " CONNECTING: " << m_remote.address().to_string(ec)
|
||||
<< ":" << m_remote.port() << "\n";
|
||||
|
@ -3209,7 +3232,7 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void peer_connection::on_connection_complete(asio::error_code const& e)
|
||||
void peer_connection::on_connection_complete(error_code const& e)
|
||||
{
|
||||
ptime completed = time_now();
|
||||
|
||||
|
@ -3230,8 +3253,7 @@ namespace libtorrent
|
|||
(*m_ses.m_logger) << time_now_string() << " CONNECTION FAILED: " << m_remote.address().to_string()
|
||||
<< ": " << e.message() << "\n";
|
||||
#endif
|
||||
set_failed();
|
||||
disconnect(e.message().c_str());
|
||||
disconnect(e.message().c_str(), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3247,7 +3269,7 @@ namespace libtorrent
|
|||
|
||||
if (m_remote.address().is_v4())
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket->set_option(type_of_service(m_ses.settings().peer_tos), ec);
|
||||
}
|
||||
|
||||
|
@ -3261,7 +3283,7 @@ namespace libtorrent
|
|||
// --------------------------
|
||||
|
||||
// throws exception when the client should be disconnected
|
||||
void peer_connection::on_send_data(asio::error_code const& error
|
||||
void peer_connection::on_send_data(error_code const& error
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
@ -3286,7 +3308,6 @@ namespace libtorrent
|
|||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
(*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n";
|
||||
#endif
|
||||
set_failed();
|
||||
disconnect(error.message().c_str());
|
||||
return;
|
||||
}
|
||||
|
@ -3306,7 +3327,7 @@ namespace libtorrent
|
|||
#ifndef NDEBUG
|
||||
void peer_connection::check_invariant() const
|
||||
{
|
||||
TORRENT_ASSERT((m_disk_recv_buffer != 0) == (m_disk_recv_buffer_size > 0));
|
||||
TORRENT_ASSERT(bool(m_disk_recv_buffer) == (m_disk_recv_buffer_size > 0));
|
||||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
if (m_disconnecting)
|
||||
|
|
|
@ -133,22 +133,8 @@ namespace libtorrent
|
|||
{
|
||||
int index = static_cast<int>(i - pieces.begin());
|
||||
piece_pos& p = m_piece_map[index];
|
||||
if (*i)
|
||||
{
|
||||
if (m_sequential_download == index) ++m_sequential_download;
|
||||
++m_num_have;
|
||||
p.set_have();
|
||||
if (p.filtered())
|
||||
{
|
||||
++m_num_have_filtered;
|
||||
TORRENT_ASSERT(m_num_filtered > 0);
|
||||
--m_num_filtered;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p.index = 0;
|
||||
}
|
||||
if (*i) we_have(index);
|
||||
else TORRENT_ASSERT(p.index == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ namespace libtorrent
|
|||
// blocks be from whole pieces, possibly by returning more blocks
|
||||
// than we requested.
|
||||
#ifndef NDEBUG
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
|
||||
#endif
|
||||
|
||||
|
@ -348,6 +348,7 @@ namespace libtorrent
|
|||
, m_torrent(t)
|
||||
, m_available_free_upload(0)
|
||||
, m_num_connect_candidates(0)
|
||||
, m_num_seeds(0)
|
||||
{ TORRENT_ASSERT(t); }
|
||||
|
||||
// disconnects and removes all peers that are now filtered
|
||||
|
@ -420,49 +421,6 @@ namespace libtorrent
|
|||
return true;
|
||||
}
|
||||
|
||||
policy::iterator policy::find_disconnect_candidate()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
iterator disconnect_peer = m_peers.end();
|
||||
double slowest_transfer_rate = (std::numeric_limits<double>::max)();
|
||||
|
||||
ptime now = time_now();
|
||||
|
||||
for (iterator i = m_peers.begin();
|
||||
i != m_peers.end(); ++i)
|
||||
{
|
||||
peer_connection* c = i->second.connection;
|
||||
if (c == 0) continue;
|
||||
if (c->is_disconnecting()) continue;
|
||||
|
||||
// never disconnect an interesting peer if we have a candidate that
|
||||
// isn't interesting
|
||||
if (disconnect_peer != m_peers.end()
|
||||
&& c->is_interesting()
|
||||
&& !disconnect_peer->second.connection->is_interesting())
|
||||
continue;
|
||||
|
||||
double transferred_amount
|
||||
= (double)c->statistics().total_payload_download();
|
||||
|
||||
time_duration connected_time = now - i->second.connected;
|
||||
|
||||
double connected_time_in_seconds = total_seconds(connected_time);
|
||||
|
||||
double transfer_rate
|
||||
= transferred_amount / (connected_time_in_seconds + 1);
|
||||
|
||||
// prefer to disconnect uninteresting peers, and secondly slow peers
|
||||
if (transfer_rate <= slowest_transfer_rate)
|
||||
{
|
||||
slowest_transfer_rate = transfer_rate;
|
||||
disconnect_peer = i;
|
||||
}
|
||||
}
|
||||
return disconnect_peer;
|
||||
}
|
||||
|
||||
policy::iterator policy::find_connect_candidate()
|
||||
{
|
||||
// too expensive
|
||||
|
@ -625,7 +583,7 @@ namespace libtorrent
|
|||
|
||||
// TODO: only allow _one_ connection to use this
|
||||
// override at a time
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
|
||||
|
||||
aux::session_impl& ses = m_torrent->session();
|
||||
|
@ -697,7 +655,7 @@ namespace libtorrent
|
|||
{
|
||||
// we don't have any info about this peer.
|
||||
// add a new entry
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
|
||||
|
||||
peer p(c.remote(), peer::not_connectable, 0);
|
||||
|
@ -1073,19 +1031,6 @@ namespace libtorrent
|
|||
return true;
|
||||
}
|
||||
|
||||
bool policy::disconnect_one_peer()
|
||||
{
|
||||
iterator p = find_disconnect_candidate();
|
||||
if (p == m_peers.end())
|
||||
return false;
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
(*p->second.connection->m_logger) << "*** CLOSING CONNECTION 'too many connections'\n";
|
||||
#endif
|
||||
|
||||
p->second.connection->disconnect("too many connections, closing");
|
||||
return true;
|
||||
}
|
||||
|
||||
// this is called whenever a peer connection is closed
|
||||
void policy::connection_closed(const peer_connection& c)
|
||||
{
|
||||
|
@ -1156,7 +1101,7 @@ namespace libtorrent
|
|||
// INVARIANT_CHECK;
|
||||
|
||||
TORRENT_ASSERT(c);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
TORRENT_ASSERT(c->remote() == c->get_socket()->remote_endpoint(ec) || ec);
|
||||
|
||||
return std::find_if(
|
||||
|
|
|
@ -253,7 +253,6 @@ namespace libtorrent
|
|||
, bool paused
|
||||
, storage_constructor_type sc)
|
||||
{
|
||||
TORRENT_ASSERT(!ti.m_half_metadata);
|
||||
boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti));
|
||||
add_torrent_params p(sc);
|
||||
p.ti = tip;
|
||||
|
@ -273,7 +272,6 @@ namespace libtorrent
|
|||
, storage_constructor_type sc
|
||||
, void* userdata)
|
||||
{
|
||||
TORRENT_ASSERT(!ti->m_half_metadata);
|
||||
add_torrent_params p(sc);
|
||||
p.ti = ti;
|
||||
p.save_path = save_path;
|
||||
|
|
|
@ -76,6 +76,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/enum_net.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
|
||||
#ifndef TORRENT_WINDOWS
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
@ -162,6 +166,7 @@ namespace aux {
|
|||
, m_auto_manage_time_scaler(0)
|
||||
, m_optimistic_unchoke_time_scaler(0)
|
||||
, m_disconnect_time_scaler(90)
|
||||
, m_auto_scrape_time_scaler(180)
|
||||
, m_incoming_connection(false)
|
||||
, m_last_tick(time_now())
|
||||
, m_torrent_sequence(0)
|
||||
|
@ -207,6 +212,11 @@ namespace aux {
|
|||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
m_logger = create_log("main_session", listen_port(), false);
|
||||
(*m_logger) << time_now_string() << "\n";
|
||||
|
||||
(*m_logger) << "sizeof(torrent): " << sizeof(torrent) << "\n";
|
||||
(*m_logger) << "sizeof(peer_connection): " << sizeof(peer_connection) << "\n";
|
||||
(*m_logger) << "sizeof(bt_peer_connection): " << sizeof(bt_peer_connection) << "\n";
|
||||
(*m_logger) << "sizeof(policy::peer): " << sizeof(policy::peer) << "\n";
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_STATS
|
||||
|
@ -250,7 +260,7 @@ namespace aux {
|
|||
*i = printable[rand() % (sizeof(printable)-1)];
|
||||
}
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timer.expires_from_now(seconds(1), ec);
|
||||
m_timer.async_wait(
|
||||
bind(&session_impl::second_tick, this, _1));
|
||||
|
@ -396,7 +406,7 @@ namespace aux {
|
|||
if (m_dht) m_dht->stop();
|
||||
m_dht_socket.close();
|
||||
#endif
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timer.cancel(ec);
|
||||
|
||||
// close the listen sockets
|
||||
|
@ -535,7 +545,7 @@ namespace aux {
|
|||
session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep
|
||||
, int retries, bool v6_only)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
listen_socket_t s;
|
||||
s.sock.reset(new socket_acceptor(m_io_service));
|
||||
s.sock->open(ep.protocol(), ec);
|
||||
|
@ -544,7 +554,7 @@ namespace aux {
|
|||
s.sock->bind(ep, ec);
|
||||
while (ec && retries > 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
ec = error_code();
|
||||
TORRENT_ASSERT(!ec);
|
||||
--retries;
|
||||
ep.port(ep.port() + 1);
|
||||
|
@ -555,7 +565,7 @@ namespace aux {
|
|||
// instead of giving up, try
|
||||
// let the OS pick a port
|
||||
ep.port(0);
|
||||
ec = asio::error_code();
|
||||
ec = error_code();
|
||||
s.sock->bind(ep, ec);
|
||||
}
|
||||
if (ec)
|
||||
|
@ -661,7 +671,7 @@ namespace aux {
|
|||
for (std::list<listen_socket_t>::const_iterator i = m_listen_sockets.begin()
|
||||
, end(m_listen_sockets.end()); i != end; ++i)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
tcp::endpoint ep = i->sock->local_endpoint(ec);
|
||||
if (ec || ep.address().is_v4()) continue;
|
||||
|
||||
|
@ -691,7 +701,7 @@ namespace aux {
|
|||
|
||||
if (!m_listen_sockets.empty())
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
tcp::endpoint local = m_listen_sockets.front().sock->local_endpoint(ec);
|
||||
if (!ec)
|
||||
{
|
||||
|
@ -713,11 +723,16 @@ namespace aux {
|
|||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
|
||||
void session_impl::on_receive_udp(asio::error_code const& e
|
||||
void session_impl::on_receive_udp(error_code const& e
|
||||
, udp::endpoint const& ep, char const* buf, int len)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
if (e == asio::error::connection_refused
|
||||
|| e == asio::error::connection_reset
|
||||
|| e == asio::error::connection_aborted)
|
||||
m_dht->on_unreachable(ep);
|
||||
|
||||
if (m_alerts.should_post(alert::info))
|
||||
{
|
||||
std::string msg = "UDP socket error from '"
|
||||
|
@ -746,7 +761,7 @@ namespace aux {
|
|||
}
|
||||
|
||||
void session_impl::on_incoming_connection(shared_ptr<socket_type> const& s
|
||||
, weak_ptr<socket_acceptor> listen_socket, asio::error_code const& e)
|
||||
, weak_ptr<socket_acceptor> listen_socket, error_code const& e)
|
||||
{
|
||||
boost::shared_ptr<socket_acceptor> listener = listen_socket.lock();
|
||||
if (!listener) return;
|
||||
|
@ -756,7 +771,7 @@ namespace aux {
|
|||
mutex_t::scoped_lock l(m_mutex);
|
||||
if (m_abort) return;
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
if (e)
|
||||
{
|
||||
tcp::endpoint ep = listener->local_endpoint(ec);
|
||||
|
@ -842,7 +857,13 @@ namespace aux {
|
|||
|
||||
// check if we have any active torrents
|
||||
// if we don't reject the connection
|
||||
if (m_torrents.empty()) return;
|
||||
if (m_torrents.empty())
|
||||
{
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << " There are no torrents, disconnect\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
bool has_active_torrent = false;
|
||||
for (torrent_map::iterator i = m_torrents.begin()
|
||||
|
@ -854,10 +875,16 @@ namespace aux {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!has_active_torrent) return;
|
||||
if (!has_active_torrent)
|
||||
{
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << " There are no _active_ torrents, disconnect\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
boost::intrusive_ptr<peer_connection> c(
|
||||
new bt_peer_connection(*this, s, 0));
|
||||
new bt_peer_connection(*this, s, endp, 0));
|
||||
#ifndef NDEBUG
|
||||
c->m_in_constructor = false;
|
||||
#endif
|
||||
|
@ -926,7 +953,7 @@ namespace aux {
|
|||
return port;
|
||||
}
|
||||
|
||||
void session_impl::second_tick(asio::error_code const& e)
|
||||
void session_impl::second_tick(error_code const& e)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_mutex);
|
||||
|
||||
|
@ -947,7 +974,7 @@ namespace aux {
|
|||
float tick_interval = total_microseconds(time_now() - m_last_tick) / 1000000.f;
|
||||
m_last_tick = time_now();
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timer.expires_from_now(seconds(1), ec);
|
||||
m_timer.async_wait(
|
||||
bind(&session_impl::second_tick, this, _1));
|
||||
|
@ -986,7 +1013,6 @@ namespace aux {
|
|||
<< m_disk_thread.disk_allocations() << "\t"
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// second_tick every torrent
|
||||
// --------------------------------------------------------------
|
||||
|
@ -1002,6 +1028,9 @@ namespace aux {
|
|||
// count the number of peers of downloading torrents
|
||||
int num_downloads_peers = 0;
|
||||
|
||||
torrent_map::iterator least_recently_scraped = m_torrents.begin();
|
||||
int num_paused_auto_managed = 0;
|
||||
|
||||
// check each torrent for tracker updates
|
||||
// TODO: do this in a timer-event in each torrent instead
|
||||
for (torrent_map::iterator i = m_torrents.begin();
|
||||
|
@ -1014,6 +1043,17 @@ namespace aux {
|
|||
else
|
||||
++uncongested_torrents;
|
||||
|
||||
if (t.is_auto_managed() && t.is_paused())
|
||||
{
|
||||
++num_paused_auto_managed;
|
||||
if (!least_recently_scraped->second->is_auto_managed()
|
||||
|| !least_recently_scraped->second->is_paused()
|
||||
|| least_recently_scraped->second->last_scrape() > t.last_scrape())
|
||||
{
|
||||
least_recently_scraped = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (t.is_finished())
|
||||
{
|
||||
++num_seeds;
|
||||
|
@ -1046,9 +1086,29 @@ namespace aux {
|
|||
++i;
|
||||
}
|
||||
|
||||
// drain the IP overhead from the bandwidth limiters
|
||||
m_download_channel.drain(m_stat.download_ip_overhead());
|
||||
m_upload_channel.drain(m_stat.upload_ip_overhead());
|
||||
|
||||
m_stat.second_tick(tick_interval);
|
||||
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// scrape paused torrents that are auto managed
|
||||
// --------------------------------------------------------------
|
||||
--m_auto_scrape_time_scaler;
|
||||
if (m_auto_scrape_time_scaler <= 0)
|
||||
{
|
||||
m_auto_scrape_time_scaler = m_settings.auto_scrape_interval
|
||||
/ (std::max)(1, num_paused_auto_managed);
|
||||
if (m_auto_scrape_time_scaler < m_settings.auto_scrape_min_interval)
|
||||
m_auto_scrape_time_scaler = m_settings.auto_scrape_min_interval;
|
||||
|
||||
if (least_recently_scraped != m_torrents.end())
|
||||
{
|
||||
least_recently_scraped->second->scrape_tracker();
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// connect new peers
|
||||
// --------------------------------------------------------------
|
||||
|
@ -1156,20 +1216,10 @@ namespace aux {
|
|||
peer_connection& c = *j->get();
|
||||
if (c.has_timed_out())
|
||||
{
|
||||
if (m_alerts.should_post(alert::debug))
|
||||
{
|
||||
m_alerts.post_alert(
|
||||
peer_error_alert(
|
||||
c.remote()
|
||||
, c.pid()
|
||||
, "connection timed out"));
|
||||
}
|
||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||
(*c.m_logger) << "*** CONNECTION TIMED OUT\n";
|
||||
#endif
|
||||
|
||||
c.set_failed();
|
||||
c.disconnect("timed out");
|
||||
c.disconnect("timed out: inactive", 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1205,17 +1255,37 @@ namespace aux {
|
|||
{
|
||||
m_disconnect_time_scaler = 90;
|
||||
|
||||
// every 90 seconds, disconnect the worst peer
|
||||
// every 90 seconds, disconnect the worst peers
|
||||
// if we have reached the connection limit
|
||||
if (num_connections() >= max_connections() && !m_torrents.empty())
|
||||
if (num_connections() >= max_connections() * m_settings.peer_turnover_cutoff
|
||||
&& !m_torrents.empty())
|
||||
{
|
||||
torrent_map::iterator i = std::max_element(m_torrents.begin(), m_torrents.end()
|
||||
, bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _1))
|
||||
< bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _2)));
|
||||
|
||||
TORRENT_ASSERT(i != m_torrents.end());
|
||||
// TODO: make the number of peers a percentage of the number of connected peers
|
||||
i->second->get_policy().disconnect_one_peer();
|
||||
int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers()
|
||||
* m_settings.peer_turnover), 1)
|
||||
, i->second->get_policy().num_connect_candidates());
|
||||
i->second->disconnect_peers(peers_to_disconnect);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we haven't reached the global max. see if any torrent
|
||||
// has reached its local limit
|
||||
for (torrent_map::iterator i = m_torrents.begin()
|
||||
, end(m_torrents.end()); i != end; ++i)
|
||||
{
|
||||
boost::shared_ptr<torrent> t = i->second;
|
||||
if (t->num_peers() < t->max_connections() * m_settings.peer_turnover_cutoff)
|
||||
continue;
|
||||
|
||||
int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers()
|
||||
* m_settings.peer_turnover), 1)
|
||||
, i->second->get_policy().num_connect_candidates());
|
||||
t->disconnect_peers(peers_to_disconnect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1276,8 +1346,8 @@ namespace aux {
|
|||
, bind(&torrent::sequence_number, _1) < bind(&torrent::sequence_number, _2));
|
||||
|
||||
std::sort(seeds.begin(), seeds.end()
|
||||
, bind(&torrent::seed_cycles_int, _1, boost::ref(m_settings))
|
||||
< bind(&torrent::seed_cycles_int, _2, boost::ref(m_settings)));
|
||||
, bind(&torrent::seed_rank, _1, boost::ref(m_settings))
|
||||
> bind(&torrent::seed_rank, _2, boost::ref(m_settings)));
|
||||
}
|
||||
|
||||
for (std::vector<torrent*>::iterator i = downloaders.begin()
|
||||
|
@ -2111,7 +2181,19 @@ namespace aux {
|
|||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (limit <= 0) limit = (std::numeric_limits<int>::max)();
|
||||
if (limit <= 0)
|
||||
{
|
||||
limit = (std::numeric_limits<int>::max)();
|
||||
#ifndef TORRENT_WINDOWS
|
||||
rlimit l;
|
||||
if (getrlimit(RLIMIT_NOFILE, &l) == 0
|
||||
&& l.rlim_cur != RLIM_INFINITY)
|
||||
{
|
||||
limit = l.rlim_cur - m_settings.file_pool_size;
|
||||
if (limit < 5) limit = 5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
m_max_connections = limit;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,13 +37,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace libtorrent
|
||||
{
|
||||
|
||||
void socks4_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
||||
void socks4_stream::name_lookup(error_code const& e, tcp::resolver::iterator i
|
||||
, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ namespace libtorrent
|
|||
|
||||
if (i == tcp::resolver::iterator())
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
error_code ec = asio::error::operation_not_supported;
|
||||
(*h)(ec);
|
||||
close(ec);
|
||||
return;
|
||||
|
@ -64,12 +64,12 @@ namespace libtorrent
|
|||
&socks4_stream::connected, this, _1, h));
|
||||
}
|
||||
|
||||
void socks4_stream::connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void socks4_stream::connected(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -86,31 +86,31 @@ namespace libtorrent
|
|||
p += m_user.size();
|
||||
write_uint8(0, p); // NULL terminator
|
||||
|
||||
asio::async_write(m_sock, asio::buffer(m_buffer)
|
||||
async_write(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&socks4_stream::handshake1, this, _1, h));
|
||||
}
|
||||
|
||||
void socks4_stream::handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void socks4_stream::handshake1(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
m_buffer.resize(8);
|
||||
asio::async_read(m_sock, asio::buffer(m_buffer)
|
||||
async_read(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&socks4_stream::handshake2, this, _1, h));
|
||||
}
|
||||
|
||||
void socks4_stream::handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void socks4_stream::handshake2(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ namespace libtorrent
|
|||
|
||||
if (reply_version != 0)
|
||||
{
|
||||
asio::error_code ec = asio::error::operation_not_supported;
|
||||
error_code ec = asio::error::operation_not_supported;
|
||||
(*h)(ec);
|
||||
close(ec);
|
||||
return;
|
||||
|
@ -137,7 +137,7 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
asio::error_code ec = asio::error::fault;
|
||||
error_code ec = asio::error::fault;
|
||||
switch (status_code)
|
||||
{
|
||||
case 91: ec = asio::error::connection_refused; break;
|
||||
|
|
|
@ -38,13 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace libtorrent
|
||||
{
|
||||
|
||||
void socks5_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i
|
||||
void socks5_stream::name_lookup(error_code const& e, tcp::resolver::iterator i
|
||||
, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e || i == tcp::resolver::iterator())
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -53,12 +53,12 @@ namespace libtorrent
|
|||
&socks5_stream::connected, this, _1, h));
|
||||
}
|
||||
|
||||
void socks5_stream::connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void socks5_stream::connected(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -79,31 +79,31 @@ namespace libtorrent
|
|||
write_uint8(0, p); // no authentication
|
||||
write_uint8(2, p); // username/password
|
||||
}
|
||||
asio::async_write(m_sock, asio::buffer(m_buffer)
|
||||
async_write(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&socks5_stream::handshake1, this, _1, h));
|
||||
}
|
||||
|
||||
void socks5_stream::handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void socks5_stream::handshake1(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
m_buffer.resize(2);
|
||||
asio::async_read(m_sock, asio::buffer(m_buffer)
|
||||
async_read(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&socks5_stream::handshake2, this, _1, h));
|
||||
}
|
||||
|
||||
void socks5_stream::handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void socks5_stream::handshake2(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ namespace libtorrent
|
|||
if (version < 5)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ namespace libtorrent
|
|||
if (m_user.empty())
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -144,41 +144,41 @@ namespace libtorrent
|
|||
write_string(m_user, p);
|
||||
write_uint8(m_password.size(), p);
|
||||
write_string(m_password, p);
|
||||
asio::async_write(m_sock, asio::buffer(m_buffer)
|
||||
async_write(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&socks5_stream::handshake3, this, _1, h));
|
||||
}
|
||||
else
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void socks5_stream::handshake3(asio::error_code const& e
|
||||
void socks5_stream::handshake3(error_code const& e
|
||||
, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
m_buffer.resize(2);
|
||||
asio::async_read(m_sock, asio::buffer(m_buffer)
|
||||
async_read(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&socks5_stream::handshake4, this, _1, h));
|
||||
}
|
||||
|
||||
void socks5_stream::handshake4(asio::error_code const& e
|
||||
void socks5_stream::handshake4(error_code const& e
|
||||
, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ namespace libtorrent
|
|||
if (version != 1)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ namespace libtorrent
|
|||
if (status != 0)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -223,31 +223,31 @@ namespace libtorrent
|
|||
write_endpoint(m_remote_endpoint, p);
|
||||
TORRENT_ASSERT(p - &m_buffer[0] == int(m_buffer.size()));
|
||||
|
||||
asio::async_write(m_sock, asio::buffer(m_buffer)
|
||||
async_write(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&socks5_stream::connect1, this, _1, h));
|
||||
}
|
||||
|
||||
void socks5_stream::connect1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void socks5_stream::connect1(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
m_buffer.resize(6 + 4); // assume an IPv4 address
|
||||
asio::async_read(m_sock, asio::buffer(m_buffer)
|
||||
async_read(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&socks5_stream::connect2, this, _1, h));
|
||||
}
|
||||
|
||||
void socks5_stream::connect2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void socks5_stream::connect2(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -260,14 +260,14 @@ namespace libtorrent
|
|||
if (version < 5)
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
int response = read_uint8(p);
|
||||
if (response != 0)
|
||||
{
|
||||
asio::error_code e = asio::error::fault;
|
||||
error_code e = asio::error::fault;
|
||||
switch (response)
|
||||
{
|
||||
case 1: e = asio::error::fault; break;
|
||||
|
@ -280,7 +280,7 @@ namespace libtorrent
|
|||
case 8: e = asio::error::address_family_not_supported; break;
|
||||
}
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -305,22 +305,22 @@ namespace libtorrent
|
|||
else
|
||||
{
|
||||
(*h)(asio::error::operation_not_supported);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
m_buffer.resize(skip_bytes);
|
||||
|
||||
asio::async_read(m_sock, asio::buffer(m_buffer)
|
||||
async_read(m_sock, asio::buffer(m_buffer)
|
||||
, boost::bind(&socks5_stream::connect3, this, _1, h));
|
||||
}
|
||||
|
||||
void socks5_stream::connect3(asio::error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
void socks5_stream::connect3(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
(*h)(e);
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -47,47 +47,23 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define for if (false) {} else for
|
||||
#endif
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
void libtorrent::stat::second_tick(float tick_interval)
|
||||
void stat_channel::second_tick(float tick_interval)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_rate_sum -= m_rate_history[history-1];
|
||||
|
||||
for (int i = history - 2; i >= 0; --i)
|
||||
{
|
||||
m_download_rate_history[i + 1] = m_download_rate_history[i];
|
||||
m_upload_rate_history[i + 1] = m_upload_rate_history[i];
|
||||
m_download_payload_rate_history[i + 1] = m_download_payload_rate_history[i];
|
||||
m_upload_payload_rate_history[i + 1] = m_upload_payload_rate_history[i];
|
||||
}
|
||||
m_rate_history[i + 1] = m_rate_history[i];
|
||||
|
||||
m_download_rate_history[0] = (m_downloaded_payload + m_downloaded_protocol)
|
||||
/ tick_interval;
|
||||
m_upload_rate_history[0] = (m_uploaded_payload + m_uploaded_protocol)
|
||||
/ tick_interval;
|
||||
m_download_payload_rate_history[0] = m_downloaded_payload / tick_interval;
|
||||
m_upload_payload_rate_history[0] = m_uploaded_payload / tick_interval;
|
||||
|
||||
m_downloaded_payload = 0;
|
||||
m_uploaded_payload = 0;
|
||||
m_downloaded_protocol = 0;
|
||||
m_uploaded_protocol = 0;
|
||||
|
||||
m_mean_download_rate = 0;
|
||||
m_mean_upload_rate = 0;
|
||||
m_mean_download_payload_rate = 0;
|
||||
m_mean_upload_payload_rate = 0;
|
||||
|
||||
for (int i = 0; i < history; ++i)
|
||||
{
|
||||
m_mean_download_rate += m_download_rate_history[i];
|
||||
m_mean_upload_rate += m_upload_rate_history[i];
|
||||
m_mean_download_payload_rate += m_download_payload_rate_history[i];
|
||||
m_mean_upload_payload_rate += m_upload_payload_rate_history[i];
|
||||
}
|
||||
|
||||
m_mean_download_rate /= history;
|
||||
m_mean_upload_rate /= history;
|
||||
m_mean_download_payload_rate /= history;
|
||||
m_mean_upload_payload_rate /= history;
|
||||
m_rate_history[0] = m_counter / tick_interval;
|
||||
m_rate_sum += m_rate_history[0];
|
||||
m_counter = 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -527,12 +527,23 @@ namespace libtorrent
|
|||
std::pair<iter_t, bool> ret = directories.insert((m_save_path / bp).string());
|
||||
bp = bp.branch_path();
|
||||
}
|
||||
#if defined(_WIN32) && defined(UNICODE)
|
||||
try
|
||||
{ fs::remove(safe_convert(p)); }
|
||||
catch (std::exception& e)
|
||||
{
|
||||
error = e.what();
|
||||
error_file = p;
|
||||
result = 1;
|
||||
}
|
||||
#else
|
||||
if (std::remove(p.c_str()) != 0 && errno != ENOENT)
|
||||
{
|
||||
error = std::strerror(errno);
|
||||
error_file = p;
|
||||
result = errno;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// remove the directories. Reverse order to delete
|
||||
|
@ -541,12 +552,23 @@ namespace libtorrent
|
|||
for (std::set<std::string>::reverse_iterator i = directories.rbegin()
|
||||
, end(directories.rend()); i != end; ++i)
|
||||
{
|
||||
#if defined(_WIN32) && defined(UNICODE)
|
||||
try
|
||||
{ fs::remove(safe_convert(*i)); }
|
||||
catch (std::exception& e)
|
||||
{
|
||||
error = e.what();
|
||||
error_file = *i;
|
||||
result = 1;
|
||||
}
|
||||
#else
|
||||
if (std::remove(i->c_str()) != 0 && errno != ENOENT)
|
||||
{
|
||||
error = std::strerror(errno);
|
||||
error_file = *i;
|
||||
result = errno;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!error.empty())
|
||||
|
@ -1230,7 +1252,7 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_ASSERT(r.length <= 16 * 1024);
|
||||
// the buffer needs to be allocated through the io_thread
|
||||
TORRENT_ASSERT(m_io_thread.is_disk_buffer(buffer.buffer()));
|
||||
TORRENT_ASSERT(m_io_thread.is_disk_buffer(buffer.get()));
|
||||
|
||||
disk_io_job j;
|
||||
j.storage = this;
|
||||
|
@ -1238,7 +1260,7 @@ namespace libtorrent
|
|||
j.piece = r.piece;
|
||||
j.offset = r.start;
|
||||
j.buffer_size = r.length;
|
||||
j.buffer = buffer.buffer();
|
||||
j.buffer = buffer.get();
|
||||
m_io_thread.add_job(j, handler);
|
||||
buffer.release();
|
||||
}
|
||||
|
@ -2465,7 +2487,8 @@ namespace libtorrent
|
|||
&& m_free_slots.empty()
|
||||
&& m_state == state_finished)
|
||||
{
|
||||
TORRENT_ASSERT(m_storage_mode != storage_mode_compact);
|
||||
TORRENT_ASSERT(m_storage_mode != storage_mode_compact
|
||||
|| m_info->num_pieces() == 0);
|
||||
}
|
||||
|
||||
if (m_storage_mode != storage_mode_compact)
|
||||
|
|
|
@ -59,6 +59,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/torrent_info.hpp"
|
||||
#include "libtorrent/tracker_manager.hpp"
|
||||
#include "libtorrent/parse_url.hpp"
|
||||
#include "libtorrent/bencode.hpp"
|
||||
#include "libtorrent/hasher.hpp"
|
||||
#include "libtorrent/entry.hpp"
|
||||
|
@ -95,20 +96,6 @@ namespace
|
|||
, tracker_failed_max = 5
|
||||
};
|
||||
|
||||
int calculate_block_size(const torrent_info& i, int default_block_size)
|
||||
{
|
||||
if (default_block_size < 1024) default_block_size = 1024;
|
||||
|
||||
// if pieces are too small, adjust the block size
|
||||
if (i.piece_length() < default_block_size)
|
||||
{
|
||||
return i.piece_length();
|
||||
}
|
||||
|
||||
// otherwise, go with the default
|
||||
return default_block_size;
|
||||
}
|
||||
|
||||
struct find_peer_by_ip
|
||||
{
|
||||
find_peer_by_ip(tcp::endpoint const& a, const torrent* t)
|
||||
|
@ -160,23 +147,18 @@ namespace libtorrent
|
|||
, entry const* resume_data
|
||||
, int seq
|
||||
, bool auto_managed)
|
||||
: m_torrent_file(tf)
|
||||
, m_abort(false)
|
||||
, m_paused(paused)
|
||||
, m_just_paused(false)
|
||||
, m_auto_managed(auto_managed)
|
||||
: m_policy(this)
|
||||
, m_active_time(seconds(0))
|
||||
, m_seeding_time(seconds(0))
|
||||
, m_total_uploaded(0)
|
||||
, m_total_downloaded(0)
|
||||
, m_started(time_now())
|
||||
, m_last_scrape(min_time())
|
||||
, m_torrent_file(tf)
|
||||
, m_event(tracker_request::started)
|
||||
, m_block_size(0)
|
||||
, m_storage(0)
|
||||
, m_next_request(time_now())
|
||||
, m_duration(1800)
|
||||
, m_complete(-1)
|
||||
, m_incomplete(-1)
|
||||
, m_host_resolver(ses.m_io_service)
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
, m_resolving_country(false)
|
||||
, m_resolve_countries(false)
|
||||
#endif
|
||||
, m_announce_timer(ses.m_io_service)
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
, m_last_dht_announce(time_now() - minutes(15))
|
||||
|
@ -184,35 +166,41 @@ namespace libtorrent
|
|||
, m_ses(ses)
|
||||
, m_picker(0)
|
||||
, m_trackers(m_torrent_file->trackers())
|
||||
, m_last_working_tracker(-1)
|
||||
, m_currently_trying_tracker(0)
|
||||
, m_failed_trackers(0)
|
||||
, m_time_scaler(0)
|
||||
, m_num_pieces(0)
|
||||
, m_sequential_download(false)
|
||||
, m_got_tracker_response(false)
|
||||
, m_ratio(0.f)
|
||||
, m_total_failed_bytes(0)
|
||||
, m_total_redundant_bytes(0)
|
||||
, m_net_interface(net_interface.address(), 0)
|
||||
, m_save_path(complete(save_path))
|
||||
, m_storage_mode(storage_mode)
|
||||
, m_state(torrent_status::queued_for_checking)
|
||||
, m_progress(0.f)
|
||||
, m_default_block_size(block_size)
|
||||
, m_connections_initialized(true)
|
||||
, m_settings(ses.settings())
|
||||
, m_storage_constructor(sc)
|
||||
, m_progress(0.f)
|
||||
, m_num_pieces(0)
|
||||
, m_ratio(0.f)
|
||||
, m_max_uploads((std::numeric_limits<int>::max)())
|
||||
, m_num_uploads(0)
|
||||
, m_max_connections((std::numeric_limits<int>::max)())
|
||||
, m_block_size(block_size)
|
||||
, m_complete(-1)
|
||||
, m_incomplete(-1)
|
||||
, m_deficit_counter(0)
|
||||
, m_policy(this)
|
||||
, m_duration(1800)
|
||||
, m_sequence_number(seq)
|
||||
, m_active_time(seconds(0))
|
||||
, m_seeding_time(seconds(0))
|
||||
, m_total_uploaded(0)
|
||||
, m_total_downloaded(0)
|
||||
, m_last_working_tracker(-1)
|
||||
, m_currently_trying_tracker(0)
|
||||
, m_failed_trackers(0)
|
||||
, m_time_scaler(0)
|
||||
, m_abort(false)
|
||||
, m_paused(paused)
|
||||
, m_just_paused(false)
|
||||
, m_auto_managed(auto_managed)
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
, m_resolving_country(false)
|
||||
, m_resolve_countries(false)
|
||||
#endif
|
||||
, m_sequential_download(false)
|
||||
, m_got_tracker_response(false)
|
||||
, m_connections_initialized(true)
|
||||
{
|
||||
if (resume_data) m_resume_data = *resume_data;
|
||||
#ifndef NDEBUG
|
||||
|
@ -234,58 +222,59 @@ namespace libtorrent
|
|||
, entry const* resume_data
|
||||
, int seq
|
||||
, bool auto_managed)
|
||||
: m_torrent_file(new torrent_info(info_hash))
|
||||
, m_abort(false)
|
||||
, m_paused(paused)
|
||||
, m_just_paused(false)
|
||||
, m_auto_managed(auto_managed)
|
||||
: m_policy(this)
|
||||
, m_active_time(seconds(0))
|
||||
, m_seeding_time(seconds(0))
|
||||
, m_total_uploaded(0)
|
||||
, m_total_downloaded(0)
|
||||
, m_started(time_now())
|
||||
, m_last_scrape(min_time())
|
||||
, m_torrent_file(new torrent_info(info_hash))
|
||||
, m_event(tracker_request::started)
|
||||
, m_block_size(0)
|
||||
, m_storage(0)
|
||||
, m_next_request(time_now())
|
||||
, m_duration(1800)
|
||||
, m_complete(-1)
|
||||
, m_incomplete(-1)
|
||||
, m_host_resolver(ses.m_io_service)
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
, m_resolving_country(false)
|
||||
, m_resolve_countries(false)
|
||||
#endif
|
||||
, m_announce_timer(ses.m_io_service)
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
, m_last_dht_announce(time_now() - minutes(15))
|
||||
#endif
|
||||
, m_ses(ses)
|
||||
, m_picker(0)
|
||||
, m_last_working_tracker(-1)
|
||||
, m_currently_trying_tracker(0)
|
||||
, m_failed_trackers(0)
|
||||
, m_time_scaler(0)
|
||||
, m_num_pieces(0)
|
||||
, m_sequential_download(false)
|
||||
, m_got_tracker_response(false)
|
||||
, m_ratio(0.f)
|
||||
, m_total_failed_bytes(0)
|
||||
, m_total_redundant_bytes(0)
|
||||
, m_net_interface(net_interface.address(), 0)
|
||||
, m_save_path(complete(save_path))
|
||||
, m_storage_mode(storage_mode)
|
||||
, m_state(torrent_status::queued_for_checking)
|
||||
, m_progress(0.f)
|
||||
, m_default_block_size(block_size)
|
||||
, m_connections_initialized(false)
|
||||
, m_settings(ses.settings())
|
||||
, m_storage_constructor(sc)
|
||||
, m_progress(0.f)
|
||||
, m_num_pieces(0)
|
||||
, m_ratio(0.f)
|
||||
, m_max_uploads((std::numeric_limits<int>::max)())
|
||||
, m_num_uploads(0)
|
||||
, m_max_connections((std::numeric_limits<int>::max)())
|
||||
, m_block_size(block_size)
|
||||
, m_complete(-1)
|
||||
, m_incomplete(-1)
|
||||
, m_deficit_counter(0)
|
||||
, m_policy(this)
|
||||
, m_duration(1800)
|
||||
, m_sequence_number(seq)
|
||||
, m_active_time(seconds(0))
|
||||
, m_seeding_time(seconds(0))
|
||||
, m_total_uploaded(0)
|
||||
, m_total_downloaded(0)
|
||||
, m_last_working_tracker(-1)
|
||||
, m_currently_trying_tracker(0)
|
||||
, m_failed_trackers(0)
|
||||
, m_time_scaler(0)
|
||||
, m_abort(false)
|
||||
, m_paused(paused)
|
||||
, m_just_paused(false)
|
||||
, m_auto_managed(auto_managed)
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
, m_resolving_country(false)
|
||||
, m_resolve_countries(false)
|
||||
#endif
|
||||
, m_sequential_download(false)
|
||||
, m_got_tracker_response(false)
|
||||
, m_connections_initialized(false)
|
||||
{
|
||||
if (resume_data) m_resume_data = *resume_data;
|
||||
#ifndef NDEBUG
|
||||
|
@ -307,7 +296,7 @@ namespace libtorrent
|
|||
boost::weak_ptr<torrent> self(shared_from_this());
|
||||
if (m_torrent_file->is_valid()) init();
|
||||
if (m_abort) return;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_announce_timer.expires_from_now(seconds(1), ec);
|
||||
m_announce_timer.async_wait(
|
||||
bind(&torrent::on_announce_disp, self, _1));
|
||||
|
@ -425,7 +414,6 @@ namespace libtorrent
|
|||
, m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
|
||||
, m_storage_mode);
|
||||
m_storage = m_owning_storage.get();
|
||||
m_block_size = calculate_block_size(*m_torrent_file, m_default_block_size);
|
||||
m_picker.reset(new piece_picker(
|
||||
m_torrent_file->piece_length() / m_block_size
|
||||
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)));
|
||||
|
@ -603,6 +591,13 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (std::vector<bool>::iterator i = m_have_pieces.begin()
|
||||
, end(m_have_pieces.end()); i != end; ++i, ++index)
|
||||
{
|
||||
if (*i) m_picker->we_have(index);
|
||||
}
|
||||
}
|
||||
|
||||
files_checked();
|
||||
|
@ -654,6 +649,8 @@ namespace libtorrent
|
|||
{
|
||||
m_have_pieces[j.offset] = true;
|
||||
++m_num_pieces;
|
||||
TORRENT_ASSERT(m_picker);
|
||||
m_picker->we_have(j.offset);
|
||||
}
|
||||
|
||||
// we're not done checking yet
|
||||
|
@ -673,7 +670,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
void torrent::on_announce_disp(boost::weak_ptr<torrent> p
|
||||
, asio::error_code const& e)
|
||||
, error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
boost::shared_ptr<torrent> t = p.lock();
|
||||
|
@ -687,7 +684,7 @@ namespace libtorrent
|
|||
|
||||
boost::weak_ptr<torrent> self(shared_from_this());
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
if (!m_torrent_file->priv())
|
||||
{
|
||||
// announce on local network every 5 minutes
|
||||
|
@ -759,6 +756,8 @@ namespace libtorrent
|
|||
req.url = m_trackers[m_currently_trying_tracker].url;
|
||||
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());
|
||||
|
||||
m_last_scrape = time_now();
|
||||
}
|
||||
|
||||
// returns true if it is time for this torrent to make another
|
||||
|
@ -837,6 +836,8 @@ namespace libtorrent
|
|||
|
||||
if (complete >= 0) m_complete = complete;
|
||||
if (incomplete >= 0) m_incomplete = incomplete;
|
||||
if (complete >= 0 && incomplete >= 0)
|
||||
m_last_scrape = time_now();
|
||||
|
||||
// connect to random peers from the list
|
||||
std::random_shuffle(peer_list.begin(), peer_list.end());
|
||||
|
@ -865,7 +866,7 @@ namespace libtorrent
|
|||
if (i->pid == m_ses.get_peer_id())
|
||||
continue;
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
tcp::endpoint a(address::from_string(i->ip, ec), i->port);
|
||||
|
||||
if (ec)
|
||||
|
@ -875,7 +876,7 @@ namespace libtorrent
|
|||
|
||||
tcp::resolver::query q(i->ip, boost::lexical_cast<std::string>(i->port));
|
||||
m_host_resolver.async_resolve(q,
|
||||
bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid));
|
||||
bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -905,7 +906,7 @@ namespace libtorrent
|
|||
m_got_tracker_response = true;
|
||||
}
|
||||
|
||||
void torrent::on_peer_name_lookup(asio::error_code const& e, tcp::resolver::iterator host
|
||||
void torrent::on_peer_name_lookup(error_code const& e, tcp::resolver::iterator host
|
||||
, peer_id pid)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
@ -1369,7 +1370,7 @@ namespace libtorrent
|
|||
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
|
||||
|
||||
m_owning_storage = 0;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_announce_timer.cancel(ec);
|
||||
m_host_resolver.cancel();
|
||||
}
|
||||
|
@ -1487,9 +1488,8 @@ namespace libtorrent
|
|||
#endif
|
||||
if (is_seed())
|
||||
{
|
||||
m_state = torrent_status::seeding;
|
||||
m_picker.reset();
|
||||
if (m_ses.settings().free_torrent_hashes)
|
||||
m_torrent_file->seed_free();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1653,6 +1653,8 @@ namespace libtorrent
|
|||
// the torrent just became finished
|
||||
if (is_finished() && !was_finished)
|
||||
finished();
|
||||
else if (!is_finished() && was_finished)
|
||||
resume_download();
|
||||
}
|
||||
|
||||
void torrent::filter_piece(int index, bool filter)
|
||||
|
@ -1912,9 +1914,20 @@ namespace libtorrent
|
|||
std::string hostname;
|
||||
int port;
|
||||
std::string path;
|
||||
boost::tie(protocol, auth, hostname, port, path)
|
||||
char const* error;
|
||||
boost::tie(protocol, auth, hostname, port, path, error)
|
||||
= parse_url_components(url);
|
||||
|
||||
if (error)
|
||||
{
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
||||
(*m_ses.m_logger) << time_now_string() << " failed to parse web seed url: " << error << "\n";
|
||||
#endif
|
||||
// never try it again
|
||||
remove_url_seed(url);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
if (protocol != "http" && protocol != "https")
|
||||
#else
|
||||
|
@ -1968,6 +1981,18 @@ namespace libtorrent
|
|||
}
|
||||
else
|
||||
{
|
||||
if (m_ses.m_port_filter.access(port) & port_filter::blocked)
|
||||
{
|
||||
if (m_ses.m_alerts.should_post(alert::warning))
|
||||
{
|
||||
m_ses.m_alerts.post_alert(
|
||||
url_seed_alert(get_handle(), url, "port blocked by port-filter"));
|
||||
}
|
||||
// never try it again
|
||||
remove_url_seed(url);
|
||||
return;
|
||||
}
|
||||
|
||||
tcp::resolver::query q(hostname, boost::lexical_cast<std::string>(port));
|
||||
m_host_resolver.async_resolve(q,
|
||||
bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url
|
||||
|
@ -1976,7 +2001,7 @@ namespace libtorrent
|
|||
|
||||
}
|
||||
|
||||
void torrent::on_proxy_name_lookup(asio::error_code const& e, tcp::resolver::iterator host
|
||||
void torrent::on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator host
|
||||
, std::string url)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
@ -1991,10 +2016,8 @@ namespace libtorrent
|
|||
{
|
||||
if (m_ses.m_alerts.should_post(alert::warning))
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "HTTP seed proxy hostname lookup failed: " << e.message();
|
||||
m_ses.m_alerts.post_alert(
|
||||
url_seed_alert(get_handle(), url, msg.str()));
|
||||
url_seed_alert(get_handle(), url, e.message()));
|
||||
}
|
||||
|
||||
// the name lookup failed for the http host. Don't try
|
||||
|
@ -2010,9 +2033,21 @@ namespace libtorrent
|
|||
using boost::tuples::ignore;
|
||||
std::string hostname;
|
||||
int port;
|
||||
boost::tie(ignore, ignore, hostname, port, ignore)
|
||||
char const* error;
|
||||
boost::tie(ignore, ignore, hostname, port, ignore, error)
|
||||
= parse_url_components(url);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (m_ses.m_alerts.should_post(alert::warning))
|
||||
{
|
||||
m_ses.m_alerts.post_alert(
|
||||
url_seed_alert(get_handle(), url, error));
|
||||
}
|
||||
remove_url_seed(url);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked)
|
||||
{
|
||||
if (m_ses.m_alerts.should_post(alert::info))
|
||||
|
@ -2028,7 +2063,7 @@ namespace libtorrent
|
|||
bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url, a));
|
||||
}
|
||||
|
||||
void torrent::on_name_lookup(asio::error_code const& e, tcp::resolver::iterator host
|
||||
void torrent::on_name_lookup(error_code const& e, tcp::resolver::iterator host
|
||||
, std::string url, tcp::endpoint proxy)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
@ -2090,7 +2125,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
std::pair<int, int> const& out_ports = m_settings.outgoing_ports;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
if (out_ports.first > 0 && out_ports.second >= out_ports.first)
|
||||
s->bind(tcp::endpoint(address(), m_ses.next_port()), ec);
|
||||
|
||||
|
@ -2135,9 +2170,7 @@ namespace libtorrent
|
|||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
(*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << e.what() << "\n";
|
||||
#endif
|
||||
|
||||
// TODO: post an error alert!
|
||||
c->disconnect(e.what());
|
||||
c->disconnect(e.what(), 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -2176,7 +2209,7 @@ namespace libtorrent
|
|||
};
|
||||
}
|
||||
|
||||
void torrent::on_country_lookup(asio::error_code const& error, tcp::resolver::iterator i
|
||||
void torrent::on_country_lookup(error_code const& error, tcp::resolver::iterator i
|
||||
, intrusive_ptr<peer_connection> p) const
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
@ -2287,6 +2320,19 @@ namespace libtorrent
|
|||
m_active_time = seconds((e != 0 && e->type() == entry::int_t)?e->integer():0);
|
||||
e = rd.find_key("seeding_time");
|
||||
m_seeding_time = seconds((e != 0 && e->type() == entry::int_t)?e->integer():0);
|
||||
|
||||
e = rd.find_key("num_seeds");
|
||||
m_complete = (e != 0 && e->type() == entry::int_t)?e->integer():-1;
|
||||
e = rd.find_key("num_downloaders");
|
||||
m_incomplete = (e != 0 && e->type() == entry::int_t)?e->integer():-1;
|
||||
/*
|
||||
m_total_uploaded = rd.find_int_value("total_uploaded");
|
||||
m_total_downloaded = rd.find_inte_value("total_downloaded");
|
||||
m_active_time = rd.find_int_value("active_time");
|
||||
m_seeding_time = rd.find_int_value("seeding_time");
|
||||
m_complete = rd.find_int_value("num_seeds", -1);
|
||||
m_incomplete = rd.find_int_value("num_downloaders", -1);
|
||||
*/
|
||||
}
|
||||
|
||||
void torrent::write_resume_data(entry& ret) const
|
||||
|
@ -2299,6 +2345,16 @@ namespace libtorrent
|
|||
|
||||
ret["active_time"] = total_seconds(m_active_time);
|
||||
ret["seeding_time"] = total_seconds(m_seeding_time);
|
||||
|
||||
int seeds = 0;
|
||||
int downloaders = 0;
|
||||
if (m_complete >= 0) seeds = m_complete;
|
||||
else seeds = m_policy.num_seeds();
|
||||
if (m_incomplete >= 0) downloaders = m_incomplete;
|
||||
else downloaders = m_policy.num_peers() - m_policy.num_seeds();
|
||||
|
||||
ret["num_seeds"] = seeds;
|
||||
ret["num_downloaders"] = downloaders;
|
||||
|
||||
ret["allocation"] = m_storage_mode == storage_mode_sparse?"sparse"
|
||||
:m_storage_mode == storage_mode_allocate?"full":"compact";
|
||||
|
@ -2369,7 +2425,7 @@ namespace libtorrent
|
|||
for (policy::const_iterator i = m_policy.begin_peer()
|
||||
, end(m_policy.end_peer()); i != end; ++i)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
if (i->second.banned)
|
||||
{
|
||||
tcp::endpoint ip = i->second.ip;
|
||||
|
@ -2538,7 +2594,7 @@ namespace libtorrent
|
|||
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s);
|
||||
TORRENT_ASSERT(ret);
|
||||
std::pair<int, int> const& out_ports = m_ses.settings().outgoing_ports;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
if (out_ports.first > 0 && out_ports.second >= out_ports.first)
|
||||
s->bind(tcp::endpoint(address(), m_ses.next_port()), ec);
|
||||
|
||||
|
@ -2571,6 +2627,7 @@ namespace libtorrent
|
|||
// add the newly connected peer to this torrent's peer list
|
||||
m_connections.insert(boost::get_pointer(c));
|
||||
m_ses.m_connections.insert(c);
|
||||
peerinfo->connection = c.get();
|
||||
c->start();
|
||||
|
||||
int timeout = settings().peer_connect_timeout;
|
||||
|
@ -2595,11 +2652,10 @@ namespace libtorrent
|
|||
return false;
|
||||
}
|
||||
#endif
|
||||
peerinfo->connection = c.get();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool torrent::set_metadata(entry const& metadata, std::string& error)
|
||||
bool torrent::set_metadata(lazy_entry const& metadata, std::string& error)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
|
@ -2683,7 +2739,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
|
||||
peer_iterator ci = m_connections.insert(p).first;
|
||||
#ifndef NDEBUG
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint(ec) || ec);
|
||||
#endif
|
||||
|
||||
|
@ -2698,7 +2754,8 @@ namespace libtorrent
|
|||
return int(m_connections.size()) < m_max_connections
|
||||
&& !m_paused
|
||||
&& m_state != torrent_status::checking_files
|
||||
&& m_state != torrent_status::queued_for_checking
|
||||
&& (m_state != torrent_status::queued_for_checking
|
||||
|| !valid_metadata())
|
||||
&& m_policy.num_connect_candidates() > 0;
|
||||
}
|
||||
|
||||
|
@ -2730,6 +2787,71 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// this returns true if lhs is a better disconnect candidate than rhs
|
||||
bool compare_disconnect_peer(peer_connection const* lhs, peer_connection const* rhs)
|
||||
{
|
||||
// prefer to disconnect peers we're not interested in
|
||||
if (lhs->is_interesting() != rhs->is_interesting())
|
||||
return rhs->is_interesting();
|
||||
|
||||
// prefer to disconnect peers that are not seeds
|
||||
if (lhs->is_seed() != rhs->is_seed())
|
||||
return rhs->is_seed();
|
||||
|
||||
// prefer to disconnect peers that are on parole
|
||||
if (lhs->on_parole() != rhs->on_parole())
|
||||
return lhs->on_parole();
|
||||
|
||||
// prefer to disconnect peers that send data at a lower rate
|
||||
size_type lhs_transferred = lhs->statistics().total_payload_download();
|
||||
size_type rhs_transferred = rhs->statistics().total_payload_download();
|
||||
|
||||
if (lhs_transferred != rhs_transferred
|
||||
&& lhs_transferred > 0
|
||||
&& rhs_transferred > 0)
|
||||
{
|
||||
ptime now = time_now();
|
||||
size_type lhs_time_connected = total_seconds(now - lhs->connected_time());
|
||||
size_type rhs_time_connected = total_seconds(now - rhs->connected_time());
|
||||
|
||||
double lhs_rate = double(lhs_transferred) / (lhs_time_connected + 1);
|
||||
double rhs_rate = double(rhs_transferred) / (rhs_time_connected + 1);
|
||||
|
||||
return lhs_rate < rhs_rate;
|
||||
}
|
||||
|
||||
// prefer to disconnect peers that chokes us
|
||||
if (lhs->is_choked() != rhs->is_choked())
|
||||
return lhs->is_choked();
|
||||
|
||||
return lhs->last_received() < rhs->last_received();
|
||||
}
|
||||
}
|
||||
|
||||
int torrent::disconnect_peers(int num)
|
||||
{
|
||||
int ret = 0;
|
||||
// buils a list of all connected peers and sort it by 'disconnectability'.
|
||||
std::vector<peer_connection*> peers(m_connections.size());
|
||||
std::copy(m_connections.begin(), m_connections.end(), peers.begin());
|
||||
std::sort(peers.begin(), peers.end(), boost::bind(&compare_disconnect_peer, _1, _2));
|
||||
|
||||
// never disconnect peers that connected less than 90 seconds ago
|
||||
ptime cut_off = time_now() - seconds(90);
|
||||
|
||||
for (std::vector<peer_connection*>::iterator i = peers.begin()
|
||||
, end(peers.end()); i != end && ret < num; ++i)
|
||||
{
|
||||
peer_connection* p = *i;
|
||||
if (p->connected_time() > cut_off) continue;
|
||||
++ret;
|
||||
p->disconnect("optimistic disconnect");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int torrent::bandwidth_throttle(int channel) const
|
||||
{
|
||||
return m_bandwidth_limit[channel].throttle();
|
||||
|
@ -2844,7 +2966,7 @@ namespace libtorrent
|
|||
{
|
||||
peer_connection* p = *i;
|
||||
TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
|
||||
if (p->is_seed())
|
||||
if (p->upload_only())
|
||||
{
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
(*p->m_logger) << "*** SEED, CLOSING CONNECTION\n";
|
||||
|
@ -2853,14 +2975,23 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
std::for_each(seeds.begin(), seeds.end()
|
||||
, bind(&peer_connection::disconnect, _1, "torrent finished, disconnecting seed"));
|
||||
, bind(&peer_connection::disconnect, _1, "torrent finished, disconnecting seed", 0));
|
||||
|
||||
TORRENT_ASSERT(m_storage);
|
||||
// we need to keep the object alive during this operation
|
||||
m_storage->async_release_files(
|
||||
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
|
||||
}
|
||||
|
||||
// this is called when we were finished, but some files were
|
||||
// marked for downloading, and we are no longer finished
|
||||
void torrent::resume_download()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_state = torrent_status::downloading;
|
||||
}
|
||||
|
||||
// called when torrent is complete (all pieces downloaded)
|
||||
void torrent::completed()
|
||||
{
|
||||
|
@ -2900,7 +3031,7 @@ namespace libtorrent
|
|||
if ((unsigned)m_currently_trying_tracker >= m_trackers.size())
|
||||
{
|
||||
int delay = tracker_retry_delay_min
|
||||
+ (std::min)(m_failed_trackers, (int)tracker_failed_max)
|
||||
+ (std::min)(int(m_failed_trackers), int(tracker_failed_max))
|
||||
* (tracker_retry_delay_max - tracker_retry_delay_min)
|
||||
/ tracker_failed_max;
|
||||
|
||||
|
@ -2968,8 +3099,6 @@ namespace libtorrent
|
|||
{
|
||||
m_state = torrent_status::seeding;
|
||||
m_picker.reset();
|
||||
if (m_ses.settings().free_torrent_hashes)
|
||||
m_torrent_file->seed_free();
|
||||
}
|
||||
|
||||
if (!m_connections_initialized)
|
||||
|
@ -3285,27 +3414,59 @@ namespace libtorrent
|
|||
m_ses.m_auto_manage_time_scaler = 0;
|
||||
}
|
||||
|
||||
float torrent::seed_cycles(session_settings const& s) const
|
||||
// the higher seed rank, the more important to seed
|
||||
int torrent::seed_rank(session_settings const& s) const
|
||||
{
|
||||
if (!is_seed()) return 0.f;
|
||||
enum flags
|
||||
{
|
||||
seed_ratio_not_met = 0x400000,
|
||||
recently_started = 0x200000,
|
||||
no_seeds = 0x100000,
|
||||
prio_mask = 0xfffff
|
||||
};
|
||||
|
||||
int seeding = total_seconds(m_seeding_time);
|
||||
int downloading = total_seconds(m_active_time) - seeding;
|
||||
if (!is_seed()) return 0;
|
||||
|
||||
// if the seed time limit is set to less than 60 minutes
|
||||
// use 60 minutes, to avoid oscillation
|
||||
float ret = seeding / float((std::max)(s.seed_time_limit, 60 * 60));
|
||||
int ret = 0;
|
||||
|
||||
// if it took less than 30 minutes to download, disregard the
|
||||
// seed_time_ratio_limit, since it would make it oscillate too frequent
|
||||
if (downloading > 30 * 60 && s.seed_time_ratio_limit >= 1.f)
|
||||
ret = (std::max)(ret, (seeding / downloading
|
||||
/ s.seed_time_ratio_limit));
|
||||
ptime now(time_now());
|
||||
|
||||
int seed_time = total_seconds(m_seeding_time);
|
||||
int download_time = total_seconds(m_active_time) - seed_time;
|
||||
|
||||
// if we haven't yet met the seed limits, set the seed_ratio_not_met
|
||||
// flag. That will make this seed prioritized
|
||||
size_type downloaded = (std::max)(m_total_downloaded, m_torrent_file->total_size());
|
||||
if (downloaded > 0 && s.share_ratio_limit >= 1.f)
|
||||
ret = (std::max)(ret, float(m_total_uploaded) / downloaded
|
||||
/ s.share_ratio_limit);
|
||||
if (seed_time < s.seed_time_limit
|
||||
&& (seed_time > 1 && download_time / float(seed_time) < s.seed_time_ratio_limit)
|
||||
&& m_total_uploaded / downloaded < s.share_ratio_limit)
|
||||
ret |= seed_ratio_not_met;
|
||||
|
||||
// if this torrent is running, and it was started less
|
||||
// than 30 minutes ago, give it priority, to avoid oscillation
|
||||
if (!is_paused() && now - m_started < minutes(30))
|
||||
ret |= recently_started;
|
||||
|
||||
// if we have any scrape data, use it to calculate
|
||||
// seed rank
|
||||
int seeds = 0;
|
||||
int downloaders = 0;
|
||||
|
||||
if (m_complete >= 0) seeds = m_complete;
|
||||
else seeds = m_policy.num_seeds();
|
||||
|
||||
if (m_incomplete >= 0) downloaders = m_incomplete;
|
||||
else downloaders = m_policy.num_peers() - m_policy.num_seeds();
|
||||
|
||||
if (seeds == 0)
|
||||
{
|
||||
ret |= no_seeds;
|
||||
ret |= downloaders & prio_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret |= (downloaders * 100 / seeds) & prio_mask;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -3402,6 +3563,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
m_paused = false;
|
||||
m_started = time_now();
|
||||
|
||||
// tell the tracker that we're back
|
||||
m_event = tracker_request::started;
|
||||
|
@ -3489,6 +3651,7 @@ namespace libtorrent
|
|||
{
|
||||
peer_connection* p = *i;
|
||||
++i;
|
||||
p->calc_ip_overhead();
|
||||
m_stat += p->statistics();
|
||||
// updates the peer connection's ul/dl bandwidth
|
||||
// resource requests
|
||||
|
@ -3504,8 +3667,7 @@ namespace libtorrent
|
|||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
(*p->m_logger) << "**ERROR**: " << e.what() << "\n";
|
||||
#endif
|
||||
p->set_failed();
|
||||
p->disconnect(e.what());
|
||||
p->disconnect(e.what(), 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -3643,8 +3805,18 @@ namespace libtorrent
|
|||
, m_have_pieces.end()
|
||||
, 0) == m_num_pieces);
|
||||
|
||||
ptime now = time_now();
|
||||
|
||||
torrent_status st;
|
||||
|
||||
if (m_last_scrape == min_time())
|
||||
{
|
||||
st.last_scrape = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
st.last_scrape = total_seconds(now - m_last_scrape);
|
||||
}
|
||||
st.up_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::upload_channel].size();
|
||||
st.down_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::download_channel].size();
|
||||
|
||||
|
@ -3654,7 +3826,7 @@ namespace libtorrent
|
|||
st.list_peers = m_policy.num_peers();
|
||||
st.list_seeds = m_policy.num_seeds();
|
||||
st.connect_candidates = m_policy.num_connect_candidates();
|
||||
st.seed_cycles = seed_cycles(m_ses.m_settings);
|
||||
st.seed_rank = seed_rank(m_ses.m_settings);
|
||||
|
||||
st.all_time_upload = m_total_uploaded;
|
||||
st.all_time_download = m_total_downloaded;
|
||||
|
@ -3668,6 +3840,7 @@ namespace libtorrent
|
|||
st.num_incomplete = m_incomplete;
|
||||
st.paused = m_paused;
|
||||
boost::tie(st.total_done, st.total_wanted_done) = bytes_done();
|
||||
TORRENT_ASSERT(st.total_wanted_done >= 0);
|
||||
TORRENT_ASSERT(st.total_done >= st.total_wanted_done);
|
||||
|
||||
// payload transfer
|
||||
|
@ -3691,7 +3864,7 @@ namespace libtorrent
|
|||
st.upload_payload_rate = m_stat.upload_payload_rate();
|
||||
|
||||
st.next_announce = boost::posix_time::seconds(
|
||||
total_seconds(next_announce() - time_now()));
|
||||
total_seconds(next_announce() - now));
|
||||
if (st.next_announce.is_negative())
|
||||
st.next_announce = boost::posix_time::seconds(0);
|
||||
|
||||
|
@ -3713,7 +3886,7 @@ namespace libtorrent
|
|||
|
||||
if (!valid_metadata())
|
||||
{
|
||||
if (m_got_tracker_response == false)
|
||||
if (m_got_tracker_response == false && m_connections.empty())
|
||||
st.state = torrent_status::connecting_to_tracker;
|
||||
else
|
||||
st.state = torrent_status::downloading_metadata;
|
||||
|
@ -3728,6 +3901,7 @@ namespace libtorrent
|
|||
// fill in status that depends on metadata
|
||||
|
||||
st.total_wanted = m_torrent_file->total_size();
|
||||
TORRENT_ASSERT(st.total_wanted >= 0);
|
||||
|
||||
if (m_picker.get() && (m_picker->num_filtered() > 0
|
||||
|| m_picker->num_have_filtered() > 0))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2003, Arvid Norberg
|
||||
Copyright (c) 2008, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
|
@ -159,13 +160,13 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
bool extract_single_file(entry const& dict, file_entry& target
|
||||
bool extract_single_file(lazy_entry const& dict, file_entry& target
|
||||
, std::string const& root_dir)
|
||||
{
|
||||
entry const* length = dict.find_key("length");
|
||||
if (length == 0 || length->type() != entry::int_t)
|
||||
lazy_entry const* length = dict.dict_find("length");
|
||||
if (length == 0 || length->type() != lazy_entry::int_t)
|
||||
return false;
|
||||
target.size = length->integer();
|
||||
target.size = length->int_value();
|
||||
target.path = root_dir;
|
||||
target.file_base = 0;
|
||||
|
||||
|
@ -173,27 +174,19 @@ namespace
|
|||
// because if it exists, it is more
|
||||
// likely to be correctly encoded
|
||||
|
||||
const entry::list_type* list = 0;
|
||||
entry const* p8 = dict.find_key("path.utf-8");
|
||||
if (p8 != 0 && p8->type() == entry::list_t)
|
||||
{
|
||||
list = &p8->list();
|
||||
}
|
||||
else
|
||||
{
|
||||
entry const* p = dict.find_key("path");
|
||||
if (p == 0 || p->type() != entry::list_t)
|
||||
return false;
|
||||
list = &p->list();
|
||||
}
|
||||
lazy_entry const* p = dict.dict_find("path.utf-8");
|
||||
if (p == 0 || p->type() != lazy_entry::list_t)
|
||||
p = dict.dict_find("path");
|
||||
if (p == 0 || p->type() != lazy_entry::list_t)
|
||||
return false;
|
||||
|
||||
for (entry::list_type::const_iterator i = list->begin();
|
||||
i != list->end(); ++i)
|
||||
for (int i = 0, end(p->list_size()); i < end; ++i)
|
||||
{
|
||||
if (i->type() != entry::string_t)
|
||||
if (p->list_at(i)->type() != lazy_entry::string_t)
|
||||
return false;
|
||||
if (i->string() != "..")
|
||||
target.path /= i->string();
|
||||
std::string path_element = p->list_at(i)->string_value();
|
||||
if (path_element != "..")
|
||||
target.path /= path_element;
|
||||
}
|
||||
verify_encoding(target);
|
||||
if (target.path.is_complete())
|
||||
|
@ -201,14 +194,15 @@ namespace
|
|||
return true;
|
||||
}
|
||||
|
||||
bool extract_files(const entry::list_type& list, std::vector<file_entry>& target
|
||||
bool extract_files(lazy_entry const& list, std::vector<file_entry>& target
|
||||
, std::string const& root_dir)
|
||||
{
|
||||
size_type offset = 0;
|
||||
for (entry::list_type::const_iterator i = list.begin(); i != list.end(); ++i)
|
||||
if (list.type() != lazy_entry::list_t) return false;
|
||||
for (int i = 0, end(list.list_size()); i < end; ++i)
|
||||
{
|
||||
target.push_back(file_entry());
|
||||
if (!extract_single_file(*i, target.back(), root_dir))
|
||||
if (!extract_single_file(*list.list_at(i), target.back(), root_dir))
|
||||
return false;
|
||||
target.back().offset = offset;
|
||||
offset += target.back().size;
|
||||
|
@ -231,25 +225,65 @@ namespace libtorrent
|
|||
{
|
||||
|
||||
// standard constructor that parses a torrent file
|
||||
torrent_info::torrent_info(const entry& torrent_file)
|
||||
torrent_info::torrent_info(entry const& torrent_file)
|
||||
: m_num_pieces(0)
|
||||
, m_creation_date(pt::ptime(pt::not_a_date_time))
|
||||
, m_multifile(false)
|
||||
, m_private(false)
|
||||
, m_extra_info(entry::dictionary_t)
|
||||
#ifndef NDEBUG
|
||||
, m_half_metadata(false)
|
||||
, m_info_section_size(0)
|
||||
, m_piece_hashes(0)
|
||||
{
|
||||
std::vector<char> tmp;
|
||||
std::back_insert_iterator<std::vector<char> > out(tmp);
|
||||
bencode(out, torrent_file);
|
||||
|
||||
lazy_entry e;
|
||||
lazy_bdecode(&tmp[0], &tmp[0] + tmp.size(), e);
|
||||
std::string error;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
if (!parse_torrent_file(e, error))
|
||||
throw invalid_torrent_file();
|
||||
#else
|
||||
read_torrent_info(e, error);
|
||||
#endif
|
||||
}
|
||||
|
||||
torrent_info::torrent_info(lazy_entry const& torrent_file)
|
||||
: m_num_pieces(0)
|
||||
, m_creation_date(pt::ptime(pt::not_a_date_time))
|
||||
, m_multifile(false)
|
||||
, m_private(false)
|
||||
, m_info_section_size(0)
|
||||
, m_piece_hashes(0)
|
||||
{
|
||||
std::string error;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
if (!read_torrent_info(torrent_file, error))
|
||||
if (!parse_torrent_file(torrent_file, error))
|
||||
throw invalid_torrent_file();
|
||||
#else
|
||||
read_torrent_info(torrent_file, error);
|
||||
#endif
|
||||
}
|
||||
|
||||
torrent_info::torrent_info(char const* buffer, int size)
|
||||
: m_num_pieces(0)
|
||||
, m_creation_date(pt::ptime(pt::not_a_date_time))
|
||||
, m_multifile(false)
|
||||
, m_private(false)
|
||||
, m_info_section_size(0)
|
||||
, m_piece_hashes(0)
|
||||
{
|
||||
std::string error;
|
||||
lazy_entry e;
|
||||
lazy_bdecode(buffer, buffer + size, e);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
if (!parse_torrent_file(e, error))
|
||||
throw invalid_torrent_file();
|
||||
#else
|
||||
read_torrent_info(e, error);
|
||||
#endif
|
||||
}
|
||||
|
||||
// constructor used for creating new torrents
|
||||
// will not contain any hashes, comments, creation date
|
||||
// just the necessary to use it with piece manager
|
||||
|
@ -263,10 +297,8 @@ namespace libtorrent
|
|||
, m_creation_date(pt::second_clock::universal_time())
|
||||
, m_multifile(false)
|
||||
, m_private(false)
|
||||
, m_extra_info(entry::dictionary_t)
|
||||
#ifndef NDEBUG
|
||||
, m_half_metadata(false)
|
||||
#endif
|
||||
, m_info_section_size(0)
|
||||
, m_piece_hashes(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -279,13 +311,35 @@ namespace libtorrent
|
|||
, m_creation_date(pt::second_clock::universal_time())
|
||||
, m_multifile(false)
|
||||
, m_private(false)
|
||||
, m_extra_info(entry::dictionary_t)
|
||||
#ifndef NDEBUG
|
||||
, m_half_metadata(false)
|
||||
#endif
|
||||
, m_info_section_size(0)
|
||||
, m_piece_hashes(0)
|
||||
{
|
||||
}
|
||||
|
||||
torrent_info::torrent_info(char const* filename)
|
||||
: m_num_pieces(0)
|
||||
, m_creation_date(pt::ptime(pt::not_a_date_time))
|
||||
, m_multifile(false)
|
||||
, m_private(false)
|
||||
{
|
||||
size_type s = fs::file_size(fs::path(filename));
|
||||
// don't load torrent files larger than 2 MB
|
||||
if (s > 2000000) return;
|
||||
std::vector<char> buf(s);
|
||||
std::ifstream f(filename);
|
||||
f.read(&buf[0], s);
|
||||
|
||||
std::string error;
|
||||
lazy_entry e;
|
||||
lazy_bdecode(&buf[0], &buf[0] + buf.size(), e);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
if (!parse_torrent_file(e, error))
|
||||
throw invalid_torrent_file();
|
||||
#else
|
||||
read_torrent_info(e, error);
|
||||
#endif
|
||||
}
|
||||
|
||||
torrent_info::~torrent_info()
|
||||
{}
|
||||
|
||||
|
@ -294,9 +348,8 @@ namespace libtorrent
|
|||
using std::swap;
|
||||
m_urls.swap(ti.m_urls);
|
||||
m_url_seeds.swap(ti.m_url_seeds);
|
||||
swap(m_piece_length, ti.m_piece_length);
|
||||
m_piece_hash.swap(ti.m_piece_hash);
|
||||
m_files.swap(ti.m_files);
|
||||
m_files.swap(ti.m_remapped_files);
|
||||
m_nodes.swap(ti.m_nodes);
|
||||
swap(m_num_pieces, ti.m_num_pieces);
|
||||
swap(m_info_hash, ti.m_info_hash);
|
||||
|
@ -306,83 +359,51 @@ namespace libtorrent
|
|||
m_created_by.swap(ti.m_created_by);
|
||||
swap(m_multifile, ti.m_multifile);
|
||||
swap(m_private, ti.m_private);
|
||||
m_extra_info.swap(ti.m_extra_info);
|
||||
#ifndef NDEBUG
|
||||
swap(m_half_metadata, ti.m_half_metadata);
|
||||
#endif
|
||||
swap(m_info_section, ti.m_info_section);
|
||||
swap(m_info_section_size, ti.m_info_section_size);
|
||||
swap(m_piece_hashes, ti.m_piece_hashes);
|
||||
swap(m_info_dict, ti.m_info_dict);
|
||||
}
|
||||
|
||||
void torrent_info::set_piece_size(int size)
|
||||
bool torrent_info::parse_info_section(lazy_entry const& info, std::string& error)
|
||||
{
|
||||
// make sure the size is an even power of 2
|
||||
#ifndef NDEBUG
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
if (size & (1 << i))
|
||||
{
|
||||
TORRENT_ASSERT((size & ~(1 << i)) == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
TORRENT_ASSERT(!m_half_metadata);
|
||||
m_piece_length = size;
|
||||
|
||||
m_num_pieces = static_cast<int>(
|
||||
(m_total_size + m_piece_length - 1) / m_piece_length);
|
||||
int old_num_pieces = static_cast<int>(m_piece_hash.size());
|
||||
|
||||
m_piece_hash.resize(m_num_pieces);
|
||||
for (int i = old_num_pieces; i < m_num_pieces; ++i)
|
||||
{
|
||||
m_piece_hash[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool torrent_info::parse_info_section(entry const& info, std::string& error)
|
||||
{
|
||||
if (info.type() != entry::dictionary_t)
|
||||
if (info.type() != lazy_entry::dict_t)
|
||||
{
|
||||
error = "'info' entry is not a dictionary";
|
||||
return false;
|
||||
}
|
||||
|
||||
// encode the info-field in order to calculate it's sha1-hash
|
||||
std::vector<char> buf;
|
||||
bencode(std::back_inserter(buf), info);
|
||||
// hash the info-field to calculate info-hash
|
||||
hasher h;
|
||||
h.update(&buf[0], (int)buf.size());
|
||||
std::pair<char const*, int> section = info.data_section();
|
||||
h.update(section.first, section.second);
|
||||
m_info_hash = h.final();
|
||||
|
||||
// copy the info section
|
||||
m_info_section_size = section.second;
|
||||
m_info_section.reset(new char[m_info_section_size]);
|
||||
memcpy(m_info_section.get(), section.first, m_info_section_size);
|
||||
TORRENT_ASSERT(section.first[0] == 'd');
|
||||
TORRENT_ASSERT(section.first[m_info_section_size-1] == 'e');
|
||||
|
||||
// extract piece length
|
||||
entry const* piece_length = info.find_key("piece length");
|
||||
if (piece_length == 0 || piece_length->type() != entry::int_t)
|
||||
m_piece_length = info.dict_find_int_value("piece length", -1);
|
||||
if (m_piece_length <= 0)
|
||||
{
|
||||
error = "invalid or missing 'piece length' entry in torrent file";
|
||||
return false;
|
||||
}
|
||||
m_piece_length = int(piece_length->integer());
|
||||
if (m_piece_length <= 0)
|
||||
|
||||
// extract file name (or the directory name if it's a multifile libtorrent)
|
||||
m_name = info.dict_find_string_value("name.utf-8");
|
||||
if (m_name.empty()) m_name = info.dict_find_string_value("name");
|
||||
|
||||
if (m_name.empty())
|
||||
{
|
||||
error = "invalid torrent. piece length <= 0";
|
||||
error = "invalid name in torrent file";
|
||||
return false;
|
||||
}
|
||||
|
||||
// extract file name (or the directory name if it's a multifile libtorrent)
|
||||
entry const* e = info.find_key("name.utf-8");
|
||||
if (e && e->type() == entry::string_t)
|
||||
{ m_name = e->string(); }
|
||||
else
|
||||
{
|
||||
entry const* e = info.find_key("name");
|
||||
if (e == 0 || e->type() != entry::string_t)
|
||||
{
|
||||
error = "invalid name in torrent file";
|
||||
return false;
|
||||
}
|
||||
m_name = e->string();
|
||||
}
|
||||
|
||||
fs::path tmp = m_name;
|
||||
if (tmp.is_complete())
|
||||
{
|
||||
|
@ -401,32 +422,31 @@ namespace libtorrent
|
|||
}
|
||||
if (m_name == ".." || m_name == ".")
|
||||
{
|
||||
|
||||
error = "invalid 'name' of torrent (possible exploit attempt)";
|
||||
return false;
|
||||
}
|
||||
|
||||
// extract file list
|
||||
entry const* i = info.find_key("files");
|
||||
lazy_entry const* i = info.dict_find_list("files");
|
||||
if (i == 0)
|
||||
{
|
||||
entry const* length = info.find_key("length");
|
||||
if (length == 0 || length->type() != entry::int_t)
|
||||
{
|
||||
error = "invalid length of torrent";
|
||||
return false;
|
||||
}
|
||||
// if there's no list of files, there has to be a length
|
||||
// field.
|
||||
file_entry e;
|
||||
e.path = m_name;
|
||||
e.offset = 0;
|
||||
e.size = length->integer();
|
||||
e.size = info.dict_find_int_value("length", -1);
|
||||
if (e.size < 0)
|
||||
{
|
||||
error = "invalid length of torrent";
|
||||
return false;
|
||||
}
|
||||
m_files.push_back(e);
|
||||
m_multifile = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!extract_files(i->list(), m_files, m_name))
|
||||
if (!extract_files(*i, m_files, m_name))
|
||||
{
|
||||
error = "failed to parse files from torrent file";
|
||||
return false;
|
||||
|
@ -443,84 +463,51 @@ namespace libtorrent
|
|||
// we want this division to round upwards, that's why we have the
|
||||
// extra addition
|
||||
|
||||
entry const* pieces_ent = info.find_key("pieces");
|
||||
if (pieces_ent == 0 || pieces_ent->type() != entry::string_t)
|
||||
m_num_pieces = static_cast<int>((m_total_size + m_piece_length - 1) / m_piece_length);
|
||||
|
||||
lazy_entry const* pieces = info.dict_find("pieces");
|
||||
if (pieces == 0 || pieces->type() != lazy_entry::string_t)
|
||||
{
|
||||
error = "invalid or missing 'pieces' entry in torrent file";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_num_pieces = static_cast<int>((m_total_size + m_piece_length - 1) / m_piece_length);
|
||||
m_piece_hash.resize(m_num_pieces);
|
||||
const std::string& hash_string = pieces_ent->string();
|
||||
|
||||
if ((int)hash_string.length() != m_num_pieces * 20)
|
||||
if (pieces->string_length() != m_num_pieces * 20)
|
||||
{
|
||||
error = "incorrect number of piece hashes in torrent file";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_num_pieces; ++i)
|
||||
std::copy(
|
||||
hash_string.begin() + i*20
|
||||
, hash_string.begin() + (i+1)*20
|
||||
, m_piece_hash[i].begin());
|
||||
m_piece_hashes = m_info_section.get() + (pieces->string_ptr() - section.first);
|
||||
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
|
||||
TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
|
||||
|
||||
for (entry::dictionary_type::const_iterator i = info.dict().begin()
|
||||
, end(info.dict().end()); i != end; ++i)
|
||||
{
|
||||
if (i->first == "pieces"
|
||||
|| i->first == "piece length"
|
||||
|| i->first == "length")
|
||||
continue;
|
||||
m_extra_info[i->first] = i->second;
|
||||
}
|
||||
|
||||
if (entry const* priv = info.find_key("private"))
|
||||
{
|
||||
if (priv->type() != entry::int_t
|
||||
|| priv->integer() != 0)
|
||||
{
|
||||
// this key exists and it's not 0.
|
||||
// consider the torrent private
|
||||
m_private = true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::vector<char> info_section_buf;
|
||||
entry gen_info_section = create_info_metadata();
|
||||
bencode(std::back_inserter(info_section_buf), gen_info_section);
|
||||
TORRENT_ASSERT(hasher(&info_section_buf[0], info_section_buf.size()).final()
|
||||
== m_info_hash);
|
||||
#endif
|
||||
m_private = info.dict_find_int_value("private", 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// extracts information from a libtorrent file and fills in the structures in
|
||||
// the torrent object
|
||||
bool torrent_info::read_torrent_info(const entry& torrent_file, std::string& error)
|
||||
bool torrent_info::parse_torrent_file(lazy_entry const& torrent_file, std::string& error)
|
||||
{
|
||||
if (torrent_file.type() != entry::dictionary_t)
|
||||
if (torrent_file.type() != lazy_entry::dict_t)
|
||||
{
|
||||
error = "torrent file is not a dictionary";
|
||||
return false;
|
||||
}
|
||||
|
||||
// extract the url of the tracker
|
||||
entry const* i = torrent_file.find_key("announce-list");
|
||||
if (i && i->type() == entry::list_t)
|
||||
lazy_entry const* i = torrent_file.dict_find_list("announce-list");
|
||||
if (i)
|
||||
{
|
||||
const entry::list_type& l = i->list();
|
||||
for (entry::list_type::const_iterator j = l.begin(); j != l.end(); ++j)
|
||||
m_urls.reserve(i->list_size());
|
||||
for (int j = 0, end(i->list_size()); j < end; ++j)
|
||||
{
|
||||
if (j->type() != entry::list_t) break;
|
||||
const entry::list_type& ll = j->list();
|
||||
for (entry::list_type::const_iterator k = ll.begin(); k != ll.end(); ++k)
|
||||
lazy_entry const* tier = i->list_at(j);
|
||||
if (tier->type() != lazy_entry::list_t) continue;
|
||||
for (int k = 0, end(tier->list_size()); k < end; ++k)
|
||||
{
|
||||
if (k->type() != entry::string_t) break;
|
||||
announce_entry e(k->string());
|
||||
e.tier = (int)std::distance(l.begin(), j);
|
||||
announce_entry e(tier->list_string_value_at(k));
|
||||
if (e.url.empty()) continue;
|
||||
e.tier = j;
|
||||
m_urls.push_back(e);
|
||||
}
|
||||
}
|
||||
|
@ -541,71 +528,62 @@ namespace libtorrent
|
|||
std::random_shuffle(start, stop);
|
||||
}
|
||||
|
||||
entry const* announce = torrent_file.find_key("announce");
|
||||
if (m_urls.empty() && announce && announce->type() == entry::string_t)
|
||||
|
||||
if (m_urls.empty())
|
||||
{
|
||||
m_urls.push_back(announce_entry(announce->string()));
|
||||
announce_entry e(torrent_file.dict_find_string_value("announce"));
|
||||
if (!e.url.empty()) m_urls.push_back(e);
|
||||
}
|
||||
|
||||
entry const* nodes = torrent_file.find_key("nodes");
|
||||
if (nodes && nodes->type() == entry::list_t)
|
||||
lazy_entry const* nodes = torrent_file.dict_find_list("nodes");
|
||||
if (nodes)
|
||||
{
|
||||
entry::list_type const& list = nodes->list();
|
||||
for (entry::list_type::const_iterator i(list.begin())
|
||||
, end(list.end()); i != end; ++i)
|
||||
for (int i = 0, end(nodes->list_size()); i < end; ++i)
|
||||
{
|
||||
if (i->type() != entry::list_t) continue;
|
||||
entry::list_type const& l = i->list();
|
||||
entry::list_type::const_iterator iter = l.begin();
|
||||
if (l.size() < 1) continue;
|
||||
if (iter->type() != entry::string_t) continue;
|
||||
std::string const& hostname = iter->string();
|
||||
++iter;
|
||||
int port = 6881;
|
||||
if (iter->type() != entry::int_t) continue;
|
||||
if (l.end() != iter) port = int(iter->integer());
|
||||
m_nodes.push_back(std::make_pair(hostname, port));
|
||||
lazy_entry const* n = nodes->list_at(i);
|
||||
if (n->type() != lazy_entry::list_t
|
||||
|| n->list_size() < 2
|
||||
|| n->list_at(0)->type() != lazy_entry::string_t
|
||||
|| n->list_at(1)->type() != lazy_entry::int_t)
|
||||
continue;
|
||||
m_nodes.push_back(std::make_pair(
|
||||
n->list_at(0)->string_value()
|
||||
, int(n->list_at(1)->int_value())));
|
||||
}
|
||||
}
|
||||
|
||||
// extract creation date
|
||||
entry const* creation_date = torrent_file.find_key("creation date");
|
||||
if (creation_date && creation_date->type() == entry::int_t)
|
||||
size_type cd = torrent_file.dict_find_int_value("creation date", -1);
|
||||
if (cd >= 0)
|
||||
{
|
||||
m_creation_date = pt::ptime(gr::date(1970, gr::Jan, 1))
|
||||
+ pt::seconds(long(creation_date->integer()));
|
||||
+ pt::seconds(long(cd));
|
||||
}
|
||||
|
||||
// if there are any url-seeds, extract them
|
||||
entry const* url_seeds = torrent_file.find_key("url-list");
|
||||
if (url_seeds && url_seeds->type() == entry::string_t)
|
||||
lazy_entry const* url_seeds = torrent_file.dict_find("url-list");
|
||||
if (url_seeds && url_seeds->type() == lazy_entry::string_t)
|
||||
{
|
||||
m_url_seeds.push_back(url_seeds->string());
|
||||
m_url_seeds.push_back(url_seeds->string_value());
|
||||
}
|
||||
else if (url_seeds && url_seeds->type() == entry::list_t)
|
||||
else if (url_seeds && url_seeds->type() == lazy_entry::list_t)
|
||||
{
|
||||
entry::list_type const& l = url_seeds->list();
|
||||
for (entry::list_type::const_iterator i = l.begin();
|
||||
i != l.end(); ++i)
|
||||
for (int i = 0, end(url_seeds->list_size()); i < end; ++i)
|
||||
{
|
||||
if (i->type() != entry::string_t) continue;
|
||||
m_url_seeds.push_back(i->string());
|
||||
lazy_entry const* url = url_seeds->list_at(i);
|
||||
if (url->type() != lazy_entry::string_t) continue;
|
||||
m_url_seeds.push_back(url->string_value());
|
||||
}
|
||||
}
|
||||
|
||||
// extract comment
|
||||
if (entry const* e = torrent_file.find_key("comment.utf-8"))
|
||||
{ m_comment = e->string(); }
|
||||
else if (entry const* e = torrent_file.find_key("comment"))
|
||||
{ m_comment = e->string(); }
|
||||
m_comment = torrent_file.dict_find_string_value("comment.utf-8");
|
||||
if (m_comment.empty()) m_comment = torrent_file.dict_find_string_value("comment");
|
||||
|
||||
if (entry const* e = torrent_file.find_key("created by.utf-8"))
|
||||
{ m_created_by = e->string(); }
|
||||
else if (entry const* e = torrent_file.find_key("created by"))
|
||||
{ m_created_by = e->string(); }
|
||||
m_created_by = torrent_file.dict_find_string_value("created by.utf-8");
|
||||
if (m_created_by.empty()) m_created_by = torrent_file.dict_find_string_value("created by");
|
||||
|
||||
entry const* info = torrent_file.find_key("info");
|
||||
if (info == 0 || info->type() != entry::dictionary_t)
|
||||
lazy_entry const* info = torrent_file.dict_find_dict("info");
|
||||
if (info == 0)
|
||||
{
|
||||
error = "missing or invalid 'info' section in torrent file";
|
||||
return false;
|
||||
|
@ -634,234 +612,6 @@ namespace libtorrent
|
|||
, bind(&announce_entry::tier, _1), bind(&announce_entry::tier, _2)));
|
||||
}
|
||||
|
||||
void torrent_info::add_file(fs::path file, size_type size)
|
||||
{
|
||||
// TORRENT_ASSERT(file.begin() != file.end());
|
||||
|
||||
if (!file.has_branch_path())
|
||||
{
|
||||
// you have already added at least one file with a
|
||||
// path to the file (branch_path), which means that
|
||||
// all the other files need to be in the same top
|
||||
// directory as the first file.
|
||||
TORRENT_ASSERT(m_files.empty());
|
||||
TORRENT_ASSERT(!m_multifile);
|
||||
m_name = file.string();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (!m_files.empty())
|
||||
TORRENT_ASSERT(m_name == *file.begin());
|
||||
#endif
|
||||
m_multifile = true;
|
||||
m_name = *file.begin();
|
||||
}
|
||||
|
||||
file_entry e;
|
||||
e.path = file;
|
||||
e.size = size;
|
||||
e.offset = m_files.empty() ? 0 : m_files.back().offset
|
||||
+ m_files.back().size;
|
||||
m_files.push_back(e);
|
||||
|
||||
m_total_size += size;
|
||||
|
||||
if (m_piece_length == 0)
|
||||
m_piece_length = 256 * 1024;
|
||||
|
||||
m_num_pieces = static_cast<int>(
|
||||
(m_total_size + m_piece_length - 1) / m_piece_length);
|
||||
int old_num_pieces = static_cast<int>(m_piece_hash.size());
|
||||
|
||||
m_piece_hash.resize(m_num_pieces);
|
||||
if (m_num_pieces > old_num_pieces)
|
||||
std::for_each(m_piece_hash.begin() + old_num_pieces
|
||||
, m_piece_hash.end(), boost::bind(&sha1_hash::clear, _1));
|
||||
}
|
||||
|
||||
void torrent_info::add_url_seed(std::string const& url)
|
||||
{
|
||||
m_url_seeds.push_back(url);
|
||||
}
|
||||
|
||||
void torrent_info::set_comment(char const* str)
|
||||
{
|
||||
m_comment = str;
|
||||
}
|
||||
|
||||
void torrent_info::set_creator(char const* str)
|
||||
{
|
||||
m_created_by = str;
|
||||
}
|
||||
|
||||
entry torrent_info::create_info_metadata() const
|
||||
{
|
||||
// you have to add files to the torrent first
|
||||
TORRENT_ASSERT(!m_files.empty());
|
||||
|
||||
entry info(m_extra_info);
|
||||
|
||||
if (!info.find_key("name"))
|
||||
info["name"] = m_name;
|
||||
|
||||
if (m_private) info["private"] = 1;
|
||||
|
||||
if (!m_multifile)
|
||||
{
|
||||
info["length"] = m_files.front().size;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!info.find_key("files"))
|
||||
{
|
||||
entry& files = info["files"];
|
||||
|
||||
for (std::vector<file_entry>::const_iterator i = m_files.begin();
|
||||
i != m_files.end(); ++i)
|
||||
{
|
||||
files.list().push_back(entry());
|
||||
entry& file_e = files.list().back();
|
||||
file_e["length"] = i->size;
|
||||
entry& path_e = file_e["path"];
|
||||
|
||||
fs::path const* file_path;
|
||||
if (i->orig_path) file_path = &(*i->orig_path);
|
||||
else file_path = &i->path;
|
||||
TORRENT_ASSERT(file_path->has_branch_path());
|
||||
TORRENT_ASSERT(*file_path->begin() == m_name);
|
||||
|
||||
for (fs::path::iterator j = boost::next(file_path->begin());
|
||||
j != file_path->end(); ++j)
|
||||
{
|
||||
path_e.list().push_back(entry(*j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info["piece length"] = piece_length();
|
||||
entry& pieces = info["pieces"];
|
||||
|
||||
std::string& p = pieces.string();
|
||||
|
||||
for (std::vector<sha1_hash>::const_iterator i = m_piece_hash.begin();
|
||||
i != m_piece_hash.end(); ++i)
|
||||
{
|
||||
p.append((char*)i->begin(), (char*)i->end());
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
entry torrent_info::create_torrent() const
|
||||
{
|
||||
TORRENT_ASSERT(m_piece_length > 0);
|
||||
|
||||
if (m_files.empty())
|
||||
{
|
||||
// TODO: throw something here
|
||||
// throw
|
||||
return entry();
|
||||
}
|
||||
|
||||
entry dict;
|
||||
|
||||
if (!m_urls.empty())
|
||||
dict["announce"] = m_urls.front().url;
|
||||
|
||||
if (!m_nodes.empty())
|
||||
{
|
||||
entry& nodes = dict["nodes"];
|
||||
entry::list_type& nodes_list = nodes.list();
|
||||
for (nodes_t::const_iterator i = m_nodes.begin()
|
||||
, end(m_nodes.end()); i != end; ++i)
|
||||
{
|
||||
entry::list_type node;
|
||||
node.push_back(entry(i->first));
|
||||
node.push_back(entry(i->second));
|
||||
nodes_list.push_back(entry(node));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_urls.size() > 1)
|
||||
{
|
||||
entry trackers(entry::list_t);
|
||||
entry tier(entry::list_t);
|
||||
int current_tier = m_urls.front().tier;
|
||||
for (std::vector<announce_entry>::const_iterator i = m_urls.begin();
|
||||
i != m_urls.end(); ++i)
|
||||
{
|
||||
if (i->tier != current_tier)
|
||||
{
|
||||
current_tier = i->tier;
|
||||
trackers.list().push_back(tier);
|
||||
tier.list().clear();
|
||||
}
|
||||
tier.list().push_back(entry(i->url));
|
||||
}
|
||||
trackers.list().push_back(tier);
|
||||
dict["announce-list"] = trackers;
|
||||
}
|
||||
|
||||
if (!m_comment.empty())
|
||||
dict["comment"] = m_comment;
|
||||
|
||||
dict["creation date"] =
|
||||
(m_creation_date - pt::ptime(gr::date(1970, gr::Jan, 1))).total_seconds();
|
||||
|
||||
if (!m_created_by.empty())
|
||||
dict["created by"] = m_created_by;
|
||||
|
||||
if (!m_url_seeds.empty())
|
||||
{
|
||||
if (m_url_seeds.size() == 1)
|
||||
{
|
||||
dict["url-list"] = m_url_seeds.front();
|
||||
}
|
||||
else
|
||||
{
|
||||
entry& list = dict["url-list"];
|
||||
for (std::vector<std::string>::const_iterator i
|
||||
= m_url_seeds.begin(); i != m_url_seeds.end(); ++i)
|
||||
{
|
||||
list.list().push_back(entry(*i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dict["info"] = create_info_metadata();
|
||||
|
||||
entry const& info_section = dict["info"];
|
||||
std::vector<char> buf;
|
||||
bencode(std::back_inserter(buf), info_section);
|
||||
m_info_hash = hasher(&buf[0], buf.size()).final();
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
void torrent_info::set_hash(int index, const sha1_hash& h)
|
||||
{
|
||||
TORRENT_ASSERT(index >= 0);
|
||||
TORRENT_ASSERT(index < (int)m_piece_hash.size());
|
||||
m_piece_hash[index] = h;
|
||||
}
|
||||
|
||||
void torrent_info::convert_file_names()
|
||||
{
|
||||
TORRENT_ASSERT(false);
|
||||
}
|
||||
|
||||
void torrent_info::seed_free()
|
||||
{
|
||||
std::vector<std::string>().swap(m_url_seeds);
|
||||
nodes_t().swap(m_nodes);
|
||||
std::vector<sha1_hash>().swap(m_piece_hash);
|
||||
#ifndef NDEBUG
|
||||
m_half_metadata = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------- start deprecation -------
|
||||
|
||||
void torrent_info::print(std::ostream& os) const
|
||||
|
@ -901,11 +651,6 @@ namespace libtorrent
|
|||
return piece_length();
|
||||
}
|
||||
|
||||
void torrent_info::add_node(std::pair<std::string, int> const& node)
|
||||
{
|
||||
m_nodes.push_back(node);
|
||||
}
|
||||
|
||||
bool torrent_info::remap_files(std::vector<file_entry> const& map)
|
||||
{
|
||||
size_type offset = 0;
|
||||
|
|
|
@ -84,7 +84,7 @@ namespace libtorrent
|
|||
|
||||
int timeout = (std::min)(
|
||||
m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timeout.expires_at(m_read_time + seconds(timeout), ec);
|
||||
m_timeout.async_wait(bind(
|
||||
&timeout_handler::timeout_callback, self(), _1));
|
||||
|
@ -99,11 +99,11 @@ namespace libtorrent
|
|||
{
|
||||
m_abort = true;
|
||||
m_completion_timeout = 0;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timeout.cancel(ec);
|
||||
}
|
||||
|
||||
void timeout_handler::timeout_callback(asio::error_code const& error)
|
||||
void timeout_handler::timeout_callback(error_code const& error)
|
||||
{
|
||||
if (error) return;
|
||||
if (m_completion_timeout == 0) return;
|
||||
|
@ -125,7 +125,7 @@ namespace libtorrent
|
|||
|
||||
int timeout = (std::min)(
|
||||
m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_timeout.expires_at(m_read_time + seconds(timeout), ec);
|
||||
m_timeout.async_wait(
|
||||
bind(&timeout_handler::timeout_callback, self(), _1));
|
||||
|
@ -180,83 +180,6 @@ namespace libtorrent
|
|||
m_connections.erase(i);
|
||||
}
|
||||
|
||||
// returns protocol, auth, hostname, port, path
|
||||
tuple<std::string, std::string, std::string, int, std::string>
|
||||
parse_url_components(std::string url)
|
||||
{
|
||||
std::string hostname; // hostname only
|
||||
std::string auth; // user:pass
|
||||
std::string protocol; // http or https for instance
|
||||
int port = 80;
|
||||
|
||||
std::string::iterator at;
|
||||
std::string::iterator colon;
|
||||
std::string::iterator port_pos;
|
||||
|
||||
// PARSE URL
|
||||
std::string::iterator start = url.begin();
|
||||
// remove white spaces in front of the url
|
||||
while (start != url.end() && (*start == ' ' || *start == '\t'))
|
||||
++start;
|
||||
std::string::iterator end
|
||||
= std::find(url.begin(), url.end(), ':');
|
||||
protocol.assign(start, end);
|
||||
|
||||
if (protocol == "https") port = 443;
|
||||
|
||||
if (end == url.end()) goto exit;
|
||||
++end;
|
||||
if (end == url.end()) goto exit;
|
||||
if (*end != '/') goto exit;
|
||||
++end;
|
||||
if (end == url.end()) goto exit;
|
||||
if (*end != '/') goto exit;
|
||||
++end;
|
||||
start = end;
|
||||
|
||||
at = std::find(start, url.end(), '@');
|
||||
colon = std::find(start, url.end(), ':');
|
||||
end = std::find(start, url.end(), '/');
|
||||
|
||||
if (at != url.end()
|
||||
&& colon != url.end()
|
||||
&& colon < at
|
||||
&& at < end)
|
||||
{
|
||||
auth.assign(start, at);
|
||||
start = at;
|
||||
++start;
|
||||
}
|
||||
|
||||
// this is for IPv6 addresses
|
||||
if (start != url.end() && *start == '[')
|
||||
{
|
||||
port_pos = std::find(start, url.end(), ']');
|
||||
if (port_pos == url.end()) goto exit;
|
||||
port_pos = std::find(port_pos, url.end(), ':');
|
||||
}
|
||||
else
|
||||
{
|
||||
port_pos = std::find(start, url.end(), ':');
|
||||
}
|
||||
|
||||
if (port_pos < end)
|
||||
{
|
||||
hostname.assign(start, port_pos);
|
||||
++port_pos;
|
||||
port = atoi(std::string(port_pos, end).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
hostname.assign(start, end);
|
||||
}
|
||||
|
||||
start = end;
|
||||
exit:
|
||||
return make_tuple(protocol, auth, hostname, port
|
||||
, std::string(start, url.end()));
|
||||
}
|
||||
|
||||
void tracker_manager::queue_request(
|
||||
io_service& ios
|
||||
, connection_queue& cc
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/read.hpp>
|
||||
#else
|
||||
#include <boost/asio/read.hpp>
|
||||
#endif
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
|
@ -22,7 +26,7 @@ udp_socket::udp_socket(asio::io_service& ios, udp_socket::callback_t const& c
|
|||
{
|
||||
}
|
||||
|
||||
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, asio::error_code& ec)
|
||||
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec)
|
||||
{
|
||||
if (ec == asio::error::operation_aborted) return;
|
||||
|
||||
|
@ -39,7 +43,7 @@ void udp_socket::send(udp::endpoint const& ep, char const* p, int len, asio::err
|
|||
m_ipv6_sock.send_to(asio::buffer(p, len), ep, 0, ec);
|
||||
}
|
||||
|
||||
void udp_socket::on_read(udp::socket* s, asio::error_code const& e, std::size_t bytes_transferred)
|
||||
void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_transferred)
|
||||
{
|
||||
if (e == asio::error::operation_aborted) return;
|
||||
|
||||
|
@ -113,7 +117,7 @@ void udp_socket::on_read(udp::socket* s, asio::error_code const& e, std::size_t
|
|||
}
|
||||
}
|
||||
|
||||
void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, asio::error_code& ec)
|
||||
void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec)
|
||||
{
|
||||
using namespace libtorrent::detail;
|
||||
|
||||
|
@ -137,7 +141,7 @@ void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, asio::err
|
|||
}
|
||||
|
||||
// unwrap the UDP packet from the SOCKS5 header
|
||||
void udp_socket::unwrap(asio::error_code const& e, char const* buf, int size)
|
||||
void udp_socket::unwrap(error_code const& e, char const* buf, int size)
|
||||
{
|
||||
using namespace libtorrent::detail;
|
||||
|
||||
|
@ -174,7 +178,7 @@ void udp_socket::unwrap(asio::error_code const& e, char const* buf, int size)
|
|||
|
||||
void udp_socket::close()
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_ipv4_sock.close(ec);
|
||||
m_ipv6_sock.close(ec);
|
||||
m_socks5_sock.close(ec);
|
||||
|
@ -186,7 +190,7 @@ void udp_socket::close()
|
|||
}
|
||||
}
|
||||
|
||||
void udp_socket::bind(udp::endpoint const& ep, asio::error_code& ec)
|
||||
void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
|
||||
{
|
||||
if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
|
||||
if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec);
|
||||
|
@ -214,7 +218,7 @@ void udp_socket::bind(udp::endpoint const& ep, asio::error_code& ec)
|
|||
|
||||
void udp_socket::bind(int port)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
|
||||
if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
|
||||
if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec);
|
||||
|
@ -239,7 +243,7 @@ void udp_socket::bind(int port)
|
|||
|
||||
void udp_socket::set_proxy_settings(proxy_settings const& ps)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socks5_sock.close(ec);
|
||||
m_tunnel_packets = false;
|
||||
|
||||
|
@ -256,7 +260,7 @@ void udp_socket::set_proxy_settings(proxy_settings const& ps)
|
|||
}
|
||||
}
|
||||
|
||||
void udp_socket::on_name_lookup(asio::error_code const& e, tcp::resolver::iterator i)
|
||||
void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i)
|
||||
{
|
||||
if (e) return;
|
||||
m_proxy_addr.address(i->endpoint().address());
|
||||
|
@ -267,7 +271,7 @@ void udp_socket::on_name_lookup(asio::error_code const& e, tcp::resolver::iterat
|
|||
|
||||
void udp_socket::on_timeout()
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socks5_sock.close(ec);
|
||||
m_connection_ticket = -1;
|
||||
}
|
||||
|
@ -275,13 +279,13 @@ void udp_socket::on_timeout()
|
|||
void udp_socket::on_connect(int ticket)
|
||||
{
|
||||
m_connection_ticket = ticket;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socks5_sock.open(m_proxy_addr.address().is_v4()?tcp::v4():tcp::v6(), ec);
|
||||
m_socks5_sock.async_connect(tcp::endpoint(m_proxy_addr.address(), m_proxy_addr.port())
|
||||
, boost::bind(&udp_socket::on_connected, this, _1));
|
||||
}
|
||||
|
||||
void udp_socket::on_connected(asio::error_code const& e)
|
||||
void udp_socket::on_connected(error_code const& e)
|
||||
{
|
||||
m_cc.done(m_connection_ticket);
|
||||
m_connection_ticket = -1;
|
||||
|
@ -308,7 +312,7 @@ void udp_socket::on_connected(asio::error_code const& e)
|
|||
, boost::bind(&udp_socket::handshake1, this, _1));
|
||||
}
|
||||
|
||||
void udp_socket::handshake1(asio::error_code const& e)
|
||||
void udp_socket::handshake1(error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
|
@ -316,7 +320,7 @@ void udp_socket::handshake1(asio::error_code const& e)
|
|||
, boost::bind(&udp_socket::handshake2, this, _1));
|
||||
}
|
||||
|
||||
void udp_socket::handshake2(asio::error_code const& e)
|
||||
void udp_socket::handshake2(error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
|
@ -336,7 +340,7 @@ void udp_socket::handshake2(asio::error_code const& e)
|
|||
{
|
||||
if (m_proxy_settings.username.empty())
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socks5_sock.close(ec);
|
||||
return;
|
||||
}
|
||||
|
@ -353,13 +357,13 @@ void udp_socket::handshake2(asio::error_code const& e)
|
|||
}
|
||||
else
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socks5_sock.close(ec);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void udp_socket::handshake3(asio::error_code const& e)
|
||||
void udp_socket::handshake3(error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
|
@ -367,7 +371,7 @@ void udp_socket::handshake3(asio::error_code const& e)
|
|||
, boost::bind(&udp_socket::handshake4, this, _1));
|
||||
}
|
||||
|
||||
void udp_socket::handshake4(asio::error_code const& e)
|
||||
void udp_socket::handshake4(error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
|
@ -400,7 +404,7 @@ void udp_socket::socks_forward_udp()
|
|||
, boost::bind(&udp_socket::connect1, this, _1));
|
||||
}
|
||||
|
||||
void udp_socket::connect1(asio::error_code const& e)
|
||||
void udp_socket::connect1(error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
|
@ -408,7 +412,7 @@ void udp_socket::connect1(asio::error_code const& e)
|
|||
, boost::bind(&udp_socket::connect2, this, _1));
|
||||
}
|
||||
|
||||
void udp_socket::connect2(asio::error_code const& e)
|
||||
void udp_socket::connect2(error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#endif
|
||||
|
||||
#include "libtorrent/tracker_manager.hpp"
|
||||
#include "libtorrent/parse_url.hpp"
|
||||
#include "libtorrent/udp_tracker_connection.hpp"
|
||||
#include "libtorrent/io.hpp"
|
||||
|
||||
|
@ -95,10 +96,18 @@ namespace libtorrent
|
|||
|
||||
std::string hostname;
|
||||
int port;
|
||||
char const* error;
|
||||
|
||||
using boost::tuples::ignore;
|
||||
boost::tie(ignore, ignore, hostname, port, ignore) = parse_url_components(req.url);
|
||||
boost::tie(ignore, ignore, hostname, port, ignore, error)
|
||||
= parse_url_components(req.url);
|
||||
|
||||
if (error)
|
||||
{
|
||||
fail(-1, error);
|
||||
return;
|
||||
}
|
||||
|
||||
udp::resolver::query q(hostname, boost::lexical_cast<std::string>(port));
|
||||
m_name_lookup.async_resolve(q
|
||||
, boost::bind(
|
||||
|
@ -113,7 +122,7 @@ namespace libtorrent
|
|||
#endif
|
||||
}
|
||||
|
||||
void udp_tracker_connection::name_lookup(asio::error_code const& error
|
||||
void udp_tracker_connection::name_lookup(error_code const& error
|
||||
, udp::resolver::iterator i)
|
||||
{
|
||||
if (error == asio::error::operation_aborted) return;
|
||||
|
@ -156,7 +165,7 @@ namespace libtorrent
|
|||
|
||||
if (cb) cb->m_tracker_address = tcp::endpoint(target_address.address(), target_address.port());
|
||||
m_target = target_address;
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
|
||||
if (ec)
|
||||
{
|
||||
|
@ -179,13 +188,13 @@ namespace libtorrent
|
|||
|
||||
void udp_tracker_connection::close()
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket.close();
|
||||
m_name_lookup.cancel();
|
||||
tracker_connection::close();
|
||||
}
|
||||
|
||||
void udp_tracker_connection::on_receive(asio::error_code const& e
|
||||
void udp_tracker_connection::on_receive(error_code const& e
|
||||
, udp::endpoint const& ep, char const* buf, int size)
|
||||
{
|
||||
// ignore resposes before we've sent any requests
|
||||
|
@ -305,7 +314,7 @@ namespace libtorrent
|
|||
detail::write_int32(m_transaction_id, ptr); // transaction_id
|
||||
TORRENT_ASSERT(ptr - buf == sizeof(buf));
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket.send(m_target, buf, 16, ec);
|
||||
m_state = action_connect;
|
||||
++m_attempts;
|
||||
|
@ -334,7 +343,7 @@ namespace libtorrent
|
|||
out += 20;
|
||||
TORRENT_ASSERT(out - buf == sizeof(buf));
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket.send(m_target, buf, sizeof(buf), ec);
|
||||
m_state = action_scrape;
|
||||
++m_attempts;
|
||||
|
@ -494,7 +503,7 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_socket.send(m_target, buf, sizeof(buf), ec);
|
||||
m_state = action_announce;
|
||||
++m_attempts;
|
||||
|
|
|
@ -35,15 +35,20 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/upnp.hpp"
|
||||
#include "libtorrent/io.hpp"
|
||||
#include "libtorrent/http_tracker_connection.hpp"
|
||||
#include "libtorrent/parse_url.hpp"
|
||||
#include "libtorrent/xml_parse.hpp"
|
||||
#include "libtorrent/connection_queue.hpp"
|
||||
#include "libtorrent/enum_net.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#if BOOST_VERSION < 103500
|
||||
#include <asio/ip/host_name.hpp>
|
||||
#include <asio/ip/multicast.hpp>
|
||||
#else
|
||||
#include <boost/asio/ip/host_name.hpp>
|
||||
#include <boost/asio/ip/multicast.hpp>
|
||||
#endif
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
|
@ -54,12 +59,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
using boost::bind;
|
||||
using namespace libtorrent;
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
bool is_local(address const& a);
|
||||
address guess_local_address(asio::io_service&);
|
||||
}
|
||||
|
||||
upnp::upnp(io_service& ios, connection_queue& cc
|
||||
, address const& listen_interface, std::string const& user_agent
|
||||
, portmap_callback_t const& cb, bool ignore_nonrouters)
|
||||
|
@ -73,7 +72,7 @@ upnp::upnp(io_service& ios, connection_queue& cc
|
|||
, m_refresh_timer(ios)
|
||||
, m_disabled(false)
|
||||
, m_closing(false)
|
||||
, m_ignore_outside_network(ignore_nonrouters)
|
||||
, m_ignore_non_routers(ignore_nonrouters)
|
||||
, m_cc(cc)
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
|
@ -103,7 +102,7 @@ void upnp::discover_device_impl()
|
|||
"MX:3\r\n"
|
||||
"\r\n\r\n";
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
#ifdef TORRENT_DEBUG_UPNP
|
||||
// simulate packet loss
|
||||
if (m_retry_count & 1)
|
||||
|
@ -215,7 +214,7 @@ void upnp::delete_mapping(int mapping)
|
|||
}
|
||||
}
|
||||
|
||||
void upnp::resend_request(asio::error_code const& e)
|
||||
void upnp::resend_request(error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
|
@ -254,9 +253,10 @@ void upnp::resend_request(asio::error_code const& e)
|
|||
m_log << time_now_string()
|
||||
<< " ==> connecting to " << d.url << std::endl;
|
||||
#endif
|
||||
if (d.upnp_connection) d.upnp_connection->close();
|
||||
d.upnp_connection.reset(new http_connection(m_io_service
|
||||
, m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2
|
||||
, boost::ref(d))));
|
||||
, boost::ref(d), _5)));
|
||||
d.upnp_connection->get(d.url, seconds(30), 1);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
@ -306,8 +306,34 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
|
|||
Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0
|
||||
|
||||
*/
|
||||
asio::error_code ec;
|
||||
if (m_ignore_outside_network && !in_local_network(m_io_service, from.address(), ec))
|
||||
error_code ec;
|
||||
if (!in_local_network(m_io_service, from.address(), ec))
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
if (ec)
|
||||
{
|
||||
m_log << time_now_string() << " <== (" << from << ") error: "
|
||||
<< ec.message() << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log << time_now_string() << " <== (" << from << ") UPnP device "
|
||||
"ignored because it's not on our local network ";
|
||||
std::vector<ip_interface> const& net = enum_net_interfaces(m_io_service, ec);
|
||||
for (std::vector<ip_interface>::const_iterator i = net.begin()
|
||||
, end(net.end()); i != end; ++i)
|
||||
{
|
||||
m_log << "(" << i->interface_address << ", " << i->netmask << ") ";
|
||||
}
|
||||
m_log << std::endl;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<ip_route> routes = enum_routes(m_io_service, ec);
|
||||
if (m_ignore_non_routers && std::find_if(routes.begin(), routes.end()
|
||||
, bind(&ip_route::gateway, _1) == from.address()) == routes.end())
|
||||
{
|
||||
// this upnp device is filtered because it's not in the
|
||||
// list of configured routers
|
||||
|
@ -319,13 +345,12 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
|
|||
}
|
||||
else
|
||||
{
|
||||
std::vector<ip_interface> const& net = enum_net_interfaces(m_io_service, ec);
|
||||
m_log << time_now_string() << " <== (" << from << ") UPnP device "
|
||||
"ignored because it's not on our network ";
|
||||
for (std::vector<ip_interface>::const_iterator i = net.begin()
|
||||
, end(net.end()); i != end; ++i)
|
||||
"ignored because it's not a router on our network ";
|
||||
for (std::vector<ip_route>::const_iterator i = routes.begin()
|
||||
, end(routes.end()); i != end; ++i)
|
||||
{
|
||||
m_log << "(" << i->interface_address << ", " << i->netmask << ") ";
|
||||
m_log << "(" << i->gateway << ", " << i->netmask << ") ";
|
||||
}
|
||||
m_log << std::endl;
|
||||
}
|
||||
|
@ -392,10 +417,21 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
|
|||
|
||||
std::string protocol;
|
||||
std::string auth;
|
||||
char const* error;
|
||||
// we don't have this device in our list. Add it
|
||||
boost::tie(protocol, auth, d.hostname, d.port, d.path)
|
||||
boost::tie(protocol, auth, d.hostname, d.port, d.path, error)
|
||||
= parse_url_components(d.url);
|
||||
|
||||
if (error)
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
<< " <== (" << from << ") Rootdevice advertized an invalid url: '" << d.url
|
||||
<< "'. " << error << ". Ignoring device" << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore the auth here. It will be re-parsed
|
||||
// by the http connection later
|
||||
|
||||
|
@ -453,7 +489,7 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
|
|||
// just to make sure we find all devices
|
||||
if (m_retry_count >= 4 && !m_devices.empty())
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_broadcast_timer.cancel(ec);
|
||||
|
||||
for (std::set<rootdevice>::iterator i = m_devices.begin()
|
||||
|
@ -473,9 +509,10 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
|
|||
m_log << time_now_string()
|
||||
<< " ==> connecting to " << d.url << std::endl;
|
||||
#endif
|
||||
if (d.upnp_connection) d.upnp_connection->close();
|
||||
d.upnp_connection.reset(new http_connection(m_io_service
|
||||
, m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2
|
||||
, boost::ref(d))));
|
||||
, boost::ref(d), _5)));
|
||||
d.upnp_connection->get(d.url, seconds(30), 1);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
|
@ -543,7 +580,7 @@ void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i)
|
|||
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
"<s:Body><u:" << soap_action << " xmlns:u=\"" << d.service_namespace << "\">";
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
soap << "<NewRemoteHost></NewRemoteHost>"
|
||||
"<NewExternalPort>" << d.mapping[i].external_port << "</NewExternalPort>"
|
||||
"<NewProtocol>" << (d.mapping[i].protocol == udp ? "UDP" : "TCP") << "</NewProtocol>"
|
||||
|
@ -612,9 +649,10 @@ void upnp::update_map(rootdevice& d, int i)
|
|||
return;
|
||||
}
|
||||
|
||||
if (d.upnp_connection) d.upnp_connection->close();
|
||||
d.upnp_connection.reset(new http_connection(m_io_service
|
||||
, m_cc, bind(&upnp::on_upnp_map_response, self(), _1, _2
|
||||
, boost::ref(d), i), true
|
||||
, boost::ref(d), i, _5), true
|
||||
, bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i)));
|
||||
|
||||
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
|
||||
|
@ -622,9 +660,10 @@ void upnp::update_map(rootdevice& d, int i)
|
|||
}
|
||||
else if (m.action == mapping_t::action_delete)
|
||||
{
|
||||
if (d.upnp_connection) d.upnp_connection->close();
|
||||
d.upnp_connection.reset(new http_connection(m_io_service
|
||||
, m_cc, bind(&upnp::on_upnp_unmap_response, self(), _1, _2
|
||||
, boost::ref(d), i), true
|
||||
, boost::ref(d), i, _5), true
|
||||
, bind(&upnp::delete_port_mapping, self(), boost::ref(d), i)));
|
||||
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
|
||||
, seconds(10), 1);
|
||||
|
@ -732,13 +771,14 @@ namespace
|
|||
|
||||
}
|
||||
|
||||
void upnp::on_upnp_xml(asio::error_code const& e
|
||||
, libtorrent::http_parser const& p, rootdevice& d)
|
||||
void upnp::on_upnp_xml(error_code const& e
|
||||
, libtorrent::http_parser const& p, rootdevice& d
|
||||
, http_connection& c)
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
||||
TORRENT_ASSERT(d.magic == 1337);
|
||||
if (d.upnp_connection)
|
||||
if (d.upnp_connection && d.upnp_connection.get() == &c)
|
||||
{
|
||||
d.upnp_connection->close();
|
||||
d.upnp_connection.reset();
|
||||
|
@ -816,7 +856,7 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
|||
|
||||
d.control_url = s.control_url;
|
||||
|
||||
update_map(d, 0);
|
||||
if (num_mappings() > 0) update_map(d, 0);
|
||||
}
|
||||
|
||||
void upnp::disable(char const* msg)
|
||||
|
@ -833,7 +873,7 @@ void upnp::disable(char const* msg)
|
|||
}
|
||||
|
||||
m_devices.clear();
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_broadcast_timer.cancel(ec);
|
||||
m_refresh_timer.cancel(ec);
|
||||
m_socket.close();
|
||||
|
@ -891,13 +931,14 @@ namespace
|
|||
|
||||
}
|
||||
|
||||
void upnp::on_upnp_map_response(asio::error_code const& e
|
||||
, libtorrent::http_parser const& p, rootdevice& d, int mapping)
|
||||
void upnp::on_upnp_map_response(error_code const& e
|
||||
, libtorrent::http_parser const& p, rootdevice& d, int mapping
|
||||
, http_connection& c)
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
||||
TORRENT_ASSERT(d.magic == 1337);
|
||||
if (d.upnp_connection)
|
||||
if (d.upnp_connection && d.upnp_connection.get() == &c)
|
||||
{
|
||||
d.upnp_connection->close();
|
||||
d.upnp_connection.reset();
|
||||
|
@ -1014,7 +1055,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
|||
if (next_expire < time_now()
|
||||
|| next_expire > m.expires)
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_refresh_timer.expires_at(m.expires, ec);
|
||||
m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1));
|
||||
}
|
||||
|
@ -1046,13 +1087,14 @@ void upnp::return_error(int mapping, int code)
|
|||
m_callback(mapping, 0, error_string);
|
||||
}
|
||||
|
||||
void upnp::on_upnp_unmap_response(asio::error_code const& e
|
||||
, libtorrent::http_parser const& p, rootdevice& d, int mapping)
|
||||
void upnp::on_upnp_unmap_response(error_code const& e
|
||||
, libtorrent::http_parser const& p, rootdevice& d, int mapping
|
||||
, http_connection& c)
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
||||
TORRENT_ASSERT(d.magic == 1337);
|
||||
if (d.upnp_connection)
|
||||
if (d.upnp_connection && d.upnp_connection.get() == &c)
|
||||
{
|
||||
d.upnp_connection->close();
|
||||
d.upnp_connection.reset();
|
||||
|
@ -1093,7 +1135,7 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e
|
|||
next(d, mapping);
|
||||
}
|
||||
|
||||
void upnp::on_expire(asio::error_code const& e)
|
||||
void upnp::on_expire(error_code const& e)
|
||||
{
|
||||
if (e) return;
|
||||
|
||||
|
@ -1125,7 +1167,7 @@ void upnp::on_expire(asio::error_code const& e)
|
|||
}
|
||||
if (next_expire != max_time())
|
||||
{
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_refresh_timer.expires_at(next_expire, ec);
|
||||
m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1));
|
||||
}
|
||||
|
@ -1135,7 +1177,7 @@ void upnp::close()
|
|||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
|
||||
asio::error_code ec;
|
||||
error_code ec;
|
||||
m_refresh_timer.cancel(ec);
|
||||
m_broadcast_timer.cancel(ec);
|
||||
m_closing = true;
|
||||
|
@ -1159,7 +1201,7 @@ void upnp::close()
|
|||
j->action = mapping_t::action_delete;
|
||||
m_mappings[j - d.mapping.begin()].protocol = none;
|
||||
}
|
||||
update_map(d, 0);
|
||||
if (num_mappings() > 0) update_map(d, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/bencode.hpp"
|
||||
#include "libtorrent/torrent.hpp"
|
||||
#include "libtorrent/extensions.hpp"
|
||||
#include "libtorrent/extensions/metadata_transfer.hpp"
|
||||
#include "libtorrent/extensions/ut_metadata.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#ifdef TORRENT_STATS
|
||||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
|
@ -89,39 +89,38 @@ namespace libtorrent { namespace
|
|||
virtual boost::shared_ptr<peer_plugin> new_connection(
|
||||
peer_connection* pc);
|
||||
|
||||
std::vector<char> const& metadata() const
|
||||
buffer::const_interval metadata() const
|
||||
{
|
||||
TORRENT_ASSERT(m_torrent.valid_metadata());
|
||||
|
||||
if (m_metadata.empty())
|
||||
if (!m_metadata)
|
||||
{
|
||||
bencode(std::back_inserter(m_metadata)
|
||||
, m_torrent.torrent_file().create_info_metadata());
|
||||
|
||||
TORRENT_ASSERT(hasher(&m_metadata[0], m_metadata.size()).final()
|
||||
m_metadata = m_torrent.torrent_file().metadata();
|
||||
m_metadata_size = m_torrent.torrent_file().metadata_size();
|
||||
TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final()
|
||||
== m_torrent.torrent_file().info_hash());
|
||||
}
|
||||
TORRENT_ASSERT(!m_metadata.empty());
|
||||
return m_metadata;
|
||||
return buffer::const_interval(m_metadata.get(), m_metadata.get()
|
||||
+ m_metadata_size);
|
||||
}
|
||||
|
||||
bool received_metadata(char const* buf, int size, int piece, int total_size)
|
||||
{
|
||||
if (m_torrent.valid_metadata()) return false;
|
||||
|
||||
if (m_metadata.empty())
|
||||
if (!m_metadata)
|
||||
{
|
||||
// verify the total_size
|
||||
if (total_size <= 0 || total_size > 500 * 1024) return false;
|
||||
|
||||
m_metadata.resize(total_size);
|
||||
m_metadata.reset(new char[total_size]);
|
||||
m_requested_metadata.resize(div_round_up(total_size, 16 * 1024), 0);
|
||||
m_metadata_size = total_size;
|
||||
}
|
||||
|
||||
if (piece < 0 || piece >= int(m_requested_metadata.size()))
|
||||
return false;
|
||||
|
||||
TORRENT_ASSERT(piece * 16 * 1024 + size <= int(m_metadata.size()));
|
||||
TORRENT_ASSERT(piece * 16 * 1024 + size <= m_metadata_size);
|
||||
std::memcpy(&m_metadata[piece * 16 * 1024], buf, size);
|
||||
// mark this piece has 'have'
|
||||
m_requested_metadata[piece] = (std::numeric_limits<int>::max)();
|
||||
|
@ -133,7 +132,7 @@ namespace libtorrent { namespace
|
|||
if (!have_all) return false;
|
||||
|
||||
hasher h;
|
||||
h.update(&m_metadata[0], (int)m_metadata.size());
|
||||
h.update(&m_metadata[0], m_metadata_size);
|
||||
sha1_hash info_hash = h.final();
|
||||
|
||||
if (info_hash != m_torrent.torrent_file().info_hash())
|
||||
|
@ -149,7 +148,8 @@ namespace libtorrent { namespace
|
|||
return false;
|
||||
}
|
||||
|
||||
entry metadata = bdecode(m_metadata.begin(), m_metadata.end());
|
||||
lazy_entry metadata;
|
||||
int ret = lazy_bdecode(m_metadata.get(), m_metadata.get() + m_metadata_size, metadata);
|
||||
std::string error;
|
||||
if (!m_torrent.set_metadata(metadata, error))
|
||||
{
|
||||
|
@ -191,7 +191,7 @@ namespace libtorrent { namespace
|
|||
{
|
||||
if (m_metadata_size > 0 || size <= 0 || size > 500 * 1024) return;
|
||||
m_metadata_size = size;
|
||||
m_metadata.resize(size);
|
||||
m_metadata.reset(new char[size]);
|
||||
m_requested_metadata.resize(div_round_up(size, 16 * 1024), 0);
|
||||
}
|
||||
|
||||
|
@ -202,10 +202,10 @@ namespace libtorrent { namespace
|
|||
// the metadata file while downloading it from
|
||||
// peers, and while sending it.
|
||||
// it is mutable because it's generated lazily
|
||||
mutable std::vector<char> m_metadata;
|
||||
mutable boost::shared_array<char> m_metadata;
|
||||
|
||||
int m_metadata_progress;
|
||||
int m_metadata_size;
|
||||
mutable int m_metadata_size;
|
||||
|
||||
// this vector keeps track of how many times each meatdata
|
||||
// block has been requested
|
||||
|
@ -231,7 +231,7 @@ namespace libtorrent { namespace
|
|||
entry& messages = h["m"];
|
||||
messages["ut_metadata"] = 15;
|
||||
if (m_torrent.valid_metadata())
|
||||
h["metadata_size"] = m_tp.metadata().size();
|
||||
h["metadata_size"] = m_tp.metadata().left();
|
||||
}
|
||||
|
||||
// called when the extension handshake from the other end is received
|
||||
|
@ -273,14 +273,14 @@ namespace libtorrent { namespace
|
|||
if (type == 1)
|
||||
{
|
||||
TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata());
|
||||
e["total_size"] = m_tp.metadata().size();
|
||||
e["total_size"] = m_tp.metadata().left();
|
||||
int offset = piece * 16 * 1024;
|
||||
metadata = &m_tp.metadata()[0] + offset;
|
||||
metadata = m_tp.metadata().begin + offset;
|
||||
metadata_piece_size = (std::min)(
|
||||
int(m_tp.metadata().size() - offset), 16 * 1024);
|
||||
int(m_tp.metadata().left() - offset), 16 * 1024);
|
||||
TORRENT_ASSERT(metadata_piece_size > 0);
|
||||
TORRENT_ASSERT(offset >= 0);
|
||||
TORRENT_ASSERT(offset + metadata_piece_size <= int(m_tp.metadata().size()));
|
||||
TORRENT_ASSERT(offset + metadata_piece_size <= int(m_tp.metadata().left()));
|
||||
}
|
||||
|
||||
char msg[200];
|
||||
|
|
|
@ -113,7 +113,7 @@ namespace libtorrent { namespace
|
|||
for (torrent::peer_iterator i = m_torrent.begin()
|
||||
, end(m_torrent.end()); i != end; ++i)
|
||||
{
|
||||
peer_connection* peer = *i;
|
||||
peer_connection* peer = *i;
|
||||
if (!send_peer(*peer)) continue;
|
||||
|
||||
tcp::endpoint const& remote = peer->remote();
|
||||
|
|
|
@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/io.hpp"
|
||||
#include "libtorrent/version.hpp"
|
||||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
#include "libtorrent/parse_url.hpp"
|
||||
|
||||
using boost::bind;
|
||||
using boost::shared_ptr;
|
||||
|
@ -72,6 +73,8 @@ namespace libtorrent
|
|||
// we want large blocks as well, so
|
||||
// we can request more bytes at once
|
||||
request_large_blocks(true);
|
||||
set_upload_only(true);
|
||||
|
||||
// we only want left-over bandwidth
|
||||
set_priority(0);
|
||||
shared_ptr<torrent> tor = t.lock();
|
||||
|
@ -95,8 +98,10 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
std::string protocol;
|
||||
boost::tie(protocol, m_auth, m_host, m_port, m_path)
|
||||
char const* error;
|
||||
boost::tie(protocol, m_auth, m_host, m_port, m_path, error)
|
||||
= parse_url_components(url);
|
||||
TORRENT_ASSERT(error == 0);
|
||||
|
||||
if (!m_auth.empty())
|
||||
m_auth = base64encode(m_auth);
|
||||
|
@ -315,7 +320,7 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void web_peer_connection::on_receive(asio::error_code const& error
|
||||
void web_peer_connection::on_receive(error_code const& error
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -349,7 +354,7 @@ namespace libtorrent
|
|||
|
||||
if (error)
|
||||
{
|
||||
disconnect("failed to parse HTTP response");
|
||||
disconnect("failed to parse HTTP response", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -380,7 +385,7 @@ namespace libtorrent
|
|||
m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url()
|
||||
, error_msg));
|
||||
}
|
||||
disconnect(error_msg.c_str());
|
||||
disconnect(error_msg.c_str(), 1);
|
||||
return;
|
||||
}
|
||||
if (!m_parser.header_finished()) break;
|
||||
|
@ -406,7 +411,7 @@ namespace libtorrent
|
|||
{
|
||||
// we should not try this server again.
|
||||
t->remove_url_seed(m_url);
|
||||
disconnect("got HTTP redirection status without location header");
|
||||
disconnect("got HTTP redirection status without location header", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -430,7 +435,7 @@ namespace libtorrent
|
|||
std::stringstream msg;
|
||||
msg << "got invalid HTTP redirection location (\"" << location << "\") "
|
||||
"expected it to end with: " << path;
|
||||
disconnect(msg.str().c_str());
|
||||
disconnect(msg.str().c_str(), 2);
|
||||
return;
|
||||
}
|
||||
location.resize(i);
|
||||
|
@ -475,7 +480,7 @@ namespace libtorrent
|
|||
t->remove_url_seed(m_url);
|
||||
std::stringstream msg;
|
||||
msg << "invalid range in HTTP response: " << range_str.str();
|
||||
disconnect(msg.str().c_str());
|
||||
disconnect(msg.str().c_str(), 2);
|
||||
return;
|
||||
}
|
||||
// the http range is inclusive
|
||||
|
@ -489,7 +494,7 @@ namespace libtorrent
|
|||
{
|
||||
// we should not try this server again.
|
||||
t->remove_url_seed(m_url);
|
||||
disconnect("no content-length in HTTP response");
|
||||
disconnect("no content-length in HTTP response", 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -501,7 +506,7 @@ namespace libtorrent
|
|||
|
||||
if (m_requests.empty() || m_file_requests.empty())
|
||||
{
|
||||
disconnect("unexpected HTTP response");
|
||||
disconnect("unexpected HTTP response", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -534,7 +539,7 @@ namespace libtorrent
|
|||
{
|
||||
// this means the end of the incoming request ends _before_ the
|
||||
// first expected byte (fs + m_piece.size())
|
||||
disconnect("invalid range in HTTP response");
|
||||
disconnect("invalid range in HTTP response", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -662,7 +667,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
// throws exception when the client should be disconnected
|
||||
void web_peer_connection::on_sent(asio::error_code const& error
|
||||
void web_peer_connection::on_sent(error_code const& error
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
|
7
setup.py
7
setup.py
|
@ -85,15 +85,10 @@ if not os.environ.has_key("CPP"):
|
|||
|
||||
# The libtorrent extension
|
||||
_extra_compile_args = [
|
||||
"-DHAVE_INCLUDE_LIBTORRENT_ASIO____ASIO_HPP=1",
|
||||
"-DHAVE_INCLUDE_LIBTORRENT_ASIO_SSL_STREAM_HPP=1",
|
||||
"-DHAVE_INCLUDE_LIBTORRENT_ASIO_IP_TCP_HPP=1",
|
||||
"-DHAVE_PTHREAD=1",
|
||||
"-DTORRENT_USE_OPENSSL=1",
|
||||
"-DHAVE_SSL=1",
|
||||
"-O2",
|
||||
"-D_FILE_OFFSET_BITS=64",
|
||||
"-DNDEBUG"
|
||||
"-DNDEBUG",
|
||||
]
|
||||
|
||||
if windows_check():
|
||||
|
|
Loading…
Reference in New Issue