mirror of
https://github.com/logos-storage/deluge.git
synced 2026-01-06 23:23:08 +00:00
libtorrent sync 2347
This commit is contained in:
parent
576cae3b26
commit
b15608252c
@ -134,7 +134,7 @@ class Torrent:
|
|||||||
|
|
||||||
def set_private_flag(self, private):
|
def set_private_flag(self, private):
|
||||||
self.private = 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):
|
def set_prioritize_first_last(self, prioritize):
|
||||||
self.prioritize_first_last = prioritize
|
self.prioritize_first_last = prioritize
|
||||||
|
|||||||
@ -28,17 +28,17 @@ namespace
|
|||||||
this->peer_plugin::add_handshake(e);
|
this->peer_plugin::add_handshake(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool on_handshake()
|
bool on_handshake(char const* reserved_bits)
|
||||||
{
|
{
|
||||||
if (override f = this->get_override("on_handshake"))
|
if (override f = this->get_override("on_handshake"))
|
||||||
return f();
|
return f();
|
||||||
else
|
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)
|
bool on_extension_handshake(entry const& e)
|
||||||
|
|||||||
@ -74,13 +74,7 @@ void bind_torrent_info()
|
|||||||
.def(init<entry const&>())
|
.def(init<entry const&>())
|
||||||
.def(init<sha1_hash 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_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("add_url_seed", &torrent_info::add_url_seed)
|
||||||
|
|
||||||
.def("name", &torrent_info::name, copy)
|
.def("name", &torrent_info::name, copy)
|
||||||
@ -91,7 +85,7 @@ void bind_torrent_info()
|
|||||||
.def("num_pieces", &torrent_info::num_pieces)
|
.def("num_pieces", &torrent_info::num_pieces)
|
||||||
.def("info_hash", &torrent_info::info_hash, copy)
|
.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("piece_size", &torrent_info::piece_size)
|
||||||
|
|
||||||
.def("num_files", &torrent_info::num_files, (arg("storage")=false))
|
.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("files", &files, (arg("storage")=false))
|
||||||
|
|
||||||
.def("priv", &torrent_info::priv)
|
.def("priv", &torrent_info::priv)
|
||||||
.def("set_priv", &torrent_info::set_priv)
|
|
||||||
.def("trackers", range(begin_trackers, end_trackers))
|
.def("trackers", range(begin_trackers, end_trackers))
|
||||||
|
|
||||||
.def("creation_date", &torrent_info::creation_date)
|
.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 */
|
/* 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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -188,7 +188,7 @@ namespace libtorrent
|
|||||||
struct TORRENT_EXPORT peer_error_alert: alert
|
struct TORRENT_EXPORT peer_error_alert: alert
|
||||||
{
|
{
|
||||||
peer_error_alert(tcp::endpoint const& pip, peer_id const& pid_, std::string const& msg)
|
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)
|
, ip(pip)
|
||||||
, pid(pid_)
|
, pid(pid_)
|
||||||
{}
|
{}
|
||||||
@ -200,6 +200,21 @@ namespace libtorrent
|
|||||||
peer_id pid;
|
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
|
struct TORRENT_EXPORT invalid_request_alert: torrent_alert
|
||||||
{
|
{
|
||||||
invalid_request_alert(
|
invalid_request_alert(
|
||||||
|
|||||||
@ -151,7 +151,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
void async_accept(boost::shared_ptr<socket_acceptor> const& listener);
|
void async_accept(boost::shared_ptr<socket_acceptor> const& listener);
|
||||||
void on_incoming_connection(boost::shared_ptr<socket_type> const& s
|
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
|
// must be locked to access the data
|
||||||
// in this struct
|
// in this struct
|
||||||
@ -489,6 +489,11 @@ namespace libtorrent
|
|||||||
// from the torrent with the most peers
|
// from the torrent with the most peers
|
||||||
int m_disconnect_time_scaler;
|
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.
|
// statistics gathered from all torrents.
|
||||||
stat m_stat;
|
stat m_stat;
|
||||||
|
|
||||||
@ -498,7 +503,7 @@ namespace libtorrent
|
|||||||
// NAT or not.
|
// NAT or not.
|
||||||
bool m_incoming_connection;
|
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_auto_managed_torrents();
|
||||||
void recalculate_unchoke_slots(int congested_torrents
|
void recalculate_unchoke_slots(int congested_torrents
|
||||||
, int uncongested_torrents);
|
, int uncongested_torrents);
|
||||||
@ -528,7 +533,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
udp_socket m_dht_socket;
|
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);
|
, udp::endpoint const& ep, char const* buf, int len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -76,6 +76,8 @@ struct history_entry
|
|||||||
history_entry(intrusive_ptr<PeerConnection> p, weak_ptr<Torrent> t
|
history_entry(intrusive_ptr<PeerConnection> p, weak_ptr<Torrent> t
|
||||||
, int a, ptime exp)
|
, int a, ptime exp)
|
||||||
: expires_at(exp), amount(a), peer(p), tor(t) {}
|
: 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;
|
ptime expires_at;
|
||||||
int amount;
|
int amount;
|
||||||
intrusive_ptr<PeerConnection> peer;
|
intrusive_ptr<PeerConnection> peer;
|
||||||
@ -111,6 +113,7 @@ struct bandwidth_manager
|
|||||||
: m_ios(ios)
|
: m_ios(ios)
|
||||||
, m_history_timer(m_ios)
|
, m_history_timer(m_ios)
|
||||||
, m_limit(bandwidth_limit::inf)
|
, m_limit(bandwidth_limit::inf)
|
||||||
|
, m_drain_quota(0)
|
||||||
, m_current_quota(0)
|
, m_current_quota(0)
|
||||||
, m_channel(channel)
|
, m_channel(channel)
|
||||||
, m_in_hand_out_bandwidth(false)
|
, m_in_hand_out_bandwidth(false)
|
||||||
@ -123,6 +126,14 @@ struct bandwidth_manager
|
|||||||
#endif
|
#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)
|
void throttle(int limit)
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
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
|
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()
|
for (typename queue_t::const_iterator i = m_queue.begin()
|
||||||
, end(m_queue.end()); i != end; ++i)
|
, 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
|
bool is_in_history(PeerConnection const* peer, boost::mutex::scoped_lock& l) const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
for (typename history_t::const_iterator i
|
for (typename history_t::const_iterator i
|
||||||
= m_history.begin(), end(m_history.end()); i != end; ++i)
|
= m_history.begin(), end(m_history.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
@ -258,12 +267,12 @@ private:
|
|||||||
|
|
||||||
if (m_abort) return;
|
if (m_abort) return;
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_history_timer.expires_at(e.expires_at, ec);
|
m_history_timer.expires_at(e.expires_at, ec);
|
||||||
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
|
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;
|
if (e) return;
|
||||||
|
|
||||||
@ -290,6 +299,7 @@ private:
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
intrusive_ptr<PeerConnection> c = e.peer;
|
intrusive_ptr<PeerConnection> c = e.peer;
|
||||||
|
if (!c) continue;
|
||||||
shared_ptr<Torrent> t = e.tor.lock();
|
shared_ptr<Torrent> t = e.tor.lock();
|
||||||
l.unlock();
|
l.unlock();
|
||||||
if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount);
|
if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount);
|
||||||
@ -300,7 +310,7 @@ private:
|
|||||||
// now, wait for the next chunk to expire
|
// now, wait for the next chunk to expire
|
||||||
if (!m_history.empty() && !m_abort)
|
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.expires_at(m_history.back().expires_at, ec);
|
||||||
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
|
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)
|
void hand_out_bandwidth(boost::mutex::scoped_lock& l)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
// if we're already handing out bandwidth, just return back
|
// if we're already handing out bandwidth, just return back
|
||||||
// to the loop further down on the callstack
|
// to the loop further down on the callstack
|
||||||
if (m_in_hand_out_bandwidth) return;
|
if (m_in_hand_out_bandwidth) return;
|
||||||
@ -332,6 +341,15 @@ private:
|
|||||||
|
|
||||||
if (amount <= 0) return;
|
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;
|
queue_t tmp;
|
||||||
while (!m_queue.empty() && amount > 0)
|
while (!m_queue.empty() && amount > 0)
|
||||||
{
|
{
|
||||||
@ -436,6 +454,10 @@ private:
|
|||||||
// the rate limit (bytes per second)
|
// the rate limit (bytes per second)
|
||||||
int m_limit;
|
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
|
// the sum of all recently handed out bandwidth blocks
|
||||||
int m_current_quota;
|
int m_current_quota;
|
||||||
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@ namespace libtorrent
|
|||||||
int common_bits(unsigned char const* b1
|
int common_bits(unsigned char const* b1
|
||||||
, unsigned char const* b2, int n);
|
, 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
|
typedef boost::function<void(udp::endpoint const& from
|
||||||
, char* buffer, int size)> receive_handler_t;
|
, char* buffer, int size)> receive_handler_t;
|
||||||
@ -59,11 +59,11 @@ namespace libtorrent
|
|||||||
class TORRENT_EXPORT broadcast_socket
|
class TORRENT_EXPORT broadcast_socket
|
||||||
{
|
{
|
||||||
public:
|
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);
|
, receive_handler_t const& handler, bool loopback = true);
|
||||||
~broadcast_socket() { close(); }
|
~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();
|
void close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -77,12 +77,12 @@ namespace libtorrent
|
|||||||
void close()
|
void close()
|
||||||
{
|
{
|
||||||
if (!socket) return;
|
if (!socket) return;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
socket->close(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);
|
, std::size_t bytes_transferred);
|
||||||
void open_unicast_socket(io_service& ios, address const& addr);
|
void open_unicast_socket(io_service& ios, address const& addr);
|
||||||
void open_multicast_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(
|
bt_peer_connection(
|
||||||
aux::session_impl& ses
|
aux::session_impl& ses
|
||||||
, boost::shared_ptr<socket_type> s
|
, boost::shared_ptr<socket_type> s
|
||||||
|
, tcp::endpoint const& remote
|
||||||
, policy::peer* peerinfo);
|
, policy::peer* peerinfo);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
@ -141,9 +142,9 @@ namespace libtorrent
|
|||||||
// called from the main loop when this connection has any
|
// called from the main loop when this connection has any
|
||||||
// work to do.
|
// work to do.
|
||||||
|
|
||||||
void on_sent(asio::error_code const& error
|
void on_sent(error_code const& error
|
||||||
, std::size_t bytes_transferred);
|
, 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::size_t bytes_transferred);
|
||||||
|
|
||||||
virtual void get_specific_peer_info(peer_info& p) const;
|
virtual void get_specific_peer_info(peer_info& p) const;
|
||||||
@ -363,6 +364,7 @@ private:
|
|||||||
// the peer indicated that it supports the
|
// the peer indicated that it supports the
|
||||||
// extension protocol
|
// extension protocol
|
||||||
bool m_supports_extensions;
|
bool m_supports_extensions;
|
||||||
|
char m_reserved_bits[20];
|
||||||
#endif
|
#endif
|
||||||
bool m_supports_dht_port;
|
bool m_supports_dht_port;
|
||||||
bool m_supports_fast;
|
bool m_supports_fast;
|
||||||
|
|||||||
@ -34,12 +34,19 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED
|
#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED
|
||||||
|
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/buffer.hpp>
|
#include <asio/buffer.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#endif
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
#if BOOST_VERSION >= 103500
|
||||||
|
namespace asio = boost::asio;
|
||||||
|
#endif
|
||||||
struct chained_buffer
|
struct chained_buffer
|
||||||
{
|
{
|
||||||
chained_buffer(): m_bytes(0), m_capacity(0) {}
|
chained_buffer(): m_bytes(0), m_capacity(0) {}
|
||||||
|
|||||||
@ -71,7 +71,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
void try_connect();
|
void try_connect();
|
||||||
void on_timeout(asio::error_code const& e);
|
void on_timeout(error_code const& e);
|
||||||
|
|
||||||
struct entry
|
struct entry
|
||||||
{
|
{
|
||||||
|
|||||||
@ -47,7 +47,13 @@ namespace libtorrent
|
|||||||
disk_buffer_holder(disk_io_thread& iothread, char* buf);
|
disk_buffer_holder(disk_io_thread& iothread, char* buf);
|
||||||
~disk_buffer_holder();
|
~disk_buffer_holder();
|
||||||
char* release();
|
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:
|
private:
|
||||||
disk_io_thread& m_iothread;
|
disk_io_thread& m_iothread;
|
||||||
char* m_buf;
|
char* m_buf;
|
||||||
|
|||||||
@ -149,7 +149,7 @@ namespace libtorrent
|
|||||||
// of disk io jobs
|
// of disk io jobs
|
||||||
struct disk_io_thread : boost::noncopyable
|
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();
|
~disk_io_thread();
|
||||||
|
|
||||||
#ifdef TORRENT_STATS
|
#ifdef TORRENT_STATS
|
||||||
@ -292,7 +292,7 @@ namespace libtorrent
|
|||||||
size_type m_writes;
|
size_type m_writes;
|
||||||
size_type m_blocks_written;
|
size_type m_blocks_written;
|
||||||
|
|
||||||
asio::io_service& m_ios;
|
io_service& m_ios;
|
||||||
|
|
||||||
// thread for performing blocking disk io operations
|
// thread for performing blocking disk io operations
|
||||||
boost::thread m_disk_io_thread;
|
boost::thread m_disk_io_thread;
|
||||||
|
|||||||
@ -167,6 +167,8 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
entry* find_key(char const* key);
|
entry* find_key(char const* key);
|
||||||
entry const* find_key(char const* key) const;
|
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;
|
void print(std::ostream& os, int indent = 0) const;
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
address interface_address;
|
address interface_address;
|
||||||
address netmask;
|
address netmask;
|
||||||
char name[32];
|
char name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ip_route
|
struct ip_route
|
||||||
@ -51,15 +51,15 @@ namespace libtorrent
|
|||||||
address destination;
|
address destination;
|
||||||
address netmask;
|
address netmask;
|
||||||
address gateway;
|
address gateway;
|
||||||
char name[32];
|
char name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
// returns a list of the configured IP interfaces
|
// returns a list of the configured IP interfaces
|
||||||
// on the machine
|
// on the machine
|
||||||
TORRENT_EXPORT std::vector<ip_interface> enum_net_interfaces(asio::io_service& ios
|
TORRENT_EXPORT std::vector<ip_interface> enum_net_interfaces(io_service& ios
|
||||||
, asio::error_code& ec);
|
, 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
|
// returns true if the specified address is on the same
|
||||||
// local network as the specified interface
|
// local network as the specified interface
|
||||||
@ -67,11 +67,11 @@ namespace libtorrent
|
|||||||
|
|
||||||
// returns true if the specified address is on the same
|
// returns true if the specified address is on the same
|
||||||
// local network as us
|
// local network as us
|
||||||
TORRENT_EXPORT bool in_local_network(asio::io_service& ios, address const& addr
|
TORRENT_EXPORT bool in_local_network(io_service& ios, address const& addr
|
||||||
, asio::error_code& ec);
|
, error_code& ec);
|
||||||
|
|
||||||
TORRENT_EXPORT address get_default_gateway(asio::io_service& ios
|
TORRENT_EXPORT address get_default_gateway(io_service& ios
|
||||||
, asio::error_code& ec);
|
, error_code& ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -51,6 +51,8 @@ namespace libtorrent
|
|||||||
|
|
||||||
TORRENT_EXPORT boost::optional<std::string> url_has_argument(
|
TORRENT_EXPORT boost::optional<std::string> url_has_argument(
|
||||||
std::string const& url, std::string argument);
|
std::string const& url, std::string argument);
|
||||||
|
|
||||||
|
TORRENT_EXPORT std::string to_hex(std::string const& s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED
|
#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
|
// means that the other end doesn't support this extension and will remove
|
||||||
// it from the list of plugins.
|
// it from the list of plugins.
|
||||||
// this is not called for web seeds
|
// 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
|
// called when the extension handshake from the other end is received
|
||||||
// if this returns false, it means that this extension isn't
|
// 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/enable_shared_from_this.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
@ -59,8 +60,8 @@ namespace libtorrent
|
|||||||
struct http_connection;
|
struct http_connection;
|
||||||
class connection_queue;
|
class connection_queue;
|
||||||
|
|
||||||
typedef boost::function<void(asio::error_code const&
|
typedef boost::function<void(error_code const&
|
||||||
, http_parser const&, char const* data, int size)> http_handler;
|
, http_parser const&, char const* data, int size, http_connection&)> http_handler;
|
||||||
|
|
||||||
typedef boost::function<void(http_connection&)> http_connect_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
|
// will always be 0
|
||||||
struct http_connection : boost::enable_shared_from_this<http_connection>, boost::noncopyable
|
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_handler const& handler, bool bottled = true
|
||||||
, http_connect_handler const& ch = http_connect_handler())
|
, http_connect_handler const& ch = http_connect_handler())
|
||||||
: m_sock(ios)
|
: m_sock(ios)
|
||||||
@ -91,6 +92,7 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
|
|||||||
, m_cc(cc)
|
, m_cc(cc)
|
||||||
, m_ssl(false)
|
, m_ssl(false)
|
||||||
, m_priority(0)
|
, m_priority(0)
|
||||||
|
, m_abort(false)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(!m_handler.empty());
|
TORRENT_ASSERT(!m_handler.empty());
|
||||||
}
|
}
|
||||||
@ -121,19 +123,19 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void on_resolve(asio::error_code const& e
|
void on_resolve(error_code const& e
|
||||||
, tcp::resolver::iterator i);
|
, tcp::resolver::iterator i);
|
||||||
|
void queue_connect();
|
||||||
void connect(int ticket, tcp::endpoint target_address);
|
void connect(int ticket, tcp::endpoint target_address);
|
||||||
void on_connect_timeout();
|
void on_connect_timeout();
|
||||||
void on_connect(asio::error_code const& e
|
void on_connect(error_code const& e);
|
||||||
/* , tcp::resolver::iterator i*/);
|
void on_write(error_code const& e);
|
||||||
void on_write(asio::error_code const& e);
|
void on_read(error_code const& e, std::size_t bytes_transferred);
|
||||||
void on_read(asio::error_code const& e, std::size_t bytes_transferred);
|
|
||||||
static void on_timeout(boost::weak_ptr<http_connection> p
|
static void on_timeout(boost::weak_ptr<http_connection> p
|
||||||
, asio::error_code const& e);
|
, error_code const& e);
|
||||||
void on_assign_bandwidth(asio::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;
|
std::vector<char> m_recvbuffer;
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
@ -158,6 +160,9 @@ private:
|
|||||||
bool m_called;
|
bool m_called;
|
||||||
std::string m_hostname;
|
std::string m_hostname;
|
||||||
std::string m_port;
|
std::string m_port;
|
||||||
|
std::string m_url;
|
||||||
|
|
||||||
|
std::list<tcp::endpoint> m_endpoints;
|
||||||
|
|
||||||
// the current download limit, in bytes per second
|
// the current download limit, in bytes per second
|
||||||
// 0 is unlimited.
|
// 0 is unlimited.
|
||||||
@ -195,6 +200,8 @@ private:
|
|||||||
// the priority we have in the connection queue.
|
// the priority we have in the connection queue.
|
||||||
// 0 is normal, 1 is high
|
// 0 is normal, 1 is high
|
||||||
int m_priority;
|
int m_priority;
|
||||||
|
|
||||||
|
bool m_abort;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@ class http_stream : public proxy_base
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit http_stream(asio::io_service& io_service)
|
explicit http_stream(io_service& io_service)
|
||||||
: proxy_base(io_service)
|
: proxy_base(io_service)
|
||||||
, m_no_connect(false)
|
, m_no_connect(false)
|
||||||
{}
|
{}
|
||||||
@ -55,7 +55,7 @@ public:
|
|||||||
m_password = password;
|
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>
|
template <class Handler>
|
||||||
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
||||||
@ -80,11 +80,11 @@ public:
|
|||||||
|
|
||||||
private:
|
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);
|
, boost::shared_ptr<handler_type> h);
|
||||||
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);
|
||||||
void handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||||
void handshake2(asio::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
|
// send and receive buffer
|
||||||
std::vector<char> m_buffer;
|
std::vector<char> m_buffer;
|
||||||
|
|||||||
@ -82,7 +82,7 @@ namespace libtorrent
|
|||||||
boost::intrusive_ptr<http_tracker_connection> self()
|
boost::intrusive_ptr<http_tracker_connection> self()
|
||||||
{ return boost::intrusive_ptr<http_tracker_connection>(this); }
|
{ 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);
|
, char const* data, int size);
|
||||||
|
|
||||||
virtual void on_timeout() {}
|
virtual void on_timeout() {}
|
||||||
|
|||||||
@ -34,14 +34,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define TORRENT_INSTANTIATE_CONNECTION
|
#define TORRENT_INSTANTIATE_CONNECTION
|
||||||
|
|
||||||
#include "libtorrent/socket_type.hpp"
|
#include "libtorrent/socket_type.hpp"
|
||||||
#include <asio/io_service.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
struct proxy_settings;
|
struct proxy_settings;
|
||||||
|
|
||||||
bool instantiate_connection(asio::io_service& ios
|
bool instantiate_connection(io_service& ios
|
||||||
, proxy_settings const& ps, socket_type& s);
|
, proxy_settings const& ps, socket_type& s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -68,7 +68,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void done();
|
void done();
|
||||||
void invoke(node_id const& id, asio::ip::udp::endpoint addr);
|
void invoke(node_id const& id, udp::endpoint addr);
|
||||||
|
|
||||||
closest_nodes(
|
closest_nodes(
|
||||||
node_id target
|
node_id target
|
||||||
|
|||||||
@ -53,6 +53,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "libtorrent/session_settings.hpp"
|
#include "libtorrent/session_settings.hpp"
|
||||||
#include "libtorrent/session_status.hpp"
|
#include "libtorrent/session_status.hpp"
|
||||||
#include "libtorrent/udp_socket.hpp"
|
#include "libtorrent/udp_socket.hpp"
|
||||||
|
#include "libtorrent/socket.hpp"
|
||||||
|
|
||||||
namespace libtorrent { namespace dht
|
namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
@ -89,19 +90,20 @@ namespace libtorrent { namespace dht
|
|||||||
// translate bittorrent kademlia message into the generic kademlia message
|
// translate bittorrent kademlia message into the generic kademlia message
|
||||||
// used by the library
|
// used by the library
|
||||||
void on_receive(udp::endpoint const& ep, char const* pkt, int size);
|
void on_receive(udp::endpoint const& ep, char const* pkt, int size);
|
||||||
|
void on_unreachable(udp::endpoint const& ep);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::intrusive_ptr<dht_tracker> self()
|
boost::intrusive_ptr<dht_tracker> self()
|
||||||
{ return boost::intrusive_ptr<dht_tracker>(this); }
|
{ 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);
|
, 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);
|
, udp::resolver::iterator host);
|
||||||
void connection_timeout(asio::error_code const& e);
|
void connection_timeout(error_code const& e);
|
||||||
void refresh_timeout(asio::error_code const& e);
|
void refresh_timeout(error_code const& e);
|
||||||
void tick(asio::error_code const& e);
|
void tick(error_code const& e);
|
||||||
|
|
||||||
void on_bootstrap();
|
void on_bootstrap();
|
||||||
void send_packet(msg const& m);
|
void send_packet(msg const& m);
|
||||||
|
|||||||
@ -48,8 +48,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
namespace libtorrent { namespace dht
|
namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
|
|
||||||
using asio::ip::udp;
|
|
||||||
|
|
||||||
typedef std::vector<char> packet_t;
|
typedef std::vector<char> packet_t;
|
||||||
|
|
||||||
class rpc_manager;
|
class rpc_manager;
|
||||||
|
|||||||
@ -36,15 +36,17 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <libtorrent/kademlia/node_id.hpp>
|
#include <libtorrent/kademlia/node_id.hpp>
|
||||||
#include "libtorrent/entry.hpp"
|
#include "libtorrent/entry.hpp"
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/ip/udp.hpp>
|
#include <asio/ip/udp.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/asio/ip/udp.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace libtorrent {
|
namespace libtorrent {
|
||||||
namespace dht {
|
namespace dht {
|
||||||
|
|
||||||
typedef std::vector<char> packet_t;
|
typedef std::vector<char> packet_t;
|
||||||
|
|
||||||
using asio::ip::udp;
|
|
||||||
|
|
||||||
namespace messages
|
namespace messages
|
||||||
{
|
{
|
||||||
enum { ping = 0, find_node = 1, get_peers = 2, announce_peer = 3, error = 4 };
|
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
|
namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
|
|
||||||
using asio::ip::udp;
|
|
||||||
|
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_DECLARE_LOG(node);
|
TORRENT_DECLARE_LOG(node);
|
||||||
#endif
|
#endif
|
||||||
@ -174,6 +172,7 @@ public:
|
|||||||
void(std::vector<node_entry> const&)> f);
|
void(std::vector<node_entry> const&)> f);
|
||||||
void add_router_node(udp::endpoint router);
|
void add_router_node(udp::endpoint router);
|
||||||
|
|
||||||
|
void unreachable(udp::endpoint const& ep);
|
||||||
void incoming(msg const& m);
|
void incoming(msg const& m);
|
||||||
|
|
||||||
void refresh();
|
void refresh();
|
||||||
|
|||||||
@ -41,20 +41,33 @@ namespace libtorrent { namespace dht
|
|||||||
|
|
||||||
struct node_entry
|
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_)
|
: id(id_)
|
||||||
, addr(addr_)
|
, addr(addr_)
|
||||||
, fail_count(0) {}
|
, fail_count(0)
|
||||||
node_entry(asio::ip::udp::endpoint addr_)
|
{
|
||||||
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
|
first_seen = time_now();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
node_entry(udp::endpoint addr_)
|
||||||
: id(0)
|
: id(0)
|
||||||
, addr(addr_)
|
, addr(addr_)
|
||||||
, fail_count(0) {}
|
, fail_count(0)
|
||||||
|
{
|
||||||
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
|
first_seen = time_now();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
node_id id;
|
node_id id;
|
||||||
udp::endpoint addr;
|
udp::endpoint addr;
|
||||||
// the number of times this node has failed to
|
// the number of times this node has failed to
|
||||||
// respond in a row
|
// respond in a row
|
||||||
int fail_count;
|
int fail_count;
|
||||||
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
|
ptime first_seen;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
} } // namespace libtorrent::dht
|
} } // namespace libtorrent::dht
|
||||||
|
|||||||
@ -55,9 +55,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
namespace libtorrent { namespace dht
|
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;
|
typedef std::vector<node_entry> bucket_t;
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,6 @@ namespace libtorrent { namespace dht
|
|||||||
|
|
||||||
struct observer;
|
struct observer;
|
||||||
|
|
||||||
using asio::ip::udp;
|
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_DECLARE_LOG(rpc);
|
TORRENT_DECLARE_LOG(rpc);
|
||||||
#endif
|
#endif
|
||||||
@ -82,6 +81,8 @@ public:
|
|||||||
, routing_table& table, send_fun const& sf);
|
, routing_table& table, send_fun const& sf);
|
||||||
~rpc_manager();
|
~rpc_manager();
|
||||||
|
|
||||||
|
void unreachable(udp::endpoint const& ep);
|
||||||
|
|
||||||
// returns true if the node needs a refresh
|
// returns true if the node needs a refresh
|
||||||
bool incoming(msg const&);
|
bool incoming(msg const&);
|
||||||
time_duration tick();
|
time_duration tick();
|
||||||
|
|||||||
@ -179,6 +179,15 @@ namespace libtorrent
|
|||||||
|
|
||||||
void clear();
|
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()
|
~lazy_entry()
|
||||||
{ clear(); }
|
{ clear(); }
|
||||||
|
|
||||||
@ -186,6 +195,17 @@ namespace libtorrent
|
|||||||
// this entry has its bencoded data
|
// this entry has its bencoded data
|
||||||
std::pair<char const*, int> data_section() const;
|
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:
|
private:
|
||||||
|
|
||||||
entry_type_t m_type;
|
entry_type_t m_type;
|
||||||
|
|||||||
@ -67,7 +67,7 @@ public:
|
|||||||
|
|
||||||
private:
|
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
|
void on_announce(udp::endpoint const& from, char* buffer
|
||||||
, std::size_t bytes_transferred);
|
, std::size_t bytes_transferred);
|
||||||
// void setup_receive();
|
// void setup_receive();
|
||||||
|
|||||||
@ -70,12 +70,12 @@ private:
|
|||||||
|
|
||||||
void update_mapping(int i);
|
void update_mapping(int i);
|
||||||
void send_map_request(int i);
|
void send_map_request(int i);
|
||||||
void resend_request(int i, asio::error_code const& e);
|
void resend_request(int i, error_code const& e);
|
||||||
void on_reply(asio::error_code const& e
|
void on_reply(error_code const& e
|
||||||
, std::size_t bytes_transferred);
|
, std::size_t bytes_transferred);
|
||||||
void try_next_mapping(int i);
|
void try_next_mapping(int i);
|
||||||
void update_expiration_timer();
|
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);
|
void disable(char const* message);
|
||||||
|
|
||||||
|
|||||||
@ -121,6 +121,7 @@ namespace libtorrent
|
|||||||
peer_connection(
|
peer_connection(
|
||||||
aux::session_impl& ses
|
aux::session_impl& ses
|
||||||
, boost::shared_ptr<socket_type> s
|
, boost::shared_ptr<socket_type> s
|
||||||
|
, tcp::endpoint const& remote
|
||||||
, policy::peer* peerinfo);
|
, policy::peer* peerinfo);
|
||||||
|
|
||||||
// this function is called after it has been constructed and properly
|
// this function is called after it has been constructed and properly
|
||||||
@ -197,6 +198,9 @@ namespace libtorrent
|
|||||||
|
|
||||||
bool is_seed() const;
|
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;
|
bool has_timed_out() const;
|
||||||
|
|
||||||
// will send a keep-alive message to the peer
|
// will send a keep-alive message to the peer
|
||||||
@ -230,6 +234,8 @@ namespace libtorrent
|
|||||||
const stat& statistics() const { return m_statistics; }
|
const stat& statistics() const { return m_statistics; }
|
||||||
void add_stat(size_type downloaded, size_type uploaded);
|
void add_stat(size_type downloaded, size_type uploaded);
|
||||||
|
|
||||||
|
void calc_ip_overhead();
|
||||||
|
|
||||||
// is called once every second by the main loop
|
// is called once every second by the main loop
|
||||||
void second_tick(float tick_interval);
|
void second_tick(float tick_interval);
|
||||||
|
|
||||||
@ -240,15 +246,18 @@ namespace libtorrent
|
|||||||
std::vector<int> const& allowed_fast();
|
std::vector<int> const& allowed_fast();
|
||||||
std::vector<int> const& suggested_pieces() const { return m_suggested_pieces; }
|
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();
|
void timed_out();
|
||||||
// this will cause this peer_connection to be disconnected.
|
// 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; }
|
bool is_disconnecting() const { return m_disconnecting; }
|
||||||
|
|
||||||
// this is called when the connection attempt has succeeded
|
// this is called when the connection attempt has succeeded
|
||||||
// and the peer_connection is supposed to set m_connecting
|
// and the peer_connection is supposed to set m_connecting
|
||||||
// to false, and stop monitor writability
|
// 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
|
// returns true if this connection is still waiting to
|
||||||
// finish the connection attempt
|
// finish the connection attempt
|
||||||
@ -288,7 +297,6 @@ namespace libtorrent
|
|||||||
bool ignore_bandwidth_limits() const
|
bool ignore_bandwidth_limits() const
|
||||||
{ return m_ignore_bandwidth_limits; }
|
{ return m_ignore_bandwidth_limits; }
|
||||||
|
|
||||||
void set_failed() { m_failed = true; }
|
|
||||||
bool failed() const { return m_failed; }
|
bool failed() const { return m_failed; }
|
||||||
|
|
||||||
int desired_queue_size() const { return m_desired_queue_size; }
|
int desired_queue_size() const { return m_desired_queue_size; }
|
||||||
@ -449,15 +457,15 @@ namespace libtorrent
|
|||||||
virtual void on_connected() = 0;
|
virtual void on_connected() = 0;
|
||||||
virtual void on_tick() {}
|
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;
|
, 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;
|
, std::size_t bytes_transferred) = 0;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||||
buffer::interval wr_recv_buffer()
|
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);
|
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
|
||||||
if (m_recv_buffer.empty()) return buffer::interval(0,0);
|
if (m_recv_buffer.empty()) return buffer::interval(0,0);
|
||||||
return buffer::interval(&m_recv_buffer[0]
|
return buffer::interval(&m_recv_buffer[0]
|
||||||
@ -501,9 +509,9 @@ namespace libtorrent
|
|||||||
|
|
||||||
// called from the main loop when this connection has any
|
// called from the main loop when this connection has any
|
||||||
// work to do.
|
// 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);
|
, 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);
|
, std::size_t bytes_transferred);
|
||||||
|
|
||||||
// this is the limit on the number of outstanding requests
|
// 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
|
void on_disk_write_complete(int ret, disk_io_job const& j
|
||||||
, peer_request r, boost::shared_ptr<torrent> t);
|
, 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
|
// the time when we last got a part of a
|
||||||
// piece packet from this peer
|
// piece packet from this peer
|
||||||
ptime m_last_piece;
|
ptime m_last_piece;
|
||||||
@ -559,28 +564,54 @@ namespace libtorrent
|
|||||||
// the time when we unchoked this peer
|
// the time when we unchoked this peer
|
||||||
ptime m_last_unchoke;
|
ptime m_last_unchoke;
|
||||||
|
|
||||||
int m_packet_size;
|
// timeouts
|
||||||
int m_recv_pos;
|
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;
|
buffer m_recv_buffer;
|
||||||
|
|
||||||
// if this peer is receiving a piece, this
|
// if this peer is receiving a piece, this
|
||||||
// points to a disk buffer that the data is
|
// points to a disk buffer that the data is
|
||||||
// read into. This eliminates a memcopy from
|
// read into. This eliminates a memcopy from
|
||||||
// the receive buffer into the disk buffer
|
// the receive buffer into the disk buffer
|
||||||
int m_disk_recv_buffer_size;
|
disk_buffer_holder m_disk_recv_buffer;
|
||||||
char* m_disk_recv_buffer;
|
|
||||||
|
|
||||||
chained_buffer m_send_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;
|
boost::shared_ptr<socket_type> m_socket;
|
||||||
// this is the peer we're actually talking to
|
// this is the peer we're actually talking to
|
||||||
// it may not necessarily be the peer we're
|
// it may not necessarily be the peer we're
|
||||||
@ -593,51 +624,12 @@ namespace libtorrent
|
|||||||
// until the info_hash is received. Then it's
|
// until the info_hash is received. Then it's
|
||||||
// set to the torrent it belongs to.
|
// set to the torrent it belongs to.
|
||||||
boost::weak_ptr<torrent> m_torrent;
|
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
|
// remote peer's id
|
||||||
peer_id m_peer_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
|
// the pieces the other end have
|
||||||
std::vector<bool> m_have_piece;
|
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
|
// the queue of requests we have got
|
||||||
// from this peer
|
// from this peer
|
||||||
@ -651,25 +643,42 @@ namespace libtorrent
|
|||||||
// from this peer
|
// from this peer
|
||||||
std::deque<piece_block> m_download_queue;
|
std::deque<piece_block> m_download_queue;
|
||||||
|
|
||||||
// the number of request we should queue up
|
// the pieces we will send to the peer
|
||||||
// at the remote end.
|
// if requested (regardless of choke state)
|
||||||
int m_desired_queue_size;
|
std::set<int> m_accept_fast;
|
||||||
|
|
||||||
// the amount of data this peer has been given
|
// the pieces the peer will send us if
|
||||||
// as free upload. This is distributed from
|
// requested (regardless of choke state)
|
||||||
// peers from which we get free download
|
std::vector<int> m_allowed_fast;
|
||||||
// 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;
|
|
||||||
|
|
||||||
// if this is true, this peer is assumed to handle all piece
|
// pieces that has been suggested to be
|
||||||
// requests in fifo order. All skipped blocks are re-requested
|
// downloaded from this peer
|
||||||
// immediately instead of having a looser requirement
|
std::vector<int> m_suggested_pieces;
|
||||||
// where blocks can be sent out of order. The default is to
|
|
||||||
// allow non-fifo order.
|
|
||||||
bool m_assume_fifo;
|
|
||||||
|
|
||||||
|
// 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
|
// the number of invalid piece-requests
|
||||||
// we have got from this peer. If the request
|
// we have got from this peer. If the request
|
||||||
// queue gets empty, and there have been
|
// queue gets empty, and there have been
|
||||||
@ -679,49 +688,6 @@ namespace libtorrent
|
|||||||
// by sending choke, unchoke.
|
// by sending choke, unchoke.
|
||||||
int m_num_invalid_requests;
|
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
|
// this is the priority with which this peer gets
|
||||||
// download bandwidth quota assigned to it.
|
// download bandwidth quota assigned to it.
|
||||||
int m_priority;
|
int m_priority;
|
||||||
@ -753,60 +719,114 @@ namespace libtorrent
|
|||||||
// approximate peer download rate
|
// approximate peer download rate
|
||||||
int m_remote_dl_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
|
// the number of bytes send to the disk-io
|
||||||
// thread that hasn't yet been completely written.
|
// thread that hasn't yet been completely written.
|
||||||
int m_outstanding_writing_bytes;
|
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
|
// if this is true, the disconnection
|
||||||
// timestamp is not updated when the connection
|
// timestamp is not updated when the connection
|
||||||
// is closed. This means the time until we can
|
// is closed. This means the time until we can
|
||||||
// reconnect to this peer is shorter, and likely
|
// reconnect to this peer is shorter, and likely
|
||||||
// immediate.
|
// immediate.
|
||||||
bool m_fast_reconnect;
|
bool m_fast_reconnect:1;
|
||||||
|
|
||||||
// the time when async_connect was called
|
// is true if it was we that connected to the peer
|
||||||
ptime m_connect;
|
// 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
|
// other side says that it's interested in downloading
|
||||||
// based on the time from when async_connect
|
// from us.
|
||||||
// was called to when on_connection_complete
|
bool m_peer_interested:1;
|
||||||
// was called. The rtt is specified in milliseconds
|
|
||||||
int m_rtt;
|
|
||||||
|
|
||||||
// the total payload download bytes
|
// the other side has told us that it won't send anymore
|
||||||
// at the last unchoke cycle. This is used to
|
// data to us for a while
|
||||||
// measure the number of bytes transferred during
|
bool m_peer_choked:1;
|
||||||
// an unchoke cycle, to unchoke peers the more bytes
|
|
||||||
// they sent us
|
|
||||||
size_type m_downloaded_at_last_unchoke;
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_GEO_IP
|
// the peer has pieces we are interested in
|
||||||
std::string m_inet_as_name;
|
bool m_interesting:1;
|
||||||
#endif
|
|
||||||
|
|
||||||
// max transfer rates seen on this peer
|
// we have choked the upload to the peer
|
||||||
int m_download_rate_peak;
|
bool m_choked:1;
|
||||||
int m_upload_rate_peak;
|
|
||||||
|
// 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
|
#ifndef NDEBUG
|
||||||
public:
|
public:
|
||||||
bool m_in_constructor;
|
bool m_in_constructor:1;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -142,6 +142,9 @@ namespace libtorrent
|
|||||||
iterator begin() { return m_number; }
|
iterator begin() { return m_number; }
|
||||||
iterator end() { return m_number+number_size; }
|
iterator end() { return m_number+number_size; }
|
||||||
|
|
||||||
|
std::string to_string() const
|
||||||
|
{ return std::string((char const*)&m_number[0], number_size); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
unsigned char m_number[number_size];
|
unsigned char m_number[number_size];
|
||||||
|
|||||||
@ -248,7 +248,6 @@ namespace libtorrent
|
|||||||
const_iterator end_peer() const { return m_peers.end(); }
|
const_iterator end_peer() const { return m_peers.end(); }
|
||||||
|
|
||||||
bool connect_one_peer();
|
bool connect_one_peer();
|
||||||
bool disconnect_one_peer();
|
|
||||||
|
|
||||||
bool has_peer(policy::peer const* p) const;
|
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
|
bool compare_peer(policy::peer const& lhs, policy::peer const& rhs
|
||||||
, address const& external_ip) const;
|
, address const& external_ip) const;
|
||||||
|
|
||||||
iterator find_disconnect_candidate();
|
|
||||||
iterator find_connect_candidate();
|
iterator find_connect_candidate();
|
||||||
|
|
||||||
bool is_connect_candidate(peer const& p, bool finished);
|
bool is_connect_candidate(peer const& p, bool finished);
|
||||||
|
|||||||
@ -38,9 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/read.hpp>
|
#include <asio/read.hpp>
|
||||||
#include <asio/write.hpp>
|
#include <asio/write.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/asio/read.hpp>
|
||||||
|
#include <boost/asio/write.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace libtorrent {
|
namespace libtorrent {
|
||||||
|
|
||||||
@ -52,7 +56,7 @@ public:
|
|||||||
typedef stream_socket::endpoint_type endpoint_type;
|
typedef stream_socket::endpoint_type endpoint_type;
|
||||||
typedef stream_socket::protocol_type protocol_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_sock(io_service)
|
||||||
, m_resolver(io_service)
|
, m_resolver(io_service)
|
||||||
{}
|
{}
|
||||||
@ -70,7 +74,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Mutable_Buffers>
|
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);
|
return m_sock.read_some(buffers, ec);
|
||||||
}
|
}
|
||||||
@ -90,7 +94,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <class IO_Control_Command>
|
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);
|
m_sock.io_control(ioc, ec);
|
||||||
}
|
}
|
||||||
@ -110,7 +114,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <class SettableSocketOption>
|
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);
|
return m_sock.set_option(opt, ec);
|
||||||
}
|
}
|
||||||
@ -122,7 +126,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#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);
|
m_sock.bind(endpoint, ec);
|
||||||
}
|
}
|
||||||
@ -134,7 +138,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#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);
|
m_sock.open(p, ec);
|
||||||
}
|
}
|
||||||
@ -148,7 +152,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void close(asio::error_code& ec)
|
void close(error_code& ec)
|
||||||
{
|
{
|
||||||
m_sock.close(ec);
|
m_sock.close(ec);
|
||||||
m_resolver.cancel();
|
m_resolver.cancel();
|
||||||
@ -161,7 +165,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
endpoint_type remote_endpoint(asio::error_code& ec) const
|
endpoint_type remote_endpoint(error_code& ec) const
|
||||||
{
|
{
|
||||||
return m_remote_endpoint;
|
return m_remote_endpoint;
|
||||||
}
|
}
|
||||||
@ -173,14 +177,14 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
endpoint_type local_endpoint(asio::error_code& ec) const
|
endpoint_type local_endpoint(error_code& ec) const
|
||||||
{
|
{
|
||||||
return m_sock.local_endpoint(ec);
|
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()
|
lowest_layer_type& lowest_layer()
|
||||||
|
|||||||
@ -129,7 +129,7 @@ namespace libtorrent
|
|||||||
, resume_data(0)
|
, resume_data(0)
|
||||||
, storage_mode(storage_mode_sparse)
|
, storage_mode(storage_mode_sparse)
|
||||||
, paused(true)
|
, paused(true)
|
||||||
, auto_managed(false)
|
, auto_managed(true)
|
||||||
, duplicate_is_error(false)
|
, duplicate_is_error(false)
|
||||||
, storage(sc)
|
, storage(sc)
|
||||||
, userdata(0)
|
, userdata(0)
|
||||||
|
|||||||
@ -102,11 +102,7 @@ namespace libtorrent
|
|||||||
, min_reconnect_time(60)
|
, min_reconnect_time(60)
|
||||||
, peer_connect_timeout(7)
|
, peer_connect_timeout(7)
|
||||||
, ignore_limits_on_local_network(true)
|
, ignore_limits_on_local_network(true)
|
||||||
#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
|
|
||||||
, connection_speed(2)
|
|
||||||
#else
|
|
||||||
, connection_speed(20)
|
, connection_speed(20)
|
||||||
#endif
|
|
||||||
, send_redundant_have(false)
|
, send_redundant_have(false)
|
||||||
, lazy_bitfields(true)
|
, lazy_bitfields(true)
|
||||||
, inactivity_timeout(600)
|
, inactivity_timeout(600)
|
||||||
@ -134,6 +130,11 @@ namespace libtorrent
|
|||||||
, share_ratio_limit(2.f)
|
, share_ratio_limit(2.f)
|
||||||
, seed_time_ratio_limit(7.f)
|
, seed_time_ratio_limit(7.f)
|
||||||
, seed_time_limit(24 * 60 * 60) // 24 hours
|
, 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
|
// this is the user agent that will be sent to the tracker
|
||||||
@ -376,6 +377,31 @@ namespace libtorrent
|
|||||||
float share_ratio_limit;
|
float share_ratio_limit;
|
||||||
float seed_time_ratio_limit;
|
float seed_time_ratio_limit;
|
||||||
int seed_time_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
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
|
|||||||
@ -45,13 +45,25 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define Protocol Protocol_
|
#define Protocol Protocol_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/ip/tcp.hpp>
|
#include <asio/ip/tcp.hpp>
|
||||||
#include <asio/ip/udp.hpp>
|
#include <asio/ip/udp.hpp>
|
||||||
#include <asio/io_service.hpp>
|
#include <asio/io_service.hpp>
|
||||||
#include <asio/deadline_timer.hpp>
|
#include <asio/deadline_timer.hpp>
|
||||||
#include <asio/write.hpp>
|
#include <asio/write.hpp>
|
||||||
|
#include <asio/read.hpp>
|
||||||
#include <asio/time_traits.hpp>
|
#include <asio/time_traits.hpp>
|
||||||
#include <asio/basic_deadline_timer.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__
|
#ifdef __OBJC__
|
||||||
#undef Protocol
|
#undef Protocol
|
||||||
@ -67,24 +79,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
#if BOOST_VERSION < 103500
|
||||||
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;
|
|
||||||
|
|
||||||
using asio::ip::tcp;
|
using asio::ip::tcp;
|
||||||
using asio::ip::udp;
|
using asio::ip::udp;
|
||||||
|
using asio::async_write;
|
||||||
|
using asio::async_read;
|
||||||
|
|
||||||
typedef asio::ip::tcp::socket stream_socket;
|
typedef asio::ip::tcp::socket stream_socket;
|
||||||
typedef asio::ip::address address;
|
typedef asio::ip::address address;
|
||||||
typedef asio::ip::address_v4 address_v4;
|
typedef asio::ip::address_v4 address_v4;
|
||||||
@ -92,14 +92,32 @@ namespace libtorrent
|
|||||||
typedef asio::ip::udp::socket datagram_socket;
|
typedef asio::ip::udp::socket datagram_socket;
|
||||||
typedef asio::ip::tcp::acceptor socket_acceptor;
|
typedef asio::ip::tcp::acceptor socket_acceptor;
|
||||||
typedef asio::io_service io_service;
|
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;
|
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)
|
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);
|
std::string a = addr.to_string(ec);
|
||||||
if (ec) return os;
|
if (ec) return os;
|
||||||
os << a;
|
os << a;
|
||||||
@ -109,7 +127,7 @@ namespace libtorrent
|
|||||||
inline std::ostream& print_endpoint(std::ostream& os, tcp::endpoint const& ep)
|
inline std::ostream& print_endpoint(std::ostream& os, tcp::endpoint const& ep)
|
||||||
{
|
{
|
||||||
address const& addr = ep.address();
|
address const& addr = ep.address();
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
std::string a = addr.to_string(ec);
|
std::string a = addr.to_string(ec);
|
||||||
if (ec) return os;
|
if (ec) return os;
|
||||||
|
|
||||||
@ -132,7 +150,7 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
else if (a.is_v6())
|
else if (a.is_v6())
|
||||||
{
|
{
|
||||||
asio::ip::address_v6::bytes_type bytes
|
address_v6::bytes_type bytes
|
||||||
= a.to_v6().to_bytes();
|
= a.to_v6().to_bytes();
|
||||||
std::copy(bytes.begin(), bytes.end(), out);
|
std::copy(bytes.begin(), bytes.end(), out);
|
||||||
}
|
}
|
||||||
@ -142,18 +160,18 @@ namespace libtorrent
|
|||||||
address read_v4_address(InIt& in)
|
address read_v4_address(InIt& in)
|
||||||
{
|
{
|
||||||
unsigned long ip = read_uint32(in);
|
unsigned long ip = read_uint32(in);
|
||||||
return asio::ip::address_v4(ip);
|
return address_v4(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class InIt>
|
template<class InIt>
|
||||||
address read_v6_address(InIt& in)
|
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;
|
bytes_t bytes;
|
||||||
for (bytes_t::iterator i = bytes.begin()
|
for (bytes_t::iterator i = bytes.begin()
|
||||||
, end(bytes.end()); i != end; ++i)
|
, end(bytes.end()); i != end; ++i)
|
||||||
*i = read_uint8(in);
|
*i = read_uint8(in);
|
||||||
return asio::ip::address_v6(bytes);
|
return address_v6(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Endpoint, class OutIt>
|
template<class Endpoint, class OutIt>
|
||||||
|
|||||||
@ -41,8 +41,8 @@ class socks4_stream : public proxy_base
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit socks4_stream(asio::io_service& io_service)
|
explicit socks4_stream(io_service& io_service_)
|
||||||
: proxy_base(io_service)
|
: proxy_base(io_service_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void set_username(std::string const& user)
|
void set_username(std::string const& user)
|
||||||
@ -50,7 +50,7 @@ public:
|
|||||||
m_user = user;
|
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>
|
template <class Handler>
|
||||||
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
||||||
@ -74,11 +74,11 @@ public:
|
|||||||
|
|
||||||
private:
|
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);
|
, boost::shared_ptr<handler_type> h);
|
||||||
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);
|
||||||
void handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||||
void handshake2(asio::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
|
// send and receive buffer
|
||||||
std::vector<char> m_buffer;
|
std::vector<char> m_buffer;
|
||||||
|
|||||||
@ -41,7 +41,7 @@ class socks5_stream : public proxy_base
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit socks5_stream(asio::io_service& io_service)
|
explicit socks5_stream(io_service& io_service)
|
||||||
: proxy_base(io_service)
|
: proxy_base(io_service)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ public:
|
|||||||
m_password = password;
|
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>
|
template <class Handler>
|
||||||
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
||||||
@ -79,17 +79,17 @@ public:
|
|||||||
|
|
||||||
private:
|
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);
|
, boost::shared_ptr<handler_type> h);
|
||||||
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);
|
||||||
void handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||||
void handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||||
void handshake3(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
void handshake3(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||||
void handshake4(asio::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 socks_connect(boost::shared_ptr<handler_type> h);
|
||||||
void connect1(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(asio::error_code const& e, boost::shared_ptr<handler_type> h);
|
void connect2(error_code const& e, boost::shared_ptr<handler_type> h);
|
||||||
void connect3(asio::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
|
// send and receive buffer
|
||||||
std::vector<char> m_buffer;
|
std::vector<char> m_buffer;
|
||||||
|
|||||||
@ -34,8 +34,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define TORRENT_SSL_STREAM_HPP_INCLUDED
|
#define TORRENT_SSL_STREAM_HPP_INCLUDED
|
||||||
|
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/ssl.hpp>
|
#include <asio/ssl.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/asio/ssl.hpp>
|
||||||
|
#endif
|
||||||
// openssl seems to believe it owns
|
// openssl seems to believe it owns
|
||||||
// this name in every single scope
|
// this name in every single scope
|
||||||
#undef set_key
|
#undef set_key
|
||||||
@ -47,7 +50,7 @@ class ssl_stream
|
|||||||
{
|
{
|
||||||
public:
|
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_context(io_service, asio::ssl::context::sslv23_client)
|
||||||
, m_sock(io_service, m_context)
|
, m_sock(io_service, m_context)
|
||||||
{
|
{
|
||||||
@ -60,7 +63,7 @@ public:
|
|||||||
typedef typename Stream::protocol_type protocol_type;
|
typedef typename Stream::protocol_type protocol_type;
|
||||||
typedef typename asio::ssl::stream<Stream> sock_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>
|
template <class Handler>
|
||||||
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
void async_connect(endpoint_type const& endpoint, Handler const& handler)
|
||||||
@ -70,7 +73,7 @@ public:
|
|||||||
// 2. perform SSL client handshake
|
// 2. perform SSL client handshake
|
||||||
|
|
||||||
// to avoid unnecessary copying of the handler,
|
// 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));
|
boost::shared_ptr<handler_type> h(new handler_type(handler));
|
||||||
|
|
||||||
m_sock.next_layer().async_connect(endpoint
|
m_sock.next_layer().async_connect(endpoint
|
||||||
@ -84,7 +87,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Mutable_Buffers>
|
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);
|
return m_sock.read_some(buffers, ec);
|
||||||
}
|
}
|
||||||
@ -104,7 +107,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <class IO_Control_Command>
|
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);
|
m_sock.next_layer().io_control(ioc, ec);
|
||||||
}
|
}
|
||||||
@ -122,7 +125,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#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);
|
m_sock.next_layer().bind(endpoint, ec);
|
||||||
}
|
}
|
||||||
@ -134,7 +137,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#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);
|
m_sock.next_layer().open(p, ec);
|
||||||
}
|
}
|
||||||
@ -151,7 +154,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void close(asio::error_code& ec)
|
void close(error_code& ec)
|
||||||
{
|
{
|
||||||
m_sock.next_layer().close(ec);
|
m_sock.next_layer().close(ec);
|
||||||
}
|
}
|
||||||
@ -163,7 +166,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#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);
|
return const_cast<sock_type&>(m_sock).next_layer().remote_endpoint(ec);
|
||||||
}
|
}
|
||||||
@ -175,14 +178,14 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#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);
|
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()
|
lowest_layer_type& lowest_layer()
|
||||||
@ -197,7 +200,7 @@ public:
|
|||||||
|
|
||||||
private:
|
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)
|
if (e)
|
||||||
{
|
{
|
||||||
@ -209,7 +212,7 @@ private:
|
|||||||
, boost::bind(&ssl_stream::handshake, this, _1, h));
|
, 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);
|
(*h)(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "libtorrent/size_type.hpp"
|
#include "libtorrent/size_type.hpp"
|
||||||
#include "libtorrent/invariant_check.hpp"
|
#include "libtorrent/invariant_check.hpp"
|
||||||
@ -44,88 +45,162 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
class TORRENT_EXPORT stat_channel
|
||||||
class TORRENT_EXPORT stat
|
|
||||||
{
|
{
|
||||||
friend class invariant_access;
|
friend class invariant_access;
|
||||||
public:
|
public:
|
||||||
enum { history = 10 };
|
enum { history = 10 };
|
||||||
|
|
||||||
stat()
|
stat_channel()
|
||||||
: m_downloaded_payload(0)
|
: m_counter(0)
|
||||||
, m_uploaded_payload(0)
|
, m_total_counter(0)
|
||||||
, m_downloaded_protocol(0)
|
, m_rate_sum(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)
|
|
||||||
{
|
{
|
||||||
std::fill(m_download_rate_history, m_download_rate_history+history, 0.f);
|
std::memset(m_rate_history, 0, sizeof(m_rate_history));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator+=(const stat& s)
|
void operator+=(stat_channel const& s)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
m_counter += s.m_counter;
|
||||||
|
m_total_counter += s.m_counter;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void received_bytes(int bytes_payload, int bytes_protocol)
|
void add(int count)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
TORRENT_ASSERT(count >= 0);
|
||||||
|
|
||||||
TORRENT_ASSERT(bytes_payload >= 0);
|
m_counter += count;
|
||||||
TORRENT_ASSERT(bytes_protocol >= 0);
|
m_total_counter += count;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// should be called once every second
|
// should be called once every second
|
||||||
void second_tick(float tick_interval);
|
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; }
|
void offset(size_type counter)
|
||||||
float download_rate() const { return m_mean_download_rate; }
|
{
|
||||||
|
TORRENT_ASSERT(counter >= 0);
|
||||||
|
m_total_counter += counter;
|
||||||
|
}
|
||||||
|
|
||||||
float upload_payload_rate() const { return m_mean_upload_payload_rate; }
|
size_type counter() const { return m_counter; }
|
||||||
float download_payload_rate() const { return m_mean_download_payload_rate; }
|
|
||||||
|
|
||||||
size_type total_payload_upload() const { return m_total_upload_payload; }
|
private:
|
||||||
size_type total_payload_download() const { return m_total_download_payload; }
|
|
||||||
|
|
||||||
size_type total_protocol_upload() const { return m_total_upload_protocol; }
|
#ifndef NDEBUG
|
||||||
size_type total_protocol_download() const { return m_total_download_protocol; }
|
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
|
// this is used to offset the statistics when a
|
||||||
// peer_connection is opened and have some previous
|
// peer_connection is opened and have some previous
|
||||||
@ -134,66 +209,33 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
TORRENT_ASSERT(downloaded >= 0);
|
TORRENT_ASSERT(downloaded >= 0);
|
||||||
TORRENT_ASSERT(uploaded >= 0);
|
TORRENT_ASSERT(uploaded >= 0);
|
||||||
m_total_download_payload += downloaded;
|
m_stat[download_payload].offset(downloaded);
|
||||||
m_total_upload_payload += uploaded;
|
m_stat[upload_payload].offset(uploaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type last_payload_downloaded() const { return m_downloaded_payload; }
|
size_type last_payload_downloaded() const
|
||||||
size_type last_payload_uploaded() const { return m_uploaded_payload; }
|
{ return m_stat[download_payload].counter(); }
|
||||||
|
size_type last_payload_uploaded() const
|
||||||
|
{ return m_stat[upload_payload].counter(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#ifndef NDEBUG
|
// these are the channels we keep stats for
|
||||||
void check_invariant() const
|
enum
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_mean_upload_rate >= 0);
|
upload_payload,
|
||||||
TORRENT_ASSERT(m_mean_download_rate >= 0);
|
upload_protocol,
|
||||||
TORRENT_ASSERT(m_mean_upload_payload_rate >= 0);
|
upload_ip_protocol,
|
||||||
TORRENT_ASSERT(m_mean_download_payload_rate >= 0);
|
download_payload,
|
||||||
TORRENT_ASSERT(m_total_upload_payload >= 0);
|
download_protocol,
|
||||||
TORRENT_ASSERT(m_total_download_payload >= 0);
|
download_ip_protocol,
|
||||||
TORRENT_ASSERT(m_total_upload_protocol >= 0);
|
num_channels
|
||||||
TORRENT_ASSERT(m_total_download_protocol >= 0);
|
};
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// history of download/upload speeds a few seconds back
|
stat_channel m_stat[num_channels];
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TORRENT_STAT_HPP_INCLUDED
|
#endif // TORRENT_STAT_HPP_INCLUDED
|
||||||
|
|
||||||
|
|||||||
@ -86,7 +86,11 @@ namespace libtorrent
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/time_traits.hpp>
|
#include <asio/time_traits.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/asio/time_traits.hpp>
|
||||||
|
#endif
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
#include "libtorrent/assert.hpp"
|
#include "libtorrent/assert.hpp"
|
||||||
|
|
||||||
@ -152,6 +156,9 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
|
|
||||||
// asio time_traits
|
// asio time_traits
|
||||||
|
#if BOOST_VERSION >= 103500
|
||||||
|
namespace boost {
|
||||||
|
#endif
|
||||||
namespace asio
|
namespace asio
|
||||||
{
|
{
|
||||||
template<>
|
template<>
|
||||||
@ -172,6 +179,9 @@ namespace asio
|
|||||||
{ return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
|
{ return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
#if BOOST_VERSION >= 103500
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__MACH__)
|
#if defined(__MACH__)
|
||||||
|
|
||||||
|
|||||||
@ -151,8 +151,7 @@ namespace libtorrent
|
|||||||
void files_checked();
|
void files_checked();
|
||||||
void start_checking();
|
void start_checking();
|
||||||
|
|
||||||
float seed_cycles(session_settings const& s) const;
|
int seed_rank(session_settings const& s) const;
|
||||||
int seed_cycles_int(session_settings const& s) const { return int(seed_cycles(s)); }
|
|
||||||
|
|
||||||
storage_mode_t storage_mode() const { return m_storage_mode; }
|
storage_mode_t storage_mode() const { return m_storage_mode; }
|
||||||
// this will flag the torrent as aborted. The main
|
// this will flag the torrent as aborted. The main
|
||||||
@ -356,6 +355,7 @@ namespace libtorrent
|
|||||||
void force_tracker_request();
|
void force_tracker_request();
|
||||||
void force_tracker_request(ptime);
|
void force_tracker_request(ptime);
|
||||||
void scrape_tracker();
|
void scrape_tracker();
|
||||||
|
ptime const& last_scrape() const { return m_last_scrape; }
|
||||||
|
|
||||||
// sets the username and password that will be sent to
|
// sets the username and password that will be sent to
|
||||||
// the tracker
|
// the tracker
|
||||||
@ -453,6 +453,7 @@ namespace libtorrent
|
|||||||
void announce_piece(int index);
|
void announce_piece(int index);
|
||||||
|
|
||||||
void disconnect_all();
|
void disconnect_all();
|
||||||
|
int disconnect_peers(int num);
|
||||||
|
|
||||||
// this is called wheh the torrent has completed
|
// this is called wheh the torrent has completed
|
||||||
// the download. It will post an event, disconnect
|
// 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
|
// this is the asio callback that is called when a name
|
||||||
// lookup for a PEER is completed.
|
// 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);
|
, peer_id pid);
|
||||||
|
|
||||||
// this is the asio callback that is called when a name
|
// this is the asio callback that is called when a name
|
||||||
// lookup for a WEB SEED is completed.
|
// 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);
|
, std::string url, tcp::endpoint proxy);
|
||||||
|
|
||||||
// this is the asio callback that is called when a name
|
// this is the asio callback that is called when a name
|
||||||
// lookup for a proxy for a web seed is completed.
|
// 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);
|
, std::string url);
|
||||||
|
|
||||||
// this is called when the torrent has finished. i.e.
|
// this is called when the torrent has finished. i.e.
|
||||||
@ -480,6 +481,11 @@ namespace libtorrent
|
|||||||
// completed() is called immediately after it.
|
// completed() is called immediately after it.
|
||||||
void finished();
|
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&);
|
void async_verify_piece(int piece_index, boost::function<void(int)> const&);
|
||||||
|
|
||||||
// this is called from the peer_connection
|
// this is called from the peer_connection
|
||||||
@ -570,7 +576,7 @@ namespace libtorrent
|
|||||||
// to the checker thread for initial checking
|
// to the checker thread for initial checking
|
||||||
// of the storage.
|
// of the storage.
|
||||||
// a return value of false indicates an error
|
// 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; }
|
int sequence_number() const { return m_sequence_number; }
|
||||||
|
|
||||||
@ -587,40 +593,43 @@ namespace libtorrent
|
|||||||
|
|
||||||
void try_next_tracker();
|
void try_next_tracker();
|
||||||
int prioritize_tracker(int tracker_index);
|
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;
|
, boost::intrusive_ptr<peer_connection> p) const;
|
||||||
bool request_bandwidth_from_session(int channel) const;
|
bool request_bandwidth_from_session(int channel) const;
|
||||||
|
|
||||||
void update_peer_interest(bool was_finished);
|
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;
|
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;
|
tracker_request::event_t m_event;
|
||||||
|
|
||||||
void parse_response(const entry& e, std::vector<peer_entry>& peer_list);
|
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
|
// if this pointer is 0, the torrent is in
|
||||||
// a state where the metadata hasn't been
|
// a state where the metadata hasn't been
|
||||||
// received yet.
|
// received yet.
|
||||||
@ -649,18 +658,6 @@ namespace libtorrent
|
|||||||
// the time of next tracker request
|
// the time of next tracker request
|
||||||
ptime m_next_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
|
#ifndef NDEBUG
|
||||||
public:
|
public:
|
||||||
#endif
|
#endif
|
||||||
@ -681,28 +678,21 @@ namespace libtorrent
|
|||||||
// resolving the address for
|
// resolving the address for
|
||||||
std::set<std::string> m_resolving_web_seeds;
|
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
|
// used to resolve the names of web seeds
|
||||||
mutable tcp::resolver m_host_resolver;
|
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
|
// this announce timer is used both
|
||||||
// by Local service discovery and
|
// by Local service discovery and
|
||||||
// by the DHT.
|
// by the DHT.
|
||||||
deadline_timer m_announce_timer;
|
deadline_timer m_announce_timer;
|
||||||
|
|
||||||
static void on_announce_disp(boost::weak_ptr<torrent> p
|
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
|
// this is called once per announce interval
|
||||||
void on_announce();
|
void on_announce();
|
||||||
@ -737,41 +727,9 @@ namespace libtorrent
|
|||||||
std::vector<announce_entry> m_trackers;
|
std::vector<announce_entry> m_trackers;
|
||||||
// this is an index into 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
|
// the bitmask that says which pieces we have
|
||||||
std::vector<bool> m_have_pieces;
|
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
|
// the number of bytes that has been
|
||||||
// downloaded that failed the hash-test
|
// downloaded that failed the hash-test
|
||||||
size_type m_total_failed_bytes;
|
size_type m_total_failed_bytes;
|
||||||
@ -791,25 +749,9 @@ namespace libtorrent
|
|||||||
|
|
||||||
// the state of this torrent (queued, checking, downloading)
|
// the state of this torrent (queued, checking, downloading)
|
||||||
torrent_status::state_t m_state;
|
torrent_status::state_t m_state;
|
||||||
float m_progress;
|
|
||||||
|
|
||||||
entry m_resume_data;
|
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
|
// if the torrent is started without metadata, it may
|
||||||
// still be given a name until the metadata is received
|
// still be given a name until the metadata is received
|
||||||
// once the metadata is received this field will no
|
// once the metadata is received this field will no
|
||||||
@ -820,6 +762,18 @@ namespace libtorrent
|
|||||||
|
|
||||||
storage_constructor_type m_storage_constructor;
|
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
|
// the maximum number of uploads for this torrent
|
||||||
int m_max_uploads;
|
int m_max_uploads;
|
||||||
|
|
||||||
@ -829,14 +783,18 @@ namespace libtorrent
|
|||||||
// the maximum number of connections for this torrent
|
// the maximum number of connections for this torrent
|
||||||
int m_max_connections;
|
int m_max_connections;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
// the size of a request block
|
||||||
bool m_files_checked;
|
// each piece is divided into these
|
||||||
#endif
|
// blocks when requested
|
||||||
|
int m_block_size;
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
|
||||||
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;
|
// -----------------------------
|
||||||
extension_list_t m_extensions;
|
// DATA FROM TRACKER RESPONSE
|
||||||
#endif
|
|
||||||
|
// the scrape data from the tracker response, this
|
||||||
|
// is optional and may be -1.
|
||||||
|
int m_complete;
|
||||||
|
int m_incomplete;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// this is the amount downloaded when this torrent
|
// this is the amount downloaded when this torrent
|
||||||
@ -858,24 +816,84 @@ namespace libtorrent
|
|||||||
// torrent object, these points are called connect_points.
|
// torrent object, these points are called connect_points.
|
||||||
int m_deficit_counter;
|
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
|
// the sequence number for this torrent, this is a
|
||||||
// monotonically increasing number for each added torrent
|
// 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
|
// the index to the last tracker that worked
|
||||||
// does not count when the torrent is stopped or paused
|
boost::int8_t m_last_working_tracker;
|
||||||
time_duration m_active_time;
|
|
||||||
|
|
||||||
// total time we've been available as a seed on this torrent
|
// the tracker that is currently (or was last)
|
||||||
// does not count when the torrent is stopped or paused
|
// tried
|
||||||
time_duration m_seeding_time;
|
boost::int8_t m_currently_trying_tracker;
|
||||||
|
|
||||||
// all time totals of uploaded and downloaded payload
|
// the number of connection attempts that has
|
||||||
// stored in resume data
|
// failed in a row, this is currently used to
|
||||||
size_type m_total_uploaded;
|
// determine the timeout until next try.
|
||||||
size_type m_total_downloaded;
|
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
|
inline ptime torrent::next_announce() const
|
||||||
|
|||||||
@ -118,7 +118,8 @@ namespace libtorrent
|
|||||||
, all_time_download(0)
|
, all_time_download(0)
|
||||||
, active_time(0)
|
, active_time(0)
|
||||||
, seeding_time(0)
|
, seeding_time(0)
|
||||||
, seed_cycles(0.f)
|
, seed_rank(0)
|
||||||
|
, last_scrape(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
enum state_t
|
enum state_t
|
||||||
@ -257,7 +258,12 @@ namespace libtorrent
|
|||||||
int active_time;
|
int active_time;
|
||||||
int seeding_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
|
struct TORRENT_EXPORT block_info
|
||||||
|
|||||||
@ -45,12 +45,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/shared_array.hpp>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "libtorrent/entry.hpp"
|
#include "libtorrent/entry.hpp"
|
||||||
|
#include "libtorrent/lazy_entry.hpp"
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
#include "libtorrent/peer_id.hpp"
|
#include "libtorrent/peer_id.hpp"
|
||||||
#include "libtorrent/size_type.hpp"
|
#include "libtorrent/size_type.hpp"
|
||||||
@ -110,18 +112,12 @@ namespace libtorrent
|
|||||||
|
|
||||||
torrent_info();
|
torrent_info();
|
||||||
torrent_info(sha1_hash const& info_hash);
|
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();
|
~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_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);
|
bool remap_files(std::vector<file_entry> const& map);
|
||||||
|
|
||||||
@ -131,10 +127,9 @@ namespace libtorrent
|
|||||||
, bool storage = false) const;
|
, bool storage = false) const;
|
||||||
|
|
||||||
std::vector<std::string> const& url_seeds() const
|
std::vector<std::string> const& url_seeds() const
|
||||||
{
|
{ return m_url_seeds; }
|
||||||
TORRENT_ASSERT(!m_half_metadata);
|
void add_url_seed(std::string const& url)
|
||||||
return m_url_seeds;
|
{ m_url_seeds.push_back(url); }
|
||||||
}
|
|
||||||
|
|
||||||
typedef std::vector<file_entry>::const_iterator file_iterator;
|
typedef std::vector<file_entry>::const_iterator file_iterator;
|
||||||
typedef std::vector<file_entry>::const_reverse_iterator reverse_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);
|
TORRENT_ASSERT(m_piece_length > 0);
|
||||||
if (!storage || m_remapped_files.empty())
|
if (!storage || m_remapped_files.empty())
|
||||||
return (int)m_files.size();
|
return int(m_files.size());
|
||||||
else
|
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())
|
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; }
|
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; }
|
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; }
|
const std::string& name() const { TORRENT_ASSERT(m_piece_length > 0); return m_name; }
|
||||||
|
|
||||||
// ------- start deprecation -------
|
// ------- 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;
|
void print(std::ostream& os) const TORRENT_DEPRECATED;
|
||||||
// ------- end deprecation -------
|
// ------- end deprecation -------
|
||||||
|
|
||||||
bool is_valid() const { return m_piece_length > 0; }
|
bool is_valid() const { return m_piece_length > 0; }
|
||||||
|
|
||||||
bool priv() const { return m_private; }
|
bool priv() const { return m_private; }
|
||||||
void set_priv(bool v) { m_private = v; }
|
|
||||||
|
|
||||||
void convert_file_names();
|
|
||||||
|
|
||||||
int piece_size(int index) const;
|
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 >= 0);
|
||||||
TORRENT_ASSERT(index < (int)m_piece_hash.size());
|
TORRENT_ASSERT(index < m_num_pieces);
|
||||||
TORRENT_ASSERT(!m_half_metadata);
|
TORRENT_ASSERT(m_piece_hashes);
|
||||||
return m_piece_hash[index];
|
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;
|
boost::optional<pt::ptime> creation_date() const;
|
||||||
@ -237,27 +237,30 @@ namespace libtorrent
|
|||||||
typedef std::vector<std::pair<std::string, int> > nodes_t;
|
typedef std::vector<std::pair<std::string, int> > nodes_t;
|
||||||
|
|
||||||
nodes_t const& nodes() const
|
nodes_t const& nodes() const
|
||||||
{
|
{ return m_nodes; }
|
||||||
TORRENT_ASSERT(!m_half_metadata);
|
void add_node(std::pair<std::string, int> const& node)
|
||||||
return m_nodes;
|
{ 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);
|
lazy_entry const* info(char const* key) const
|
||||||
|
{
|
||||||
entry const* extra(char const* key) const
|
if (m_info_dict.type() == lazy_entry::none_t)
|
||||||
{ return m_extra_info.find_key(key); }
|
lazy_bdecode(m_info_section.get(), m_info_section.get()
|
||||||
|
+ m_info_section_size, m_info_dict);
|
||||||
// frees parts of the metadata that isn't
|
return m_info_dict.dict_find(key);
|
||||||
// used by seeds
|
}
|
||||||
void seed_free();
|
|
||||||
|
|
||||||
void swap(torrent_info& ti);
|
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:
|
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
|
// the urls to the trackers
|
||||||
std::vector<announce_entry> m_urls;
|
std::vector<announce_entry> m_urls;
|
||||||
@ -269,9 +272,6 @@ namespace libtorrent
|
|||||||
// in an uninitialized state
|
// in an uninitialized state
|
||||||
int m_piece_length;
|
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
|
// the list of files that this torrent consists of
|
||||||
std::vector<file_entry> m_files;
|
std::vector<file_entry> m_files;
|
||||||
|
|
||||||
@ -293,7 +293,7 @@ namespace libtorrent
|
|||||||
// the hash that identifies this torrent
|
// the hash that identifies this torrent
|
||||||
// is mutable because it's calculated
|
// is mutable because it's calculated
|
||||||
// lazily
|
// lazily
|
||||||
mutable sha1_hash m_info_hash;
|
sha1_hash m_info_hash;
|
||||||
|
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
@ -321,18 +321,19 @@ namespace libtorrent
|
|||||||
// be announced on the dht
|
// be announced on the dht
|
||||||
bool m_private;
|
bool m_private;
|
||||||
|
|
||||||
// contains any non-parsed entries from the info-section
|
// this is a copy of the info section from the torrent.
|
||||||
// these are kept in order to be able to accurately
|
// it use maintained in this flat format in order to
|
||||||
// reproduce the info-section when sending the metadata
|
// make it available through the metadata extension
|
||||||
// to peers.
|
boost::shared_array<char> m_info_section;
|
||||||
entry m_extra_info;
|
int m_info_section_size;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
// this is a pointer into the m_info_section buffer
|
||||||
public:
|
// pointing to the first byte of the first sha-1 hash
|
||||||
// this is set to true when seed_free() is called
|
char const* m_piece_hashes;
|
||||||
bool m_half_metadata;
|
|
||||||
private:
|
// the info section parsed. points into m_info_section
|
||||||
#endif
|
// 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
|
// 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 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
|
struct TORRENT_EXPORT tracker_request
|
||||||
{
|
{
|
||||||
tracker_request()
|
tracker_request()
|
||||||
@ -160,7 +157,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void timeout_callback(asio::error_code const&);
|
void timeout_callback(error_code const&);
|
||||||
|
|
||||||
boost::intrusive_ptr<timeout_handler> self()
|
boost::intrusive_ptr<timeout_handler> self()
|
||||||
{ return boost::intrusive_ptr<timeout_handler>(this); }
|
{ return boost::intrusive_ptr<timeout_handler>(this); }
|
||||||
|
|||||||
@ -46,16 +46,16 @@ namespace libtorrent
|
|||||||
class udp_socket
|
class udp_socket
|
||||||
{
|
{
|
||||||
public:
|
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::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(); }
|
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 send(udp::endpoint const& ep, char const* p, int len, error_code& ec);
|
||||||
void bind(udp::endpoint const& ep, asio::error_code& ec);
|
void bind(udp::endpoint const& ep, error_code& ec);
|
||||||
void bind(int port);
|
void bind(int port);
|
||||||
void close();
|
void close();
|
||||||
int local_port() const { return m_bind_port; }
|
int local_port() const { return m_bind_port; }
|
||||||
@ -67,21 +67,21 @@ namespace libtorrent
|
|||||||
|
|
||||||
callback_t m_callback;
|
callback_t m_callback;
|
||||||
|
|
||||||
void on_read(udp::socket* sock, asio::error_code const& e, std::size_t bytes_transferred);
|
void on_read(udp::socket* sock, error_code const& e, std::size_t bytes_transferred);
|
||||||
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);
|
||||||
void on_timeout();
|
void on_timeout();
|
||||||
void on_connect(int ticket);
|
void on_connect(int ticket);
|
||||||
void on_connected(asio::error_code const& ec);
|
void on_connected(error_code const& ec);
|
||||||
void handshake1(asio::error_code const& e);
|
void handshake1(error_code const& e);
|
||||||
void handshake2(asio::error_code const& e);
|
void handshake2(error_code const& e);
|
||||||
void handshake3(asio::error_code const& e);
|
void handshake3(error_code const& e);
|
||||||
void handshake4(asio::error_code const& e);
|
void handshake4(error_code const& e);
|
||||||
void socks_forward_udp();
|
void socks_forward_udp();
|
||||||
void connect1(asio::error_code const& e);
|
void connect1(error_code const& e);
|
||||||
void connect2(asio::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 wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec);
|
||||||
void unwrap(asio::error_code const& e, char const* buf, int size);
|
void unwrap(error_code const& e, char const* buf, int size);
|
||||||
|
|
||||||
udp::socket m_ipv4_sock;
|
udp::socket m_ipv4_sock;
|
||||||
udp::socket m_ipv6_sock;
|
udp::socket m_ipv6_sock;
|
||||||
|
|||||||
@ -89,10 +89,10 @@ namespace libtorrent
|
|||||||
boost::intrusive_ptr<udp_tracker_connection> self()
|
boost::intrusive_ptr<udp_tracker_connection> self()
|
||||||
{ return boost::intrusive_ptr<udp_tracker_connection>(this); }
|
{ return boost::intrusive_ptr<udp_tracker_connection>(this); }
|
||||||
|
|
||||||
void name_lookup(asio::error_code const& error, udp::resolver::iterator i);
|
void name_lookup(error_code const& error, udp::resolver::iterator i);
|
||||||
void timeout(asio::error_code const& error);
|
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);
|
, char const* buf, int size);
|
||||||
void on_connect_response(char const* buf, int size);
|
void on_connect_response(char const* buf, int size);
|
||||||
void on_announce_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 };
|
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
|
void on_reply(udp::endpoint const& from, char* buffer
|
||||||
, std::size_t bytes_transferred);
|
, std::size_t bytes_transferred);
|
||||||
|
|
||||||
@ -102,15 +102,16 @@ private:
|
|||||||
void update_map(rootdevice& d, int i);
|
void update_map(rootdevice& d, int i);
|
||||||
|
|
||||||
|
|
||||||
void on_upnp_xml(asio::error_code const& e
|
void on_upnp_xml(error_code const& e
|
||||||
, libtorrent::http_parser const& p, rootdevice& d);
|
|
||||||
void on_upnp_map_response(asio::error_code const& e
|
|
||||||
, libtorrent::http_parser const& p, rootdevice& d
|
, libtorrent::http_parser const& p, rootdevice& d
|
||||||
, int mapping);
|
, http_connection& c);
|
||||||
void on_upnp_unmap_response(asio::error_code const& e
|
void on_upnp_map_response(error_code const& e
|
||||||
, libtorrent::http_parser const& p, rootdevice& d
|
, libtorrent::http_parser const& p, rootdevice& d
|
||||||
, int mapping);
|
, int mapping, http_connection& c);
|
||||||
void on_expire(asio::error_code const& e);
|
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 disable(char const* msg);
|
||||||
void return_error(int mapping, int code);
|
void return_error(int mapping, int code);
|
||||||
@ -237,7 +238,7 @@ private:
|
|||||||
// current retry count
|
// current retry count
|
||||||
int m_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
|
// the udp socket used to send and receive
|
||||||
// multicast messages on the network
|
// multicast messages on the network
|
||||||
@ -252,7 +253,7 @@ private:
|
|||||||
|
|
||||||
bool m_disabled;
|
bool m_disabled;
|
||||||
bool m_closing;
|
bool m_closing;
|
||||||
bool m_ignore_outside_network;
|
bool m_ignore_non_routers;
|
||||||
|
|
||||||
connection_queue& m_cc;
|
connection_queue& m_cc;
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,11 @@
|
|||||||
# include <boost/type_traits/add_pointer.hpp>
|
# include <boost/type_traits/add_pointer.hpp>
|
||||||
# include <boost/noncopyable.hpp>
|
# include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/io_service.hpp>
|
#include <asio/io_service.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/asio/io_service.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
# define NETWORK_VARIANT_STREAM_LIMIT 5
|
# define NETWORK_VARIANT_STREAM_LIMIT 5
|
||||||
|
|
||||||
@ -48,7 +52,7 @@ namespace aux
|
|||||||
template<class IO_Control_Command>
|
template<class IO_Control_Command>
|
||||||
struct io_control_visitor_ec: boost::static_visitor<>
|
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_) {}
|
: ioc(ioc), ec(ec_) {}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -61,7 +65,7 @@ namespace aux
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
IO_Control_Command& ioc;
|
IO_Control_Command& ioc;
|
||||||
asio::error_code& ec;
|
error_code& ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class IO_Control_Command>
|
template<class IO_Control_Command>
|
||||||
@ -112,7 +116,7 @@ namespace aux
|
|||||||
struct bind_visitor_ec
|
struct bind_visitor_ec
|
||||||
: boost::static_visitor<>
|
: boost::static_visitor<>
|
||||||
{
|
{
|
||||||
bind_visitor_ec(EndpointType const& ep, asio::error_code& ec_)
|
bind_visitor_ec(EndpointType const& ep, error_code& ec_)
|
||||||
: endpoint(ep)
|
: endpoint(ep)
|
||||||
, ec(ec_)
|
, ec(ec_)
|
||||||
{}
|
{}
|
||||||
@ -124,7 +128,7 @@ namespace aux
|
|||||||
void operator()(boost::blank) const {}
|
void operator()(boost::blank) const {}
|
||||||
|
|
||||||
EndpointType const& endpoint;
|
EndpointType const& endpoint;
|
||||||
asio::error_code& ec;
|
error_code& ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class EndpointType>
|
template <class EndpointType>
|
||||||
@ -150,7 +154,7 @@ namespace aux
|
|||||||
struct open_visitor_ec
|
struct open_visitor_ec
|
||||||
: boost::static_visitor<>
|
: boost::static_visitor<>
|
||||||
{
|
{
|
||||||
open_visitor_ec(Protocol const& p, asio::error_code& ec_)
|
open_visitor_ec(Protocol const& p, error_code& ec_)
|
||||||
: proto(p)
|
: proto(p)
|
||||||
, ec(ec_)
|
, ec(ec_)
|
||||||
{}
|
{}
|
||||||
@ -162,7 +166,7 @@ namespace aux
|
|||||||
void operator()(boost::blank) const {}
|
void operator()(boost::blank) const {}
|
||||||
|
|
||||||
Protocol const& proto;
|
Protocol const& proto;
|
||||||
asio::error_code& ec;
|
error_code& ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Protocol>
|
template <class Protocol>
|
||||||
@ -201,7 +205,7 @@ namespace aux
|
|||||||
struct close_visitor_ec
|
struct close_visitor_ec
|
||||||
: boost::static_visitor<>
|
: boost::static_visitor<>
|
||||||
{
|
{
|
||||||
close_visitor_ec(asio::error_code& ec_)
|
close_visitor_ec(error_code& ec_)
|
||||||
: ec(ec_)
|
: ec(ec_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -211,7 +215,7 @@ namespace aux
|
|||||||
|
|
||||||
void operator()(boost::blank) const {}
|
void operator()(boost::blank) const {}
|
||||||
|
|
||||||
asio::error_code& ec;
|
error_code& ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct close_visitor
|
struct close_visitor
|
||||||
@ -230,18 +234,18 @@ namespace aux
|
|||||||
struct remote_endpoint_visitor_ec
|
struct remote_endpoint_visitor_ec
|
||||||
: boost::static_visitor<EndpointType>
|
: boost::static_visitor<EndpointType>
|
||||||
{
|
{
|
||||||
remote_endpoint_visitor_ec(asio::error_code& ec)
|
remote_endpoint_visitor_ec(error_code& ec_)
|
||||||
: error_code(ec)
|
: ec(ec_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
EndpointType operator()(T const* p) const
|
EndpointType operator()(T const* p) const
|
||||||
{ return p->remote_endpoint(error_code); }
|
{ return p->remote_endpoint(ec); }
|
||||||
|
|
||||||
EndpointType operator()(boost::blank) const
|
EndpointType operator()(boost::blank) const
|
||||||
{ return EndpointType(); }
|
{ return EndpointType(); }
|
||||||
|
|
||||||
asio::error_code& error_code;
|
error_code& ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class EndpointType>
|
template <class EndpointType>
|
||||||
@ -270,29 +274,29 @@ namespace aux
|
|||||||
void operator()(T* p) const
|
void operator()(T* p) const
|
||||||
{ p->set_option(opt_); }
|
{ p->set_option(opt_); }
|
||||||
|
|
||||||
void operator()(boost::blank) const {}
|
void operator()(boost::blank) const {}
|
||||||
|
|
||||||
SettableSocketOption const& opt_;
|
SettableSocketOption const& opt_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class SettableSocketOption>
|
template <class SettableSocketOption>
|
||||||
struct set_option_visitor_ec
|
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)
|
: opt_(opt)
|
||||||
, ec_(ec)
|
, ec_(ec)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
asio::error_code operator()(T* p) const
|
error_code operator()(T* p) const
|
||||||
{ return p->set_option(opt_, ec_); }
|
{ return p->set_option(opt_, ec_); }
|
||||||
|
|
||||||
asio::error_code operator()(boost::blank) const
|
error_code operator()(boost::blank) const
|
||||||
{ return ec_; }
|
{ return ec_; }
|
||||||
|
|
||||||
SettableSocketOption const& opt_;
|
SettableSocketOption const& opt_;
|
||||||
asio::error_code& ec_;
|
error_code& ec_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -------------- local_endpoint -----------
|
// -------------- local_endpoint -----------
|
||||||
@ -301,14 +305,14 @@ namespace aux
|
|||||||
struct local_endpoint_visitor_ec
|
struct local_endpoint_visitor_ec
|
||||||
: boost::static_visitor<EndpointType>
|
: boost::static_visitor<EndpointType>
|
||||||
{
|
{
|
||||||
local_endpoint_visitor_ec(asio::error_code& ec)
|
local_endpoint_visitor_ec(error_code& ec_)
|
||||||
: error_code(ec)
|
: ec(ec_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
EndpointType operator()(T const* p) const
|
EndpointType operator()(T const* p) const
|
||||||
{
|
{
|
||||||
return p->local_endpoint(error_code);
|
return p->local_endpoint(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndpointType operator()(boost::blank) const
|
EndpointType operator()(boost::blank) const
|
||||||
@ -316,7 +320,7 @@ namespace aux
|
|||||||
return EndpointType();
|
return EndpointType();
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::error_code& error_code;
|
error_code& ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class EndpointType>
|
template <class EndpointType>
|
||||||
@ -372,7 +376,7 @@ namespace aux
|
|||||||
std::size_t operator()(T* p) const
|
std::size_t operator()(T* p) const
|
||||||
{ return p->read_some(buffers); }
|
{ return p->read_some(buffers); }
|
||||||
|
|
||||||
std::size_t operator()(boost::blank) const
|
std::size_t operator()(boost::blank) const
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
|
|
||||||
Mutable_Buffers const& buffers;
|
Mutable_Buffers const& buffers;
|
||||||
@ -382,7 +386,7 @@ namespace aux
|
|||||||
struct read_some_visitor_ec
|
struct read_some_visitor_ec
|
||||||
: boost::static_visitor<std::size_t>
|
: 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)
|
: buffers(buffers)
|
||||||
, ec(ec_)
|
, ec(ec_)
|
||||||
{}
|
{}
|
||||||
@ -391,11 +395,11 @@ namespace aux
|
|||||||
std::size_t operator()(T* p) const
|
std::size_t operator()(T* p) const
|
||||||
{ return p->read_some(buffers, ec); }
|
{ return p->read_some(buffers, ec); }
|
||||||
|
|
||||||
std::size_t operator()(boost::blank) const
|
std::size_t operator()(boost::blank) const
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
|
|
||||||
Mutable_Buffers const& buffers;
|
Mutable_Buffers const& buffers;
|
||||||
asio::error_code& ec;
|
error_code& ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -------------- async_write_some -----------
|
// -------------- async_write_some -----------
|
||||||
@ -427,7 +431,7 @@ namespace aux
|
|||||||
struct in_avail_visitor_ec
|
struct in_avail_visitor_ec
|
||||||
: boost::static_visitor<std::size_t>
|
: boost::static_visitor<std::size_t>
|
||||||
{
|
{
|
||||||
in_avail_visitor_ec(asio::error_code& ec_)
|
in_avail_visitor_ec(error_code& ec_)
|
||||||
: ec(ec_)
|
: ec(ec_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -442,7 +446,7 @@ namespace aux
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::error_code& ec;
|
error_code& ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct in_avail_visitor
|
struct in_avail_visitor
|
||||||
@ -524,11 +528,11 @@ public:
|
|||||||
typedef typename S0::endpoint_type endpoint_type;
|
typedef typename S0::endpoint_type endpoint_type;
|
||||||
typedef typename S0::protocol_type protocol_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()) {}
|
: m_io_service(ios), m_variant(boost::blank()) {}
|
||||||
|
|
||||||
template <class S>
|
template <class S>
|
||||||
void instantiate(asio::io_service& ios)
|
void instantiate(io_service& ios)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(&ios == &m_io_service);
|
TORRENT_ASSERT(&ios == &m_io_service);
|
||||||
std::auto_ptr<S> owned(new S(ios));
|
std::auto_ptr<S> owned(new S(ios));
|
||||||
@ -540,7 +544,7 @@ public:
|
|||||||
template <class S>
|
template <class S>
|
||||||
S& get()
|
S& get()
|
||||||
{
|
{
|
||||||
return *boost::get<S*>(m_variant);
|
return *boost::get<S*>(m_variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool instantiated() const
|
bool instantiated() const
|
||||||
@ -554,7 +558,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Mutable_Buffers>
|
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());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(
|
return boost::apply_visitor(
|
||||||
@ -612,7 +616,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class IO_Control_Command>
|
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());
|
TORRENT_ASSERT(instantiated());
|
||||||
boost::apply_visitor(
|
boost::apply_visitor(
|
||||||
@ -627,7 +631,7 @@ public:
|
|||||||
boost::apply_visitor(aux::bind_visitor<endpoint_type>(endpoint), m_variant);
|
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());
|
TORRENT_ASSERT(instantiated());
|
||||||
boost::apply_visitor(
|
boost::apply_visitor(
|
||||||
@ -641,7 +645,7 @@ public:
|
|||||||
boost::apply_visitor(aux::open_visitor<protocol_type>(p), m_variant);
|
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());
|
TORRENT_ASSERT(instantiated());
|
||||||
boost::apply_visitor(
|
boost::apply_visitor(
|
||||||
@ -660,7 +664,7 @@ public:
|
|||||||
boost::apply_visitor(aux::close_visitor(), m_variant);
|
boost::apply_visitor(aux::close_visitor(), m_variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
void close(asio::error_code& ec)
|
void close(error_code& ec)
|
||||||
{
|
{
|
||||||
if (!instantiated()) return;
|
if (!instantiated()) return;
|
||||||
boost::apply_visitor(
|
boost::apply_visitor(
|
||||||
@ -674,7 +678,7 @@ public:
|
|||||||
return boost::apply_visitor(aux::in_avail_visitor(), m_variant);
|
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());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(
|
return boost::apply_visitor(
|
||||||
@ -688,7 +692,7 @@ public:
|
|||||||
return boost::apply_visitor(aux::remote_endpoint_visitor<endpoint_type>(), m_variant);
|
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());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(
|
return boost::apply_visitor(
|
||||||
@ -705,20 +709,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class SettableSocketOption>
|
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());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(aux::set_option_visitor_ec<SettableSocketOption>(opt, ec)
|
return boost::apply_visitor(aux::set_option_visitor_ec<SettableSocketOption>(opt, ec)
|
||||||
, m_variant);
|
, m_variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint_type local_endpoint() const
|
endpoint_type local_endpoint() const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(instantiated());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_type>(), m_variant);
|
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());
|
TORRENT_ASSERT(instantiated());
|
||||||
return boost::apply_visitor(
|
return boost::apply_visitor(
|
||||||
@ -726,7 +730,7 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::io_service& get_io_service()
|
io_service& get_io_service()
|
||||||
{
|
{
|
||||||
return m_io_service;
|
return m_io_service;
|
||||||
}
|
}
|
||||||
@ -740,7 +744,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
asio::io_service& m_io_service;
|
io_service& m_io_service;
|
||||||
variant_type m_variant;
|
variant_type m_variant;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -102,9 +102,9 @@ namespace libtorrent
|
|||||||
|
|
||||||
// called from the main loop when this connection has any
|
// called from the main loop when this connection has any
|
||||||
// work to do.
|
// work to do.
|
||||||
void on_sent(asio::error_code const& error
|
void on_sent(error_code const& error
|
||||||
, std::size_t bytes_transferred);
|
, 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::size_t bytes_transferred);
|
||||||
|
|
||||||
std::string const& url() const { return m_url; }
|
std::string const& url() const { return m_url; }
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "GeoIP.h"
|
#include "libtorrent/GeoIP.h"
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|||||||
@ -30,8 +30,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/ip/host_name.hpp>
|
#include <asio/ip/host_name.hpp>
|
||||||
#include <asio/ip/multicast.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 <boost/bind.hpp>
|
||||||
|
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
@ -75,10 +81,10 @@ namespace libtorrent
|
|||||||
return addr.to_v6() == address_v6::any();
|
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
|
// 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);
|
std::vector<ip_interface> const& interfaces = enum_net_interfaces(ios, ec);
|
||||||
address ret = address_v4::any();
|
address ret = address_v4::any();
|
||||||
for (std::vector<ip_interface>::const_iterator i = interfaces.begin()
|
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());
|
- 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
|
, udp::endpoint const& multicast_endpoint
|
||||||
, receive_handler_t const& handler
|
, receive_handler_t const& handler
|
||||||
, bool loopback)
|
, bool loopback)
|
||||||
@ -148,7 +154,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
using namespace asio::ip::multicast;
|
using namespace asio::ip::multicast;
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
std::vector<ip_interface> interfaces = enum_net_interfaces(ios, ec);
|
std::vector<ip_interface> interfaces = enum_net_interfaces(ios, ec);
|
||||||
|
|
||||||
if (multicast_endpoint.address().is_v4())
|
if (multicast_endpoint.address().is_v4())
|
||||||
@ -179,7 +185,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
using namespace asio::ip::multicast;
|
using namespace asio::ip::multicast;
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
|
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
|
||||||
if (addr.is_v4())
|
if (addr.is_v4())
|
||||||
s->open(udp::v4(), ec);
|
s->open(udp::v4(), ec);
|
||||||
@ -205,7 +211,7 @@ namespace libtorrent
|
|||||||
void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr)
|
void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr)
|
||||||
{
|
{
|
||||||
using namespace asio::ip::multicast;
|
using namespace asio::ip::multicast;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
|
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
|
||||||
s->open(addr.is_v4() ? udp::v4() : udp::v6(), ec);
|
s->open(addr.is_v4() ? udp::v4() : udp::v6(), ec);
|
||||||
if (ec) return;
|
if (ec) return;
|
||||||
@ -220,13 +226,13 @@ namespace libtorrent
|
|||||||
, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
|
, 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()
|
for (std::list<socket_entry>::iterator i = m_unicast_sockets.begin()
|
||||||
, end(m_unicast_sockets.end()); i != end; ++i)
|
, end(m_unicast_sockets.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
if (!i->socket) continue;
|
if (!i->socket) continue;
|
||||||
asio::error_code e;
|
error_code e;
|
||||||
i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
|
i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << " to: " << m_multicast_endpoint << std::endl;
|
// 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)
|
, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
if (ec || bytes_transferred == 0 || !m_on_receive) return;
|
if (ec || bytes_transferred == 0 || !m_on_receive) return;
|
||||||
|
|||||||
@ -125,8 +125,9 @@ namespace libtorrent
|
|||||||
bt_peer_connection::bt_peer_connection(
|
bt_peer_connection::bt_peer_connection(
|
||||||
session_impl& ses
|
session_impl& ses
|
||||||
, boost::shared_ptr<socket_type> s
|
, boost::shared_ptr<socket_type> s
|
||||||
|
, tcp::endpoint const& remote
|
||||||
, policy::peer* peerinfo)
|
, policy::peer* peerinfo)
|
||||||
: peer_connection(ses, s, peerinfo)
|
: peer_connection(ses, s, remote, peerinfo)
|
||||||
, m_state(read_protocol_identifier)
|
, m_state(read_protocol_identifier)
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
, m_supports_extensions(false)
|
, m_supports_extensions(false)
|
||||||
@ -800,13 +801,14 @@ namespace libtorrent
|
|||||||
TORRENT_ASSERT(received > 0);
|
TORRENT_ASSERT(received > 0);
|
||||||
if (packet_size() != 1)
|
if (packet_size() != 1)
|
||||||
{
|
{
|
||||||
disconnect("'choke' message size != 1");
|
disconnect("'choke' message size != 1", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
if (!packet_finished()) return;
|
if (!packet_finished()) return;
|
||||||
|
|
||||||
incoming_choke();
|
incoming_choke();
|
||||||
|
if (is_disconnecting()) return;
|
||||||
if (!m_supports_fast)
|
if (!m_supports_fast)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||||
@ -834,7 +836,7 @@ namespace libtorrent
|
|||||||
TORRENT_ASSERT(received > 0);
|
TORRENT_ASSERT(received > 0);
|
||||||
if (packet_size() != 1)
|
if (packet_size() != 1)
|
||||||
{
|
{
|
||||||
disconnect("'unchoke' message size != 1");
|
disconnect("'unchoke' message size != 1", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@ -854,7 +856,7 @@ namespace libtorrent
|
|||||||
TORRENT_ASSERT(received > 0);
|
TORRENT_ASSERT(received > 0);
|
||||||
if (packet_size() != 1)
|
if (packet_size() != 1)
|
||||||
{
|
{
|
||||||
disconnect("'interested' message size != 1");
|
disconnect("'interested' message size != 1", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@ -874,7 +876,7 @@ namespace libtorrent
|
|||||||
TORRENT_ASSERT(received > 0);
|
TORRENT_ASSERT(received > 0);
|
||||||
if (packet_size() != 1)
|
if (packet_size() != 1)
|
||||||
{
|
{
|
||||||
disconnect("'not interested' message size != 1");
|
disconnect("'not interested' message size != 1", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@ -894,7 +896,7 @@ namespace libtorrent
|
|||||||
TORRENT_ASSERT(received > 0);
|
TORRENT_ASSERT(received > 0);
|
||||||
if (packet_size() != 5)
|
if (packet_size() != 5)
|
||||||
{
|
{
|
||||||
disconnect("'have' message size != 5");
|
disconnect("'have' message size != 5", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@ -926,7 +928,7 @@ namespace libtorrent
|
|||||||
if (t->valid_metadata()
|
if (t->valid_metadata()
|
||||||
&& packet_size() - 1 != ((int)get_bitfield().size() + 7) / 8)
|
&& packet_size() - 1 != ((int)get_bitfield().size() + 7) / 8)
|
||||||
{
|
{
|
||||||
disconnect("bitfield with invalid size");
|
disconnect("bitfield with invalid size", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -963,7 +965,7 @@ namespace libtorrent
|
|||||||
TORRENT_ASSERT(received > 0);
|
TORRENT_ASSERT(received > 0);
|
||||||
if (packet_size() != 13)
|
if (packet_size() != 13)
|
||||||
{
|
{
|
||||||
disconnect("'request' message size != 13");
|
disconnect("'request' message size != 13", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@ -1021,6 +1023,7 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
|
|
||||||
incoming_piece_fragment();
|
incoming_piece_fragment();
|
||||||
|
if (is_disconnecting()) return;
|
||||||
if (!packet_finished()) return;
|
if (!packet_finished()) return;
|
||||||
|
|
||||||
const char* ptr = recv_buffer.begin + 1;
|
const char* ptr = recv_buffer.begin + 1;
|
||||||
@ -1044,7 +1047,7 @@ namespace libtorrent
|
|||||||
TORRENT_ASSERT(received > 0);
|
TORRENT_ASSERT(received > 0);
|
||||||
if (packet_size() != 13)
|
if (packet_size() != 13)
|
||||||
{
|
{
|
||||||
disconnect("'cancel' message size != 13");
|
disconnect("'cancel' message size != 13", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@ -1071,14 +1074,14 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (!m_supports_dht_port)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(received > 0);
|
TORRENT_ASSERT(received > 0);
|
||||||
if (packet_size() != 3)
|
if (packet_size() != 3)
|
||||||
{
|
{
|
||||||
disconnect("'dht_port' message size != 3");
|
disconnect("'dht_port' message size != 3", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@ -1098,7 +1101,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (!m_supports_fast)
|
if (!m_supports_fast)
|
||||||
{
|
{
|
||||||
disconnect("got 'suggest_piece' without FAST excension support");
|
disconnect("got 'suggest_piece' without FAST excension support", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1118,7 +1121,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (!m_supports_fast)
|
if (!m_supports_fast)
|
||||||
{
|
{
|
||||||
disconnect("got 'have_all' without FAST extension support");
|
disconnect("got 'have_all' without FAST extension support", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@ -1131,7 +1134,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (!m_supports_fast)
|
if (!m_supports_fast)
|
||||||
{
|
{
|
||||||
disconnect("got 'have_none' without FAST extension support");
|
disconnect("got 'have_none' without FAST extension support", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@ -1144,7 +1147,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (!m_supports_fast)
|
if (!m_supports_fast)
|
||||||
{
|
{
|
||||||
disconnect("got 'reject_request' without FAST extension support");
|
disconnect("got 'reject_request' without FAST extension support", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,7 +1171,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (!m_supports_fast)
|
if (!m_supports_fast)
|
||||||
{
|
{
|
||||||
disconnect("got 'allowed_fast' without FAST extension support");
|
disconnect("got 'allowed_fast' without FAST extension support", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1193,13 +1196,13 @@ namespace libtorrent
|
|||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
if (packet_size() < 2)
|
if (packet_size() < 2)
|
||||||
{
|
{
|
||||||
disconnect("'extended' message smaller than 2 bytes");
|
disconnect("'extended' message smaller than 2 bytes", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (associated_torrent().expired())
|
if (associated_torrent().expired())
|
||||||
{
|
{
|
||||||
disconnect("'extended' message sent before proper handshake");
|
disconnect("'extended' message sent before proper handshake", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1229,7 +1232,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
msg << "unknown extended message id: " << extended_id;
|
msg << "unknown extended message id: " << extended_id;
|
||||||
disconnect(msg.str().c_str());
|
disconnect(msg.str().c_str(), 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1298,6 +1301,12 @@ namespace libtorrent
|
|||||||
m_max_out_request_queue = 1;
|
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"))
|
if (entry* myip = root.find_key("yourip"))
|
||||||
{
|
{
|
||||||
// TODO: don't trust this blindly
|
// 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)
|
bool bt_peer_connection::dispatch_message(int received)
|
||||||
@ -1350,7 +1364,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
msg << "unkown message id: " << packet_type << " size: " << packet_size();
|
msg << "unkown message id: " << packet_type << " size: " << packet_size();
|
||||||
disconnect(msg.str().c_str());
|
disconnect(msg.str().c_str(), 2);
|
||||||
return packet_finished();
|
return packet_finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1553,6 +1567,9 @@ namespace libtorrent
|
|||||||
detail::write_address(remote().address(), out);
|
detail::write_address(remote().address(), out);
|
||||||
handshake["yourip"] = remote_address;
|
handshake["yourip"] = remote_address;
|
||||||
handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue;
|
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();
|
tcp::endpoint ep = m_ses.get_ipv6_interface();
|
||||||
if (ep != tcp::endpoint())
|
if (ep != tcp::endpoint())
|
||||||
@ -1671,7 +1688,7 @@ namespace libtorrent
|
|||||||
detail::write_int32(r.start, ptr);
|
detail::write_int32(r.start, ptr);
|
||||||
send_buffer(msg, sizeof(msg));
|
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::bind(&session_impl::free_disk_buffer
|
||||||
, boost::ref(m_ses), _1));
|
, boost::ref(m_ses), _1));
|
||||||
buffer.release();
|
buffer.release();
|
||||||
@ -1707,7 +1724,7 @@ namespace libtorrent
|
|||||||
// --------------------------
|
// --------------------------
|
||||||
|
|
||||||
// throws exception when the client should be disconnected
|
// 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)
|
, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
@ -1802,7 +1819,7 @@ namespace libtorrent
|
|||||||
if (recv_buffer.left() < 20)
|
if (recv_buffer.left() < 20)
|
||||||
{
|
{
|
||||||
if (packet_finished())
|
if (packet_finished())
|
||||||
disconnect("sync hash not found");
|
disconnect("sync hash not found", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1828,7 +1845,7 @@ namespace libtorrent
|
|||||||
m_sync_bytes_read += bytes_processed;
|
m_sync_bytes_read += bytes_processed;
|
||||||
if (m_sync_bytes_read >= 512)
|
if (m_sync_bytes_read >= 512)
|
||||||
{
|
{
|
||||||
disconnect("sync hash not found within 532 bytes");
|
disconnect("sync hash not found within 532 bytes", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1913,7 +1930,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (!m_RC4_handler.get())
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1925,7 +1942,7 @@ namespace libtorrent
|
|||||||
const char sh_vc[] = {0,0,0,0, 0,0,0,0};
|
const char sh_vc[] = {0,0,0,0, 0,0,0,0};
|
||||||
if (!std::equal(sh_vc, sh_vc+8, recv_buffer.begin + 20))
|
if (!std::equal(sh_vc, sh_vc+8, recv_buffer.begin + 20))
|
||||||
{
|
{
|
||||||
disconnect("unable to verify constant");
|
disconnect("unable to verify constant", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1947,7 +1964,7 @@ namespace libtorrent
|
|||||||
if (recv_buffer.left() < 8)
|
if (recv_buffer.left() < 8)
|
||||||
{
|
{
|
||||||
if (packet_finished())
|
if (packet_finished())
|
||||||
disconnect("sync verification constant not found");
|
disconnect("sync verification constant not found", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1972,7 +1989,7 @@ namespace libtorrent
|
|||||||
m_sync_bytes_read += bytes_processed;
|
m_sync_bytes_read += bytes_processed;
|
||||||
if (m_sync_bytes_read >= 512)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2035,7 +2052,7 @@ namespace libtorrent
|
|||||||
case pe_settings::plaintext:
|
case pe_settings::plaintext:
|
||||||
if (!(crypto_field & 0x01))
|
if (!(crypto_field & 0x01))
|
||||||
{
|
{
|
||||||
disconnect("plaintext not provided");
|
disconnect("plaintext not provided", 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
crypto_select = 0x01;
|
crypto_select = 0x01;
|
||||||
@ -2043,7 +2060,7 @@ namespace libtorrent
|
|||||||
case pe_settings::rc4:
|
case pe_settings::rc4:
|
||||||
if (!(crypto_field & 0x02))
|
if (!(crypto_field & 0x02))
|
||||||
{
|
{
|
||||||
disconnect("rc4 not provided");
|
disconnect("rc4 not provided", 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
crypto_select = 0x02;
|
crypto_select = 0x02;
|
||||||
@ -2065,7 +2082,7 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
if (!crypto_select)
|
if (!crypto_select)
|
||||||
{
|
{
|
||||||
disconnect("rc4/plaintext not provided");
|
disconnect("rc4/plaintext not provided", 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2083,7 +2100,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
if (allowed_enc_level == pe_settings::plaintext)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
m_rc4_encrypted = true;
|
m_rc4_encrypted = true;
|
||||||
@ -2092,14 +2109,14 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
if (allowed_enc_level == pe_settings::rc4)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
m_rc4_encrypted = false;
|
m_rc4_encrypted = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
disconnect("unsupported crypto method selected by peer");
|
disconnect("unsupported crypto method selected by peer", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2107,7 +2124,7 @@ namespace libtorrent
|
|||||||
int len_pad = detail::read_int16(recv_buffer.begin);
|
int len_pad = detail::read_int16(recv_buffer.begin);
|
||||||
if (len_pad < 0 || len_pad > 512)
|
if (len_pad < 0 || len_pad > 512)
|
||||||
{
|
{
|
||||||
disconnect("invalid pad length");
|
disconnect("invalid pad length", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2145,7 +2162,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (len_ia < 0)
|
if (len_ia < 0)
|
||||||
{
|
{
|
||||||
disconnect("invalid len_ia in handshake");
|
disconnect("invalid len_ia in handshake", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2277,7 +2294,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
TORRENT_ASSERT((!is_local() && m_encrypted) || is_local());
|
TORRENT_ASSERT((!is_local() && m_encrypted) || is_local());
|
||||||
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
|
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
|
||||||
disconnect("incorrect protocol identifier");
|
disconnect("incorrect protocol identifier", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2329,6 +2346,7 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DISABLE_EXTENSIONS
|
#ifndef DISABLE_EXTENSIONS
|
||||||
|
std::memcpy(m_reserved_bits, recv_buffer.begin, 20);
|
||||||
if ((recv_buffer[5] & 0x10))
|
if ((recv_buffer[5] & 0x10))
|
||||||
m_supports_extensions = true;
|
m_supports_extensions = true;
|
||||||
#endif
|
#endif
|
||||||
@ -2360,7 +2378,7 @@ namespace libtorrent
|
|||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << " received invalid info_hash\n";
|
(*m_logger) << " received invalid info_hash\n";
|
||||||
#endif
|
#endif
|
||||||
disconnect("invalid info-hash in handshake");
|
disconnect("invalid info-hash in handshake", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2449,8 +2467,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (pid == m_ses.get_peer_id())
|
if (pid == m_ses.get_peer_id())
|
||||||
{
|
{
|
||||||
set_failed();
|
disconnect("closing connection to ourself", 1);
|
||||||
disconnect("closing connection to ourself");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2466,8 +2483,7 @@ namespace libtorrent
|
|||||||
// since it most likely is ourself then
|
// since it most likely is ourself then
|
||||||
if (pid == m_ses.get_peer_id())
|
if (pid == m_ses.get_peer_id())
|
||||||
{
|
{
|
||||||
set_failed();
|
disconnect("closing connection to ourself", 1);
|
||||||
disconnect("closing connection to ourself");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2475,7 +2491,7 @@ namespace libtorrent
|
|||||||
for (extension_list_t::iterator i = m_extensions.begin()
|
for (extension_list_t::iterator i = m_extensions.begin()
|
||||||
, end(m_extensions.end()); i != end;)
|
, end(m_extensions.end()); i != end;)
|
||||||
{
|
{
|
||||||
if (!(*i)->on_handshake())
|
if (!(*i)->on_handshake(m_reserved_bits))
|
||||||
{
|
{
|
||||||
i = m_extensions.erase(i);
|
i = m_extensions.erase(i);
|
||||||
}
|
}
|
||||||
@ -2484,6 +2500,7 @@ namespace libtorrent
|
|||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
if (m_supports_extensions) write_extensions();
|
if (m_supports_extensions) write_extensions();
|
||||||
#endif
|
#endif
|
||||||
@ -2542,13 +2559,14 @@ namespace libtorrent
|
|||||||
// packet too large
|
// packet too large
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
msg << "packet > 1 MB (" << (unsigned int)packet_size << " bytes)";
|
msg << "packet > 1 MB (" << (unsigned int)packet_size << " bytes)";
|
||||||
disconnect(msg.str().c_str());
|
disconnect(msg.str().c_str(), 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet_size == 0)
|
if (packet_size == 0)
|
||||||
{
|
{
|
||||||
incoming_keepalive();
|
incoming_keepalive();
|
||||||
|
if (is_disconnecting()) return;
|
||||||
// keepalive message
|
// keepalive message
|
||||||
m_state = read_packet_size;
|
m_state = read_packet_size;
|
||||||
cut_receive_buffer(4, 4);
|
cut_receive_buffer(4, 4);
|
||||||
@ -2586,8 +2604,7 @@ namespace libtorrent
|
|||||||
// SEND DATA
|
// SEND DATA
|
||||||
// --------------------------
|
// --------------------------
|
||||||
|
|
||||||
// throws exception when the client should be disconnected
|
void bt_peer_connection::on_sent(error_code const& error
|
||||||
void bt_peer_connection::on_sent(asio::error_code const& error
|
|
||||||
, std::size_t bytes_transferred)
|
, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|||||||
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include "libtorrent/invariant_check.hpp"
|
#include "libtorrent/invariant_check.hpp"
|
||||||
#include "libtorrent/connection_queue.hpp"
|
#include "libtorrent/connection_queue.hpp"
|
||||||
|
#include "libtorrent/socket.hpp"
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
@ -112,7 +113,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
void connection_queue::close()
|
void connection_queue::close()
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timer.cancel(ec);
|
m_timer.cancel(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +154,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (m_queue.empty())
|
if (m_queue.empty())
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timer.cancel(ec);
|
m_timer.cancel(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -166,7 +167,7 @@ namespace libtorrent
|
|||||||
ptime expire = time_now() + i->timeout;
|
ptime expire = time_now() + i->timeout;
|
||||||
if (m_num_connecting == 0)
|
if (m_num_connecting == 0)
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timer.expires_at(expire, ec);
|
m_timer.expires_at(expire, ec);
|
||||||
m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
|
m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
|
||||||
}
|
}
|
||||||
@ -206,7 +207,7 @@ namespace libtorrent
|
|||||||
};
|
};
|
||||||
#endif
|
#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);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
@ -251,7 +252,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (next_expire < max_time())
|
if (next_expire < max_time())
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timer.expires_at(next_expire, ec);
|
m_timer.expires_at(next_expire, ec);
|
||||||
m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
|
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));
|
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* disk_buffer_holder::release()
|
||||||
{
|
{
|
||||||
char* ret = m_buf;
|
char* ret = m_buf;
|
||||||
|
|||||||
@ -182,7 +182,6 @@ namespace libtorrent
|
|||||||
disk_io_thread::cache_t& cache
|
disk_io_thread::cache_t& cache
|
||||||
, disk_io_job const& j, mutex_t::scoped_lock& l)
|
, disk_io_job const& j, mutex_t::scoped_lock& l)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
for (cache_t::iterator i = cache.begin()
|
for (cache_t::iterator i = cache.begin()
|
||||||
, end(cache.end()); i != end; ++i)
|
, end(cache.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
@ -196,7 +195,6 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
ptime now = time_now();
|
ptime now = time_now();
|
||||||
|
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -213,7 +211,6 @@ namespace libtorrent
|
|||||||
|
|
||||||
void disk_io_thread::free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l)
|
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 piece_size = p.storage->info()->piece_size(p.piece);
|
||||||
int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size;
|
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)
|
void disk_io_thread::flush_oldest_piece(mutex_t::scoped_lock& l)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
// first look if there are any read cache entries that can
|
// first look if there are any read cache entries that can
|
||||||
// be cleared
|
// be cleared
|
||||||
@ -275,7 +271,6 @@ namespace libtorrent
|
|||||||
void disk_io_thread::flush(disk_io_thread::cache_t::iterator e
|
void disk_io_thread::flush(disk_io_thread::cache_t::iterator e
|
||||||
, mutex_t::scoped_lock& l)
|
, mutex_t::scoped_lock& l)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
cached_piece_entry& p = *e;
|
cached_piece_entry& p = *e;
|
||||||
int piece_size = p.storage->info()->piece_size(p.piece);
|
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)
|
void disk_io_thread::cache_block(disk_io_job& j, mutex_t::scoped_lock& l)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
TORRENT_ASSERT(find_cached_piece(m_pieces, j, l) == m_pieces.end());
|
TORRENT_ASSERT(find_cached_piece(m_pieces, j, l) == m_pieces.end());
|
||||||
cached_piece_entry p;
|
cached_piece_entry p;
|
||||||
@ -365,8 +359,6 @@ namespace libtorrent
|
|||||||
// read or -1 if there was an error
|
// 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)
|
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 piece_size = p.storage->info()->piece_size(p.piece);
|
||||||
int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size;
|
int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size;
|
||||||
|
|
||||||
@ -436,8 +428,6 @@ namespace libtorrent
|
|||||||
, cache_t::iterator ignore
|
, cache_t::iterator ignore
|
||||||
, mutex_t::scoped_lock& l)
|
, mutex_t::scoped_lock& l)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
|
|
||||||
if (m_cache_size - m_cache_stats.cache_size < num_blocks)
|
if (m_cache_size - m_cache_stats.cache_size < num_blocks)
|
||||||
{
|
{
|
||||||
// there's not enough room in the cache, clear a piece
|
// there's not enough room in the cache, clear a piece
|
||||||
@ -452,8 +442,6 @@ namespace libtorrent
|
|||||||
// or the number of bytes read
|
// or the number of bytes read
|
||||||
int disk_io_thread::cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l)
|
int disk_io_thread::cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
int piece_size = j.storage->info()->piece_size(j.piece);
|
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)
|
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);
|
TORRENT_ASSERT(j.buffer);
|
||||||
|
|
||||||
if (!m_use_read_cache) return -2;
|
if (!m_use_read_cache) return -2;
|
||||||
@ -707,7 +694,6 @@ namespace libtorrent
|
|||||||
|
|
||||||
char* disk_io_thread::allocate_buffer(mutex_t::scoped_lock& l)
|
char* disk_io_thread::allocate_buffer(mutex_t::scoped_lock& l)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
#ifdef TORRENT_STATS
|
#ifdef TORRENT_STATS
|
||||||
++m_allocations;
|
++m_allocations;
|
||||||
#endif
|
#endif
|
||||||
@ -720,7 +706,6 @@ namespace libtorrent
|
|||||||
|
|
||||||
void disk_io_thread::free_buffer(char* buf, mutex_t::scoped_lock& l)
|
void disk_io_thread::free_buffer(char* buf, mutex_t::scoped_lock& l)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(l.locked());
|
|
||||||
#ifdef TORRENT_STATS
|
#ifdef TORRENT_STATS
|
||||||
--m_allocations;
|
--m_allocations;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -35,8 +35,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
#include "libtorrent/entry.hpp"
|
#include "libtorrent/entry.hpp"
|
||||||
#include "libtorrent/config.hpp"
|
#include "libtorrent/config.hpp"
|
||||||
|
#include "libtorrent/escape_string.hpp"
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
namespace std
|
namespace std
|
||||||
@ -54,19 +56,6 @@ namespace
|
|||||||
TORRENT_ASSERT(o);
|
TORRENT_ASSERT(o);
|
||||||
o->~T();
|
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
|
namespace libtorrent
|
||||||
@ -94,6 +83,16 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
|
|
||||||
entry& entry::operator[](char const* key)
|
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);
|
dictionary_type::iterator i = dict().find(key);
|
||||||
if (i != dict().end()) return i->second;
|
if (i != dict().end()) return i->second;
|
||||||
@ -103,21 +102,11 @@ namespace libtorrent
|
|||||||
return ret->second;
|
return ret->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
entry& entry::operator[](std::string const& key)
|
|
||||||
{
|
|
||||||
return (*this)[key.c_str()];
|
|
||||||
}
|
|
||||||
|
|
||||||
entry* entry::find_key(char const* key)
|
entry* entry::find_key(char const* key)
|
||||||
{
|
{
|
||||||
dictionary_type::iterator i = std::find_if(
|
dictionary_type::iterator i = dict().find(key);
|
||||||
dict().begin()
|
|
||||||
, dict().end()
|
|
||||||
, compare_string(key));
|
|
||||||
if (i == dict().end()) return 0;
|
if (i == dict().end()) return 0;
|
||||||
return &i->second;
|
return &i->second;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry const* entry::find_key(char const* key) const
|
entry const* entry::find_key(char const* key) const
|
||||||
@ -127,6 +116,20 @@ namespace libtorrent
|
|||||||
return &i->second;
|
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
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
const entry& entry::operator[](char const* key) const
|
const entry& entry::operator[](char const* key) const
|
||||||
{
|
{
|
||||||
@ -370,21 +373,8 @@ namespace libtorrent
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (binary_string)
|
if (binary_string) os << to_hex(string()) << "\n";
|
||||||
{
|
else os << string() << "\n";
|
||||||
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";
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case list_t:
|
case list_t:
|
||||||
{
|
{
|
||||||
@ -399,8 +389,21 @@ namespace libtorrent
|
|||||||
os << "dictionary\n";
|
os << "dictionary\n";
|
||||||
for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
|
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 << " ";
|
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
|
if (i->second.type() != entry::string_t
|
||||||
&& i->second.type() != entry::int_t)
|
&& i->second.type() != entry::int_t)
|
||||||
os << "\n";
|
os << "\n";
|
||||||
|
|||||||
@ -35,8 +35,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "libtorrent/enum_net.hpp"
|
#include "libtorrent/enum_net.hpp"
|
||||||
#include "libtorrent/broadcast_socket.hpp"
|
#include "libtorrent/broadcast_socket.hpp"
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/ip/host_name.hpp>
|
#include <asio/ip/host_name.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/asio/ip/host_name.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined TORRENT_BSD
|
#if defined TORRENT_BSD
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
@ -225,7 +228,7 @@ namespace libtorrent
|
|||||||
== (iface.interface_address.to_v4().to_ulong() & iface.netmask.to_v4().to_ulong());
|
== (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);
|
std::vector<ip_interface> const& net = enum_net_interfaces(ios, ec);
|
||||||
if (ec) return false;
|
if (ec) return false;
|
||||||
@ -237,7 +240,7 @@ namespace libtorrent
|
|||||||
return false;
|
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;
|
std::vector<ip_interface> ret;
|
||||||
// covers linux, MacOS X and BSD distributions
|
// covers linux, MacOS X and BSD distributions
|
||||||
@ -254,7 +257,7 @@ namespace libtorrent
|
|||||||
ifc.ifc_buf = buf;
|
ifc.ifc_buf = buf;
|
||||||
if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
|
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);
|
close(s);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -283,7 +286,7 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ec = asio::error_code(errno, asio::error::system_category);
|
ec = error_code(errno, asio::error::system_category);
|
||||||
close(s);
|
close(s);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -310,7 +313,7 @@ namespace libtorrent
|
|||||||
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
|
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (s == SOCKET_ERROR)
|
if (s == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
ec = asio::error_code(WSAGetLastError(), asio::error::system_category);
|
ec = error_code(WSAGetLastError(), asio::error::system_category);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +323,7 @@ namespace libtorrent
|
|||||||
if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, 0, 0, buffer,
|
if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, 0, 0, buffer,
|
||||||
sizeof(buffer), &size, 0, 0) != 0)
|
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);
|
closesocket(s);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -356,16 +359,21 @@ namespace libtorrent
|
|||||||
return ret;
|
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);
|
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()
|
std::vector<ip_route>::iterator i = std::find_if(ret.begin(), ret.end()
|
||||||
, boost::bind(&ip_route::destination, _1) == address());
|
, boost::bind(&ip_route::destination, _1) == address());
|
||||||
|
#endif
|
||||||
if (i == ret.end()) return address();
|
if (i == ret.end()) return address();
|
||||||
return i->gateway;
|
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;
|
std::vector<ip_route> ret;
|
||||||
|
|
||||||
@ -390,14 +398,14 @@ namespace libtorrent
|
|||||||
int s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
|
int s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
|
||||||
if (s == -1)
|
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>();
|
return std::vector<ip_route>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int n = write(s, &m, len);
|
int n = write(s, &m, len);
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
{
|
{
|
||||||
ec = asio::error_code(errno, asio::error::system_category);
|
ec = error_code(errno, asio::error::system_category);
|
||||||
close(s);
|
close(s);
|
||||||
return std::vector<ip_route>();
|
return std::vector<ip_route>();
|
||||||
}
|
}
|
||||||
@ -412,7 +420,7 @@ namespace libtorrent
|
|||||||
n = read(s, &m, len);
|
n = read(s, &m, len);
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
{
|
{
|
||||||
ec = asio::error_code(errno, asio::error::system_category);
|
ec = error_code(errno, asio::error::system_category);
|
||||||
close(s);
|
close(s);
|
||||||
return std::vector<ip_route>();
|
return std::vector<ip_route>();
|
||||||
}
|
}
|
||||||
@ -423,7 +431,7 @@ namespace libtorrent
|
|||||||
std::cout << " rtm_type: " << ptr->rtm_type << std::endl;
|
std::cout << " rtm_type: " << ptr->rtm_type << std::endl;
|
||||||
if (ptr->rtm_errno)
|
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>();
|
return std::vector<ip_route>();
|
||||||
}
|
}
|
||||||
if (m.m_rtm.rtm_flags & RTF_UP == 0
|
if (m.m_rtm.rtm_flags & RTF_UP == 0
|
||||||
@ -475,7 +483,7 @@ namespace libtorrent
|
|||||||
size_t needed = 0;
|
size_t needed = 0;
|
||||||
if (sysctl(mib, 6, 0, &needed, 0, 0) < 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>();
|
return std::vector<ip_route>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,7 +501,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0)
|
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>();
|
return std::vector<ip_route>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +555,6 @@ namespace libtorrent
|
|||||||
return std::vector<ip_route>();
|
return std::vector<ip_route>();
|
||||||
}
|
}
|
||||||
|
|
||||||
address ret;
|
|
||||||
if (GetAdaptersInfo(adapter_info, &out_buf_size) == NO_ERROR)
|
if (GetAdaptersInfo(adapter_info, &out_buf_size) == NO_ERROR)
|
||||||
{
|
{
|
||||||
for (PIP_ADAPTER_INFO adapter = adapter_info;
|
for (PIP_ADAPTER_INFO adapter = adapter_info;
|
||||||
@ -555,14 +562,14 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
|
|
||||||
ip_route r;
|
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.gateway = address::from_string(adapter->GatewayList.IpAddress.String, ec);
|
||||||
r.netmask = address::from_string(adapter->IpAddressList.IpMask.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)
|
if (ec)
|
||||||
{
|
{
|
||||||
ec = asio::error_code();
|
ec = error_code();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ret.push_back(r);
|
ret.push_back(r);
|
||||||
@ -573,8 +580,6 @@ namespace libtorrent
|
|||||||
free(adapter_info);
|
free(adapter_info);
|
||||||
FreeLibrary(iphlp);
|
FreeLibrary(iphlp);
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
#elif defined TORRENT_LINUX
|
#elif defined TORRENT_LINUX
|
||||||
|
|
||||||
enum { BUFSIZE = 8192 };
|
enum { BUFSIZE = 8192 };
|
||||||
@ -582,7 +587,7 @@ namespace libtorrent
|
|||||||
int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE);
|
int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE);
|
||||||
if (sock < 0)
|
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>();
|
return std::vector<ip_route>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,7 +605,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (send(sock, nl_msg, nl_msg->nlmsg_len, 0) < 0)
|
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);
|
close(sock);
|
||||||
return std::vector<ip_route>();
|
return std::vector<ip_route>();
|
||||||
}
|
}
|
||||||
@ -608,7 +613,7 @@ namespace libtorrent
|
|||||||
int len = read_nl_sock(sock, msg, BUFSIZE, seq, getpid());
|
int len = read_nl_sock(sock, msg, BUFSIZE, seq, getpid());
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
{
|
{
|
||||||
ec = asio::error_code(errno, asio::error::system_category);
|
ec = error_code(errno, asio::error::system_category);
|
||||||
close(sock);
|
close(sock);
|
||||||
return std::vector<ip_route>();
|
return std::vector<ip_route>();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -352,5 +352,17 @@ namespace libtorrent
|
|||||||
return url.substr(pos, url.find('&', pos) - pos);
|
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/escape_string.hpp"
|
||||||
#include "libtorrent/instantiate_connection.hpp"
|
#include "libtorrent/instantiate_connection.hpp"
|
||||||
#include "libtorrent/gzip.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/bind.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <asio/ip/tcp.hpp>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using boost::bind;
|
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 auth;
|
||||||
std::string hostname;
|
std::string hostname;
|
||||||
std::string path;
|
std::string path;
|
||||||
|
char const* error;
|
||||||
int port;
|
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);
|
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";
|
"\r\n";
|
||||||
|
|
||||||
sendbuffer = headers.str();
|
sendbuffer = headers.str();
|
||||||
|
m_url = url;
|
||||||
start(hostname, boost::lexical_cast<std::string>(port), timeout, prio
|
start(hostname, boost::lexical_cast<std::string>(port), timeout, prio
|
||||||
, ps, ssl, handle_redirects, bind_addr);
|
, 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;
|
if (ps) m_proxy = *ps;
|
||||||
|
|
||||||
m_timeout = timeout;
|
m_timeout = timeout;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timer.expires_from_now(m_timeout, ec);
|
m_timer.expires_from_now(m_timeout, ec);
|
||||||
m_timer.async_wait(bind(&http_connection::on_timeout
|
m_timer.async_wait(bind(&http_connection::on_timeout
|
||||||
, boost::weak_ptr<http_connection>(shared_from_this()), _1));
|
, 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
|
if (m_sock.is_open() && m_hostname == hostname && m_port == port
|
||||||
&& m_ssl == ssl && m_bind_addr == bind_addr)
|
&& 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));
|
, bind(&http_connection::on_write, shared_from_this(), _1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_ssl = ssl;
|
m_ssl = ssl;
|
||||||
m_bind_addr = bind_addr;
|
m_bind_addr = bind_addr;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_sock.close(ec);
|
m_sock.close(ec);
|
||||||
|
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
@ -168,7 +180,7 @@ void http_connection::start(std::string const& hostname, std::string const& port
|
|||||||
#endif
|
#endif
|
||||||
if (m_bind_addr != address_v4::any())
|
if (m_bind_addr != address_v4::any())
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_sock.bind(tcp::endpoint(m_bind_addr, 0), ec);
|
m_sock.bind(tcp::endpoint(m_bind_addr, 0), ec);
|
||||||
if (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()
|
void http_connection::on_connect_timeout()
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(m_connection_ticket >= 0);
|
||||||
if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
|
if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
|
||||||
m_connection_ticket = -1;
|
m_connection_ticket = -1;
|
||||||
|
|
||||||
callback(asio::error::timed_out);
|
if (!m_endpoints.empty())
|
||||||
close();
|
{
|
||||||
|
m_sock.close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
callback(asio::error::timed_out);
|
||||||
|
close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void http_connection::on_timeout(boost::weak_ptr<http_connection> p
|
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();
|
boost::shared_ptr<http_connection> c = p.lock();
|
||||||
if (!c) return;
|
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 (e == asio::error::operation_aborted) return;
|
||||||
|
|
||||||
if (c->m_last_receive + c->m_timeout < time_now())
|
if (c->m_last_receive + c->m_timeout < time_now())
|
||||||
{
|
{
|
||||||
c->callback(asio::error::timed_out);
|
if (c->m_connection_ticket > -1 && !c->m_endpoints.empty())
|
||||||
c->close();
|
{
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!c->m_sock.is_open()) 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.expires_at(c->m_last_receive + c->m_timeout, ec);
|
||||||
c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1));
|
c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void http_connection::close()
|
void http_connection::close()
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timer.cancel(ec);
|
m_timer.cancel(ec);
|
||||||
m_limiter_timer.cancel(ec);
|
m_limiter_timer.cancel(ec);
|
||||||
m_sock.close(ec);
|
m_sock.close(ec);
|
||||||
m_hostname.clear();
|
m_hostname.clear();
|
||||||
m_port.clear();
|
m_port.clear();
|
||||||
|
|
||||||
if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
|
|
||||||
m_connection_ticket = -1;
|
|
||||||
|
|
||||||
m_handler.clear();
|
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)
|
, tcp::resolver::iterator i)
|
||||||
{
|
{
|
||||||
if (e)
|
if (e)
|
||||||
@ -243,21 +268,26 @@ void http_connection::on_resolve(asio::error_code const& e
|
|||||||
}
|
}
|
||||||
TORRENT_ASSERT(i != tcp::resolver::iterator());
|
TORRENT_ASSERT(i != tcp::resolver::iterator());
|
||||||
|
|
||||||
// look for an address that has the same kind as the one
|
std::transform(i, tcp::resolver::iterator(), std::back_inserter(m_endpoints)
|
||||||
// we're binding to. To make sure a tracker get our
|
, boost::bind(&tcp::resolver::iterator::value_type::endpoint, _1));
|
||||||
// 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);
|
|
||||||
|
|
||||||
if (target != end)
|
// 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,
|
||||||
target_address = *target;
|
// 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())
|
||||||
m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, target_address)
|
> (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())
|
, bind(&http_connection::on_connect_timeout, shared_from_this())
|
||||||
, m_timeout, m_priority);
|
, m_timeout, m_priority);
|
||||||
}
|
}
|
||||||
@ -266,35 +296,35 @@ void http_connection::connect(int ticket, tcp::endpoint target_address)
|
|||||||
{
|
{
|
||||||
m_connection_ticket = ticket;
|
m_connection_ticket = ticket;
|
||||||
m_sock.async_connect(target_address, boost::bind(&http_connection::on_connect
|
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
|
void http_connection::on_connect(error_code const& e)
|
||||||
/*, tcp::resolver::iterator i*/)
|
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(m_connection_ticket >= 0);
|
||||||
|
m_cc.done(m_connection_ticket);
|
||||||
|
|
||||||
|
m_last_receive = time_now();
|
||||||
if (!e)
|
if (!e)
|
||||||
{
|
{
|
||||||
m_last_receive = time_now();
|
|
||||||
if (m_connect_handler) m_connect_handler(*this);
|
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));
|
, 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.
|
// The connection failed. Try the next endpoint in the list.
|
||||||
m_sock.close();
|
m_sock.close();
|
||||||
m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i)
|
queue_connect();
|
||||||
, bind(&http_connection::on_connect_timeout, shared_from_this())
|
|
||||||
, m_timeout, m_priority);
|
|
||||||
}
|
}
|
||||||
*/ else
|
else
|
||||||
{
|
{
|
||||||
callback(e);
|
callback(e);
|
||||||
close();
|
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)
|
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;
|
std::string error;
|
||||||
if (inflate_gzip(data, size, buf, max_bottled_buffer, 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();
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -317,11 +347,11 @@ void http_connection::callback(asio::error_code const& e, char const* data, int
|
|||||||
}
|
}
|
||||||
m_called = true;
|
m_called = true;
|
||||||
m_timer.cancel();
|
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)
|
if (e)
|
||||||
{
|
{
|
||||||
@ -340,7 +370,7 @@ void http_connection::on_write(asio::error_code const& e)
|
|||||||
if (m_download_quota == 0)
|
if (m_download_quota == 0)
|
||||||
{
|
{
|
||||||
if (!m_limiter_timer_active)
|
if (!m_limiter_timer_active)
|
||||||
on_assign_bandwidth(asio::error_code());
|
on_assign_bandwidth(error_code());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,7 +380,7 @@ void http_connection::on_write(asio::error_code const& e)
|
|||||||
, shared_from_this(), _1, _2));
|
, 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)
|
, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
if (m_rate_limit)
|
if (m_rate_limit)
|
||||||
@ -394,7 +424,7 @@ void http_connection::on_read(asio::error_code const& e
|
|||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
// HTTP parse error
|
// HTTP parse error
|
||||||
asio::error_code ec = asio::error::fault;
|
error_code ec = asio::error::fault;
|
||||||
callback(ec, 0, 0);
|
callback(ec, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -407,17 +437,44 @@ void http_connection::on_read(asio::error_code const& e
|
|||||||
if (code >= 300 && code < 400)
|
if (code >= 300 && code < 400)
|
||||||
{
|
{
|
||||||
// attempt a redirect
|
// attempt a redirect
|
||||||
std::string const& url = m_parser.header("location");
|
std::string const& location = m_parser.header("location");
|
||||||
if (url.empty())
|
if (location.empty())
|
||||||
{
|
{
|
||||||
// missing location header
|
// missing location header
|
||||||
callback(e);
|
callback(asio::error::fault);
|
||||||
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_sock.close(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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +491,7 @@ void http_connection::on_read(asio::error_code const& e
|
|||||||
}
|
}
|
||||||
else if (m_bottled && m_parser.finished())
|
else if (m_bottled && m_parser.finished())
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timer.cancel(ec);
|
m_timer.cancel(ec);
|
||||||
callback(e, m_parser.get_body().begin, m_parser.get_body().left());
|
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_download_quota == 0)
|
||||||
{
|
{
|
||||||
if (!m_limiter_timer_active)
|
if (!m_limiter_timer_active)
|
||||||
on_assign_bandwidth(asio::error_code());
|
on_assign_bandwidth(error_code());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,7 +529,7 @@ void http_connection::on_read(asio::error_code const& e
|
|||||||
, shared_from_this(), _1, _2));
|
, 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
|
if ((e == asio::error::operation_aborted
|
||||||
&& m_limiter_timer_active)
|
&& m_limiter_timer_active)
|
||||||
@ -499,7 +556,7 @@ void http_connection::on_assign_bandwidth(asio::error_code const& e)
|
|||||||
, bind(&http_connection::on_read
|
, bind(&http_connection::on_read
|
||||||
, shared_from_this(), _1, _2));
|
, shared_from_this(), _1, _2));
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_limiter_timer_active = true;
|
m_limiter_timer_active = true;
|
||||||
m_limiter_timer.expires_from_now(milliseconds(250), ec);
|
m_limiter_timer.expires_from_now(milliseconds(250), ec);
|
||||||
m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth
|
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)
|
if (!m_limiter_timer_active)
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_limiter_timer_active = true;
|
m_limiter_timer_active = true;
|
||||||
m_limiter_timer.expires_from_now(milliseconds(250), ec);
|
m_limiter_timer.expires_from_now(milliseconds(250), ec);
|
||||||
m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth
|
m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth
|
||||||
|
|||||||
@ -38,13 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
namespace libtorrent
|
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)
|
, boost::shared_ptr<handler_type> h)
|
||||||
{
|
{
|
||||||
if (e || i == tcp::resolver::iterator())
|
if (e || i == tcp::resolver::iterator())
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -53,12 +53,12 @@ namespace libtorrent
|
|||||||
&http_stream::connected, this, _1, h));
|
&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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -82,32 +82,32 @@ namespace libtorrent
|
|||||||
m_user + ":" + m_password) + "\r\n", p);
|
m_user + ":" + m_password) + "\r\n", p);
|
||||||
}
|
}
|
||||||
write_string("\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));
|
, 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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read one byte from the socket
|
// read one byte from the socket
|
||||||
m_buffer.resize(1);
|
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));
|
, 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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ namespace libtorrent
|
|||||||
if (status == 0)
|
if (status == 0)
|
||||||
{
|
{
|
||||||
(*h)(asio::error::operation_not_supported);
|
(*h)(asio::error::operation_not_supported);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ namespace libtorrent
|
|||||||
if (code != 200)
|
if (code != 200)
|
||||||
{
|
{
|
||||||
(*h)(asio::error::operation_not_supported);
|
(*h)(asio::error::operation_not_supported);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
// read another byte from the socket
|
// read another byte from the socket
|
||||||
m_buffer.resize(read_pos + 1);
|
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));
|
, boost::bind(&http_stream::handshake2, this, _1, h));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -194,7 +194,7 @@ namespace libtorrent
|
|||||||
tracker_connection::close();
|
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)
|
, http_parser const& parser, char const* data, int size)
|
||||||
{
|
{
|
||||||
// keep this alive
|
// keep this alive
|
||||||
@ -313,9 +313,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (tracker_req().kind == tracker_request::scrape_request)
|
if (tracker_req().kind == tracker_request::scrape_request)
|
||||||
{
|
{
|
||||||
std::string ih;
|
std::string ih = tracker_req().info_hash.to_string();
|
||||||
std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end()
|
|
||||||
, std::back_inserter(ih));
|
|
||||||
|
|
||||||
entry const* files = e.find_key("files");
|
entry const* files = e.find_key("files");
|
||||||
if (files == 0 || files->type() != entry::dictionary_t)
|
if (files == 0 || files->type() != entry::dictionary_t)
|
||||||
@ -324,7 +322,7 @@ namespace libtorrent
|
|||||||
return;
|
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)
|
if (scrape_data == 0 || scrape_data->type() != entry::dictionary_t)
|
||||||
{
|
{
|
||||||
fail(-1, "missing or invalid info-hash entry in scrape response");
|
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 "libtorrent/socket_type.hpp"
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <asio/io_service.hpp>
|
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
|
||||||
bool instantiate_connection(asio::io_service& ios
|
bool instantiate_connection(io_service& ios
|
||||||
, proxy_settings const& ps, socket_type& s)
|
, proxy_settings const& ps, socket_type& s)
|
||||||
{
|
{
|
||||||
if (ps.type == proxy_settings::none)
|
if (ps.type == proxy_settings::none)
|
||||||
|
|||||||
@ -40,8 +40,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
namespace libtorrent { namespace dht
|
namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
|
|
||||||
using asio::ip::udp;
|
|
||||||
|
|
||||||
closest_nodes_observer::~closest_nodes_observer()
|
closest_nodes_observer::~closest_nodes_observer()
|
||||||
{
|
{
|
||||||
if (m_algorithm) m_algorithm->failed(m_self, true);
|
if (m_algorithm) m_algorithm->failed(m_self, true);
|
||||||
|
|||||||
@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "libtorrent/bencode.hpp"
|
#include "libtorrent/bencode.hpp"
|
||||||
#include "libtorrent/io.hpp"
|
#include "libtorrent/io.hpp"
|
||||||
#include "libtorrent/version.hpp"
|
#include "libtorrent/version.hpp"
|
||||||
|
#include "libtorrent/escape_string.hpp"
|
||||||
|
|
||||||
using boost::ref;
|
using boost::ref;
|
||||||
using boost::lexical_cast;
|
using boost::lexical_cast;
|
||||||
@ -66,9 +67,6 @@ enum
|
|||||||
key_refresh = 5 // generate a new write token key every 5 minutes
|
key_refresh = 5 // generate a new write token key every 5 minutes
|
||||||
};
|
};
|
||||||
|
|
||||||
using asio::ip::udp;
|
|
||||||
typedef asio::ip::address_v4 address;
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const int tick_period = 1; // minutes
|
const int tick_period = 1; // minutes
|
||||||
@ -228,7 +226,7 @@ namespace libtorrent { namespace dht
|
|||||||
s.dht_global_nodes = m_dht.num_global_nodes();
|
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
|
try
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
@ -247,7 +245,7 @@ namespace libtorrent { namespace dht
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void dht_tracker::refresh_timeout(asio::error_code const& e)
|
void dht_tracker::refresh_timeout(error_code const& e)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
@ -263,7 +261,7 @@ namespace libtorrent { namespace dht
|
|||||||
TORRENT_ASSERT(false);
|
TORRENT_ASSERT(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
void dht_tracker::tick(asio::error_code const& e)
|
void dht_tracker::tick(error_code const& e)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
@ -375,6 +373,12 @@ namespace libtorrent { namespace dht
|
|||||||
m_dht.announce(ih, listen_port, f);
|
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
|
// translate bittorrent kademlia message into the generice kademlia message
|
||||||
// used by the library
|
// used by the library
|
||||||
void dht_tracker::on_receive(udp::endpoint const& ep, char const* buf, int bytes_transferred)
|
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)
|
if (match->count == 20)
|
||||||
{
|
{
|
||||||
TORRENT_LOG(dht_tracker) << time_now_string() << " BANNING PEER [ ip: "
|
TORRENT_LOG(dht_tracker) << time_now_string() << " BANNING PEER [ ip: "
|
||||||
<< ep << " | time: " << total_milliseconds((now - match->limit) + seconds(5)) / 1000.f
|
<< ep << " time: " << total_milliseconds((now - match->limit) + seconds(5)) / 1000.f
|
||||||
<< " | count: " << match->count << " ]";
|
<< " count: " << match->count << " ]";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// we've received 20 messages in less than 5 seconds from
|
// 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);
|
entry e = bdecode(buf, buf + bytes_transferred);
|
||||||
|
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << time_now_string() << " RECEIVED ["
|
std::stringstream log_line;
|
||||||
<< ep << "]:";
|
log_line << time_now_string() << " RECEIVED ["
|
||||||
|
" ip: " << ep;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
libtorrent::dht::msg m;
|
libtorrent::dht::msg m;
|
||||||
@ -461,36 +466,36 @@ namespace libtorrent { namespace dht
|
|||||||
if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "UT"))
|
if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "UT"))
|
||||||
{
|
{
|
||||||
++m_ut_message_input;
|
++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"))
|
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "LT"))
|
||||||
{
|
{
|
||||||
++m_lt_message_input;
|
++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"))
|
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MP"))
|
||||||
{
|
{
|
||||||
++m_mp_message_input;
|
++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"))
|
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "GR"))
|
||||||
{
|
{
|
||||||
++m_gr_message_input;
|
++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"))
|
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MO"))
|
||||||
{
|
{
|
||||||
++m_mo_message_input;
|
++m_mo_message_input;
|
||||||
TORRENT_LOG(dht_tracker) << " client: Mono Torrent";
|
log_line << " c: Mono Torrent";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TORRENT_LOG(dht_tracker) << " client: " << client;
|
log_line << " c: " << client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception&)
|
catch (std::exception&)
|
||||||
{
|
{
|
||||||
TORRENT_LOG(dht_tracker) << " client: generic";
|
log_line << " c: generic";
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -499,8 +504,8 @@ namespace libtorrent { namespace dht
|
|||||||
if (msg_type == "r")
|
if (msg_type == "r")
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " reply: transaction: "
|
log_line << " r: " << messages::ids[m.message_id]
|
||||||
<< m.transaction_id;
|
<< " t: " << to_hex(m.transaction_id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m.reply = true;
|
m.reply = true;
|
||||||
@ -528,7 +533,7 @@ namespace libtorrent { namespace dht
|
|||||||
read_endpoint_list<tcp::endpoint>(n, m.peers);
|
read_endpoint_list<tcp::endpoint>(n, m.peers);
|
||||||
}
|
}
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size();
|
log_line << " p: " << m.peers.size();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,7 +553,7 @@ namespace libtorrent { namespace dht
|
|||||||
id, read_v4_endpoint<udp::endpoint>(i)));
|
id, read_v4_endpoint<udp::endpoint>(i)));
|
||||||
}
|
}
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " nodes: " << m.nodes.size();
|
log_line << " n: " << m.nodes.size();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,7 +578,7 @@ namespace libtorrent { namespace dht
|
|||||||
id, read_v6_endpoint<udp::endpoint>(in)));
|
id, read_v6_endpoint<udp::endpoint>(in)));
|
||||||
}
|
}
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " nodes2 + nodes: " << m.nodes.size();
|
log_line << " n2: " << m.nodes.size();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,7 +595,7 @@ namespace libtorrent { namespace dht
|
|||||||
|
|
||||||
std::string request_kind(e["q"].string());
|
std::string request_kind(e["q"].string());
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " query: " << request_kind;
|
log_line << " q: " << request_kind;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (request_kind == "ping")
|
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");
|
if (target.size() != 20) throw std::runtime_error("invalid size of target id");
|
||||||
std::copy(target.begin(), target.end(), m.info_hash.begin());
|
std::copy(target.begin(), target.end(), m.info_hash.begin());
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " target: "
|
log_line << " t: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||||
<< boost::lexical_cast<std::string>(m.info_hash);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m.message_id = libtorrent::dht::messages::find_node;
|
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());
|
std::copy(info_hash.begin(), info_hash.end(), m.info_hash.begin());
|
||||||
m.message_id = libtorrent::dht::messages::get_peers;
|
m.message_id = libtorrent::dht::messages::get_peers;
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " info_hash: "
|
log_line << " ih: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||||
<< boost::lexical_cast<std::string>(m.info_hash);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (request_kind == "announce_peer")
|
else if (request_kind == "announce_peer")
|
||||||
@ -633,9 +636,8 @@ namespace libtorrent { namespace dht
|
|||||||
m.write_token = a["token"];
|
m.write_token = a["token"];
|
||||||
m.message_id = libtorrent::dht::messages::announce_peer;
|
m.message_id = libtorrent::dht::messages::announce_peer;
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " info_hash: "
|
log_line << " ih: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||||
<< boost::lexical_cast<std::string>(m.info_hash);
|
log_line << " p: " << m.port;
|
||||||
TORRENT_LOG(dht_tracker) << " port: " << m.port;
|
|
||||||
|
|
||||||
if (!m_dht.verify_token(m))
|
if (!m_dht.verify_token(m))
|
||||||
++m_failed_announces;
|
++m_failed_announces;
|
||||||
@ -657,8 +659,8 @@ namespace libtorrent { namespace dht
|
|||||||
m.error_msg = list.back().string();
|
m.error_msg = list.back().string();
|
||||||
m.error_code = list.front().integer();
|
m.error_code = list.front().integer();
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " incoming error: " << m.error_code << " "
|
log_line << " incoming error: " << m.error_code
|
||||||
<< m.error_msg;
|
<< " " << m.error_msg;
|
||||||
#endif
|
#endif
|
||||||
throw std::runtime_error("DHT error message");
|
throw std::runtime_error("DHT error message");
|
||||||
}
|
}
|
||||||
@ -677,7 +679,7 @@ namespace libtorrent { namespace dht
|
|||||||
++m_queries_received[m.message_id];
|
++m_queries_received[m.message_id];
|
||||||
m_queries_bytes_received[m.message_id] += int(bytes_transferred);
|
m_queries_bytes_received[m.message_id] += int(bytes_transferred);
|
||||||
}
|
}
|
||||||
TORRENT_LOG(dht_tracker) << e;
|
TORRENT_LOG(dht_tracker) << log_line.str() << " ]";
|
||||||
#endif
|
#endif
|
||||||
TORRENT_ASSERT(m.message_id != messages::error);
|
TORRENT_ASSERT(m.message_id != messages::error);
|
||||||
m_dht.incoming(m);
|
m_dht.incoming(m);
|
||||||
@ -739,7 +741,7 @@ namespace libtorrent { namespace dht
|
|||||||
bind(&dht_tracker::on_name_lookup, self(), _1, _2));
|
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
|
, udp::resolver::iterator host) try
|
||||||
{
|
{
|
||||||
if (e || host == udp::resolver::iterator()) return;
|
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));
|
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
|
, udp::resolver::iterator host) try
|
||||||
{
|
{
|
||||||
if (e || host == udp::resolver::iterator()) return;
|
if (e || host == udp::resolver::iterator()) return;
|
||||||
@ -809,9 +811,6 @@ namespace libtorrent { namespace dht
|
|||||||
p.list().push_back(entry(endpoint));
|
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);
|
e["v"] = std::string(version_str, version_str + 4);
|
||||||
|
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << time_now_string()
|
std::stringstream log_line;
|
||||||
<< " SENDING [" << m.addr << "]:";
|
log_line << time_now_string()
|
||||||
TORRENT_LOG(dht_tracker) << " transaction: " << m.transaction_id;
|
<< " SENDING [ ip: " << m.addr
|
||||||
|
<< " t: " << to_hex(m.transaction_id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m.message_id == messages::error)
|
if (m.message_id == messages::error)
|
||||||
@ -843,8 +843,8 @@ namespace libtorrent { namespace dht
|
|||||||
error_list.list().push_back(entry(m.error_msg));
|
error_list.list().push_back(entry(m.error_msg));
|
||||||
e["e"] = error_list;
|
e["e"] = error_list;
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << time_now_string()
|
log_line << " err: " << m.error_code
|
||||||
<< " outgoing error: " << m.error_code << " " << m.error_msg;
|
<< " msg: " << m.error_msg;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (m.reply)
|
else if (m.reply)
|
||||||
@ -855,8 +855,7 @@ namespace libtorrent { namespace dht
|
|||||||
r["id"] = std::string(m.id.begin(), m.id.end());
|
r["id"] = std::string(m.id.begin(), m.id.end());
|
||||||
|
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << time_now_string()
|
log_line << " r: " << messages::ids[m.message_id];
|
||||||
<< " reply: " << messages::ids[m.message_id];
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m.write_token.type() != entry::undefined_t)
|
if (m.write_token.type() != entry::undefined_t)
|
||||||
@ -892,7 +891,7 @@ namespace libtorrent { namespace dht
|
|||||||
p.list().push_back(entry(endpoint));
|
p.list().push_back(entry(endpoint));
|
||||||
}
|
}
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size();
|
log_line << " p: " << m.peers.size();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -916,8 +915,7 @@ namespace libtorrent { namespace dht
|
|||||||
e["q"] = messages::ids[m.message_id];
|
e["q"] = messages::ids[m.message_id];
|
||||||
|
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " query: "
|
log_line << " q: " << messages::ids[m.message_id];
|
||||||
<< messages::ids[m.message_id];
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (m.message_id)
|
switch (m.message_id)
|
||||||
@ -926,8 +924,7 @@ namespace libtorrent { namespace dht
|
|||||||
{
|
{
|
||||||
a["target"] = std::string(m.info_hash.begin(), m.info_hash.end());
|
a["target"] = std::string(m.info_hash.begin(), m.info_hash.end());
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " target: "
|
log_line << " target: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||||
<< boost::lexical_cast<std::string>(m.info_hash);
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -935,8 +932,7 @@ namespace libtorrent { namespace dht
|
|||||||
{
|
{
|
||||||
a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end());
|
a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end());
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker) << " info_hash: "
|
log_line << " ih: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||||
<< boost::lexical_cast<std::string>(m.info_hash);
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -945,9 +941,8 @@ namespace libtorrent { namespace dht
|
|||||||
a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end());
|
a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end());
|
||||||
a["token"] = m.write_token;
|
a["token"] = m.write_token;
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_LOG(dht_tracker)
|
log_line << " p: " << m.port
|
||||||
<< " port: " << m.port
|
<< " ih: " << boost::lexical_cast<std::string>(m.info_hash);
|
||||||
<< " info_hash: " << boost::lexical_cast<std::string>(m.info_hash);
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
@ -957,7 +952,7 @@ namespace libtorrent { namespace dht
|
|||||||
|
|
||||||
m_send_buf.clear();
|
m_send_buf.clear();
|
||||||
bencode(std::back_inserter(m_send_buf), e);
|
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);
|
m_sock.send(m.addr, &m_send_buf[0], (int)m_send_buf.size(), ec);
|
||||||
|
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
@ -972,7 +967,7 @@ namespace libtorrent { namespace dht
|
|||||||
{
|
{
|
||||||
m_queries_out_bytes += m_send_buf.size();
|
m_queries_out_bytes += m_send_buf.size();
|
||||||
}
|
}
|
||||||
TORRENT_LOG(dht_tracker) << e;
|
TORRENT_LOG(dht_tracker) << log_line.str() << " ]";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!m.piggy_backed_ping) return;
|
if (!m.piggy_backed_ping) return;
|
||||||
|
|||||||
@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <libtorrent/kademlia/routing_table.hpp>
|
#include <libtorrent/kademlia/routing_table.hpp>
|
||||||
#include <libtorrent/kademlia/rpc_manager.hpp>
|
#include <libtorrent/kademlia/rpc_manager.hpp>
|
||||||
#include <libtorrent/io.hpp>
|
#include <libtorrent/io.hpp>
|
||||||
|
#include <libtorrent/socket.hpp>
|
||||||
|
|
||||||
namespace libtorrent { namespace dht
|
namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
@ -101,7 +102,7 @@ find_data::find_data(
|
|||||||
add_requests();
|
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)
|
if (m_done)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -65,8 +65,6 @@ namespace
|
|||||||
// TODO: configurable?
|
// TODO: configurable?
|
||||||
enum { announce_interval = 30 };
|
enum { announce_interval = 30 };
|
||||||
|
|
||||||
using asio::ip::udp;
|
|
||||||
|
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_DEFINE_LOG(node)
|
TORRENT_DEFINE_LOG(node)
|
||||||
#endif
|
#endif
|
||||||
@ -245,6 +243,11 @@ void node_impl::refresh_bucket(int bucket) try
|
|||||||
}
|
}
|
||||||
catch (std::exception&) {}
|
catch (std::exception&) {}
|
||||||
|
|
||||||
|
void node_impl::unreachable(udp::endpoint const& ep)
|
||||||
|
{
|
||||||
|
m_rpc.unreachable(ep);
|
||||||
|
}
|
||||||
|
|
||||||
void node_impl::incoming(msg const& m)
|
void node_impl::incoming(msg const& m)
|
||||||
{
|
{
|
||||||
if (m_rpc.incoming(m))
|
if (m_rpc.incoming(m))
|
||||||
@ -269,6 +272,9 @@ namespace
|
|||||||
for (std::vector<node_entry>::const_iterator i = v.begin()
|
for (std::vector<node_entry>::const_iterator i = v.begin()
|
||||||
, end(v.end()); i != end; ++i)
|
, 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));
|
observer_ptr o(new (rpc.allocator().malloc()) get_peers_observer(ih, listen_port, rpc, f));
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
o->m_in_constructor = false;
|
o->m_in_constructor = false;
|
||||||
|
|||||||
@ -47,8 +47,6 @@ using boost::bind;
|
|||||||
namespace libtorrent { namespace dht
|
namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
|
|
||||||
using asio::ip::udp;
|
|
||||||
|
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_DEFINE_LOG(refresh)
|
TORRENT_DEFINE_LOG(refresh)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -50,8 +50,9 @@ using boost::uint8_t;
|
|||||||
namespace libtorrent { namespace dht
|
namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
|
|
||||||
using asio::ip::udp;
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
typedef asio::ip::address_v4 address;
|
TORRENT_DEFINE_LOG(table)
|
||||||
|
#endif
|
||||||
|
|
||||||
routing_table::routing_table(node_id const& id, int bucket_size
|
routing_table::routing_table(node_id const& id, int bucket_size
|
||||||
, dht_settings const& settings)
|
, dht_settings const& settings)
|
||||||
@ -225,6 +226,15 @@ void routing_table::node_failed(node_id const& id)
|
|||||||
if (rb.empty())
|
if (rb.empty())
|
||||||
{
|
{
|
||||||
++i->fail_count;
|
++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)
|
if (i->fail_count >= m_settings.max_fail_count)
|
||||||
{
|
{
|
||||||
b.erase(i);
|
b.erase(i);
|
||||||
|
|||||||
@ -159,6 +159,39 @@ void rpc_manager::check_invariant() const
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
bool rpc_manager::incoming(msg const& m)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|||||||
@ -39,7 +39,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
using boost::bind;
|
using boost::bind;
|
||||||
using asio::ip::udp;
|
|
||||||
|
|
||||||
namespace libtorrent { namespace dht
|
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)
|
void traversal_algorithm::traverse(node_id const& id, udp::endpoint addr)
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#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
|
#endif
|
||||||
add_entry(id, addr, 0);
|
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];
|
std::pair<char const*, lazy_entry>* tmp = new (std::nothrow) std::pair<char const*, lazy_entry>[capacity];
|
||||||
if (tmp == 0) return 0;
|
if (tmp == 0) return 0;
|
||||||
std::memcpy(tmp, m_data.dict, sizeof(std::pair<char const*, lazy_entry>) * m_size);
|
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;
|
delete[] m_data.dict;
|
||||||
m_data.dict = tmp;
|
m_data.dict = tmp;
|
||||||
m_capacity = capacity;
|
m_capacity = capacity;
|
||||||
@ -299,6 +300,7 @@ namespace libtorrent
|
|||||||
lazy_entry* tmp = new (std::nothrow) lazy_entry[capacity];
|
lazy_entry* tmp = new (std::nothrow) lazy_entry[capacity];
|
||||||
if (tmp == 0) return 0;
|
if (tmp == 0) return 0;
|
||||||
std::memcpy(tmp, m_data.list, sizeof(lazy_entry) * m_size);
|
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;
|
delete[] m_data.list;
|
||||||
m_data.list = tmp;
|
m_data.list = tmp;
|
||||||
m_capacity = capacity;
|
m_capacity = capacity;
|
||||||
@ -330,6 +332,7 @@ namespace libtorrent
|
|||||||
case dict_t: delete[] m_data.dict; break;
|
case dict_t: delete[] m_data.dict; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
m_data.start = 0;
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
m_capacity = 0;
|
m_capacity = 0;
|
||||||
m_type = none_t;
|
m_type = none_t;
|
||||||
@ -370,7 +373,8 @@ namespace libtorrent
|
|||||||
bool one_liner = (e.list_size() == 0
|
bool one_liner = (e.list_size() == 0
|
||||||
|| e.list_at(0)->type() == lazy_entry::int_t
|
|| e.list_at(0)->type() == lazy_entry::int_t
|
||||||
|| (e.list_at(0)->type() == lazy_entry::string_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;
|
&& e.list_size() < 5;
|
||||||
if (!one_liner) os << "\n";
|
if (!one_liner) os << "\n";
|
||||||
for (int i = 0; i < e.list_size(); ++i)
|
for (int i = 0; i < e.list_size(); ++i)
|
||||||
@ -388,7 +392,7 @@ namespace libtorrent
|
|||||||
bool one_liner = (e.dict_size() == 0
|
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::int_t
|
||||||
|| (e.dict_at(0).second->type() == lazy_entry::string_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_at(0).first.size() < 10)
|
||||||
&& e.dict_size() < 5;
|
&& e.dict_size() < 5;
|
||||||
|
|
||||||
|
|||||||
@ -40,8 +40,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/ip/host_name.hpp>
|
#include <asio/ip/host_name.hpp>
|
||||||
#include <asio/ip/multicast.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 <boost/thread/mutex.hpp>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
@ -52,7 +57,7 @@ using namespace libtorrent;
|
|||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
// defined in broadcast_socket.cpp
|
// 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
|
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();
|
std::string const& msg = btsearch.str();
|
||||||
|
|
||||||
m_retry_count = 1;
|
m_retry_count = 1;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socket.send(msg.c_str(), int(msg.size()), ec);
|
m_socket.send(msg.c_str(), int(msg.size()), ec);
|
||||||
if (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));
|
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;
|
if (e) return;
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socket.send(msg.c_str(), int(msg.size()), ec);
|
m_socket.send(msg.c_str(), int(msg.size()), ec);
|
||||||
|
|
||||||
++m_retry_count;
|
++m_retry_count;
|
||||||
@ -192,7 +197,7 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
|
|||||||
void lsd::close()
|
void lsd::close()
|
||||||
{
|
{
|
||||||
m_socket.close();
|
m_socket.close();
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_broadcast_timer.cancel(ec);
|
m_broadcast_timer.cancel(ec);
|
||||||
m_disabled = true;
|
m_disabled = true;
|
||||||
m_callback.clear();
|
m_callback.clear();
|
||||||
|
|||||||
@ -47,6 +47,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#if BOOST_VERSION >= 103500
|
||||||
|
#include <boost/system/error_code.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/version.hpp>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
@ -57,8 +62,10 @@ using boost::iostreams::mapped_file_params;
|
|||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
|
#if BOOST_VERSION >= 103500
|
||||||
|
using boost::system::error_code;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct mapped_file_pool
|
struct mapped_file_pool
|
||||||
{
|
{
|
||||||
@ -78,7 +85,7 @@ namespace libtorrent
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (file_size > 0)
|
if (file_size > 0)
|
||||||
{
|
{
|
||||||
fs::system_error_type ec;
|
error_code ec;
|
||||||
fs::file_status st = fs::status(path, ec);
|
fs::file_status st = fs::status(path, ec);
|
||||||
TORRENT_ASSERT(!fs::exists(st));
|
TORRENT_ASSERT(!fs::exists(st));
|
||||||
}
|
}
|
||||||
@ -197,7 +204,11 @@ namespace libtorrent
|
|||||||
size_type start = (offset / view_size) * view_size;
|
size_type start = (offset / view_size) * view_size;
|
||||||
TORRENT_ASSERT(start + view_size >= offset + length);
|
TORRENT_ASSERT(start + view_size >= offset + length);
|
||||||
|
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
fs::system_error_type ec;
|
fs::system_error_type ec;
|
||||||
|
#else
|
||||||
|
error_code ec;
|
||||||
|
#endif
|
||||||
fs::file_status st = fs::status(p, ec);
|
fs::file_status st = fs::status(p, ec);
|
||||||
|
|
||||||
m_files.push_back(file_entry());
|
m_files.push_back(file_entry());
|
||||||
|
|||||||
@ -55,6 +55,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "libtorrent/extensions.hpp"
|
#include "libtorrent/extensions.hpp"
|
||||||
#include "libtorrent/extensions/metadata_transfer.hpp"
|
#include "libtorrent/extensions/metadata_transfer.hpp"
|
||||||
#include "libtorrent/alert_types.hpp"
|
#include "libtorrent/alert_types.hpp"
|
||||||
|
#include "libtorrent/buffer.hpp"
|
||||||
|
|
||||||
namespace libtorrent { namespace
|
namespace libtorrent { namespace
|
||||||
{
|
{
|
||||||
@ -107,40 +108,37 @@ namespace libtorrent { namespace
|
|||||||
|
|
||||||
virtual void on_files_checked()
|
virtual void on_files_checked()
|
||||||
{
|
{
|
||||||
// if the torrent is a seed, copy the metadata from
|
// if the torrent is a seed, make a reference to
|
||||||
// the torrent before it is deallocated
|
// the metadata from the torrent before it is deallocated
|
||||||
if (m_torrent.is_seed())
|
if (m_torrent.is_seed()) metadata();
|
||||||
metadata();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual boost::shared_ptr<peer_plugin> new_connection(
|
virtual boost::shared_ptr<peer_plugin> new_connection(
|
||||||
peer_connection* pc);
|
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_metadata = m_torrent.torrent_file().metadata();
|
||||||
, m_torrent.torrent_file().create_info_metadata());
|
m_metadata_size = m_torrent.torrent_file().metadata_size();
|
||||||
|
TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final()
|
||||||
TORRENT_ASSERT(hasher(&m_metadata[0], m_metadata.size()).final()
|
|
||||||
== m_torrent.torrent_file().info_hash());
|
== m_torrent.torrent_file().info_hash());
|
||||||
}
|
}
|
||||||
TORRENT_ASSERT(!m_metadata.empty());
|
return buffer::const_interval(m_metadata.get(), m_metadata.get()
|
||||||
return m_metadata;
|
+ m_metadata_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool received_metadata(char const* buf, int size, int offset, int total_size)
|
bool received_metadata(char const* buf, int size, int offset, int total_size)
|
||||||
{
|
{
|
||||||
if (m_torrent.valid_metadata()) return false;
|
if (m_torrent.valid_metadata()) return false;
|
||||||
|
|
||||||
if ((int)m_metadata.size() < total_size)
|
if (!m_metadata || m_metadata_size < total_size)
|
||||||
m_metadata.resize(total_size);
|
{
|
||||||
|
m_metadata.reset(new char[total_size]);
|
||||||
std::copy(
|
m_metadata_size = total_size;
|
||||||
buf
|
}
|
||||||
, buf + size
|
std::copy(buf, buf + size, &m_metadata[offset]);
|
||||||
, &m_metadata[offset]);
|
|
||||||
|
|
||||||
if (m_have_metadata.empty())
|
if (m_have_metadata.empty())
|
||||||
m_have_metadata.resize(256, false);
|
m_have_metadata.resize(256, false);
|
||||||
@ -163,7 +161,7 @@ namespace libtorrent { namespace
|
|||||||
if (!have_all) return false;
|
if (!have_all) return false;
|
||||||
|
|
||||||
hasher h;
|
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();
|
sha1_hash info_hash = h.final();
|
||||||
|
|
||||||
if (info_hash != m_torrent.torrent_file().info_hash())
|
if (info_hash != m_torrent.torrent_file().info_hash())
|
||||||
@ -184,9 +182,10 @@ namespace libtorrent { namespace
|
|||||||
return false;
|
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;
|
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
|
// this means the metadata is correct, since we
|
||||||
// verified it against the info-hash, but we
|
// verified it against the info-hash, but we
|
||||||
@ -240,10 +239,10 @@ namespace libtorrent { namespace
|
|||||||
// the metadata file while downloading it from
|
// the metadata file while downloading it from
|
||||||
// peers, and while sending it.
|
// peers, and while sending it.
|
||||||
// it is mutable because it's generated lazily
|
// 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_progress;
|
||||||
int m_metadata_size;
|
mutable int m_metadata_size;
|
||||||
|
|
||||||
// this is a bitfield of size 256, each bit represents
|
// this is a bitfield of size 256, each bit represents
|
||||||
// a piece of the metadata. It is set to one if we
|
// 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())
|
if (m_torrent.valid_metadata() && !m_torrent.torrent_file().priv())
|
||||||
{
|
{
|
||||||
std::pair<int, int> offset
|
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);
|
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);
|
detail::write_uint8(m_message_index, i.begin);
|
||||||
// means 'data packet'
|
// means 'data packet'
|
||||||
detail::write_uint8(1, i.begin);
|
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);
|
detail::write_uint32(offset.first, i.begin);
|
||||||
std::vector<char> const& metadata = m_tp.metadata();
|
char const* metadata = m_tp.metadata().begin;
|
||||||
std::copy(metadata.begin() + offset.first
|
std::copy(metadata + offset.first
|
||||||
, metadata.begin() + offset.first + offset.second, i.begin);
|
, metadata + offset.first + offset.second, i.begin);
|
||||||
i.begin += offset.second;
|
i.begin += offset.second;
|
||||||
TORRENT_ASSERT(i.begin == i.end);
|
TORRENT_ASSERT(i.begin == i.end);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "libtorrent/pch.hpp"
|
#include "libtorrent/pch.hpp"
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/ip/host_name.hpp>
|
#include <asio/ip/host_name.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/asio/ip/host_name.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "libtorrent/natpmp.hpp"
|
#include "libtorrent/natpmp.hpp"
|
||||||
#include "libtorrent/io.hpp"
|
#include "libtorrent/io.hpp"
|
||||||
@ -63,7 +67,7 @@ void natpmp::rebind(address const& listen_interface)
|
|||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
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);
|
address gateway = get_default_gateway(m_socket.get_io_service(), ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
@ -198,7 +202,7 @@ void natpmp::try_next_mapping(int i)
|
|||||||
{
|
{
|
||||||
if (m_abort)
|
if (m_abort)
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_send_timer.cancel(ec);
|
m_send_timer.cancel(ec);
|
||||||
m_socket.close(ec);
|
m_socket.close(ec);
|
||||||
}
|
}
|
||||||
@ -264,7 +268,7 @@ void natpmp::send_map_request(int i)
|
|||||||
<< " ttl: " << ttl << " ]" << std::endl;
|
<< " ttl: " << ttl << " ]" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint, 0, ec);
|
m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint, 0, ec);
|
||||||
// linear back-off instead of exponential
|
// linear back-off instead of exponential
|
||||||
++m_retry_count;
|
++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));
|
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;
|
if (e) return;
|
||||||
|
|
||||||
@ -290,7 +294,7 @@ void natpmp::resend_request(int i, asio::error_code const& e)
|
|||||||
send_map_request(i);
|
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)
|
, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
using namespace libtorrent::detail;
|
using namespace libtorrent::detail;
|
||||||
@ -305,7 +309,7 @@ void natpmp::on_reply(asio::error_code const& e
|
|||||||
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_send_timer.cancel(ec);
|
m_send_timer.cancel(ec);
|
||||||
|
|
||||||
TORRENT_ASSERT(m_currently_mapping >= 0);
|
TORRENT_ASSERT(m_currently_mapping >= 0);
|
||||||
@ -439,7 +443,7 @@ void natpmp::update_expiration_timer()
|
|||||||
<< " ttl: " << total_seconds(min_expire - time_now())
|
<< " ttl: " << total_seconds(min_expire - time_now())
|
||||||
<< " ]" << std::endl;
|
<< " ]" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
if (m_next_refresh >= 0) m_refresh_timer.cancel(ec);
|
if (m_next_refresh >= 0) m_refresh_timer.cancel(ec);
|
||||||
m_refresh_timer.expires_from_now(min_expire - now, ec);
|
m_refresh_timer.expires_from_now(min_expire - now, ec);
|
||||||
m_refresh_timer.async_wait(bind(&natpmp::mapping_expired, self(), _1, min_index));
|
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;
|
if (e) return;
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
@ -463,7 +467,7 @@ void natpmp::close()
|
|||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
m_abort = true;
|
m_abort = true;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||||
m_log << time_now_string() << " close" << std::endl;
|
m_log << time_now_string() << " close" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -64,7 +64,7 @@ namespace libtorrent
|
|||||||
session_impl& ses
|
session_impl& ses
|
||||||
, boost::weak_ptr<torrent> tor
|
, boost::weak_ptr<torrent> tor
|
||||||
, shared_ptr<socket_type> s
|
, shared_ptr<socket_type> s
|
||||||
, tcp::endpoint const& remote
|
, tcp::endpoint const& endp
|
||||||
, policy::peer* peerinfo)
|
, policy::peer* peerinfo)
|
||||||
:
|
:
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@ -73,41 +73,28 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
m_ses(ses)
|
m_ses(ses)
|
||||||
, m_max_out_request_queue(m_ses.settings().max_out_request_queue)
|
, 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_piece(time_now())
|
||||||
, m_last_request(time_now())
|
, m_last_request(time_now())
|
||||||
, m_last_incoming_request(min_time())
|
, m_last_incoming_request(min_time())
|
||||||
, m_last_unchoke(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_packet_size(0)
|
||||||
, m_recv_pos(0)
|
, m_recv_pos(0)
|
||||||
, m_disk_recv_buffer_size(0)
|
, m_disk_recv_buffer_size(0)
|
||||||
, m_disk_recv_buffer(0)
|
|
||||||
, m_reading_bytes(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_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_priority(1)
|
||||||
, m_upload_limit(bandwidth_limit::inf)
|
, m_upload_limit(bandwidth_limit::inf)
|
||||||
, m_download_limit(bandwidth_limit::inf)
|
, m_download_limit(bandwidth_limit::inf)
|
||||||
@ -116,13 +103,27 @@ namespace libtorrent
|
|||||||
, m_connection_ticket(-1)
|
, m_connection_ticket(-1)
|
||||||
, m_remote_bytes_dled(0)
|
, m_remote_bytes_dled(0)
|
||||||
, m_remote_dl_rate(0)
|
, m_remote_dl_rate(0)
|
||||||
, m_remote_dl_update(time_now())
|
|
||||||
, m_outstanding_writing_bytes(0)
|
, m_outstanding_writing_bytes(0)
|
||||||
, m_fast_reconnect(false)
|
|
||||||
, m_rtt(0)
|
|
||||||
, m_downloaded_at_last_unchoke(0)
|
|
||||||
, m_download_rate_peak(0)
|
, m_download_rate_peak(0)
|
||||||
, m_upload_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
|
#ifndef NDEBUG
|
||||||
, m_in_constructor(true)
|
, m_in_constructor(true)
|
||||||
#endif
|
#endif
|
||||||
@ -164,6 +165,7 @@ namespace libtorrent
|
|||||||
peer_connection::peer_connection(
|
peer_connection::peer_connection(
|
||||||
session_impl& ses
|
session_impl& ses
|
||||||
, boost::shared_ptr<socket_type> s
|
, boost::shared_ptr<socket_type> s
|
||||||
|
, tcp::endpoint const& endp
|
||||||
, policy::peer* peerinfo)
|
, policy::peer* peerinfo)
|
||||||
:
|
:
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@ -172,39 +174,27 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
m_ses(ses)
|
m_ses(ses)
|
||||||
, m_max_out_request_queue(m_ses.settings().max_out_request_queue)
|
, 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_piece(time_now())
|
||||||
, m_last_request(time_now())
|
, m_last_request(time_now())
|
||||||
, m_last_incoming_request(min_time())
|
, m_last_incoming_request(min_time())
|
||||||
, m_last_unchoke(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_packet_size(0)
|
||||||
, m_recv_pos(0)
|
, m_recv_pos(0)
|
||||||
, m_disk_recv_buffer_size(0)
|
, m_disk_recv_buffer_size(0)
|
||||||
, m_disk_recv_buffer(0)
|
|
||||||
, m_reading_bytes(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_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_priority(1)
|
||||||
, m_upload_limit(bandwidth_limit::inf)
|
, m_upload_limit(bandwidth_limit::inf)
|
||||||
, m_download_limit(bandwidth_limit::inf)
|
, m_download_limit(bandwidth_limit::inf)
|
||||||
@ -213,13 +203,27 @@ namespace libtorrent
|
|||||||
, m_connection_ticket(-1)
|
, m_connection_ticket(-1)
|
||||||
, m_remote_bytes_dled(0)
|
, m_remote_bytes_dled(0)
|
||||||
, m_remote_dl_rate(0)
|
, m_remote_dl_rate(0)
|
||||||
, m_remote_dl_update(time_now())
|
|
||||||
, m_outstanding_writing_bytes(0)
|
, m_outstanding_writing_bytes(0)
|
||||||
, m_fast_reconnect(false)
|
|
||||||
, m_rtt(0)
|
|
||||||
, m_downloaded_at_last_unchoke(0)
|
|
||||||
, m_download_rate_peak(0)
|
, m_download_rate_peak(0)
|
||||||
, m_upload_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
|
#ifndef NDEBUG
|
||||||
, m_in_constructor(true)
|
, m_in_constructor(true)
|
||||||
#endif
|
#endif
|
||||||
@ -243,8 +247,8 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
TORRENT_ASSERT(m_socket->remote_endpoint() == remote() || ec);
|
TORRENT_ASSERT(m_socket->remote_endpoint(ec) == m_remote || ec);
|
||||||
m_logger = m_ses.create_log(remote().address().to_string(ec) + "_"
|
m_logger = m_ses.create_log(remote().address().to_string(ec) + "_"
|
||||||
+ boost::lexical_cast<std::string>(remote().port()), m_ses.listen_port());
|
+ boost::lexical_cast<std::string>(remote().port()), m_ses.listen_port());
|
||||||
(*m_logger) << "*** INCOMING CONNECTION\n";
|
(*m_logger) << "*** INCOMING CONNECTION\n";
|
||||||
@ -286,12 +290,13 @@ namespace libtorrent
|
|||||||
|
|
||||||
void peer_connection::start()
|
void peer_connection::start()
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(m_peer_info == 0 || m_peer_info->connection == this);
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
|
|
||||||
if (!t)
|
if (!t)
|
||||||
{
|
{
|
||||||
tcp::socket::non_blocking_io ioc(true);
|
tcp::socket::non_blocking_io ioc(true);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socket->io_control(ioc, ec);
|
m_socket->io_control(ioc, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
@ -439,7 +444,7 @@ namespace libtorrent
|
|||||||
// if this is a web seed. we don't have a peer_info struct
|
// if this is a web seed. we don't have a peer_info struct
|
||||||
if (m_peer_info) m_peer_info->seed = true;
|
if (m_peer_info) m_peer_info->seed = true;
|
||||||
// if we're a seed too, disconnect
|
// 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");
|
disconnect("seed to seed connection redundant");
|
||||||
return;
|
return;
|
||||||
@ -476,12 +481,7 @@ namespace libtorrent
|
|||||||
TORRENT_ASSERT(!m_in_constructor);
|
TORRENT_ASSERT(!m_in_constructor);
|
||||||
TORRENT_ASSERT(m_disconnecting);
|
TORRENT_ASSERT(m_disconnecting);
|
||||||
|
|
||||||
if (m_disk_recv_buffer)
|
m_disk_recv_buffer_size = 0;
|
||||||
{
|
|
||||||
m_ses.free_disk_buffer(m_disk_recv_buffer);
|
|
||||||
m_disk_recv_buffer = 0;
|
|
||||||
m_disk_recv_buffer_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
if (m_logger)
|
if (m_logger)
|
||||||
@ -616,6 +616,7 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
if (peer_info_struct())
|
if (peer_info_struct())
|
||||||
{
|
{
|
||||||
@ -701,7 +702,7 @@ namespace libtorrent
|
|||||||
(*m_logger) << " " << i->second->torrent_file().info_hash() << "\n";
|
(*m_logger) << " " << i->second->torrent_file().info_hash() << "\n";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
disconnect("got invalid info-hash");
|
disconnect("got invalid info-hash", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,6 +786,7 @@ namespace libtorrent
|
|||||||
if ((*i)->on_choke()) return;
|
if ((*i)->on_choke()) return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string() << " <== CHOKE\n";
|
(*m_logger) << time_now_string() << " <== CHOKE\n";
|
||||||
@ -838,6 +840,8 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
std::deque<piece_block>::iterator i = std::find_if(
|
std::deque<piece_block>::iterator i = std::find_if(
|
||||||
m_download_queue.begin(), m_download_queue.end()
|
m_download_queue.begin(), m_download_queue.end()
|
||||||
, bind(match_request, boost::cref(r), _1, t->block_size()));
|
, bind(match_request, boost::cref(r), _1, t->block_size()));
|
||||||
@ -921,6 +925,7 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (is_disconnecting()) return;
|
||||||
if (t->have_piece(index)) return;
|
if (t->have_piece(index)) return;
|
||||||
|
|
||||||
if (m_suggested_pieces.size() > 9)
|
if (m_suggested_pieces.size() > 9)
|
||||||
@ -956,6 +961,8 @@ namespace libtorrent
|
|||||||
(*m_logger) << time_now_string() << " <== UNCHOKE\n";
|
(*m_logger) << time_now_string() << " <== UNCHOKE\n";
|
||||||
#endif
|
#endif
|
||||||
m_peer_choked = false;
|
m_peer_choked = false;
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
t->get_policy().unchoked(*this);
|
t->get_policy().unchoked(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -982,6 +989,7 @@ namespace libtorrent
|
|||||||
(*m_logger) << time_now_string() << " <== INTERESTED\n";
|
(*m_logger) << time_now_string() << " <== INTERESTED\n";
|
||||||
#endif
|
#endif
|
||||||
m_peer_interested = true;
|
m_peer_interested = true;
|
||||||
|
if (is_disconnecting()) return;
|
||||||
t->get_policy().interested(*this);
|
t->get_policy().interested(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1006,11 +1014,12 @@ namespace libtorrent
|
|||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string() << " <== NOT_INTERESTED\n";
|
(*m_logger) << time_now_string() << " <== NOT_INTERESTED\n";
|
||||||
#endif
|
#endif
|
||||||
|
m_peer_interested = false;
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
TORRENT_ASSERT(t);
|
TORRENT_ASSERT(t);
|
||||||
|
|
||||||
m_peer_interested = false;
|
|
||||||
t->get_policy().not_interested(*this);
|
t->get_policy().not_interested(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1033,6 +1042,8 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string()
|
(*m_logger) << time_now_string()
|
||||||
<< " <== HAVE [ piece: " << index << "]\n";
|
<< " <== HAVE [ piece: " << index << "]\n";
|
||||||
@ -1059,7 +1070,7 @@ namespace libtorrent
|
|||||||
// if we got an invalid message, abort
|
// if we got an invalid message, abort
|
||||||
if (index >= int(m_have_piece.size()) || index < 0)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1099,11 +1110,11 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_seed())
|
if (upload_only())
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_peer_info);
|
TORRENT_ASSERT(m_peer_info);
|
||||||
m_peer_info->seed = true;
|
if (is_seed()) m_peer_info->seed = true;
|
||||||
if (t->is_finished())
|
if (t->is_finished() && m_ses.settings().close_redundant_connections)
|
||||||
{
|
{
|
||||||
disconnect("seed to seed connection redundant");
|
disconnect("seed to seed connection redundant");
|
||||||
return;
|
return;
|
||||||
@ -1131,6 +1142,8 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string() << " <== BITFIELD ";
|
(*m_logger) << time_now_string() << " <== BITFIELD ";
|
||||||
|
|
||||||
@ -1151,7 +1164,7 @@ namespace libtorrent
|
|||||||
msg << "got bitfield with invalid size: " << (bitfield.size() / 8)
|
msg << "got bitfield with invalid size: " << (bitfield.size() / 8)
|
||||||
<< "bytes. expected: " << (m_have_piece.size() / 8)
|
<< "bytes. expected: " << (m_have_piece.size() / 8)
|
||||||
<< " bytes";
|
<< " bytes";
|
||||||
disconnect(msg.str().c_str());
|
disconnect(msg.str().c_str(), 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1178,7 +1191,7 @@ namespace libtorrent
|
|||||||
// if this is a web seed. we don't have a peer_info struct
|
// if this is a web seed. we don't have a peer_info struct
|
||||||
if (m_peer_info) m_peer_info->seed = true;
|
if (m_peer_info) m_peer_info->seed = true;
|
||||||
// if we're a seed too, disconnect
|
// 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");
|
disconnect("seed to seed connection redundant, disconnecting");
|
||||||
return;
|
return;
|
||||||
@ -1220,6 +1233,7 @@ namespace libtorrent
|
|||||||
m_num_pieces = num_pieces;
|
m_num_pieces = num_pieces;
|
||||||
|
|
||||||
if (interesting) t->get_policy().peer_is_interesting(*this);
|
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;
|
if ((*i)->on_request(r)) return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
if (!t->valid_metadata())
|
if (!t->valid_metadata())
|
||||||
{
|
{
|
||||||
@ -1426,7 +1441,7 @@ namespace libtorrent
|
|||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
TORRENT_ASSERT(t);
|
TORRENT_ASSERT(t);
|
||||||
|
|
||||||
TORRENT_ASSERT(m_disk_recv_buffer == 0);
|
TORRENT_ASSERT(!m_disk_recv_buffer);
|
||||||
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
|
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
@ -1436,6 +1451,7 @@ namespace libtorrent
|
|||||||
if ((*i)->on_piece(p, data)) return;
|
if ((*i)->on_piece(p, data)) return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
check_postcondition post_checker_(t);
|
check_postcondition post_checker_(t);
|
||||||
@ -1461,7 +1477,7 @@ namespace libtorrent
|
|||||||
"start: " << p.start << " | "
|
"start: " << p.start << " | "
|
||||||
"length: " << p.length << " ]\n";
|
"length: " << p.length << " ]\n";
|
||||||
#endif
|
#endif
|
||||||
disconnect("got invalid piece packet");
|
disconnect("got invalid piece packet", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1648,6 +1664,7 @@ namespace libtorrent
|
|||||||
if ((*i)->on_cancel(r)) return;
|
if ((*i)->on_cancel(r)) return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string()
|
(*m_logger) << time_now_string()
|
||||||
@ -1717,6 +1734,7 @@ namespace libtorrent
|
|||||||
if ((*i)->on_have_all()) return;
|
if ((*i)->on_have_all()) return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
m_have_all = true;
|
m_have_all = true;
|
||||||
|
|
||||||
@ -1739,7 +1757,7 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// if we're a seed too, disconnect
|
// 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");
|
disconnect("seed to seed connection redundant, disconnecting");
|
||||||
return;
|
return;
|
||||||
@ -1762,13 +1780,13 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
|
||||||
TORRENT_ASSERT(t);
|
|
||||||
|
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string() << " <== HAVE_NONE\n";
|
(*m_logger) << time_now_string() << " <== HAVE_NONE\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
|
TORRENT_ASSERT(t);
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
for (extension_list_t::iterator i = m_extensions.begin()
|
for (extension_list_t::iterator i = m_extensions.begin()
|
||||||
, end(m_extensions.end()); i != end; ++i)
|
, end(m_extensions.end()); i != end; ++i)
|
||||||
@ -1776,8 +1794,9 @@ namespace libtorrent
|
|||||||
if ((*i)->on_have_none()) return;
|
if ((*i)->on_have_none()) return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (is_disconnecting()) return;
|
||||||
if (m_peer_info) m_peer_info->seed = false;
|
if (m_peer_info) m_peer_info->seed = false;
|
||||||
|
|
||||||
TORRENT_ASSERT(!m_have_piece.empty() || !t->ready_for_connections());
|
TORRENT_ASSERT(!m_have_piece.empty() || !t->ready_for_connections());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1803,6 +1822,7 @@ namespace libtorrent
|
|||||||
if ((*i)->on_allowed_fast(index)) return;
|
if ((*i)->on_allowed_fast(index)) return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
if (index < 0 || index >= int(m_have_piece.size()))
|
if (index < 0 || index >= int(m_have_piece.size()))
|
||||||
{
|
{
|
||||||
@ -2109,6 +2129,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
if (handled = (*i)->write_request(r)) break;
|
if (handled = (*i)->write_request(r)) break;
|
||||||
}
|
}
|
||||||
|
if (is_disconnecting()) return;
|
||||||
if (!handled)
|
if (!handled)
|
||||||
{
|
{
|
||||||
write_request(r);
|
write_request(r);
|
||||||
@ -2141,24 +2162,38 @@ namespace libtorrent
|
|||||||
(*m_ses.m_logger) << time_now_string() << " CONNECTION TIMED OUT: " << m_remote.address().to_string()
|
(*m_ses.m_logger) << time_now_string() << " CONNECTION TIMED OUT: " << m_remote.address().to_string()
|
||||||
<< "\n";
|
<< "\n";
|
||||||
#endif
|
#endif
|
||||||
set_failed();
|
disconnect("timed out: connect", 1);
|
||||||
disconnect("timed out");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||||
|
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
#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
|
#endif
|
||||||
// we cannot do this in a constructor
|
// we cannot do this in a constructor
|
||||||
TORRENT_ASSERT(m_in_constructor == false);
|
TORRENT_ASSERT(m_in_constructor == false);
|
||||||
|
if (error > 0) m_failed = true;
|
||||||
|
if (m_disconnecting) return;
|
||||||
boost::intrusive_ptr<peer_connection> me(this);
|
boost::intrusive_ptr<peer_connection> me(this);
|
||||||
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
if (m_disconnecting) return;
|
|
||||||
if (m_connecting && m_connection_ticket >= 0)
|
if (m_connecting && m_connection_ticket >= 0)
|
||||||
{
|
{
|
||||||
m_ses.m_half_open.done(m_connection_ticket);
|
m_ses.m_half_open.done(m_connection_ticket);
|
||||||
@ -2167,13 +2202,18 @@ namespace libtorrent
|
|||||||
|
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
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(
|
if (error > 1 && m_ses.m_alerts.should_post(alert::info))
|
||||||
peer_error_alert(
|
{
|
||||||
remote()
|
m_ses.m_alerts.post_alert(
|
||||||
, pid()
|
peer_error_alert(remote(), pid(), message));
|
||||||
, 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)
|
if (t)
|
||||||
@ -2207,7 +2247,7 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_disconnecting = true;
|
m_disconnecting = true;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socket->close(ec);
|
m_socket->close(ec);
|
||||||
m_ses.close_connection(this, message);
|
m_ses.close_connection(this, message);
|
||||||
}
|
}
|
||||||
@ -2372,17 +2412,17 @@ namespace libtorrent
|
|||||||
|
|
||||||
TORRENT_ASSERT(m_packet_size > 0);
|
TORRENT_ASSERT(m_packet_size > 0);
|
||||||
TORRENT_ASSERT(m_recv_pos <= m_packet_size - disk_buffer_size);
|
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);
|
TORRENT_ASSERT(disk_buffer_size <= 16 * 1024);
|
||||||
|
|
||||||
if (disk_buffer_size > 16 * 1024)
|
if (disk_buffer_size > 16 * 1024)
|
||||||
{
|
{
|
||||||
disconnect("invalid piece size");
|
disconnect("invalid piece size", 2);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_disk_recv_buffer = m_ses.allocate_disk_buffer();
|
m_disk_recv_buffer.reset(m_ses.allocate_disk_buffer());
|
||||||
if (m_disk_recv_buffer == 0)
|
if (!m_disk_recv_buffer)
|
||||||
{
|
{
|
||||||
disconnect("out of memory");
|
disconnect("out of memory");
|
||||||
return false;
|
return false;
|
||||||
@ -2393,10 +2433,8 @@ namespace libtorrent
|
|||||||
|
|
||||||
char* peer_connection::release_disk_receive_buffer()
|
char* peer_connection::release_disk_receive_buffer()
|
||||||
{
|
{
|
||||||
char* ret = m_disk_recv_buffer;
|
|
||||||
m_disk_recv_buffer = 0;
|
|
||||||
m_disk_recv_buffer_size = 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)
|
void peer_connection::cut_receive_buffer(int size, int packet_size)
|
||||||
@ -2420,11 +2458,17 @@ namespace libtorrent
|
|||||||
m_packet_size = packet_size;
|
m_packet_size = packet_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void peer_connection::calc_ip_overhead()
|
||||||
|
{
|
||||||
|
m_statistics.calc_ip_overhead();
|
||||||
|
}
|
||||||
|
|
||||||
void peer_connection::second_tick(float tick_interval)
|
void peer_connection::second_tick(float tick_interval)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
ptime now(time_now());
|
ptime now(time_now());
|
||||||
|
boost::intrusive_ptr<peer_connection> me(self());
|
||||||
|
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
if (!t || m_disconnecting)
|
if (!t || m_disconnecting)
|
||||||
@ -2466,6 +2510,7 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
if (is_disconnecting()) return;
|
||||||
|
|
||||||
if (!t->valid_metadata()) return;
|
if (!t->valid_metadata()) return;
|
||||||
|
|
||||||
@ -2829,7 +2874,7 @@ namespace libtorrent
|
|||||||
if (int(m_recv_buffer.size()) < regular_buffer_size)
|
if (int(m_recv_buffer.size()) < regular_buffer_size)
|
||||||
m_recv_buffer.resize(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
|
// only receive into regular buffer
|
||||||
TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size()));
|
TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size()));
|
||||||
@ -2841,7 +2886,7 @@ namespace libtorrent
|
|||||||
// only receive into disk buffer
|
// only receive into disk buffer
|
||||||
TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0);
|
TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0);
|
||||||
TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size);
|
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)
|
, max_receive)
|
||||||
, bind(&peer_connection::on_receive_data, self(), _1, _2));
|
, bind(&peer_connection::on_receive_data, self(), _1, _2));
|
||||||
}
|
}
|
||||||
@ -2856,7 +2901,7 @@ namespace libtorrent
|
|||||||
boost::array<asio::mutable_buffer, 2> vec;
|
boost::array<asio::mutable_buffer, 2> vec;
|
||||||
vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos]
|
vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos]
|
||||||
, regular_buffer_size - 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);
|
, max_receive - regular_buffer_size + m_recv_pos);
|
||||||
m_socket->async_read_some(vec, bind(&peer_connection::on_receive_data
|
m_socket->async_read_some(vec, bind(&peer_connection::on_receive_data
|
||||||
, self(), _1, _2));
|
, self(), _1, _2));
|
||||||
@ -2874,7 +2919,7 @@ namespace libtorrent
|
|||||||
std::pair<buffer::interval, buffer::interval> vec;
|
std::pair<buffer::interval, buffer::interval> vec;
|
||||||
int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size;
|
int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size;
|
||||||
TORRENT_ASSERT(regular_buffer_size >= 0);
|
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]
|
vec.first = buffer::interval(&m_recv_buffer[0]
|
||||||
+ m_recv_pos - bytes, &m_recv_buffer[0] + m_recv_pos);
|
+ 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)
|
else if (m_recv_pos - bytes >= regular_buffer_size)
|
||||||
{
|
{
|
||||||
vec.first = buffer::interval(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 + m_recv_pos
|
- regular_buffer_size - bytes, m_disk_recv_buffer.get() + m_recv_pos
|
||||||
- regular_buffer_size);
|
- regular_buffer_size);
|
||||||
vec.second = buffer::interval(0,0);
|
vec.second = buffer::interval(0,0);
|
||||||
}
|
}
|
||||||
@ -2893,8 +2938,8 @@ namespace libtorrent
|
|||||||
TORRENT_ASSERT(m_recv_pos > regular_buffer_size);
|
TORRENT_ASSERT(m_recv_pos > regular_buffer_size);
|
||||||
vec.first = buffer::interval(&m_recv_buffer[0] + m_recv_pos - bytes
|
vec.first = buffer::interval(&m_recv_buffer[0] + m_recv_pos - bytes
|
||||||
, &m_recv_buffer[0] + regular_buffer_size);
|
, &m_recv_buffer[0] + regular_buffer_size);
|
||||||
vec.second = buffer::interval(m_disk_recv_buffer
|
vec.second = buffer::interval(m_disk_recv_buffer.get()
|
||||||
, m_disk_recv_buffer + m_recv_pos - regular_buffer_size);
|
, m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size);
|
||||||
}
|
}
|
||||||
TORRENT_ASSERT(vec.first.left() + vec.second.left() == bytes);
|
TORRENT_ASSERT(vec.first.left() + vec.second.left() == bytes);
|
||||||
return vec;
|
return vec;
|
||||||
@ -2998,7 +3043,7 @@ namespace libtorrent
|
|||||||
// --------------------------
|
// --------------------------
|
||||||
|
|
||||||
// throws exception when the client should be disconnected
|
// 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)
|
, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||||
@ -3014,7 +3059,6 @@ namespace libtorrent
|
|||||||
(*m_logger) << time_now_string() << " **ERROR**: "
|
(*m_logger) << time_now_string() << " **ERROR**: "
|
||||||
<< error.message() << "[in peer_connection::on_receive_data]\n";
|
<< error.message() << "[in peer_connection::on_receive_data]\n";
|
||||||
#endif
|
#endif
|
||||||
set_failed();
|
|
||||||
on_receive(error, bytes_transferred);
|
on_receive(error, bytes_transferred);
|
||||||
disconnect(error.message().c_str());
|
disconnect(error.message().c_str());
|
||||||
return;
|
return;
|
||||||
@ -3063,8 +3107,8 @@ namespace libtorrent
|
|||||||
if (int(m_recv_buffer.size()) < regular_buffer_size)
|
if (int(m_recv_buffer.size()) < regular_buffer_size)
|
||||||
m_recv_buffer.resize(regular_buffer_size);
|
m_recv_buffer.resize(regular_buffer_size);
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
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
|
// only receive into regular buffer
|
||||||
TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size()));
|
TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size()));
|
||||||
@ -3076,7 +3120,7 @@ namespace libtorrent
|
|||||||
// only receive into disk buffer
|
// only receive into disk buffer
|
||||||
TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0);
|
TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0);
|
||||||
TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size);
|
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 - regular_buffer_size, (std::min)(m_packet_size
|
||||||
- m_recv_pos, max_receive)), ec);
|
- m_recv_pos, max_receive)), ec);
|
||||||
}
|
}
|
||||||
@ -3091,7 +3135,7 @@ namespace libtorrent
|
|||||||
boost::array<asio::mutable_buffer, 2> vec;
|
boost::array<asio::mutable_buffer, 2> vec;
|
||||||
vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos]
|
vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos]
|
||||||
, regular_buffer_size - 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
|
, (std::min)(m_disk_recv_buffer_size
|
||||||
, max_receive - regular_buffer_size + m_recv_pos));
|
, max_receive - regular_buffer_size + m_recv_pos));
|
||||||
bytes_transferred = m_socket->read_some(vec, ec);
|
bytes_transferred = m_socket->read_some(vec, ec);
|
||||||
@ -3107,27 +3151,6 @@ namespace libtorrent
|
|||||||
|
|
||||||
setup_receive();
|
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
|
bool peer_connection::can_write() const
|
||||||
{
|
{
|
||||||
@ -3158,7 +3181,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
#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_ses.m_logger) << time_now_string() << " CONNECTING: " << m_remote.address().to_string(ec)
|
||||||
<< ":" << m_remote.port() << "\n";
|
<< ":" << 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();
|
ptime completed = time_now();
|
||||||
|
|
||||||
@ -3230,8 +3253,7 @@ namespace libtorrent
|
|||||||
(*m_ses.m_logger) << time_now_string() << " CONNECTION FAILED: " << m_remote.address().to_string()
|
(*m_ses.m_logger) << time_now_string() << " CONNECTION FAILED: " << m_remote.address().to_string()
|
||||||
<< ": " << e.message() << "\n";
|
<< ": " << e.message() << "\n";
|
||||||
#endif
|
#endif
|
||||||
set_failed();
|
disconnect(e.message().c_str(), 1);
|
||||||
disconnect(e.message().c_str());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3247,7 +3269,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (m_remote.address().is_v4())
|
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);
|
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
|
// 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)
|
, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
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
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
(*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n";
|
(*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n";
|
||||||
#endif
|
#endif
|
||||||
set_failed();
|
|
||||||
disconnect(error.message().c_str());
|
disconnect(error.message().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3306,7 +3327,7 @@ namespace libtorrent
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void peer_connection::check_invariant() const
|
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();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
if (m_disconnecting)
|
if (m_disconnecting)
|
||||||
|
|||||||
@ -133,22 +133,8 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
int index = static_cast<int>(i - pieces.begin());
|
int index = static_cast<int>(i - pieces.begin());
|
||||||
piece_pos& p = m_piece_map[index];
|
piece_pos& p = m_piece_map[index];
|
||||||
if (*i)
|
if (*i) we_have(index);
|
||||||
{
|
else TORRENT_ASSERT(p.index == 0);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -225,7 +225,7 @@ namespace libtorrent
|
|||||||
// blocks be from whole pieces, possibly by returning more blocks
|
// blocks be from whole pieces, possibly by returning more blocks
|
||||||
// than we requested.
|
// than we requested.
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
|
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -348,6 +348,7 @@ namespace libtorrent
|
|||||||
, m_torrent(t)
|
, m_torrent(t)
|
||||||
, m_available_free_upload(0)
|
, m_available_free_upload(0)
|
||||||
, m_num_connect_candidates(0)
|
, m_num_connect_candidates(0)
|
||||||
|
, m_num_seeds(0)
|
||||||
{ TORRENT_ASSERT(t); }
|
{ TORRENT_ASSERT(t); }
|
||||||
|
|
||||||
// disconnects and removes all peers that are now filtered
|
// disconnects and removes all peers that are now filtered
|
||||||
@ -420,49 +421,6 @@ namespace libtorrent
|
|||||||
return true;
|
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()
|
policy::iterator policy::find_connect_candidate()
|
||||||
{
|
{
|
||||||
// too expensive
|
// too expensive
|
||||||
@ -625,7 +583,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
// TODO: only allow _one_ connection to use this
|
// TODO: only allow _one_ connection to use this
|
||||||
// override at a time
|
// override at a time
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
|
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
|
||||||
|
|
||||||
aux::session_impl& ses = m_torrent->session();
|
aux::session_impl& ses = m_torrent->session();
|
||||||
@ -697,7 +655,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
// we don't have any info about this peer.
|
// we don't have any info about this peer.
|
||||||
// add a new entry
|
// add a new entry
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
|
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
|
||||||
|
|
||||||
peer p(c.remote(), peer::not_connectable, 0);
|
peer p(c.remote(), peer::not_connectable, 0);
|
||||||
@ -1073,19 +1031,6 @@ namespace libtorrent
|
|||||||
return true;
|
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
|
// this is called whenever a peer connection is closed
|
||||||
void policy::connection_closed(const peer_connection& c)
|
void policy::connection_closed(const peer_connection& c)
|
||||||
{
|
{
|
||||||
@ -1156,7 +1101,7 @@ namespace libtorrent
|
|||||||
// INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
TORRENT_ASSERT(c);
|
TORRENT_ASSERT(c);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
TORRENT_ASSERT(c->remote() == c->get_socket()->remote_endpoint(ec) || ec);
|
TORRENT_ASSERT(c->remote() == c->get_socket()->remote_endpoint(ec) || ec);
|
||||||
|
|
||||||
return std::find_if(
|
return std::find_if(
|
||||||
|
|||||||
@ -253,7 +253,6 @@ namespace libtorrent
|
|||||||
, bool paused
|
, bool paused
|
||||||
, storage_constructor_type sc)
|
, storage_constructor_type sc)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(!ti.m_half_metadata);
|
|
||||||
boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti));
|
boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti));
|
||||||
add_torrent_params p(sc);
|
add_torrent_params p(sc);
|
||||||
p.ti = tip;
|
p.ti = tip;
|
||||||
@ -273,7 +272,6 @@ namespace libtorrent
|
|||||||
, storage_constructor_type sc
|
, storage_constructor_type sc
|
||||||
, void* userdata)
|
, void* userdata)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(!ti->m_half_metadata);
|
|
||||||
add_torrent_params p(sc);
|
add_torrent_params p(sc);
|
||||||
p.ti = ti;
|
p.ti = ti;
|
||||||
p.save_path = save_path;
|
p.save_path = save_path;
|
||||||
|
|||||||
@ -76,6 +76,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "libtorrent/enum_net.hpp"
|
#include "libtorrent/enum_net.hpp"
|
||||||
#include "libtorrent/config.hpp"
|
#include "libtorrent/config.hpp"
|
||||||
|
|
||||||
|
#ifndef TORRENT_WINDOWS
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||||
|
|
||||||
#include <openssl/crypto.h>
|
#include <openssl/crypto.h>
|
||||||
@ -162,6 +166,7 @@ namespace aux {
|
|||||||
, m_auto_manage_time_scaler(0)
|
, m_auto_manage_time_scaler(0)
|
||||||
, m_optimistic_unchoke_time_scaler(0)
|
, m_optimistic_unchoke_time_scaler(0)
|
||||||
, m_disconnect_time_scaler(90)
|
, m_disconnect_time_scaler(90)
|
||||||
|
, m_auto_scrape_time_scaler(180)
|
||||||
, m_incoming_connection(false)
|
, m_incoming_connection(false)
|
||||||
, m_last_tick(time_now())
|
, m_last_tick(time_now())
|
||||||
, m_torrent_sequence(0)
|
, m_torrent_sequence(0)
|
||||||
@ -207,6 +212,11 @@ namespace aux {
|
|||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
m_logger = create_log("main_session", listen_port(), false);
|
m_logger = create_log("main_session", listen_port(), false);
|
||||||
(*m_logger) << time_now_string() << "\n";
|
(*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
|
#endif
|
||||||
|
|
||||||
#ifdef TORRENT_STATS
|
#ifdef TORRENT_STATS
|
||||||
@ -250,7 +260,7 @@ namespace aux {
|
|||||||
*i = printable[rand() % (sizeof(printable)-1)];
|
*i = printable[rand() % (sizeof(printable)-1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timer.expires_from_now(seconds(1), ec);
|
m_timer.expires_from_now(seconds(1), ec);
|
||||||
m_timer.async_wait(
|
m_timer.async_wait(
|
||||||
bind(&session_impl::second_tick, this, _1));
|
bind(&session_impl::second_tick, this, _1));
|
||||||
@ -396,7 +406,7 @@ namespace aux {
|
|||||||
if (m_dht) m_dht->stop();
|
if (m_dht) m_dht->stop();
|
||||||
m_dht_socket.close();
|
m_dht_socket.close();
|
||||||
#endif
|
#endif
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timer.cancel(ec);
|
m_timer.cancel(ec);
|
||||||
|
|
||||||
// close the listen sockets
|
// close the listen sockets
|
||||||
@ -535,7 +545,7 @@ namespace aux {
|
|||||||
session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep
|
session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep
|
||||||
, int retries, bool v6_only)
|
, int retries, bool v6_only)
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
listen_socket_t s;
|
listen_socket_t s;
|
||||||
s.sock.reset(new socket_acceptor(m_io_service));
|
s.sock.reset(new socket_acceptor(m_io_service));
|
||||||
s.sock->open(ep.protocol(), ec);
|
s.sock->open(ep.protocol(), ec);
|
||||||
@ -544,7 +554,7 @@ namespace aux {
|
|||||||
s.sock->bind(ep, ec);
|
s.sock->bind(ep, ec);
|
||||||
while (ec && retries > 0)
|
while (ec && retries > 0)
|
||||||
{
|
{
|
||||||
ec = asio::error_code();
|
ec = error_code();
|
||||||
TORRENT_ASSERT(!ec);
|
TORRENT_ASSERT(!ec);
|
||||||
--retries;
|
--retries;
|
||||||
ep.port(ep.port() + 1);
|
ep.port(ep.port() + 1);
|
||||||
@ -555,7 +565,7 @@ namespace aux {
|
|||||||
// instead of giving up, try
|
// instead of giving up, try
|
||||||
// let the OS pick a port
|
// let the OS pick a port
|
||||||
ep.port(0);
|
ep.port(0);
|
||||||
ec = asio::error_code();
|
ec = error_code();
|
||||||
s.sock->bind(ep, ec);
|
s.sock->bind(ep, ec);
|
||||||
}
|
}
|
||||||
if (ec)
|
if (ec)
|
||||||
@ -661,7 +671,7 @@ namespace aux {
|
|||||||
for (std::list<listen_socket_t>::const_iterator i = m_listen_sockets.begin()
|
for (std::list<listen_socket_t>::const_iterator i = m_listen_sockets.begin()
|
||||||
, end(m_listen_sockets.end()); i != end; ++i)
|
, end(m_listen_sockets.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
tcp::endpoint ep = i->sock->local_endpoint(ec);
|
tcp::endpoint ep = i->sock->local_endpoint(ec);
|
||||||
if (ec || ep.address().is_v4()) continue;
|
if (ec || ep.address().is_v4()) continue;
|
||||||
|
|
||||||
@ -691,7 +701,7 @@ namespace aux {
|
|||||||
|
|
||||||
if (!m_listen_sockets.empty())
|
if (!m_listen_sockets.empty())
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
tcp::endpoint local = m_listen_sockets.front().sock->local_endpoint(ec);
|
tcp::endpoint local = m_listen_sockets.front().sock->local_endpoint(ec);
|
||||||
if (!ec)
|
if (!ec)
|
||||||
{
|
{
|
||||||
@ -713,11 +723,16 @@ namespace aux {
|
|||||||
|
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#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)
|
, udp::endpoint const& ep, char const* buf, int len)
|
||||||
{
|
{
|
||||||
if (e)
|
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))
|
if (m_alerts.should_post(alert::info))
|
||||||
{
|
{
|
||||||
std::string msg = "UDP socket error from '"
|
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
|
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();
|
boost::shared_ptr<socket_acceptor> listener = listen_socket.lock();
|
||||||
if (!listener) return;
|
if (!listener) return;
|
||||||
@ -756,7 +771,7 @@ namespace aux {
|
|||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
if (m_abort) return;
|
if (m_abort) return;
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
tcp::endpoint ep = listener->local_endpoint(ec);
|
tcp::endpoint ep = listener->local_endpoint(ec);
|
||||||
@ -842,7 +857,13 @@ namespace aux {
|
|||||||
|
|
||||||
// check if we have any active torrents
|
// check if we have any active torrents
|
||||||
// if we don't reject the connection
|
// 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;
|
bool has_active_torrent = false;
|
||||||
for (torrent_map::iterator i = m_torrents.begin()
|
for (torrent_map::iterator i = m_torrents.begin()
|
||||||
@ -854,10 +875,16 @@ namespace aux {
|
|||||||
break;
|
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(
|
boost::intrusive_ptr<peer_connection> c(
|
||||||
new bt_peer_connection(*this, s, 0));
|
new bt_peer_connection(*this, s, endp, 0));
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
c->m_in_constructor = false;
|
c->m_in_constructor = false;
|
||||||
#endif
|
#endif
|
||||||
@ -926,7 +953,7 @@ namespace aux {
|
|||||||
return port;
|
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);
|
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;
|
float tick_interval = total_microseconds(time_now() - m_last_tick) / 1000000.f;
|
||||||
m_last_tick = time_now();
|
m_last_tick = time_now();
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timer.expires_from_now(seconds(1), ec);
|
m_timer.expires_from_now(seconds(1), ec);
|
||||||
m_timer.async_wait(
|
m_timer.async_wait(
|
||||||
bind(&session_impl::second_tick, this, _1));
|
bind(&session_impl::second_tick, this, _1));
|
||||||
@ -986,7 +1013,6 @@ namespace aux {
|
|||||||
<< m_disk_thread.disk_allocations() << "\t"
|
<< m_disk_thread.disk_allocations() << "\t"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
// second_tick every torrent
|
// second_tick every torrent
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
@ -1002,6 +1028,9 @@ namespace aux {
|
|||||||
// count the number of peers of downloading torrents
|
// count the number of peers of downloading torrents
|
||||||
int num_downloads_peers = 0;
|
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
|
// check each torrent for tracker updates
|
||||||
// TODO: do this in a timer-event in each torrent instead
|
// TODO: do this in a timer-event in each torrent instead
|
||||||
for (torrent_map::iterator i = m_torrents.begin();
|
for (torrent_map::iterator i = m_torrents.begin();
|
||||||
@ -1014,6 +1043,17 @@ namespace aux {
|
|||||||
else
|
else
|
||||||
++uncongested_torrents;
|
++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())
|
if (t.is_finished())
|
||||||
{
|
{
|
||||||
++num_seeds;
|
++num_seeds;
|
||||||
@ -1046,9 +1086,29 @@ namespace aux {
|
|||||||
++i;
|
++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);
|
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
|
// connect new peers
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
@ -1156,20 +1216,10 @@ namespace aux {
|
|||||||
peer_connection& c = *j->get();
|
peer_connection& c = *j->get();
|
||||||
if (c.has_timed_out())
|
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)
|
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||||
(*c.m_logger) << "*** CONNECTION TIMED OUT\n";
|
(*c.m_logger) << "*** CONNECTION TIMED OUT\n";
|
||||||
#endif
|
#endif
|
||||||
|
c.disconnect("timed out: inactive", 1);
|
||||||
c.set_failed();
|
|
||||||
c.disconnect("timed out");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1205,17 +1255,37 @@ namespace aux {
|
|||||||
{
|
{
|
||||||
m_disconnect_time_scaler = 90;
|
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 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()
|
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, _1))
|
||||||
< bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _2)));
|
< bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _2)));
|
||||||
|
|
||||||
TORRENT_ASSERT(i != m_torrents.end());
|
TORRENT_ASSERT(i != m_torrents.end());
|
||||||
// TODO: make the number of peers a percentage of the number of connected peers
|
int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers()
|
||||||
i->second->get_policy().disconnect_one_peer();
|
* 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));
|
, bind(&torrent::sequence_number, _1) < bind(&torrent::sequence_number, _2));
|
||||||
|
|
||||||
std::sort(seeds.begin(), seeds.end()
|
std::sort(seeds.begin(), seeds.end()
|
||||||
, bind(&torrent::seed_cycles_int, _1, boost::ref(m_settings))
|
, bind(&torrent::seed_rank, _1, boost::ref(m_settings))
|
||||||
< bind(&torrent::seed_cycles_int, _2, boost::ref(m_settings)));
|
> bind(&torrent::seed_rank, _2, boost::ref(m_settings)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::vector<torrent*>::iterator i = downloaders.begin()
|
for (std::vector<torrent*>::iterator i = downloaders.begin()
|
||||||
@ -2111,7 +2181,19 @@ namespace aux {
|
|||||||
|
|
||||||
INVARIANT_CHECK;
|
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;
|
m_max_connections = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,13 +37,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
namespace libtorrent
|
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)
|
, boost::shared_ptr<handler_type> h)
|
||||||
{
|
{
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (i == tcp::resolver::iterator())
|
if (i == tcp::resolver::iterator())
|
||||||
{
|
{
|
||||||
asio::error_code ec = asio::error::operation_not_supported;
|
error_code ec = asio::error::operation_not_supported;
|
||||||
(*h)(ec);
|
(*h)(ec);
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
@ -64,12 +64,12 @@ namespace libtorrent
|
|||||||
&socks4_stream::connected, this, _1, h));
|
&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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -86,31 +86,31 @@ namespace libtorrent
|
|||||||
p += m_user.size();
|
p += m_user.size();
|
||||||
write_uint8(0, p); // NULL terminator
|
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));
|
, 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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_buffer.resize(8);
|
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));
|
, 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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (reply_version != 0)
|
if (reply_version != 0)
|
||||||
{
|
{
|
||||||
asio::error_code ec = asio::error::operation_not_supported;
|
error_code ec = asio::error::operation_not_supported;
|
||||||
(*h)(ec);
|
(*h)(ec);
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
@ -137,7 +137,7 @@ namespace libtorrent
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::error_code ec = asio::error::fault;
|
error_code ec = asio::error::fault;
|
||||||
switch (status_code)
|
switch (status_code)
|
||||||
{
|
{
|
||||||
case 91: ec = asio::error::connection_refused; break;
|
case 91: ec = asio::error::connection_refused; break;
|
||||||
|
|||||||
@ -38,13 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
namespace libtorrent
|
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)
|
, boost::shared_ptr<handler_type> h)
|
||||||
{
|
{
|
||||||
if (e || i == tcp::resolver::iterator())
|
if (e || i == tcp::resolver::iterator())
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -53,12 +53,12 @@ namespace libtorrent
|
|||||||
&socks5_stream::connected, this, _1, h));
|
&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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -79,31 +79,31 @@ namespace libtorrent
|
|||||||
write_uint8(0, p); // no authentication
|
write_uint8(0, p); // no authentication
|
||||||
write_uint8(2, p); // username/password
|
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));
|
, 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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_buffer.resize(2);
|
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));
|
, 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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -117,7 +117,7 @@ namespace libtorrent
|
|||||||
if (version < 5)
|
if (version < 5)
|
||||||
{
|
{
|
||||||
(*h)(asio::error::operation_not_supported);
|
(*h)(asio::error::operation_not_supported);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -131,7 +131,7 @@ namespace libtorrent
|
|||||||
if (m_user.empty())
|
if (m_user.empty())
|
||||||
{
|
{
|
||||||
(*h)(asio::error::operation_not_supported);
|
(*h)(asio::error::operation_not_supported);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -144,41 +144,41 @@ namespace libtorrent
|
|||||||
write_string(m_user, p);
|
write_string(m_user, p);
|
||||||
write_uint8(m_password.size(), p);
|
write_uint8(m_password.size(), p);
|
||||||
write_string(m_password, 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));
|
, boost::bind(&socks5_stream::handshake3, this, _1, h));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(*h)(asio::error::operation_not_supported);
|
(*h)(asio::error::operation_not_supported);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void socks5_stream::handshake3(asio::error_code const& e
|
void socks5_stream::handshake3(error_code const& e
|
||||||
, boost::shared_ptr<handler_type> h)
|
, boost::shared_ptr<handler_type> h)
|
||||||
{
|
{
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_buffer.resize(2);
|
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));
|
, 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)
|
, boost::shared_ptr<handler_type> h)
|
||||||
{
|
{
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@ namespace libtorrent
|
|||||||
if (version != 1)
|
if (version != 1)
|
||||||
{
|
{
|
||||||
(*h)(asio::error::operation_not_supported);
|
(*h)(asio::error::operation_not_supported);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -200,7 +200,7 @@ namespace libtorrent
|
|||||||
if (status != 0)
|
if (status != 0)
|
||||||
{
|
{
|
||||||
(*h)(asio::error::operation_not_supported);
|
(*h)(asio::error::operation_not_supported);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -223,31 +223,31 @@ namespace libtorrent
|
|||||||
write_endpoint(m_remote_endpoint, p);
|
write_endpoint(m_remote_endpoint, p);
|
||||||
TORRENT_ASSERT(p - &m_buffer[0] == int(m_buffer.size()));
|
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));
|
, 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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_buffer.resize(6 + 4); // assume an IPv4 address
|
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));
|
, 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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -260,14 +260,14 @@ namespace libtorrent
|
|||||||
if (version < 5)
|
if (version < 5)
|
||||||
{
|
{
|
||||||
(*h)(asio::error::operation_not_supported);
|
(*h)(asio::error::operation_not_supported);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int response = read_uint8(p);
|
int response = read_uint8(p);
|
||||||
if (response != 0)
|
if (response != 0)
|
||||||
{
|
{
|
||||||
asio::error_code e = asio::error::fault;
|
error_code e = asio::error::fault;
|
||||||
switch (response)
|
switch (response)
|
||||||
{
|
{
|
||||||
case 1: e = asio::error::fault; break;
|
case 1: e = asio::error::fault; break;
|
||||||
@ -280,7 +280,7 @@ namespace libtorrent
|
|||||||
case 8: e = asio::error::address_family_not_supported; break;
|
case 8: e = asio::error::address_family_not_supported; break;
|
||||||
}
|
}
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -305,22 +305,22 @@ namespace libtorrent
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
(*h)(asio::error::operation_not_supported);
|
(*h)(asio::error::operation_not_supported);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_buffer.resize(skip_bytes);
|
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));
|
, 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)
|
if (e)
|
||||||
{
|
{
|
||||||
(*h)(e);
|
(*h)(e);
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
close(ec);
|
close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,47 +47,23 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define for if (false) {} else for
|
#define for if (false) {} else for
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace libtorrent;
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
|
||||||
void libtorrent::stat::second_tick(float tick_interval)
|
void stat_channel::second_tick(float tick_interval)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
m_rate_sum -= m_rate_history[history-1];
|
||||||
|
|
||||||
for (int i = history - 2; i >= 0; --i)
|
for (int i = history - 2; i >= 0; --i)
|
||||||
{
|
m_rate_history[i + 1] = m_rate_history[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_download_rate_history[0] = (m_downloaded_payload + m_downloaded_protocol)
|
m_rate_history[0] = m_counter / tick_interval;
|
||||||
/ tick_interval;
|
m_rate_sum += m_rate_history[0];
|
||||||
m_upload_rate_history[0] = (m_uploaded_payload + m_uploaded_protocol)
|
m_counter = 0;
|
||||||
/ 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -527,12 +527,23 @@ namespace libtorrent
|
|||||||
std::pair<iter_t, bool> ret = directories.insert((m_save_path / bp).string());
|
std::pair<iter_t, bool> ret = directories.insert((m_save_path / bp).string());
|
||||||
bp = bp.branch_path();
|
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)
|
if (std::remove(p.c_str()) != 0 && errno != ENOENT)
|
||||||
{
|
{
|
||||||
error = std::strerror(errno);
|
error = std::strerror(errno);
|
||||||
error_file = p;
|
error_file = p;
|
||||||
result = errno;
|
result = errno;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the directories. Reverse order to delete
|
// remove the directories. Reverse order to delete
|
||||||
@ -541,12 +552,23 @@ namespace libtorrent
|
|||||||
for (std::set<std::string>::reverse_iterator i = directories.rbegin()
|
for (std::set<std::string>::reverse_iterator i = directories.rbegin()
|
||||||
, end(directories.rend()); i != end; ++i)
|
, 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)
|
if (std::remove(i->c_str()) != 0 && errno != ENOENT)
|
||||||
{
|
{
|
||||||
error = std::strerror(errno);
|
error = std::strerror(errno);
|
||||||
error_file = *i;
|
error_file = *i;
|
||||||
result = errno;
|
result = errno;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error.empty())
|
if (!error.empty())
|
||||||
@ -1230,7 +1252,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
TORRENT_ASSERT(r.length <= 16 * 1024);
|
TORRENT_ASSERT(r.length <= 16 * 1024);
|
||||||
// the buffer needs to be allocated through the io_thread
|
// 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;
|
disk_io_job j;
|
||||||
j.storage = this;
|
j.storage = this;
|
||||||
@ -1238,7 +1260,7 @@ namespace libtorrent
|
|||||||
j.piece = r.piece;
|
j.piece = r.piece;
|
||||||
j.offset = r.start;
|
j.offset = r.start;
|
||||||
j.buffer_size = r.length;
|
j.buffer_size = r.length;
|
||||||
j.buffer = buffer.buffer();
|
j.buffer = buffer.get();
|
||||||
m_io_thread.add_job(j, handler);
|
m_io_thread.add_job(j, handler);
|
||||||
buffer.release();
|
buffer.release();
|
||||||
}
|
}
|
||||||
@ -2465,7 +2487,8 @@ namespace libtorrent
|
|||||||
&& m_free_slots.empty()
|
&& m_free_slots.empty()
|
||||||
&& m_state == state_finished)
|
&& 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)
|
if (m_storage_mode != storage_mode_compact)
|
||||||
|
|||||||
@ -59,6 +59,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "libtorrent/session.hpp"
|
#include "libtorrent/session.hpp"
|
||||||
#include "libtorrent/torrent_info.hpp"
|
#include "libtorrent/torrent_info.hpp"
|
||||||
#include "libtorrent/tracker_manager.hpp"
|
#include "libtorrent/tracker_manager.hpp"
|
||||||
|
#include "libtorrent/parse_url.hpp"
|
||||||
#include "libtorrent/bencode.hpp"
|
#include "libtorrent/bencode.hpp"
|
||||||
#include "libtorrent/hasher.hpp"
|
#include "libtorrent/hasher.hpp"
|
||||||
#include "libtorrent/entry.hpp"
|
#include "libtorrent/entry.hpp"
|
||||||
@ -95,20 +96,6 @@ namespace
|
|||||||
, tracker_failed_max = 5
|
, 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
|
struct find_peer_by_ip
|
||||||
{
|
{
|
||||||
find_peer_by_ip(tcp::endpoint const& a, const torrent* t)
|
find_peer_by_ip(tcp::endpoint const& a, const torrent* t)
|
||||||
@ -160,23 +147,18 @@ namespace libtorrent
|
|||||||
, entry const* resume_data
|
, entry const* resume_data
|
||||||
, int seq
|
, int seq
|
||||||
, bool auto_managed)
|
, bool auto_managed)
|
||||||
: m_torrent_file(tf)
|
: m_policy(this)
|
||||||
, m_abort(false)
|
, m_active_time(seconds(0))
|
||||||
, m_paused(paused)
|
, m_seeding_time(seconds(0))
|
||||||
, m_just_paused(false)
|
, m_total_uploaded(0)
|
||||||
, m_auto_managed(auto_managed)
|
, m_total_downloaded(0)
|
||||||
|
, m_started(time_now())
|
||||||
|
, m_last_scrape(min_time())
|
||||||
|
, m_torrent_file(tf)
|
||||||
, m_event(tracker_request::started)
|
, m_event(tracker_request::started)
|
||||||
, m_block_size(0)
|
|
||||||
, m_storage(0)
|
, m_storage(0)
|
||||||
, m_next_request(time_now())
|
, m_next_request(time_now())
|
||||||
, m_duration(1800)
|
|
||||||
, m_complete(-1)
|
|
||||||
, m_incomplete(-1)
|
|
||||||
, m_host_resolver(ses.m_io_service)
|
, 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)
|
, m_announce_timer(ses.m_io_service)
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
, m_last_dht_announce(time_now() - minutes(15))
|
, m_last_dht_announce(time_now() - minutes(15))
|
||||||
@ -184,35 +166,41 @@ namespace libtorrent
|
|||||||
, m_ses(ses)
|
, m_ses(ses)
|
||||||
, m_picker(0)
|
, m_picker(0)
|
||||||
, m_trackers(m_torrent_file->trackers())
|
, 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_failed_bytes(0)
|
||||||
, m_total_redundant_bytes(0)
|
, m_total_redundant_bytes(0)
|
||||||
, m_net_interface(net_interface.address(), 0)
|
, m_net_interface(net_interface.address(), 0)
|
||||||
, m_save_path(complete(save_path))
|
, m_save_path(complete(save_path))
|
||||||
, m_storage_mode(storage_mode)
|
, m_storage_mode(storage_mode)
|
||||||
, m_state(torrent_status::queued_for_checking)
|
, 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_settings(ses.settings())
|
||||||
, m_storage_constructor(sc)
|
, 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_max_uploads((std::numeric_limits<int>::max)())
|
||||||
, m_num_uploads(0)
|
, m_num_uploads(0)
|
||||||
, m_max_connections((std::numeric_limits<int>::max)())
|
, m_max_connections((std::numeric_limits<int>::max)())
|
||||||
|
, m_block_size(block_size)
|
||||||
|
, m_complete(-1)
|
||||||
|
, m_incomplete(-1)
|
||||||
, m_deficit_counter(0)
|
, m_deficit_counter(0)
|
||||||
, m_policy(this)
|
, m_duration(1800)
|
||||||
, m_sequence_number(seq)
|
, m_sequence_number(seq)
|
||||||
, m_active_time(seconds(0))
|
, m_last_working_tracker(-1)
|
||||||
, m_seeding_time(seconds(0))
|
, m_currently_trying_tracker(0)
|
||||||
, m_total_uploaded(0)
|
, m_failed_trackers(0)
|
||||||
, m_total_downloaded(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;
|
if (resume_data) m_resume_data = *resume_data;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@ -234,58 +222,59 @@ namespace libtorrent
|
|||||||
, entry const* resume_data
|
, entry const* resume_data
|
||||||
, int seq
|
, int seq
|
||||||
, bool auto_managed)
|
, bool auto_managed)
|
||||||
: m_torrent_file(new torrent_info(info_hash))
|
: m_policy(this)
|
||||||
, m_abort(false)
|
, m_active_time(seconds(0))
|
||||||
, m_paused(paused)
|
, m_seeding_time(seconds(0))
|
||||||
, m_just_paused(false)
|
, m_total_uploaded(0)
|
||||||
, m_auto_managed(auto_managed)
|
, 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_event(tracker_request::started)
|
||||||
, m_block_size(0)
|
|
||||||
, m_storage(0)
|
, m_storage(0)
|
||||||
, m_next_request(time_now())
|
, m_next_request(time_now())
|
||||||
, m_duration(1800)
|
|
||||||
, m_complete(-1)
|
|
||||||
, m_incomplete(-1)
|
|
||||||
, m_host_resolver(ses.m_io_service)
|
, 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)
|
, m_announce_timer(ses.m_io_service)
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
, m_last_dht_announce(time_now() - minutes(15))
|
, m_last_dht_announce(time_now() - minutes(15))
|
||||||
#endif
|
#endif
|
||||||
, m_ses(ses)
|
, m_ses(ses)
|
||||||
, m_picker(0)
|
, 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_failed_bytes(0)
|
||||||
, m_total_redundant_bytes(0)
|
, m_total_redundant_bytes(0)
|
||||||
, m_net_interface(net_interface.address(), 0)
|
, m_net_interface(net_interface.address(), 0)
|
||||||
, m_save_path(complete(save_path))
|
, m_save_path(complete(save_path))
|
||||||
, m_storage_mode(storage_mode)
|
, m_storage_mode(storage_mode)
|
||||||
, m_state(torrent_status::queued_for_checking)
|
, 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_settings(ses.settings())
|
||||||
, m_storage_constructor(sc)
|
, 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_max_uploads((std::numeric_limits<int>::max)())
|
||||||
, m_num_uploads(0)
|
, m_num_uploads(0)
|
||||||
, m_max_connections((std::numeric_limits<int>::max)())
|
, m_max_connections((std::numeric_limits<int>::max)())
|
||||||
|
, m_block_size(block_size)
|
||||||
|
, m_complete(-1)
|
||||||
|
, m_incomplete(-1)
|
||||||
, m_deficit_counter(0)
|
, m_deficit_counter(0)
|
||||||
, m_policy(this)
|
, m_duration(1800)
|
||||||
, m_sequence_number(seq)
|
, m_sequence_number(seq)
|
||||||
, m_active_time(seconds(0))
|
, m_last_working_tracker(-1)
|
||||||
, m_seeding_time(seconds(0))
|
, m_currently_trying_tracker(0)
|
||||||
, m_total_uploaded(0)
|
, m_failed_trackers(0)
|
||||||
, m_total_downloaded(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;
|
if (resume_data) m_resume_data = *resume_data;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@ -307,7 +296,7 @@ namespace libtorrent
|
|||||||
boost::weak_ptr<torrent> self(shared_from_this());
|
boost::weak_ptr<torrent> self(shared_from_this());
|
||||||
if (m_torrent_file->is_valid()) init();
|
if (m_torrent_file->is_valid()) init();
|
||||||
if (m_abort) return;
|
if (m_abort) return;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_announce_timer.expires_from_now(seconds(1), ec);
|
m_announce_timer.expires_from_now(seconds(1), ec);
|
||||||
m_announce_timer.async_wait(
|
m_announce_timer.async_wait(
|
||||||
bind(&torrent::on_announce_disp, self, _1));
|
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_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
|
||||||
, m_storage_mode);
|
, m_storage_mode);
|
||||||
m_storage = m_owning_storage.get();
|
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_picker.reset(new piece_picker(
|
||||||
m_torrent_file->piece_length() / m_block_size
|
m_torrent_file->piece_length() / m_block_size
|
||||||
, int((m_torrent_file->total_size()+m_block_size-1)/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();
|
files_checked();
|
||||||
@ -654,6 +649,8 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
m_have_pieces[j.offset] = true;
|
m_have_pieces[j.offset] = true;
|
||||||
++m_num_pieces;
|
++m_num_pieces;
|
||||||
|
TORRENT_ASSERT(m_picker);
|
||||||
|
m_picker->we_have(j.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we're not done checking yet
|
// we're not done checking yet
|
||||||
@ -673,7 +670,7 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
|
|
||||||
void torrent::on_announce_disp(boost::weak_ptr<torrent> p
|
void torrent::on_announce_disp(boost::weak_ptr<torrent> p
|
||||||
, asio::error_code const& e)
|
, error_code const& e)
|
||||||
{
|
{
|
||||||
if (e) return;
|
if (e) return;
|
||||||
boost::shared_ptr<torrent> t = p.lock();
|
boost::shared_ptr<torrent> t = p.lock();
|
||||||
@ -687,7 +684,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
boost::weak_ptr<torrent> self(shared_from_this());
|
boost::weak_ptr<torrent> self(shared_from_this());
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
if (!m_torrent_file->priv())
|
if (!m_torrent_file->priv())
|
||||||
{
|
{
|
||||||
// announce on local network every 5 minutes
|
// announce on local network every 5 minutes
|
||||||
@ -759,6 +756,8 @@ namespace libtorrent
|
|||||||
req.url = m_trackers[m_currently_trying_tracker].url;
|
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
|
m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
|
||||||
, tracker_login(), m_ses.m_listen_interface.address(), shared_from_this());
|
, tracker_login(), 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
|
// 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 (complete >= 0) m_complete = complete;
|
||||||
if (incomplete >= 0) m_incomplete = incomplete;
|
if (incomplete >= 0) m_incomplete = incomplete;
|
||||||
|
if (complete >= 0 && incomplete >= 0)
|
||||||
|
m_last_scrape = time_now();
|
||||||
|
|
||||||
// connect to random peers from the list
|
// connect to random peers from the list
|
||||||
std::random_shuffle(peer_list.begin(), peer_list.end());
|
std::random_shuffle(peer_list.begin(), peer_list.end());
|
||||||
@ -865,7 +866,7 @@ namespace libtorrent
|
|||||||
if (i->pid == m_ses.get_peer_id())
|
if (i->pid == m_ses.get_peer_id())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
tcp::endpoint a(address::from_string(i->ip, ec), i->port);
|
tcp::endpoint a(address::from_string(i->ip, ec), i->port);
|
||||||
|
|
||||||
if (ec)
|
if (ec)
|
||||||
@ -875,7 +876,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
tcp::resolver::query q(i->ip, boost::lexical_cast<std::string>(i->port));
|
tcp::resolver::query q(i->ip, boost::lexical_cast<std::string>(i->port));
|
||||||
m_host_resolver.async_resolve(q,
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -905,7 +906,7 @@ namespace libtorrent
|
|||||||
m_got_tracker_response = true;
|
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)
|
, peer_id pid)
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
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));
|
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
|
||||||
|
|
||||||
m_owning_storage = 0;
|
m_owning_storage = 0;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_announce_timer.cancel(ec);
|
m_announce_timer.cancel(ec);
|
||||||
m_host_resolver.cancel();
|
m_host_resolver.cancel();
|
||||||
}
|
}
|
||||||
@ -1487,9 +1488,8 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
if (is_seed())
|
if (is_seed())
|
||||||
{
|
{
|
||||||
|
m_state = torrent_status::seeding;
|
||||||
m_picker.reset();
|
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
|
// the torrent just became finished
|
||||||
if (is_finished() && !was_finished)
|
if (is_finished() && !was_finished)
|
||||||
finished();
|
finished();
|
||||||
|
else if (!is_finished() && was_finished)
|
||||||
|
resume_download();
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent::filter_piece(int index, bool filter)
|
void torrent::filter_piece(int index, bool filter)
|
||||||
@ -1912,9 +1914,20 @@ namespace libtorrent
|
|||||||
std::string hostname;
|
std::string hostname;
|
||||||
int port;
|
int port;
|
||||||
std::string path;
|
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);
|
= 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
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
if (protocol != "http" && protocol != "https")
|
if (protocol != "http" && protocol != "https")
|
||||||
#else
|
#else
|
||||||
@ -1968,6 +1981,18 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
else
|
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));
|
tcp::resolver::query q(hostname, boost::lexical_cast<std::string>(port));
|
||||||
m_host_resolver.async_resolve(q,
|
m_host_resolver.async_resolve(q,
|
||||||
bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url
|
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)
|
, std::string url)
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
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))
|
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(
|
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
|
// the name lookup failed for the http host. Don't try
|
||||||
@ -2010,9 +2033,21 @@ namespace libtorrent
|
|||||||
using boost::tuples::ignore;
|
using boost::tuples::ignore;
|
||||||
std::string hostname;
|
std::string hostname;
|
||||||
int port;
|
int port;
|
||||||
boost::tie(ignore, ignore, hostname, port, ignore)
|
char const* error;
|
||||||
|
boost::tie(ignore, ignore, hostname, port, ignore, error)
|
||||||
= parse_url_components(url);
|
= 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_ip_filter.access(a.address()) & ip_filter::blocked)
|
||||||
{
|
{
|
||||||
if (m_ses.m_alerts.should_post(alert::info))
|
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));
|
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)
|
, std::string url, tcp::endpoint proxy)
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
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;
|
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)
|
if (out_ports.first > 0 && out_ports.second >= out_ports.first)
|
||||||
s->bind(tcp::endpoint(address(), m_ses.next_port()), ec);
|
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
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
(*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << e.what() << "\n";
|
(*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << e.what() << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
c->disconnect(e.what(), 1);
|
||||||
// TODO: post an error alert!
|
|
||||||
c->disconnect(e.what());
|
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
, intrusive_ptr<peer_connection> p) const
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
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);
|
m_active_time = seconds((e != 0 && e->type() == entry::int_t)?e->integer():0);
|
||||||
e = rd.find_key("seeding_time");
|
e = rd.find_key("seeding_time");
|
||||||
m_seeding_time = seconds((e != 0 && e->type() == entry::int_t)?e->integer():0);
|
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
|
void torrent::write_resume_data(entry& ret) const
|
||||||
@ -2299,6 +2345,16 @@ namespace libtorrent
|
|||||||
|
|
||||||
ret["active_time"] = total_seconds(m_active_time);
|
ret["active_time"] = total_seconds(m_active_time);
|
||||||
ret["seeding_time"] = total_seconds(m_seeding_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"
|
ret["allocation"] = m_storage_mode == storage_mode_sparse?"sparse"
|
||||||
:m_storage_mode == storage_mode_allocate?"full":"compact";
|
:m_storage_mode == storage_mode_allocate?"full":"compact";
|
||||||
@ -2369,7 +2425,7 @@ namespace libtorrent
|
|||||||
for (policy::const_iterator i = m_policy.begin_peer()
|
for (policy::const_iterator i = m_policy.begin_peer()
|
||||||
, end(m_policy.end_peer()); i != end; ++i)
|
, end(m_policy.end_peer()); i != end; ++i)
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
if (i->second.banned)
|
if (i->second.banned)
|
||||||
{
|
{
|
||||||
tcp::endpoint ip = i->second.ip;
|
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);
|
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s);
|
||||||
TORRENT_ASSERT(ret);
|
TORRENT_ASSERT(ret);
|
||||||
std::pair<int, int> const& out_ports = m_ses.settings().outgoing_ports;
|
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)
|
if (out_ports.first > 0 && out_ports.second >= out_ports.first)
|
||||||
s->bind(tcp::endpoint(address(), m_ses.next_port()), ec);
|
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
|
// add the newly connected peer to this torrent's peer list
|
||||||
m_connections.insert(boost::get_pointer(c));
|
m_connections.insert(boost::get_pointer(c));
|
||||||
m_ses.m_connections.insert(c);
|
m_ses.m_connections.insert(c);
|
||||||
|
peerinfo->connection = c.get();
|
||||||
c->start();
|
c->start();
|
||||||
|
|
||||||
int timeout = settings().peer_connect_timeout;
|
int timeout = settings().peer_connect_timeout;
|
||||||
@ -2595,11 +2652,10 @@ namespace libtorrent
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
peerinfo->connection = c.get();
|
|
||||||
return true;
|
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;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
@ -2683,7 +2739,7 @@ namespace libtorrent
|
|||||||
TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
|
TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
|
||||||
peer_iterator ci = m_connections.insert(p).first;
|
peer_iterator ci = m_connections.insert(p).first;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint(ec) || ec);
|
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint(ec) || ec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2698,7 +2754,8 @@ namespace libtorrent
|
|||||||
return int(m_connections.size()) < m_max_connections
|
return int(m_connections.size()) < m_max_connections
|
||||||
&& !m_paused
|
&& !m_paused
|
||||||
&& m_state != torrent_status::checking_files
|
&& 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;
|
&& 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
|
int torrent::bandwidth_throttle(int channel) const
|
||||||
{
|
{
|
||||||
return m_bandwidth_limit[channel].throttle();
|
return m_bandwidth_limit[channel].throttle();
|
||||||
@ -2844,7 +2966,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
peer_connection* p = *i;
|
peer_connection* p = *i;
|
||||||
TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
|
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
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
(*p->m_logger) << "*** SEED, CLOSING CONNECTION\n";
|
(*p->m_logger) << "*** SEED, CLOSING CONNECTION\n";
|
||||||
@ -2853,14 +2975,23 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::for_each(seeds.begin(), seeds.end()
|
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);
|
TORRENT_ASSERT(m_storage);
|
||||||
// we need to keep the object alive during this operation
|
// we need to keep the object alive during this operation
|
||||||
m_storage->async_release_files(
|
m_storage->async_release_files(
|
||||||
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
|
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)
|
// called when torrent is complete (all pieces downloaded)
|
||||||
void torrent::completed()
|
void torrent::completed()
|
||||||
{
|
{
|
||||||
@ -2900,7 +3031,7 @@ namespace libtorrent
|
|||||||
if ((unsigned)m_currently_trying_tracker >= m_trackers.size())
|
if ((unsigned)m_currently_trying_tracker >= m_trackers.size())
|
||||||
{
|
{
|
||||||
int delay = tracker_retry_delay_min
|
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_retry_delay_max - tracker_retry_delay_min)
|
||||||
/ tracker_failed_max;
|
/ tracker_failed_max;
|
||||||
|
|
||||||
@ -2968,8 +3099,6 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
m_state = torrent_status::seeding;
|
m_state = torrent_status::seeding;
|
||||||
m_picker.reset();
|
m_picker.reset();
|
||||||
if (m_ses.settings().free_torrent_hashes)
|
|
||||||
m_torrent_file->seed_free();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_connections_initialized)
|
if (!m_connections_initialized)
|
||||||
@ -3285,27 +3414,59 @@ namespace libtorrent
|
|||||||
m_ses.m_auto_manage_time_scaler = 0;
|
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);
|
if (!is_seed()) return 0;
|
||||||
int downloading = total_seconds(m_active_time) - seeding;
|
|
||||||
|
|
||||||
// if the seed time limit is set to less than 60 minutes
|
int ret = 0;
|
||||||
// use 60 minutes, to avoid oscillation
|
|
||||||
float ret = seeding / float((std::max)(s.seed_time_limit, 60 * 60));
|
|
||||||
|
|
||||||
// if it took less than 30 minutes to download, disregard the
|
ptime now(time_now());
|
||||||
// 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));
|
|
||||||
|
|
||||||
|
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());
|
size_type downloaded = (std::max)(m_total_downloaded, m_torrent_file->total_size());
|
||||||
if (downloaded > 0 && s.share_ratio_limit >= 1.f)
|
if (seed_time < s.seed_time_limit
|
||||||
ret = (std::max)(ret, float(m_total_uploaded) / downloaded
|
&& (seed_time > 1 && download_time / float(seed_time) < s.seed_time_ratio_limit)
|
||||||
/ s.share_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;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -3402,6 +3563,7 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_paused = false;
|
m_paused = false;
|
||||||
|
m_started = time_now();
|
||||||
|
|
||||||
// tell the tracker that we're back
|
// tell the tracker that we're back
|
||||||
m_event = tracker_request::started;
|
m_event = tracker_request::started;
|
||||||
@ -3489,6 +3651,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
peer_connection* p = *i;
|
peer_connection* p = *i;
|
||||||
++i;
|
++i;
|
||||||
|
p->calc_ip_overhead();
|
||||||
m_stat += p->statistics();
|
m_stat += p->statistics();
|
||||||
// updates the peer connection's ul/dl bandwidth
|
// updates the peer connection's ul/dl bandwidth
|
||||||
// resource requests
|
// resource requests
|
||||||
@ -3504,8 +3667,7 @@ namespace libtorrent
|
|||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
(*p->m_logger) << "**ERROR**: " << e.what() << "\n";
|
(*p->m_logger) << "**ERROR**: " << e.what() << "\n";
|
||||||
#endif
|
#endif
|
||||||
p->set_failed();
|
p->disconnect(e.what(), 1);
|
||||||
p->disconnect(e.what());
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -3643,8 +3805,18 @@ namespace libtorrent
|
|||||||
, m_have_pieces.end()
|
, m_have_pieces.end()
|
||||||
, 0) == m_num_pieces);
|
, 0) == m_num_pieces);
|
||||||
|
|
||||||
|
ptime now = time_now();
|
||||||
|
|
||||||
torrent_status st;
|
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.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();
|
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_peers = m_policy.num_peers();
|
||||||
st.list_seeds = m_policy.num_seeds();
|
st.list_seeds = m_policy.num_seeds();
|
||||||
st.connect_candidates = m_policy.num_connect_candidates();
|
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_upload = m_total_uploaded;
|
||||||
st.all_time_download = m_total_downloaded;
|
st.all_time_download = m_total_downloaded;
|
||||||
@ -3668,6 +3840,7 @@ namespace libtorrent
|
|||||||
st.num_incomplete = m_incomplete;
|
st.num_incomplete = m_incomplete;
|
||||||
st.paused = m_paused;
|
st.paused = m_paused;
|
||||||
boost::tie(st.total_done, st.total_wanted_done) = bytes_done();
|
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);
|
TORRENT_ASSERT(st.total_done >= st.total_wanted_done);
|
||||||
|
|
||||||
// payload transfer
|
// payload transfer
|
||||||
@ -3691,7 +3864,7 @@ namespace libtorrent
|
|||||||
st.upload_payload_rate = m_stat.upload_payload_rate();
|
st.upload_payload_rate = m_stat.upload_payload_rate();
|
||||||
|
|
||||||
st.next_announce = boost::posix_time::seconds(
|
st.next_announce = boost::posix_time::seconds(
|
||||||
total_seconds(next_announce() - time_now()));
|
total_seconds(next_announce() - now));
|
||||||
if (st.next_announce.is_negative())
|
if (st.next_announce.is_negative())
|
||||||
st.next_announce = boost::posix_time::seconds(0);
|
st.next_announce = boost::posix_time::seconds(0);
|
||||||
|
|
||||||
@ -3713,7 +3886,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (!valid_metadata())
|
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;
|
st.state = torrent_status::connecting_to_tracker;
|
||||||
else
|
else
|
||||||
st.state = torrent_status::downloading_metadata;
|
st.state = torrent_status::downloading_metadata;
|
||||||
@ -3728,6 +3901,7 @@ namespace libtorrent
|
|||||||
// fill in status that depends on metadata
|
// fill in status that depends on metadata
|
||||||
|
|
||||||
st.total_wanted = m_torrent_file->total_size();
|
st.total_wanted = m_torrent_file->total_size();
|
||||||
|
TORRENT_ASSERT(st.total_wanted >= 0);
|
||||||
|
|
||||||
if (m_picker.get() && (m_picker->num_filtered() > 0
|
if (m_picker.get() && (m_picker->num_filtered() > 0
|
||||||
|| m_picker->num_have_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.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
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/lexical_cast.hpp>
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/next_prior.hpp>
|
#include <boost/next_prior.hpp>
|
||||||
#include <boost/bind.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)
|
, std::string const& root_dir)
|
||||||
{
|
{
|
||||||
entry const* length = dict.find_key("length");
|
lazy_entry const* length = dict.dict_find("length");
|
||||||
if (length == 0 || length->type() != entry::int_t)
|
if (length == 0 || length->type() != lazy_entry::int_t)
|
||||||
return false;
|
return false;
|
||||||
target.size = length->integer();
|
target.size = length->int_value();
|
||||||
target.path = root_dir;
|
target.path = root_dir;
|
||||||
target.file_base = 0;
|
target.file_base = 0;
|
||||||
|
|
||||||
@ -173,27 +174,19 @@ namespace
|
|||||||
// because if it exists, it is more
|
// because if it exists, it is more
|
||||||
// likely to be correctly encoded
|
// likely to be correctly encoded
|
||||||
|
|
||||||
const entry::list_type* list = 0;
|
lazy_entry const* p = dict.dict_find("path.utf-8");
|
||||||
entry const* p8 = dict.find_key("path.utf-8");
|
if (p == 0 || p->type() != lazy_entry::list_t)
|
||||||
if (p8 != 0 && p8->type() == entry::list_t)
|
p = dict.dict_find("path");
|
||||||
{
|
if (p == 0 || p->type() != lazy_entry::list_t)
|
||||||
list = &p8->list();
|
return false;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entry const* p = dict.find_key("path");
|
|
||||||
if (p == 0 || p->type() != entry::list_t)
|
|
||||||
return false;
|
|
||||||
list = &p->list();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (entry::list_type::const_iterator i = list->begin();
|
for (int i = 0, end(p->list_size()); i < end; ++i)
|
||||||
i != list->end(); ++i)
|
|
||||||
{
|
{
|
||||||
if (i->type() != entry::string_t)
|
if (p->list_at(i)->type() != lazy_entry::string_t)
|
||||||
return false;
|
return false;
|
||||||
if (i->string() != "..")
|
std::string path_element = p->list_at(i)->string_value();
|
||||||
target.path /= i->string();
|
if (path_element != "..")
|
||||||
|
target.path /= path_element;
|
||||||
}
|
}
|
||||||
verify_encoding(target);
|
verify_encoding(target);
|
||||||
if (target.path.is_complete())
|
if (target.path.is_complete())
|
||||||
@ -201,14 +194,15 @@ namespace
|
|||||||
return true;
|
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)
|
, std::string const& root_dir)
|
||||||
{
|
{
|
||||||
size_type offset = 0;
|
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());
|
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;
|
return false;
|
||||||
target.back().offset = offset;
|
target.back().offset = offset;
|
||||||
offset += target.back().size;
|
offset += target.back().size;
|
||||||
@ -231,25 +225,65 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
|
|
||||||
// standard constructor that parses a torrent file
|
// 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_num_pieces(0)
|
||||||
, m_creation_date(pt::ptime(pt::not_a_date_time))
|
, m_creation_date(pt::ptime(pt::not_a_date_time))
|
||||||
, m_multifile(false)
|
, m_multifile(false)
|
||||||
, m_private(false)
|
, m_private(false)
|
||||||
, m_extra_info(entry::dictionary_t)
|
, m_info_section_size(0)
|
||||||
#ifndef NDEBUG
|
, m_piece_hashes(0)
|
||||||
, m_half_metadata(false)
|
{
|
||||||
|
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
|
#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;
|
std::string error;
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
if (!read_torrent_info(torrent_file, error))
|
if (!parse_torrent_file(torrent_file, error))
|
||||||
throw invalid_torrent_file();
|
throw invalid_torrent_file();
|
||||||
#else
|
#else
|
||||||
read_torrent_info(torrent_file, error);
|
read_torrent_info(torrent_file, error);
|
||||||
#endif
|
#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
|
// constructor used for creating new torrents
|
||||||
// will not contain any hashes, comments, creation date
|
// will not contain any hashes, comments, creation date
|
||||||
// just the necessary to use it with piece manager
|
// just the necessary to use it with piece manager
|
||||||
@ -263,10 +297,8 @@ namespace libtorrent
|
|||||||
, m_creation_date(pt::second_clock::universal_time())
|
, m_creation_date(pt::second_clock::universal_time())
|
||||||
, m_multifile(false)
|
, m_multifile(false)
|
||||||
, m_private(false)
|
, m_private(false)
|
||||||
, m_extra_info(entry::dictionary_t)
|
, m_info_section_size(0)
|
||||||
#ifndef NDEBUG
|
, m_piece_hashes(0)
|
||||||
, m_half_metadata(false)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,13 +311,35 @@ namespace libtorrent
|
|||||||
, m_creation_date(pt::second_clock::universal_time())
|
, m_creation_date(pt::second_clock::universal_time())
|
||||||
, m_multifile(false)
|
, m_multifile(false)
|
||||||
, m_private(false)
|
, m_private(false)
|
||||||
, m_extra_info(entry::dictionary_t)
|
, m_info_section_size(0)
|
||||||
#ifndef NDEBUG
|
, m_piece_hashes(0)
|
||||||
, m_half_metadata(false)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
torrent_info::~torrent_info()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -294,9 +348,8 @@ namespace libtorrent
|
|||||||
using std::swap;
|
using std::swap;
|
||||||
m_urls.swap(ti.m_urls);
|
m_urls.swap(ti.m_urls);
|
||||||
m_url_seeds.swap(ti.m_url_seeds);
|
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_files);
|
||||||
|
m_files.swap(ti.m_remapped_files);
|
||||||
m_nodes.swap(ti.m_nodes);
|
m_nodes.swap(ti.m_nodes);
|
||||||
swap(m_num_pieces, ti.m_num_pieces);
|
swap(m_num_pieces, ti.m_num_pieces);
|
||||||
swap(m_info_hash, ti.m_info_hash);
|
swap(m_info_hash, ti.m_info_hash);
|
||||||
@ -306,83 +359,51 @@ namespace libtorrent
|
|||||||
m_created_by.swap(ti.m_created_by);
|
m_created_by.swap(ti.m_created_by);
|
||||||
swap(m_multifile, ti.m_multifile);
|
swap(m_multifile, ti.m_multifile);
|
||||||
swap(m_private, ti.m_private);
|
swap(m_private, ti.m_private);
|
||||||
m_extra_info.swap(ti.m_extra_info);
|
swap(m_info_section, ti.m_info_section);
|
||||||
#ifndef NDEBUG
|
swap(m_info_section_size, ti.m_info_section_size);
|
||||||
swap(m_half_metadata, ti.m_half_metadata);
|
swap(m_piece_hashes, ti.m_piece_hashes);
|
||||||
#endif
|
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
|
if (info.type() != lazy_entry::dict_t)
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
error = "'info' entry is not a dictionary";
|
error = "'info' entry is not a dictionary";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode the info-field in order to calculate it's sha1-hash
|
// hash the info-field to calculate info-hash
|
||||||
std::vector<char> buf;
|
|
||||||
bencode(std::back_inserter(buf), info);
|
|
||||||
hasher h;
|
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();
|
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
|
// extract piece length
|
||||||
entry const* piece_length = info.find_key("piece length");
|
m_piece_length = info.dict_find_int_value("piece length", -1);
|
||||||
if (piece_length == 0 || piece_length->type() != entry::int_t)
|
if (m_piece_length <= 0)
|
||||||
{
|
{
|
||||||
error = "invalid or missing 'piece length' entry in torrent file";
|
error = "invalid or missing 'piece length' entry in torrent file";
|
||||||
return false;
|
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;
|
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;
|
fs::path tmp = m_name;
|
||||||
if (tmp.is_complete())
|
if (tmp.is_complete())
|
||||||
{
|
{
|
||||||
@ -401,32 +422,31 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
if (m_name == ".." || m_name == ".")
|
if (m_name == ".." || m_name == ".")
|
||||||
{
|
{
|
||||||
|
|
||||||
error = "invalid 'name' of torrent (possible exploit attempt)";
|
error = "invalid 'name' of torrent (possible exploit attempt)";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract file list
|
// extract file list
|
||||||
entry const* i = info.find_key("files");
|
lazy_entry const* i = info.dict_find_list("files");
|
||||||
if (i == 0)
|
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
|
// if there's no list of files, there has to be a length
|
||||||
// field.
|
// field.
|
||||||
file_entry e;
|
file_entry e;
|
||||||
e.path = m_name;
|
e.path = m_name;
|
||||||
e.offset = 0;
|
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_files.push_back(e);
|
||||||
|
m_multifile = false;
|
||||||
}
|
}
|
||||||
else
|
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";
|
error = "failed to parse files from torrent file";
|
||||||
return false;
|
return false;
|
||||||
@ -443,84 +463,51 @@ namespace libtorrent
|
|||||||
// we want this division to round upwards, that's why we have the
|
// we want this division to round upwards, that's why we have the
|
||||||
// extra addition
|
// extra addition
|
||||||
|
|
||||||
entry const* pieces_ent = info.find_key("pieces");
|
m_num_pieces = static_cast<int>((m_total_size + m_piece_length - 1) / m_piece_length);
|
||||||
if (pieces_ent == 0 || pieces_ent->type() != entry::string_t)
|
|
||||||
|
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";
|
error = "invalid or missing 'pieces' entry in torrent file";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_num_pieces = static_cast<int>((m_total_size + m_piece_length - 1) / m_piece_length);
|
if (pieces->string_length() != m_num_pieces * 20)
|
||||||
m_piece_hash.resize(m_num_pieces);
|
|
||||||
const std::string& hash_string = pieces_ent->string();
|
|
||||||
|
|
||||||
if ((int)hash_string.length() != m_num_pieces * 20)
|
|
||||||
{
|
{
|
||||||
error = "incorrect number of piece hashes in torrent file";
|
error = "incorrect number of piece hashes in torrent file";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < m_num_pieces; ++i)
|
m_piece_hashes = m_info_section.get() + (pieces->string_ptr() - section.first);
|
||||||
std::copy(
|
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
|
||||||
hash_string.begin() + i*20
|
TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
|
||||||
, hash_string.begin() + (i+1)*20
|
|
||||||
, m_piece_hash[i].begin());
|
|
||||||
|
|
||||||
for (entry::dictionary_type::const_iterator i = info.dict().begin()
|
m_private = info.dict_find_int_value("private", 0);
|
||||||
, 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
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extracts information from a libtorrent file and fills in the structures in
|
bool torrent_info::parse_torrent_file(lazy_entry const& torrent_file, std::string& error)
|
||||||
// the torrent object
|
|
||||||
bool torrent_info::read_torrent_info(const entry& 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";
|
error = "torrent file is not a dictionary";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract the url of the tracker
|
// extract the url of the tracker
|
||||||
entry const* i = torrent_file.find_key("announce-list");
|
lazy_entry const* i = torrent_file.dict_find_list("announce-list");
|
||||||
if (i && i->type() == entry::list_t)
|
if (i)
|
||||||
{
|
{
|
||||||
const entry::list_type& l = i->list();
|
m_urls.reserve(i->list_size());
|
||||||
for (entry::list_type::const_iterator j = l.begin(); j != l.end(); ++j)
|
for (int j = 0, end(i->list_size()); j < end; ++j)
|
||||||
{
|
{
|
||||||
if (j->type() != entry::list_t) break;
|
lazy_entry const* tier = i->list_at(j);
|
||||||
const entry::list_type& ll = j->list();
|
if (tier->type() != lazy_entry::list_t) continue;
|
||||||
for (entry::list_type::const_iterator k = ll.begin(); k != ll.end(); ++k)
|
for (int k = 0, end(tier->list_size()); k < end; ++k)
|
||||||
{
|
{
|
||||||
if (k->type() != entry::string_t) break;
|
announce_entry e(tier->list_string_value_at(k));
|
||||||
announce_entry e(k->string());
|
if (e.url.empty()) continue;
|
||||||
e.tier = (int)std::distance(l.begin(), j);
|
e.tier = j;
|
||||||
m_urls.push_back(e);
|
m_urls.push_back(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -541,71 +528,62 @@ namespace libtorrent
|
|||||||
std::random_shuffle(start, stop);
|
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");
|
lazy_entry const* nodes = torrent_file.dict_find_list("nodes");
|
||||||
if (nodes && nodes->type() == entry::list_t)
|
if (nodes)
|
||||||
{
|
{
|
||||||
entry::list_type const& list = nodes->list();
|
for (int i = 0, end(nodes->list_size()); i < end; ++i)
|
||||||
for (entry::list_type::const_iterator i(list.begin())
|
|
||||||
, end(list.end()); i != end; ++i)
|
|
||||||
{
|
{
|
||||||
if (i->type() != entry::list_t) continue;
|
lazy_entry const* n = nodes->list_at(i);
|
||||||
entry::list_type const& l = i->list();
|
if (n->type() != lazy_entry::list_t
|
||||||
entry::list_type::const_iterator iter = l.begin();
|
|| n->list_size() < 2
|
||||||
if (l.size() < 1) continue;
|
|| n->list_at(0)->type() != lazy_entry::string_t
|
||||||
if (iter->type() != entry::string_t) continue;
|
|| n->list_at(1)->type() != lazy_entry::int_t)
|
||||||
std::string const& hostname = iter->string();
|
continue;
|
||||||
++iter;
|
m_nodes.push_back(std::make_pair(
|
||||||
int port = 6881;
|
n->list_at(0)->string_value()
|
||||||
if (iter->type() != entry::int_t) continue;
|
, int(n->list_at(1)->int_value())));
|
||||||
if (l.end() != iter) port = int(iter->integer());
|
|
||||||
m_nodes.push_back(std::make_pair(hostname, port));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract creation date
|
// extract creation date
|
||||||
entry const* creation_date = torrent_file.find_key("creation date");
|
size_type cd = torrent_file.dict_find_int_value("creation date", -1);
|
||||||
if (creation_date && creation_date->type() == entry::int_t)
|
if (cd >= 0)
|
||||||
{
|
{
|
||||||
m_creation_date = pt::ptime(gr::date(1970, gr::Jan, 1))
|
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
|
// if there are any url-seeds, extract them
|
||||||
entry const* url_seeds = torrent_file.find_key("url-list");
|
lazy_entry const* url_seeds = torrent_file.dict_find("url-list");
|
||||||
if (url_seeds && url_seeds->type() == entry::string_t)
|
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 (int i = 0, end(url_seeds->list_size()); i < end; ++i)
|
||||||
for (entry::list_type::const_iterator i = l.begin();
|
|
||||||
i != l.end(); ++i)
|
|
||||||
{
|
{
|
||||||
if (i->type() != entry::string_t) continue;
|
lazy_entry const* url = url_seeds->list_at(i);
|
||||||
m_url_seeds.push_back(i->string());
|
if (url->type() != lazy_entry::string_t) continue;
|
||||||
|
m_url_seeds.push_back(url->string_value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract comment
|
m_comment = torrent_file.dict_find_string_value("comment.utf-8");
|
||||||
if (entry const* e = torrent_file.find_key("comment.utf-8"))
|
if (m_comment.empty()) m_comment = torrent_file.dict_find_string_value("comment");
|
||||||
{ m_comment = e->string(); }
|
|
||||||
else if (entry const* e = torrent_file.find_key("comment"))
|
|
||||||
{ m_comment = e->string(); }
|
|
||||||
|
|
||||||
if (entry const* e = torrent_file.find_key("created by.utf-8"))
|
m_created_by = torrent_file.dict_find_string_value("created by.utf-8");
|
||||||
{ m_created_by = e->string(); }
|
if (m_created_by.empty()) m_created_by = torrent_file.dict_find_string_value("created by");
|
||||||
else if (entry const* e = torrent_file.find_key("created by"))
|
|
||||||
{ m_created_by = e->string(); }
|
|
||||||
|
|
||||||
entry const* info = torrent_file.find_key("info");
|
lazy_entry const* info = torrent_file.dict_find_dict("info");
|
||||||
if (info == 0 || info->type() != entry::dictionary_t)
|
if (info == 0)
|
||||||
{
|
{
|
||||||
error = "missing or invalid 'info' section in torrent file";
|
error = "missing or invalid 'info' section in torrent file";
|
||||||
return false;
|
return false;
|
||||||
@ -634,234 +612,6 @@ namespace libtorrent
|
|||||||
, bind(&announce_entry::tier, _1), bind(&announce_entry::tier, _2)));
|
, 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 -------
|
// ------- start deprecation -------
|
||||||
|
|
||||||
void torrent_info::print(std::ostream& os) const
|
void torrent_info::print(std::ostream& os) const
|
||||||
@ -901,11 +651,6 @@ namespace libtorrent
|
|||||||
return piece_length();
|
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)
|
bool torrent_info::remap_files(std::vector<file_entry> const& map)
|
||||||
{
|
{
|
||||||
size_type offset = 0;
|
size_type offset = 0;
|
||||||
|
|||||||
@ -84,7 +84,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
int timeout = (std::min)(
|
int timeout = (std::min)(
|
||||||
m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
|
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.expires_at(m_read_time + seconds(timeout), ec);
|
||||||
m_timeout.async_wait(bind(
|
m_timeout.async_wait(bind(
|
||||||
&timeout_handler::timeout_callback, self(), _1));
|
&timeout_handler::timeout_callback, self(), _1));
|
||||||
@ -99,11 +99,11 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
m_abort = true;
|
m_abort = true;
|
||||||
m_completion_timeout = 0;
|
m_completion_timeout = 0;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_timeout.cancel(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 (error) return;
|
||||||
if (m_completion_timeout == 0) return;
|
if (m_completion_timeout == 0) return;
|
||||||
@ -125,7 +125,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
int timeout = (std::min)(
|
int timeout = (std::min)(
|
||||||
m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
|
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.expires_at(m_read_time + seconds(timeout), ec);
|
||||||
m_timeout.async_wait(
|
m_timeout.async_wait(
|
||||||
bind(&timeout_handler::timeout_callback, self(), _1));
|
bind(&timeout_handler::timeout_callback, self(), _1));
|
||||||
@ -180,83 +180,6 @@ namespace libtorrent
|
|||||||
m_connections.erase(i);
|
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(
|
void tracker_manager::queue_request(
|
||||||
io_service& ios
|
io_service& ios
|
||||||
, connection_queue& cc
|
, connection_queue& cc
|
||||||
|
|||||||
@ -4,7 +4,11 @@
|
|||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/array.hpp>
|
#include <boost/array.hpp>
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/read.hpp>
|
#include <asio/read.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/asio/read.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace libtorrent;
|
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;
|
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);
|
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;
|
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;
|
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
|
// 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;
|
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()
|
void udp_socket::close()
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_ipv4_sock.close(ec);
|
m_ipv4_sock.close(ec);
|
||||||
m_ipv6_sock.close(ec);
|
m_ipv6_sock.close(ec);
|
||||||
m_socks5_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_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
|
||||||
if (m_ipv6_sock.is_open()) m_ipv6_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)
|
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_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
|
||||||
if (m_ipv6_sock.is_open()) m_ipv6_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)
|
void udp_socket::set_proxy_settings(proxy_settings const& ps)
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socks5_sock.close(ec);
|
m_socks5_sock.close(ec);
|
||||||
m_tunnel_packets = false;
|
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;
|
if (e) return;
|
||||||
m_proxy_addr.address(i->endpoint().address());
|
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()
|
void udp_socket::on_timeout()
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socks5_sock.close(ec);
|
m_socks5_sock.close(ec);
|
||||||
m_connection_ticket = -1;
|
m_connection_ticket = -1;
|
||||||
}
|
}
|
||||||
@ -275,13 +279,13 @@ void udp_socket::on_timeout()
|
|||||||
void udp_socket::on_connect(int ticket)
|
void udp_socket::on_connect(int ticket)
|
||||||
{
|
{
|
||||||
m_connection_ticket = 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.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())
|
m_socks5_sock.async_connect(tcp::endpoint(m_proxy_addr.address(), m_proxy_addr.port())
|
||||||
, boost::bind(&udp_socket::on_connected, this, _1));
|
, 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_cc.done(m_connection_ticket);
|
||||||
m_connection_ticket = -1;
|
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));
|
, 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;
|
if (e) return;
|
||||||
|
|
||||||
@ -316,7 +320,7 @@ void udp_socket::handshake1(asio::error_code const& e)
|
|||||||
, boost::bind(&udp_socket::handshake2, this, _1));
|
, 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;
|
if (e) return;
|
||||||
|
|
||||||
@ -336,7 +340,7 @@ void udp_socket::handshake2(asio::error_code const& e)
|
|||||||
{
|
{
|
||||||
if (m_proxy_settings.username.empty())
|
if (m_proxy_settings.username.empty())
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socks5_sock.close(ec);
|
m_socks5_sock.close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -353,13 +357,13 @@ void udp_socket::handshake2(asio::error_code const& e)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socks5_sock.close(ec);
|
m_socks5_sock.close(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void udp_socket::handshake3(asio::error_code const& e)
|
void udp_socket::handshake3(error_code const& e)
|
||||||
{
|
{
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
|
||||||
@ -367,7 +371,7 @@ void udp_socket::handshake3(asio::error_code const& e)
|
|||||||
, boost::bind(&udp_socket::handshake4, this, _1));
|
, 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;
|
if (e) return;
|
||||||
|
|
||||||
@ -400,7 +404,7 @@ void udp_socket::socks_forward_udp()
|
|||||||
, boost::bind(&udp_socket::connect1, this, _1));
|
, 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;
|
if (e) return;
|
||||||
|
|
||||||
@ -408,7 +412,7 @@ void udp_socket::connect1(asio::error_code const& e)
|
|||||||
, boost::bind(&udp_socket::connect2, this, _1));
|
, 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;
|
if (e) return;
|
||||||
|
|
||||||
|
|||||||
@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "libtorrent/tracker_manager.hpp"
|
#include "libtorrent/tracker_manager.hpp"
|
||||||
|
#include "libtorrent/parse_url.hpp"
|
||||||
#include "libtorrent/udp_tracker_connection.hpp"
|
#include "libtorrent/udp_tracker_connection.hpp"
|
||||||
#include "libtorrent/io.hpp"
|
#include "libtorrent/io.hpp"
|
||||||
|
|
||||||
@ -95,10 +96,18 @@ namespace libtorrent
|
|||||||
|
|
||||||
std::string hostname;
|
std::string hostname;
|
||||||
int port;
|
int port;
|
||||||
|
char const* error;
|
||||||
|
|
||||||
using boost::tuples::ignore;
|
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));
|
udp::resolver::query q(hostname, boost::lexical_cast<std::string>(port));
|
||||||
m_name_lookup.async_resolve(q
|
m_name_lookup.async_resolve(q
|
||||||
, boost::bind(
|
, boost::bind(
|
||||||
@ -113,7 +122,7 @@ namespace libtorrent
|
|||||||
#endif
|
#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)
|
, udp::resolver::iterator i)
|
||||||
{
|
{
|
||||||
if (error == asio::error::operation_aborted) return;
|
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());
|
if (cb) cb->m_tracker_address = tcp::endpoint(target_address.address(), target_address.port());
|
||||||
m_target = target_address;
|
m_target = target_address;
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
|
m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
@ -179,13 +188,13 @@ namespace libtorrent
|
|||||||
|
|
||||||
void udp_tracker_connection::close()
|
void udp_tracker_connection::close()
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socket.close();
|
m_socket.close();
|
||||||
m_name_lookup.cancel();
|
m_name_lookup.cancel();
|
||||||
tracker_connection::close();
|
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)
|
, udp::endpoint const& ep, char const* buf, int size)
|
||||||
{
|
{
|
||||||
// ignore resposes before we've sent any requests
|
// ignore resposes before we've sent any requests
|
||||||
@ -305,7 +314,7 @@ namespace libtorrent
|
|||||||
detail::write_int32(m_transaction_id, ptr); // transaction_id
|
detail::write_int32(m_transaction_id, ptr); // transaction_id
|
||||||
TORRENT_ASSERT(ptr - buf == sizeof(buf));
|
TORRENT_ASSERT(ptr - buf == sizeof(buf));
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socket.send(m_target, buf, 16, ec);
|
m_socket.send(m_target, buf, 16, ec);
|
||||||
m_state = action_connect;
|
m_state = action_connect;
|
||||||
++m_attempts;
|
++m_attempts;
|
||||||
@ -334,7 +343,7 @@ namespace libtorrent
|
|||||||
out += 20;
|
out += 20;
|
||||||
TORRENT_ASSERT(out - buf == sizeof(buf));
|
TORRENT_ASSERT(out - buf == sizeof(buf));
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socket.send(m_target, buf, sizeof(buf), ec);
|
m_socket.send(m_target, buf, sizeof(buf), ec);
|
||||||
m_state = action_scrape;
|
m_state = action_scrape;
|
||||||
++m_attempts;
|
++m_attempts;
|
||||||
@ -494,7 +503,7 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_socket.send(m_target, buf, sizeof(buf), ec);
|
m_socket.send(m_target, buf, sizeof(buf), ec);
|
||||||
m_state = action_announce;
|
m_state = action_announce;
|
||||||
++m_attempts;
|
++m_attempts;
|
||||||
|
|||||||
@ -35,15 +35,20 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
#include "libtorrent/upnp.hpp"
|
#include "libtorrent/upnp.hpp"
|
||||||
#include "libtorrent/io.hpp"
|
#include "libtorrent/io.hpp"
|
||||||
#include "libtorrent/http_tracker_connection.hpp"
|
#include "libtorrent/parse_url.hpp"
|
||||||
#include "libtorrent/xml_parse.hpp"
|
#include "libtorrent/xml_parse.hpp"
|
||||||
#include "libtorrent/connection_queue.hpp"
|
#include "libtorrent/connection_queue.hpp"
|
||||||
#include "libtorrent/enum_net.hpp"
|
#include "libtorrent/enum_net.hpp"
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
|
#if BOOST_VERSION < 103500
|
||||||
#include <asio/ip/host_name.hpp>
|
#include <asio/ip/host_name.hpp>
|
||||||
#include <asio/ip/multicast.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 <boost/thread/mutex.hpp>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
@ -54,12 +59,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
using boost::bind;
|
using boost::bind;
|
||||||
using namespace libtorrent;
|
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
|
upnp::upnp(io_service& ios, connection_queue& cc
|
||||||
, address const& listen_interface, std::string const& user_agent
|
, address const& listen_interface, std::string const& user_agent
|
||||||
, portmap_callback_t const& cb, bool ignore_nonrouters)
|
, 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_refresh_timer(ios)
|
||||||
, m_disabled(false)
|
, m_disabled(false)
|
||||||
, m_closing(false)
|
, m_closing(false)
|
||||||
, m_ignore_outside_network(ignore_nonrouters)
|
, m_ignore_non_routers(ignore_nonrouters)
|
||||||
, m_cc(cc)
|
, m_cc(cc)
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
@ -103,7 +102,7 @@ void upnp::discover_device_impl()
|
|||||||
"MX:3\r\n"
|
"MX:3\r\n"
|
||||||
"\r\n\r\n";
|
"\r\n\r\n";
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
#ifdef TORRENT_DEBUG_UPNP
|
#ifdef TORRENT_DEBUG_UPNP
|
||||||
// simulate packet loss
|
// simulate packet loss
|
||||||
if (m_retry_count & 1)
|
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;
|
if (e) return;
|
||||||
|
|
||||||
@ -254,9 +253,10 @@ void upnp::resend_request(asio::error_code const& e)
|
|||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " ==> connecting to " << d.url << std::endl;
|
<< " ==> connecting to " << d.url << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
if (d.upnp_connection) d.upnp_connection->close();
|
||||||
d.upnp_connection.reset(new http_connection(m_io_service
|
d.upnp_connection.reset(new http_connection(m_io_service
|
||||||
, m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2
|
, 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);
|
d.upnp_connection->get(d.url, seconds(30), 1);
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
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
|
Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0
|
||||||
|
|
||||||
*/
|
*/
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
if (m_ignore_outside_network && !in_local_network(m_io_service, from.address(), 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
|
// this upnp device is filtered because it's not in the
|
||||||
// list of configured routers
|
// list of configured routers
|
||||||
@ -319,13 +345,12 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<ip_interface> const& net = enum_net_interfaces(m_io_service, ec);
|
|
||||||
m_log << time_now_string() << " <== (" << from << ") UPnP device "
|
m_log << time_now_string() << " <== (" << from << ") UPnP device "
|
||||||
"ignored because it's not on our network ";
|
"ignored because it's not a router on our network ";
|
||||||
for (std::vector<ip_interface>::const_iterator i = net.begin()
|
for (std::vector<ip_route>::const_iterator i = routes.begin()
|
||||||
, end(net.end()); i != end; ++i)
|
, end(routes.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
m_log << "(" << i->interface_address << ", " << i->netmask << ") ";
|
m_log << "(" << i->gateway << ", " << i->netmask << ") ";
|
||||||
}
|
}
|
||||||
m_log << std::endl;
|
m_log << std::endl;
|
||||||
}
|
}
|
||||||
@ -392,10 +417,21 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
|
|||||||
|
|
||||||
std::string protocol;
|
std::string protocol;
|
||||||
std::string auth;
|
std::string auth;
|
||||||
|
char const* error;
|
||||||
// we don't have this device in our list. Add it
|
// 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);
|
= 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
|
// ignore the auth here. It will be re-parsed
|
||||||
// by the http connection later
|
// 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
|
// just to make sure we find all devices
|
||||||
if (m_retry_count >= 4 && !m_devices.empty())
|
if (m_retry_count >= 4 && !m_devices.empty())
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_broadcast_timer.cancel(ec);
|
m_broadcast_timer.cancel(ec);
|
||||||
|
|
||||||
for (std::set<rootdevice>::iterator i = m_devices.begin()
|
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()
|
m_log << time_now_string()
|
||||||
<< " ==> connecting to " << d.url << std::endl;
|
<< " ==> connecting to " << d.url << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
if (d.upnp_connection) d.upnp_connection->close();
|
||||||
d.upnp_connection.reset(new http_connection(m_io_service
|
d.upnp_connection.reset(new http_connection(m_io_service
|
||||||
, m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2
|
, 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);
|
d.upnp_connection->get(d.url, seconds(30), 1);
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#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:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||||
"<s:Body><u:" << soap_action << " xmlns:u=\"" << d.service_namespace << "\">";
|
"<s:Body><u:" << soap_action << " xmlns:u=\"" << d.service_namespace << "\">";
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
soap << "<NewRemoteHost></NewRemoteHost>"
|
soap << "<NewRemoteHost></NewRemoteHost>"
|
||||||
"<NewExternalPort>" << d.mapping[i].external_port << "</NewExternalPort>"
|
"<NewExternalPort>" << d.mapping[i].external_port << "</NewExternalPort>"
|
||||||
"<NewProtocol>" << (d.mapping[i].protocol == udp ? "UDP" : "TCP") << "</NewProtocol>"
|
"<NewProtocol>" << (d.mapping[i].protocol == udp ? "UDP" : "TCP") << "</NewProtocol>"
|
||||||
@ -612,9 +649,10 @@ void upnp::update_map(rootdevice& d, int i)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (d.upnp_connection) d.upnp_connection->close();
|
||||||
d.upnp_connection.reset(new http_connection(m_io_service
|
d.upnp_connection.reset(new http_connection(m_io_service
|
||||||
, m_cc, bind(&upnp::on_upnp_map_response, self(), _1, _2
|
, 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)));
|
, bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i)));
|
||||||
|
|
||||||
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
|
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)
|
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
|
d.upnp_connection.reset(new http_connection(m_io_service
|
||||||
, m_cc, bind(&upnp::on_upnp_unmap_response, self(), _1, _2
|
, 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)));
|
, bind(&upnp::delete_port_mapping, self(), boost::ref(d), i)));
|
||||||
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
|
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
|
||||||
, seconds(10), 1);
|
, seconds(10), 1);
|
||||||
@ -732,13 +771,14 @@ namespace
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void upnp::on_upnp_xml(asio::error_code const& e
|
void upnp::on_upnp_xml(error_code const& e
|
||||||
, libtorrent::http_parser const& p, rootdevice& d)
|
, libtorrent::http_parser const& p, rootdevice& d
|
||||||
|
, http_connection& c)
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
TORRENT_ASSERT(d.magic == 1337);
|
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->close();
|
||||||
d.upnp_connection.reset();
|
d.upnp_connection.reset();
|
||||||
@ -816,7 +856,7 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
|||||||
|
|
||||||
d.control_url = s.control_url;
|
d.control_url = s.control_url;
|
||||||
|
|
||||||
update_map(d, 0);
|
if (num_mappings() > 0) update_map(d, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void upnp::disable(char const* msg)
|
void upnp::disable(char const* msg)
|
||||||
@ -833,7 +873,7 @@ void upnp::disable(char const* msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_devices.clear();
|
m_devices.clear();
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_broadcast_timer.cancel(ec);
|
m_broadcast_timer.cancel(ec);
|
||||||
m_refresh_timer.cancel(ec);
|
m_refresh_timer.cancel(ec);
|
||||||
m_socket.close();
|
m_socket.close();
|
||||||
@ -891,13 +931,14 @@ namespace
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void upnp::on_upnp_map_response(asio::error_code const& e
|
void upnp::on_upnp_map_response(error_code const& e
|
||||||
, libtorrent::http_parser const& p, rootdevice& d, int mapping)
|
, libtorrent::http_parser const& p, rootdevice& d, int mapping
|
||||||
|
, http_connection& c)
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
TORRENT_ASSERT(d.magic == 1337);
|
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->close();
|
||||||
d.upnp_connection.reset();
|
d.upnp_connection.reset();
|
||||||
@ -1014,7 +1055,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
|||||||
if (next_expire < time_now()
|
if (next_expire < time_now()
|
||||||
|| next_expire > m.expires)
|
|| next_expire > m.expires)
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_refresh_timer.expires_at(m.expires, ec);
|
m_refresh_timer.expires_at(m.expires, ec);
|
||||||
m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1));
|
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);
|
m_callback(mapping, 0, error_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void upnp::on_upnp_unmap_response(asio::error_code const& e
|
void upnp::on_upnp_unmap_response(error_code const& e
|
||||||
, libtorrent::http_parser const& p, rootdevice& d, int mapping)
|
, libtorrent::http_parser const& p, rootdevice& d, int mapping
|
||||||
|
, http_connection& c)
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
TORRENT_ASSERT(d.magic == 1337);
|
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->close();
|
||||||
d.upnp_connection.reset();
|
d.upnp_connection.reset();
|
||||||
@ -1093,7 +1135,7 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e
|
|||||||
next(d, mapping);
|
next(d, mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
void upnp::on_expire(asio::error_code const& e)
|
void upnp::on_expire(error_code const& e)
|
||||||
{
|
{
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
|
||||||
@ -1125,7 +1167,7 @@ void upnp::on_expire(asio::error_code const& e)
|
|||||||
}
|
}
|
||||||
if (next_expire != max_time())
|
if (next_expire != max_time())
|
||||||
{
|
{
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_refresh_timer.expires_at(next_expire, ec);
|
m_refresh_timer.expires_at(next_expire, ec);
|
||||||
m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1));
|
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);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
asio::error_code ec;
|
error_code ec;
|
||||||
m_refresh_timer.cancel(ec);
|
m_refresh_timer.cancel(ec);
|
||||||
m_broadcast_timer.cancel(ec);
|
m_broadcast_timer.cancel(ec);
|
||||||
m_closing = true;
|
m_closing = true;
|
||||||
@ -1159,7 +1201,7 @@ void upnp::close()
|
|||||||
j->action = mapping_t::action_delete;
|
j->action = mapping_t::action_delete;
|
||||||
m_mappings[j - d.mapping.begin()].protocol = none;
|
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/bencode.hpp"
|
||||||
#include "libtorrent/torrent.hpp"
|
#include "libtorrent/torrent.hpp"
|
||||||
#include "libtorrent/extensions.hpp"
|
#include "libtorrent/extensions.hpp"
|
||||||
#include "libtorrent/extensions/metadata_transfer.hpp"
|
#include "libtorrent/extensions/ut_metadata.hpp"
|
||||||
#include "libtorrent/alert_types.hpp"
|
#include "libtorrent/alert_types.hpp"
|
||||||
#ifdef TORRENT_STATS
|
#ifdef TORRENT_STATS
|
||||||
#include "libtorrent/aux_/session_impl.hpp"
|
#include "libtorrent/aux_/session_impl.hpp"
|
||||||
@ -89,39 +89,38 @@ namespace libtorrent { namespace
|
|||||||
virtual boost::shared_ptr<peer_plugin> new_connection(
|
virtual boost::shared_ptr<peer_plugin> new_connection(
|
||||||
peer_connection* pc);
|
peer_connection* pc);
|
||||||
|
|
||||||
std::vector<char> const& metadata() const
|
buffer::const_interval metadata() const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_torrent.valid_metadata());
|
TORRENT_ASSERT(m_torrent.valid_metadata());
|
||||||
|
if (!m_metadata)
|
||||||
if (m_metadata.empty())
|
|
||||||
{
|
{
|
||||||
bencode(std::back_inserter(m_metadata)
|
m_metadata = m_torrent.torrent_file().metadata();
|
||||||
, m_torrent.torrent_file().create_info_metadata());
|
m_metadata_size = m_torrent.torrent_file().metadata_size();
|
||||||
|
TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final()
|
||||||
TORRENT_ASSERT(hasher(&m_metadata[0], m_metadata.size()).final()
|
|
||||||
== m_torrent.torrent_file().info_hash());
|
== m_torrent.torrent_file().info_hash());
|
||||||
}
|
}
|
||||||
TORRENT_ASSERT(!m_metadata.empty());
|
return buffer::const_interval(m_metadata.get(), m_metadata.get()
|
||||||
return m_metadata;
|
+ m_metadata_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool received_metadata(char const* buf, int size, int piece, int total_size)
|
bool received_metadata(char const* buf, int size, int piece, int total_size)
|
||||||
{
|
{
|
||||||
if (m_torrent.valid_metadata()) return false;
|
if (m_torrent.valid_metadata()) return false;
|
||||||
|
|
||||||
if (m_metadata.empty())
|
if (!m_metadata)
|
||||||
{
|
{
|
||||||
// verify the total_size
|
// verify the total_size
|
||||||
if (total_size <= 0 || total_size > 500 * 1024) return false;
|
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_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()))
|
if (piece < 0 || piece >= int(m_requested_metadata.size()))
|
||||||
return false;
|
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);
|
std::memcpy(&m_metadata[piece * 16 * 1024], buf, size);
|
||||||
// mark this piece has 'have'
|
// mark this piece has 'have'
|
||||||
m_requested_metadata[piece] = (std::numeric_limits<int>::max)();
|
m_requested_metadata[piece] = (std::numeric_limits<int>::max)();
|
||||||
@ -133,7 +132,7 @@ namespace libtorrent { namespace
|
|||||||
if (!have_all) return false;
|
if (!have_all) return false;
|
||||||
|
|
||||||
hasher h;
|
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();
|
sha1_hash info_hash = h.final();
|
||||||
|
|
||||||
if (info_hash != m_torrent.torrent_file().info_hash())
|
if (info_hash != m_torrent.torrent_file().info_hash())
|
||||||
@ -149,7 +148,8 @@ namespace libtorrent { namespace
|
|||||||
return false;
|
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;
|
std::string error;
|
||||||
if (!m_torrent.set_metadata(metadata, 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;
|
if (m_metadata_size > 0 || size <= 0 || size > 500 * 1024) return;
|
||||||
m_metadata_size = size;
|
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);
|
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
|
// the metadata file while downloading it from
|
||||||
// peers, and while sending it.
|
// peers, and while sending it.
|
||||||
// it is mutable because it's generated lazily
|
// 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_progress;
|
||||||
int m_metadata_size;
|
mutable int m_metadata_size;
|
||||||
|
|
||||||
// this vector keeps track of how many times each meatdata
|
// this vector keeps track of how many times each meatdata
|
||||||
// block has been requested
|
// block has been requested
|
||||||
@ -231,7 +231,7 @@ namespace libtorrent { namespace
|
|||||||
entry& messages = h["m"];
|
entry& messages = h["m"];
|
||||||
messages["ut_metadata"] = 15;
|
messages["ut_metadata"] = 15;
|
||||||
if (m_torrent.valid_metadata())
|
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
|
// called when the extension handshake from the other end is received
|
||||||
@ -273,14 +273,14 @@ namespace libtorrent { namespace
|
|||||||
if (type == 1)
|
if (type == 1)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata());
|
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;
|
int offset = piece * 16 * 1024;
|
||||||
metadata = &m_tp.metadata()[0] + offset;
|
metadata = m_tp.metadata().begin + offset;
|
||||||
metadata_piece_size = (std::min)(
|
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(metadata_piece_size > 0);
|
||||||
TORRENT_ASSERT(offset >= 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];
|
char msg[200];
|
||||||
|
|||||||
@ -113,7 +113,7 @@ namespace libtorrent { namespace
|
|||||||
for (torrent::peer_iterator i = m_torrent.begin()
|
for (torrent::peer_iterator i = m_torrent.begin()
|
||||||
, end(m_torrent.end()); i != end; ++i)
|
, end(m_torrent.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
peer_connection* peer = *i;
|
peer_connection* peer = *i;
|
||||||
if (!send_peer(*peer)) continue;
|
if (!send_peer(*peer)) continue;
|
||||||
|
|
||||||
tcp::endpoint const& remote = peer->remote();
|
tcp::endpoint const& remote = peer->remote();
|
||||||
|
|||||||
@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "libtorrent/io.hpp"
|
#include "libtorrent/io.hpp"
|
||||||
#include "libtorrent/version.hpp"
|
#include "libtorrent/version.hpp"
|
||||||
#include "libtorrent/aux_/session_impl.hpp"
|
#include "libtorrent/aux_/session_impl.hpp"
|
||||||
|
#include "libtorrent/parse_url.hpp"
|
||||||
|
|
||||||
using boost::bind;
|
using boost::bind;
|
||||||
using boost::shared_ptr;
|
using boost::shared_ptr;
|
||||||
@ -72,6 +73,8 @@ namespace libtorrent
|
|||||||
// we want large blocks as well, so
|
// we want large blocks as well, so
|
||||||
// we can request more bytes at once
|
// we can request more bytes at once
|
||||||
request_large_blocks(true);
|
request_large_blocks(true);
|
||||||
|
set_upload_only(true);
|
||||||
|
|
||||||
// we only want left-over bandwidth
|
// we only want left-over bandwidth
|
||||||
set_priority(0);
|
set_priority(0);
|
||||||
shared_ptr<torrent> tor = t.lock();
|
shared_ptr<torrent> tor = t.lock();
|
||||||
@ -95,8 +98,10 @@ namespace libtorrent
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string protocol;
|
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);
|
= parse_url_components(url);
|
||||||
|
TORRENT_ASSERT(error == 0);
|
||||||
|
|
||||||
if (!m_auth.empty())
|
if (!m_auth.empty())
|
||||||
m_auth = base64encode(m_auth);
|
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)
|
, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
@ -349,7 +354,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
disconnect("failed to parse HTTP response");
|
disconnect("failed to parse HTTP response", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,7 +385,7 @@ namespace libtorrent
|
|||||||
m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url()
|
m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url()
|
||||||
, error_msg));
|
, error_msg));
|
||||||
}
|
}
|
||||||
disconnect(error_msg.c_str());
|
disconnect(error_msg.c_str(), 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!m_parser.header_finished()) break;
|
if (!m_parser.header_finished()) break;
|
||||||
@ -406,7 +411,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
// we should not try this server again.
|
// we should not try this server again.
|
||||||
t->remove_url_seed(m_url);
|
t->remove_url_seed(m_url);
|
||||||
disconnect("got HTTP redirection status without location header");
|
disconnect("got HTTP redirection status without location header", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +435,7 @@ namespace libtorrent
|
|||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
msg << "got invalid HTTP redirection location (\"" << location << "\") "
|
msg << "got invalid HTTP redirection location (\"" << location << "\") "
|
||||||
"expected it to end with: " << path;
|
"expected it to end with: " << path;
|
||||||
disconnect(msg.str().c_str());
|
disconnect(msg.str().c_str(), 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
location.resize(i);
|
location.resize(i);
|
||||||
@ -475,7 +480,7 @@ namespace libtorrent
|
|||||||
t->remove_url_seed(m_url);
|
t->remove_url_seed(m_url);
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
msg << "invalid range in HTTP response: " << range_str.str();
|
msg << "invalid range in HTTP response: " << range_str.str();
|
||||||
disconnect(msg.str().c_str());
|
disconnect(msg.str().c_str(), 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// the http range is inclusive
|
// the http range is inclusive
|
||||||
@ -489,7 +494,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
// we should not try this server again.
|
// we should not try this server again.
|
||||||
t->remove_url_seed(m_url);
|
t->remove_url_seed(m_url);
|
||||||
disconnect("no content-length in HTTP response");
|
disconnect("no content-length in HTTP response", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -501,7 +506,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (m_requests.empty() || m_file_requests.empty())
|
if (m_requests.empty() || m_file_requests.empty())
|
||||||
{
|
{
|
||||||
disconnect("unexpected HTTP response");
|
disconnect("unexpected HTTP response", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,7 +539,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
// this means the end of the incoming request ends _before_ the
|
// this means the end of the incoming request ends _before_ the
|
||||||
// first expected byte (fs + m_piece.size())
|
// first expected byte (fs + m_piece.size())
|
||||||
disconnect("invalid range in HTTP response");
|
disconnect("invalid range in HTTP response", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,7 +667,7 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
|
|
||||||
// throws exception when the client should be disconnected
|
// 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)
|
, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|||||||
7
setup.py
7
setup.py
@ -85,15 +85,10 @@ if not os.environ.has_key("CPP"):
|
|||||||
|
|
||||||
# The libtorrent extension
|
# The libtorrent extension
|
||||||
_extra_compile_args = [
|
_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",
|
"-DTORRENT_USE_OPENSSL=1",
|
||||||
"-DHAVE_SSL=1",
|
|
||||||
"-O2",
|
"-O2",
|
||||||
"-D_FILE_OFFSET_BITS=64",
|
"-D_FILE_OFFSET_BITS=64",
|
||||||
"-DNDEBUG"
|
"-DNDEBUG",
|
||||||
]
|
]
|
||||||
|
|
||||||
if windows_check():
|
if windows_check():
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user