libtorrent sync 2347

This commit is contained in:
Andrew Resch 2008-05-20 06:23:48 +00:00
parent 576cae3b26
commit b15608252c
98 changed files with 2453 additions and 2129 deletions

View File

@ -134,7 +134,7 @@ class Torrent:
def set_private_flag(self, private):
self.private = private
self.handle.get_torrent_info().set_priv(private)
#self.handle.get_torrent_info().set_priv(private)
def set_prioritize_first_last(self, prioritize):
self.prioritize_first_last = prioritize

View File

@ -28,17 +28,17 @@ namespace
this->peer_plugin::add_handshake(e);
}
bool on_handshake()
bool on_handshake(char const* reserved_bits)
{
if (override f = this->get_override("on_handshake"))
return f();
else
return peer_plugin::on_handshake();
return peer_plugin::on_handshake(reserved_bits);
}
bool default_on_handshake()
bool default_on_handshake(char const* reserved_bits)
{
return this->peer_plugin::on_handshake();
return this->peer_plugin::on_handshake(reserved_bits);
}
bool on_extension_handshake(entry const& e)

View File

@ -74,13 +74,7 @@ void bind_torrent_info()
.def(init<entry const&>())
.def(init<sha1_hash const&>())
.def("create_torrent", &torrent_info::create_torrent)
.def("set_comment", &torrent_info::set_comment)
.def("set_piece_size", &torrent_info::set_piece_size)
.def("set_creator", &torrent_info::set_creator)
.def("set_hash", &torrent_info::set_hash)
.def("add_tracker", &torrent_info::add_tracker, (arg("url"), arg("tier")=0))
.def("add_file", &torrent_info::add_file)
.def("add_url_seed", &torrent_info::add_url_seed)
.def("name", &torrent_info::name, copy)
@ -91,7 +85,7 @@ void bind_torrent_info()
.def("num_pieces", &torrent_info::num_pieces)
.def("info_hash", &torrent_info::info_hash, copy)
.def("hash_for_piece", &torrent_info::hash_for_piece, copy)
.def("hash_for_piece", &torrent_info::hash_for_piece)
.def("piece_size", &torrent_info::piece_size)
.def("num_files", &torrent_info::num_files, (arg("storage")=false))
@ -99,7 +93,6 @@ void bind_torrent_info()
.def("files", &files, (arg("storage")=false))
.def("priv", &torrent_info::priv)
.def("set_priv", &torrent_info::set_priv)
.def("trackers", range(begin_trackers, end_trackers))
.def("creation_date", &torrent_info::creation_date)

View File

@ -173,10 +173,6 @@ GEOIP_API const char * GeoIP_region_name_by_code(const char *country_code, const
/* Get timezone from country and region code */
GEOIP_API const char * GeoIP_time_zone_by_country_and_region(const char *country_code, const char *region_code);
#ifdef BSD
#define memcpy(dest, src, n) bcopy(src, dest, n)
#endif
#ifdef __cplusplus
}
#endif

View File

@ -188,7 +188,7 @@ namespace libtorrent
struct TORRENT_EXPORT peer_error_alert: alert
{
peer_error_alert(tcp::endpoint const& pip, peer_id const& pid_, std::string const& msg)
: alert(alert::debug, msg)
: alert(alert::info, msg)
, ip(pip)
, pid(pid_)
{}
@ -200,6 +200,21 @@ namespace libtorrent
peer_id pid;
};
struct TORRENT_EXPORT peer_disconnected_alert: alert
{
peer_disconnected_alert(tcp::endpoint const& pip, peer_id const& pid_, std::string const& msg)
: alert(alert::debug, msg)
, ip(pip)
, pid(pid_)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_disconnected_alert(*this)); }
tcp::endpoint ip;
peer_id pid;
};
struct TORRENT_EXPORT invalid_request_alert: torrent_alert
{
invalid_request_alert(

View File

@ -151,7 +151,7 @@ namespace libtorrent
void async_accept(boost::shared_ptr<socket_acceptor> const& listener);
void on_incoming_connection(boost::shared_ptr<socket_type> const& s
, boost::weak_ptr<socket_acceptor> listener, asio::error_code const& e);
, boost::weak_ptr<socket_acceptor> listener, error_code const& e);
// must be locked to access the data
// in this struct
@ -489,6 +489,11 @@ namespace libtorrent
// from the torrent with the most peers
int m_disconnect_time_scaler;
// when this scaler reaches zero, it will
// scrape one of the auto managed, paused,
// torrents.
int m_auto_scrape_time_scaler;
// statistics gathered from all torrents.
stat m_stat;
@ -498,7 +503,7 @@ namespace libtorrent
// NAT or not.
bool m_incoming_connection;
void second_tick(asio::error_code const& e);
void second_tick(error_code const& e);
void recalculate_auto_managed_torrents();
void recalculate_unchoke_slots(int congested_torrents
, int uncongested_torrents);
@ -528,7 +533,7 @@ namespace libtorrent
udp_socket m_dht_socket;
void on_receive_udp(asio::error_code const& e
void on_receive_udp(error_code const& e
, udp::endpoint const& ep, char const* buf, int len);
#endif

View File

@ -76,6 +76,8 @@ struct history_entry
history_entry(intrusive_ptr<PeerConnection> p, weak_ptr<Torrent> t
, int a, ptime exp)
: expires_at(exp), amount(a), peer(p), tor(t) {}
history_entry(int a, ptime exp)
: expires_at(exp), amount(a), peer(), tor() {}
ptime expires_at;
int amount;
intrusive_ptr<PeerConnection> peer;
@ -111,6 +113,7 @@ struct bandwidth_manager
: m_ios(ios)
, m_history_timer(m_ios)
, m_limit(bandwidth_limit::inf)
, m_drain_quota(0)
, m_current_quota(0)
, m_channel(channel)
, m_in_hand_out_bandwidth(false)
@ -123,6 +126,14 @@ struct bandwidth_manager
#endif
}
void drain(int bytes)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(bytes >= 0);
m_drain_quota += bytes;
if (m_drain_quota > m_limit * 5) m_drain_quota = m_limit * 5;
}
void throttle(int limit)
{
mutex_t::scoped_lock l(m_mutex);
@ -154,7 +165,6 @@ struct bandwidth_manager
bool is_queued(PeerConnection const* peer, boost::mutex::scoped_lock& l) const
{
TORRENT_ASSERT(l.locked());
for (typename queue_t::const_iterator i = m_queue.begin()
, end(m_queue.end()); i != end; ++i)
{
@ -171,7 +181,6 @@ struct bandwidth_manager
bool is_in_history(PeerConnection const* peer, boost::mutex::scoped_lock& l) const
{
TORRENT_ASSERT(l.locked());
for (typename history_t::const_iterator i
= m_history.begin(), end(m_history.end()); i != end; ++i)
{
@ -258,12 +267,12 @@ private:
if (m_abort) return;
asio::error_code ec;
error_code ec;
m_history_timer.expires_at(e.expires_at, ec);
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
}
void on_history_expire(asio::error_code const& e)
void on_history_expire(error_code const& e)
{
if (e) return;
@ -290,6 +299,7 @@ private:
<< std::endl;
#endif
intrusive_ptr<PeerConnection> c = e.peer;
if (!c) continue;
shared_ptr<Torrent> t = e.tor.lock();
l.unlock();
if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount);
@ -300,7 +310,7 @@ private:
// now, wait for the next chunk to expire
if (!m_history.empty() && !m_abort)
{
asio::error_code ec;
error_code ec;
m_history_timer.expires_at(m_history.back().expires_at, ec);
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
}
@ -313,7 +323,6 @@ private:
void hand_out_bandwidth(boost::mutex::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
// if we're already handing out bandwidth, just return back
// to the loop further down on the callstack
if (m_in_hand_out_bandwidth) return;
@ -332,6 +341,15 @@ private:
if (amount <= 0) return;
if (m_drain_quota > 0)
{
int drain_amount = (std::min)(m_drain_quota, amount);
m_drain_quota -= drain_amount;
amount -= drain_amount;
add_history_entry(history_entry<PeerConnection, Torrent>(
drain_amount, now + bw_window_size));
}
queue_t tmp;
while (!m_queue.empty() && amount > 0)
{
@ -436,6 +454,10 @@ private:
// the rate limit (bytes per second)
int m_limit;
// bytes to drain without handing out to a peer
// used to deduct the IP overhead
int m_drain_quota;
// the sum of all recently handed out bandwidth blocks
int m_current_quota;

View File

@ -51,7 +51,7 @@ namespace libtorrent
int common_bits(unsigned char const* b1
, unsigned char const* b2, int n);
TORRENT_EXPORT address guess_local_address(asio::io_service&);
TORRENT_EXPORT address guess_local_address(io_service&);
typedef boost::function<void(udp::endpoint const& from
, char* buffer, int size)> receive_handler_t;
@ -59,11 +59,11 @@ namespace libtorrent
class TORRENT_EXPORT broadcast_socket
{
public:
broadcast_socket(asio::io_service& ios, udp::endpoint const& multicast_endpoint
broadcast_socket(io_service& ios, udp::endpoint const& multicast_endpoint
, receive_handler_t const& handler, bool loopback = true);
~broadcast_socket() { close(); }
void send(char const* buffer, int size, asio::error_code& ec);
void send(char const* buffer, int size, error_code& ec);
void close();
private:
@ -77,12 +77,12 @@ namespace libtorrent
void close()
{
if (!socket) return;
asio::error_code ec;
error_code ec;
socket->close(ec);
}
};
void on_receive(socket_entry* s, asio::error_code const& ec
void on_receive(socket_entry* s, error_code const& ec
, std::size_t bytes_transferred);
void open_unicast_socket(io_service& ios, address const& addr);
void open_multicast_socket(io_service& ios, address const& addr

View File

@ -100,6 +100,7 @@ namespace libtorrent
bt_peer_connection(
aux::session_impl& ses
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo);
void start();
@ -141,9 +142,9 @@ namespace libtorrent
// called from the main loop when this connection has any
// work to do.
void on_sent(asio::error_code const& error
void on_sent(error_code const& error
, std::size_t bytes_transferred);
void on_receive(asio::error_code const& error
void on_receive(error_code const& error
, std::size_t bytes_transferred);
virtual void get_specific_peer_info(peer_info& p) const;
@ -363,6 +364,7 @@ private:
// the peer indicated that it supports the
// extension protocol
bool m_supports_extensions;
char m_reserved_bits[20];
#endif
bool m_supports_dht_port;
bool m_supports_fast;

View File

@ -34,12 +34,19 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED
#include <boost/function.hpp>
#if BOOST_VERSION < 103500
#include <asio/buffer.hpp>
#else
#include <boost/asio/buffer.hpp>
#endif
#include <list>
#include <cstring>
namespace libtorrent
{
#if BOOST_VERSION >= 103500
namespace asio = boost::asio;
#endif
struct chained_buffer
{
chained_buffer(): m_bytes(0), m_capacity(0) {}

View File

@ -71,7 +71,7 @@ public:
private:
void try_connect();
void on_timeout(asio::error_code const& e);
void on_timeout(error_code const& e);
struct entry
{

View File

@ -47,7 +47,13 @@ namespace libtorrent
disk_buffer_holder(disk_io_thread& iothread, char* buf);
~disk_buffer_holder();
char* release();
char* buffer() const { return m_buf; }
char* get() const { return m_buf; }
void reset(char* buf = 0);
typedef char* (disk_buffer_holder::*unspecified_bool_type)();
operator unspecified_bool_type() const
{ return m_buf == 0? 0: &disk_buffer_holder::release; }
private:
disk_io_thread& m_iothread;
char* m_buf;

View File

@ -149,7 +149,7 @@ namespace libtorrent
// of disk io jobs
struct disk_io_thread : boost::noncopyable
{
disk_io_thread(asio::io_service& ios, int block_size = 16 * 1024);
disk_io_thread(io_service& ios, int block_size = 16 * 1024);
~disk_io_thread();
#ifdef TORRENT_STATS
@ -292,7 +292,7 @@ namespace libtorrent
size_type m_writes;
size_type m_blocks_written;
asio::io_service& m_ios;
io_service& m_ios;
// thread for performing blocking disk io operations
boost::thread m_disk_io_thread;

View File

@ -167,6 +167,8 @@ namespace libtorrent
#endif
entry* find_key(char const* key);
entry const* find_key(char const* key) const;
entry* find_key(std::string const& key);
entry const* find_key(std::string const& key) const;
void print(std::ostream& os, int indent = 0) const;

View File

@ -43,7 +43,7 @@ namespace libtorrent
{
address interface_address;
address netmask;
char name[32];
char name[64];
};
struct ip_route
@ -51,15 +51,15 @@ namespace libtorrent
address destination;
address netmask;
address gateway;
char name[32];
char name[64];
};
// returns a list of the configured IP interfaces
// on the machine
TORRENT_EXPORT std::vector<ip_interface> enum_net_interfaces(asio::io_service& ios
, asio::error_code& ec);
TORRENT_EXPORT std::vector<ip_interface> enum_net_interfaces(io_service& ios
, error_code& ec);
TORRENT_EXPORT std::vector<ip_route> enum_routes(asio::io_service& ios, asio::error_code& ec);
TORRENT_EXPORT std::vector<ip_route> enum_routes(io_service& ios, error_code& ec);
// returns true if the specified address is on the same
// local network as the specified interface
@ -67,11 +67,11 @@ namespace libtorrent
// returns true if the specified address is on the same
// local network as us
TORRENT_EXPORT bool in_local_network(asio::io_service& ios, address const& addr
, asio::error_code& ec);
TORRENT_EXPORT bool in_local_network(io_service& ios, address const& addr
, error_code& ec);
TORRENT_EXPORT address get_default_gateway(asio::io_service& ios
, asio::error_code& ec);
TORRENT_EXPORT address get_default_gateway(io_service& ios
, error_code& ec);
}
#endif

View File

@ -51,6 +51,8 @@ namespace libtorrent
TORRENT_EXPORT boost::optional<std::string> url_has_argument(
std::string const& url, std::string argument);
TORRENT_EXPORT std::string to_hex(std::string const& s);
}
#endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED

View File

@ -99,7 +99,7 @@ namespace libtorrent
// means that the other end doesn't support this extension and will remove
// it from the list of plugins.
// this is not called for web seeds
virtual bool on_handshake() { return true; }
virtual bool on_handshake(char const* reserved_bits) { return true; }
// called when the extension handshake from the other end is received
// if this returns false, it means that this extension isn't

View File

@ -39,6 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>
#include <vector>
#include <list>
#include <string>
#include "libtorrent/socket.hpp"
@ -59,8 +60,8 @@ namespace libtorrent
struct http_connection;
class connection_queue;
typedef boost::function<void(asio::error_code const&
, http_parser const&, char const* data, int size)> http_handler;
typedef boost::function<void(error_code const&
, http_parser const&, char const* data, int size, http_connection&)> http_handler;
typedef boost::function<void(http_connection&)> http_connect_handler;
@ -70,7 +71,7 @@ typedef boost::function<void(http_connection&)> http_connect_handler;
// will always be 0
struct http_connection : boost::enable_shared_from_this<http_connection>, boost::noncopyable
{
http_connection(asio::io_service& ios, connection_queue& cc
http_connection(io_service& ios, connection_queue& cc
, http_handler const& handler, bool bottled = true
, http_connect_handler const& ch = http_connect_handler())
: m_sock(ios)
@ -91,6 +92,7 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
, m_cc(cc)
, m_ssl(false)
, m_priority(0)
, m_abort(false)
{
TORRENT_ASSERT(!m_handler.empty());
}
@ -121,19 +123,19 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
private:
void on_resolve(asio::error_code const& e
void on_resolve(error_code const& e
, tcp::resolver::iterator i);
void queue_connect();
void connect(int ticket, tcp::endpoint target_address);
void on_connect_timeout();
void on_connect(asio::error_code const& e
/* , tcp::resolver::iterator i*/);
void on_write(asio::error_code const& e);
void on_read(asio::error_code const& e, std::size_t bytes_transferred);
void on_connect(error_code const& e);
void on_write(error_code const& e);
void on_read(error_code const& e, std::size_t bytes_transferred);
static void on_timeout(boost::weak_ptr<http_connection> p
, asio::error_code const& e);
void on_assign_bandwidth(asio::error_code const& e);
, error_code const& e);
void on_assign_bandwidth(error_code const& e);
void callback(asio::error_code const& e, char const* data = 0, int size = 0);
void callback(error_code const& e, char const* data = 0, int size = 0);
std::vector<char> m_recvbuffer;
#ifdef TORRENT_USE_OPENSSL
@ -158,6 +160,9 @@ private:
bool m_called;
std::string m_hostname;
std::string m_port;
std::string m_url;
std::list<tcp::endpoint> m_endpoints;
// the current download limit, in bytes per second
// 0 is unlimited.
@ -195,6 +200,8 @@ private:
// the priority we have in the connection queue.
// 0 is normal, 1 is high
int m_priority;
bool m_abort;
};
}

View File

@ -41,7 +41,7 @@ class http_stream : public proxy_base
{
public:
explicit http_stream(asio::io_service& io_service)
explicit http_stream(io_service& io_service)
: proxy_base(io_service)
, m_no_connect(false)
{}
@ -55,7 +55,7 @@ public:
m_password = password;
}
typedef boost::function<void(asio::error_code const&)> handler_type;
typedef boost::function<void(error_code const&)> handler_type;
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
@ -80,11 +80,11 @@ public:
private:
void name_lookup(asio::error_code const& e, tcp::resolver::iterator i
void name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h);
void connected(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
// send and receive buffer
std::vector<char> m_buffer;

View File

@ -82,7 +82,7 @@ namespace libtorrent
boost::intrusive_ptr<http_tracker_connection> self()
{ return boost::intrusive_ptr<http_tracker_connection>(this); }
void on_response(asio::error_code const& ec, http_parser const& parser
void on_response(error_code const& ec, http_parser const& parser
, char const* data, int size);
virtual void on_timeout() {}

View File

@ -34,14 +34,13 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_INSTANTIATE_CONNECTION
#include "libtorrent/socket_type.hpp"
#include <asio/io_service.hpp>
#include <boost/shared_ptr.hpp>
namespace libtorrent
{
struct proxy_settings;
bool instantiate_connection(asio::io_service& ios
bool instantiate_connection(io_service& ios
, proxy_settings const& ps, socket_type& s);
}

View File

@ -68,7 +68,7 @@ public:
private:
void done();
void invoke(node_id const& id, asio::ip::udp::endpoint addr);
void invoke(node_id const& id, udp::endpoint addr);
closest_nodes(
node_id target

View File

@ -53,6 +53,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/session_settings.hpp"
#include "libtorrent/session_status.hpp"
#include "libtorrent/udp_socket.hpp"
#include "libtorrent/socket.hpp"
namespace libtorrent { namespace dht
{
@ -89,19 +90,20 @@ namespace libtorrent { namespace dht
// translate bittorrent kademlia message into the generic kademlia message
// used by the library
void on_receive(udp::endpoint const& ep, char const* pkt, int size);
void on_unreachable(udp::endpoint const& ep);
private:
boost::intrusive_ptr<dht_tracker> self()
{ return boost::intrusive_ptr<dht_tracker>(this); }
void on_name_lookup(asio::error_code const& e
void on_name_lookup(error_code const& e
, udp::resolver::iterator host);
void on_router_name_lookup(asio::error_code const& e
void on_router_name_lookup(error_code const& e
, udp::resolver::iterator host);
void connection_timeout(asio::error_code const& e);
void refresh_timeout(asio::error_code const& e);
void tick(asio::error_code const& e);
void connection_timeout(error_code const& e);
void refresh_timeout(error_code const& e);
void tick(error_code const& e);
void on_bootstrap();
void send_packet(msg const& m);

View File

@ -48,8 +48,6 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent { namespace dht
{
using asio::ip::udp;
typedef std::vector<char> packet_t;
class rpc_manager;

View File

@ -36,15 +36,17 @@ POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <libtorrent/kademlia/node_id.hpp>
#include "libtorrent/entry.hpp"
#if BOOST_VERSION < 103500
#include <asio/ip/udp.hpp>
#else
#include <boost/asio/ip/udp.hpp>
#endif
namespace libtorrent {
namespace dht {
typedef std::vector<char> packet_t;
using asio::ip::udp;
namespace messages
{
enum { ping = 0, find_node = 1, get_peers = 2, announce_peer = 3, error = 4 };

View File

@ -56,8 +56,6 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent { namespace dht
{
using asio::ip::udp;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(node);
#endif
@ -174,6 +172,7 @@ public:
void(std::vector<node_entry> const&)> f);
void add_router_node(udp::endpoint router);
void unreachable(udp::endpoint const& ep);
void incoming(msg const& m);
void refresh();

View File

@ -41,20 +41,33 @@ namespace libtorrent { namespace dht
struct node_entry
{
node_entry(node_id const& id_, asio::ip::udp::endpoint addr_)
node_entry(node_id const& id_, udp::endpoint addr_)
: id(id_)
, addr(addr_)
, fail_count(0) {}
node_entry(asio::ip::udp::endpoint addr_)
, fail_count(0)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
first_seen = time_now();
#endif
}
node_entry(udp::endpoint addr_)
: id(0)
, addr(addr_)
, fail_count(0) {}
, fail_count(0)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
first_seen = time_now();
#endif
}
node_id id;
udp::endpoint addr;
// the number of times this node has failed to
// respond in a row
int fail_count;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
ptime first_seen;
#endif
};
} } // namespace libtorrent::dht

View File

@ -55,9 +55,10 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent { namespace dht
{
using asio::ip::udp;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(table);
#endif
//TORRENT_DECLARE_LOG(table);
typedef std::vector<node_entry> bucket_t;

View File

@ -56,7 +56,6 @@ namespace libtorrent { namespace dht
struct observer;
using asio::ip::udp;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(rpc);
#endif
@ -82,6 +81,8 @@ public:
, routing_table& table, send_fun const& sf);
~rpc_manager();
void unreachable(udp::endpoint const& ep);
// returns true if the node needs a refresh
bool incoming(msg const&);
time_duration tick();

View File

@ -179,6 +179,15 @@ namespace libtorrent
void clear();
// releases ownership of any memory allocated
void release()
{
m_data.start = 0;
m_size = 0;
m_capacity = 0;
m_type = none_t;
}
~lazy_entry()
{ clear(); }
@ -186,6 +195,17 @@ namespace libtorrent
// this entry has its bencoded data
std::pair<char const*, int> data_section() const;
void swap(lazy_entry& e)
{
using std::swap;
swap(m_type, e.m_type);
swap(m_data.start, e.m_data.start);
swap(m_size, e.m_size);
swap(m_capacity, e.m_capacity);
swap(m_begin, e.m_begin);
swap(m_end, e.m_end);
}
private:
entry_type_t m_type;

View File

@ -67,7 +67,7 @@ public:
private:
void resend_announce(asio::error_code const& e, std::string msg);
void resend_announce(error_code const& e, std::string msg);
void on_announce(udp::endpoint const& from, char* buffer
, std::size_t bytes_transferred);
// void setup_receive();

View File

@ -70,12 +70,12 @@ private:
void update_mapping(int i);
void send_map_request(int i);
void resend_request(int i, asio::error_code const& e);
void on_reply(asio::error_code const& e
void resend_request(int i, error_code const& e);
void on_reply(error_code const& e
, std::size_t bytes_transferred);
void try_next_mapping(int i);
void update_expiration_timer();
void mapping_expired(asio::error_code const& e, int i);
void mapping_expired(error_code const& e, int i);
void disable(char const* message);

View File

@ -121,6 +121,7 @@ namespace libtorrent
peer_connection(
aux::session_impl& ses
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo);
// this function is called after it has been constructed and properly
@ -197,6 +198,9 @@ namespace libtorrent
bool is_seed() const;
void set_upload_only(bool u) { m_upload_only = u; }
bool upload_only() const { return m_upload_only; }
bool has_timed_out() const;
// will send a keep-alive message to the peer
@ -230,6 +234,8 @@ namespace libtorrent
const stat& statistics() const { return m_statistics; }
void add_stat(size_type downloaded, size_type uploaded);
void calc_ip_overhead();
// is called once every second by the main loop
void second_tick(float tick_interval);
@ -240,15 +246,18 @@ namespace libtorrent
std::vector<int> const& allowed_fast();
std::vector<int> const& suggested_pieces() const { return m_suggested_pieces; }
ptime connected_time() const { return m_connect; }
ptime last_received() const { return m_last_receive; }
void timed_out();
// this will cause this peer_connection to be disconnected.
void disconnect(char const* message);
void disconnect(char const* message, int error = 0);
bool is_disconnecting() const { return m_disconnecting; }
// this is called when the connection attempt has succeeded
// and the peer_connection is supposed to set m_connecting
// to false, and stop monitor writability
void on_connection_complete(asio::error_code const& e);
void on_connection_complete(error_code const& e);
// returns true if this connection is still waiting to
// finish the connection attempt
@ -288,7 +297,6 @@ namespace libtorrent
bool ignore_bandwidth_limits() const
{ return m_ignore_bandwidth_limits; }
void set_failed() { m_failed = true; }
bool failed() const { return m_failed; }
int desired_queue_size() const { return m_desired_queue_size; }
@ -449,15 +457,15 @@ namespace libtorrent
virtual void on_connected() = 0;
virtual void on_tick() {}
virtual void on_receive(asio::error_code const& error
virtual void on_receive(error_code const& error
, std::size_t bytes_transferred) = 0;
virtual void on_sent(asio::error_code const& error
virtual void on_sent(error_code const& error
, std::size_t bytes_transferred) = 0;
#ifndef TORRENT_DISABLE_ENCRYPTION
buffer::interval wr_recv_buffer()
{
TORRENT_ASSERT(m_disk_recv_buffer == 0);
TORRENT_ASSERT(!m_disk_recv_buffer);
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
if (m_recv_buffer.empty()) return buffer::interval(0,0);
return buffer::interval(&m_recv_buffer[0]
@ -501,9 +509,9 @@ namespace libtorrent
// called from the main loop when this connection has any
// work to do.
void on_send_data(asio::error_code const& error
void on_send_data(error_code const& error
, std::size_t bytes_transferred);
void on_receive_data(asio::error_code const& error
void on_receive_data(error_code const& error
, std::size_t bytes_transferred);
// this is the limit on the number of outstanding requests
@ -544,9 +552,6 @@ namespace libtorrent
void on_disk_write_complete(int ret, disk_io_job const& j
, peer_request r, boost::shared_ptr<torrent> t);
// the timeout in seconds
int m_timeout;
// the time when we last got a part of a
// piece packet from this peer
ptime m_last_piece;
@ -559,28 +564,54 @@ namespace libtorrent
// the time when we unchoked this peer
ptime m_last_unchoke;
int m_packet_size;
int m_recv_pos;
// timeouts
ptime m_last_receive;
ptime m_last_sent;
// a timestamp when the remote download rate
// was last updated
ptime m_remote_dl_update;
// the time when async_connect was called
ptime m_connect;
// the time when this peer sent us a not_interested message
// the last time.
ptime m_became_uninterested;
// the time when we sent a not_interested message to
// this peer the last time.
ptime m_became_uninteresting;
// the amount of data this peer has been given
// as free upload. This is distributed from
// peers from which we get free download
// this will be negative on a peer from which
// we get free download, and positive on peers
// that we give the free upload, to keep the balance.
size_type m_free_upload;
// the total payload download bytes
// at the last unchoke cycle. This is used to
// measure the number of bytes transferred during
// an unchoke cycle, to unchoke peers the more bytes
// they sent us
size_type m_downloaded_at_last_unchoke;
#ifndef TORRENT_DISABLE_GEO_IP
std::string m_inet_as_name;
#endif
buffer m_recv_buffer;
// if this peer is receiving a piece, this
// points to a disk buffer that the data is
// read into. This eliminates a memcopy from
// the receive buffer into the disk buffer
int m_disk_recv_buffer_size;
char* m_disk_recv_buffer;
disk_buffer_holder m_disk_recv_buffer;
chained_buffer m_send_buffer;
// the number of bytes we are currently reading
// from disk, that will be added to the send
// buffer as soon as they complete
int m_reading_bytes;
// timeouts
ptime m_last_receive;
ptime m_last_sent;
boost::shared_ptr<socket_type> m_socket;
// this is the peer we're actually talking to
// it may not necessarily be the peer we're
@ -593,51 +624,12 @@ namespace libtorrent
// until the info_hash is received. Then it's
// set to the torrent it belongs to.
boost::weak_ptr<torrent> m_torrent;
// is true if it was we that connected to the peer
// and false if we got an incoming connection
// could be considered: true = local, false = remote
bool m_active;
// remote peer's id
peer_id m_peer_id;
// other side says that it's interested in downloading
// from us.
bool m_peer_interested;
// the other side has told us that it won't send anymore
// data to us for a while
bool m_peer_choked;
// the peer has pieces we are interested in
bool m_interesting;
// we have choked the upload to the peer
bool m_choked;
// this is set to true if the connection timed
// out or closed the connection. In that
// case we will not try to reconnect to
// this peer
bool m_failed;
// if this is set to true, the peer will not
// request bandwidth from the limiter, but instead
// just send and receive as much as possible.
bool m_ignore_bandwidth_limits;
// the pieces the other end have
std::vector<bool> m_have_piece;
// this is set to true when a have_all
// message is received. This information
// is used to fill the bitmask in init()
bool m_have_all;
// the number of pieces this peer
// has. Must be the same as
// std::count(m_have_piece.begin(),
// m_have_piece.end(), true)
int m_num_pieces;
// the queue of requests we have got
// from this peer
@ -651,24 +643,41 @@ namespace libtorrent
// from this peer
std::deque<piece_block> m_download_queue;
// the number of request we should queue up
// at the remote end.
int m_desired_queue_size;
// the pieces we will send to the peer
// if requested (regardless of choke state)
std::set<int> m_accept_fast;
// the amount of data this peer has been given
// as free upload. This is distributed from
// peers from which we get free download
// this will be negative on a peer from which
// we get free download, and positive on peers
// that we give the free upload, to keep the balance.
size_type m_free_upload;
// the pieces the peer will send us if
// requested (regardless of choke state)
std::vector<int> m_allowed_fast;
// if this is true, this peer is assumed to handle all piece
// requests in fifo order. All skipped blocks are re-requested
// immediately instead of having a looser requirement
// where blocks can be sent out of order. The default is to
// allow non-fifo order.
bool m_assume_fifo;
// pieces that has been suggested to be
// downloaded from this peer
std::vector<int> m_suggested_pieces;
// the number of pieces this peer
// has. Must be the same as
// std::count(m_have_piece.begin(),
// m_have_piece.end(), true)
int m_num_pieces;
// the timeout in seconds
int m_timeout;
// the size (in bytes) of the bittorrent message
// we're currently receiving
int m_packet_size;
// the number of bytes of the bittorrent payload
// we've received so far
int m_recv_pos;
int m_disk_recv_buffer_size;
// the number of bytes we are currently reading
// from disk, that will be added to the send
// buffer as soon as they complete
int m_reading_bytes;
// the number of invalid piece-requests
// we have got from this peer. If the request
@ -679,49 +688,6 @@ namespace libtorrent
// by sending choke, unchoke.
int m_num_invalid_requests;
// this is true if this connection has been added
// to the list of connections that will be closed.
bool m_disconnecting;
// the time when this peer sent us a not_interested message
// the last time.
ptime m_became_uninterested;
// the time when we sent a not_interested message to
// this peer the last time.
ptime m_became_uninteresting;
// this is true until this socket has become
// writable for the first time (i.e. the
// connection completed). While connecting
// the timeout will not be triggered. This is
// because windows XP SP2 may delay connection
// attempts, which means that the connection
// may not even have been attempted when the
// time out is reached.
bool m_connecting;
// This is true until connect is called on the
// peer_connection's socket. It is false on incoming
// connections.
bool m_queued;
// if set to non-zero, this peer will always prefer
// to request entire n pieces, rather than blocks.
// where n is the value of this variable.
// if it is 0, the download rate limit setting
// will be used to determine if whole pieces
// are preferred.
int m_prefer_whole_pieces;
// if this is true, the blocks picked by the piece
// picker will be merged before passed to the
// request function. i.e. subsequent blocks are
// merged into larger blocks. This is used by
// the http-downloader, to request whole pieces
// at a time.
bool m_request_large_blocks;
// this is the priority with which this peer gets
// download bandwidth quota assigned to it.
int m_priority;
@ -753,60 +719,114 @@ namespace libtorrent
// approximate peer download rate
int m_remote_dl_rate;
// a timestamp when the remote download rate
// was last updated
ptime m_remote_dl_update;
// the pieces we will send to the peer
// if requested (regardless of choke state)
std::set<int> m_accept_fast;
// the pieces the peer will send us if
// requested (regardless of choke state)
std::vector<int> m_allowed_fast;
// pieces that has been suggested to be
// downloaded from this peer
std::vector<int> m_suggested_pieces;
// the number of bytes send to the disk-io
// thread that hasn't yet been completely written.
int m_outstanding_writing_bytes;
// max transfer rates seen on this peer
int m_download_rate_peak;
int m_upload_rate_peak;
// estimated round trip time to this peer
// based on the time from when async_connect
// was called to when on_connection_complete
// was called. The rtt is specified in milliseconds
boost::uint16_t m_rtt;
// if set to non-zero, this peer will always prefer
// to request entire n pieces, rather than blocks.
// where n is the value of this variable.
// if it is 0, the download rate limit setting
// will be used to determine if whole pieces
// are preferred.
boost::uint8_t m_prefer_whole_pieces;
// the number of request we should queue up
// at the remote end.
boost::uint8_t m_desired_queue_size;
// if this is true, the disconnection
// timestamp is not updated when the connection
// is closed. This means the time until we can
// reconnect to this peer is shorter, and likely
// immediate.
bool m_fast_reconnect;
bool m_fast_reconnect:1;
// the time when async_connect was called
ptime m_connect;
// is true if it was we that connected to the peer
// and false if we got an incoming connection
// could be considered: true = local, false = remote
bool m_active:1;
// estimated round trip time to this peer
// based on the time from when async_connect
// was called to when on_connection_complete
// was called. The rtt is specified in milliseconds
int m_rtt;
// other side says that it's interested in downloading
// from us.
bool m_peer_interested:1;
// the total payload download bytes
// at the last unchoke cycle. This is used to
// measure the number of bytes transferred during
// an unchoke cycle, to unchoke peers the more bytes
// they sent us
size_type m_downloaded_at_last_unchoke;
// the other side has told us that it won't send anymore
// data to us for a while
bool m_peer_choked:1;
#ifndef TORRENT_DISABLE_GEO_IP
std::string m_inet_as_name;
#endif
// the peer has pieces we are interested in
bool m_interesting:1;
// max transfer rates seen on this peer
int m_download_rate_peak;
int m_upload_rate_peak;
// we have choked the upload to the peer
bool m_choked:1;
// this is set to true if the connection timed
// out or closed the connection. In that
// case we will not try to reconnect to
// this peer
bool m_failed:1;
// if this is set to true, the peer will not
// request bandwidth from the limiter, but instead
// just send and receive as much as possible.
bool m_ignore_bandwidth_limits:1;
// this is set to true when a have_all
// message is received. This information
// is used to fill the bitmask in init()
bool m_have_all:1;
// if this is true, this peer is assumed to handle all piece
// requests in fifo order. All skipped blocks are re-requested
// immediately instead of having a looser requirement
// where blocks can be sent out of order. The default is to
// allow non-fifo order.
bool m_assume_fifo:1;
// this is true if this connection has been added
// to the list of connections that will be closed.
bool m_disconnecting:1;
// this is true until this socket has become
// writable for the first time (i.e. the
// connection completed). While connecting
// the timeout will not be triggered. This is
// because windows XP SP2 may delay connection
// attempts, which means that the connection
// may not even have been attempted when the
// time out is reached.
bool m_connecting:1;
// This is true until connect is called on the
// peer_connection's socket. It is false on incoming
// connections.
bool m_queued:1;
// if this is true, the blocks picked by the piece
// picker will be merged before passed to the
// request function. i.e. subsequent blocks are
// merged into larger blocks. This is used by
// the http-downloader, to request whole pieces
// at a time.
bool m_request_large_blocks:1;
// set to true when this peer is only uploading
bool m_upload_only:1;
#ifndef NDEBUG
public:
bool m_in_constructor;
bool m_in_constructor:1;
#endif
};
}

View File

@ -142,6 +142,9 @@ namespace libtorrent
iterator begin() { return m_number; }
iterator end() { return m_number+number_size; }
std::string to_string() const
{ return std::string((char const*)&m_number[0], number_size); }
private:
unsigned char m_number[number_size];

View File

@ -248,7 +248,6 @@ namespace libtorrent
const_iterator end_peer() const { return m_peers.end(); }
bool connect_one_peer();
bool disconnect_one_peer();
bool has_peer(policy::peer const* p) const;
@ -267,7 +266,6 @@ namespace libtorrent
bool compare_peer(policy::peer const& lhs, policy::peer const& rhs
, address const& external_ip) const;
iterator find_disconnect_candidate();
iterator find_connect_candidate();
bool is_connect_candidate(peer const& p, bool finished);

View File

@ -38,9 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#if BOOST_VERSION < 103500
#include <asio/read.hpp>
#include <asio/write.hpp>
#else
#include <boost/asio/read.hpp>
#include <boost/asio/write.hpp>
#endif
namespace libtorrent {
@ -52,7 +56,7 @@ public:
typedef stream_socket::endpoint_type endpoint_type;
typedef stream_socket::protocol_type protocol_type;
explicit proxy_base(asio::io_service& io_service)
explicit proxy_base(io_service& io_service)
: m_sock(io_service)
, m_resolver(io_service)
{}
@ -70,7 +74,7 @@ public:
}
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
{
return m_sock.read_some(buffers, ec);
}
@ -90,7 +94,7 @@ public:
#endif
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc, asio::error_code& ec)
void io_control(IO_Control_Command& ioc, error_code& ec)
{
m_sock.io_control(ioc, ec);
}
@ -110,7 +114,7 @@ public:
#endif
template <class SettableSocketOption>
asio::error_code set_option(SettableSocketOption const& opt, asio::error_code& ec)
error_code set_option(SettableSocketOption const& opt, error_code& ec)
{
return m_sock.set_option(opt, ec);
}
@ -122,7 +126,7 @@ public:
}
#endif
void bind(endpoint_type const& endpoint, asio::error_code& ec)
void bind(endpoint_type const& endpoint, error_code& ec)
{
m_sock.bind(endpoint, ec);
}
@ -134,7 +138,7 @@ public:
}
#endif
void open(protocol_type const& p, asio::error_code& ec)
void open(protocol_type const& p, error_code& ec)
{
m_sock.open(p, ec);
}
@ -148,7 +152,7 @@ public:
}
#endif
void close(asio::error_code& ec)
void close(error_code& ec)
{
m_sock.close(ec);
m_resolver.cancel();
@ -161,7 +165,7 @@ public:
}
#endif
endpoint_type remote_endpoint(asio::error_code& ec) const
endpoint_type remote_endpoint(error_code& ec) const
{
return m_remote_endpoint;
}
@ -173,14 +177,14 @@ public:
}
#endif
endpoint_type local_endpoint(asio::error_code& ec) const
endpoint_type local_endpoint(error_code& ec) const
{
return m_sock.local_endpoint(ec);
}
asio::io_service& io_service()
io_service& get_io_service()
{
return m_sock.io_service();
return m_sock.get_io_service();
}
lowest_layer_type& lowest_layer()

View File

@ -129,7 +129,7 @@ namespace libtorrent
, resume_data(0)
, storage_mode(storage_mode_sparse)
, paused(true)
, auto_managed(false)
, auto_managed(true)
, duplicate_is_error(false)
, storage(sc)
, userdata(0)

View File

@ -102,11 +102,7 @@ namespace libtorrent
, min_reconnect_time(60)
, peer_connect_timeout(7)
, ignore_limits_on_local_network(true)
#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
, connection_speed(2)
#else
, connection_speed(20)
#endif
, send_redundant_have(false)
, lazy_bitfields(true)
, inactivity_timeout(600)
@ -134,6 +130,11 @@ namespace libtorrent
, share_ratio_limit(2.f)
, seed_time_ratio_limit(7.f)
, seed_time_limit(24 * 60 * 60) // 24 hours
, peer_turnover(1 / 50.f)
, peer_turnover_cutoff(1.f)
, close_redundant_connections(true)
, auto_scrape_interval(1800)
, auto_scrape_min_interval(300)
{}
// this is the user agent that will be sent to the tracker
@ -376,6 +377,31 @@ namespace libtorrent
float share_ratio_limit;
float seed_time_ratio_limit;
int seed_time_limit;
// the percentage of peers to disconnect every
// 90 seconds (if we're at the peer limit)
// defaults to 1/50:th
float peer_turnover;
// when we are connected to more than
// limit * peer_turnover_enable peers
// disconnect peer_turnover fraction
// of the peers
float peer_turnover_cutoff;
// if this is true (default) connections where both
// ends have no utility in keeping the connection open
// are closed. for instance if both ends have completed
// their downloads
bool close_redundant_connections;
// the number of seconds between scrapes of
// queued torrents (auto managed and paused)
int auto_scrape_interval;
// the minimum number of seconds between any
// automatic scrape (regardless of torrent)
int auto_scrape_min_interval;
};
#ifndef TORRENT_DISABLE_DHT

View File

@ -45,13 +45,25 @@ POSSIBILITY OF SUCH DAMAGE.
#define Protocol Protocol_
#endif
#if BOOST_VERSION < 103500
#include <asio/ip/tcp.hpp>
#include <asio/ip/udp.hpp>
#include <asio/io_service.hpp>
#include <asio/deadline_timer.hpp>
#include <asio/write.hpp>
#include <asio/read.hpp>
#include <asio/time_traits.hpp>
#include <asio/basic_deadline_timer.hpp>
#else
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/read.hpp>
#include <boost/asio/time_traits.hpp>
#include <boost/asio/basic_deadline_timer.hpp>
#endif
#ifdef __OBJC__
#undef Protocol
@ -67,24 +79,12 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
/*
namespace asio = boost::asio;
using boost::asio::ipv4::tcp;
using boost::asio::ipv4::address;
using boost::asio::stream_socket;
using boost::asio::datagram_socket;
using boost::asio::socket_acceptor;
using boost::asio::io_service;
using boost::asio::ipv4::host_resolver;
using boost::asio::async_write;
using boost::asio::ipv4::host;
using boost::asio::deadline_timer;
*/
// namespace asio = ::asio;
#if BOOST_VERSION < 103500
using asio::ip::tcp;
using asio::ip::udp;
using asio::async_write;
using asio::async_read;
typedef asio::ip::tcp::socket stream_socket;
typedef asio::ip::address address;
typedef asio::ip::address_v4 address_v4;
@ -92,14 +92,32 @@ namespace libtorrent
typedef asio::ip::udp::socket datagram_socket;
typedef asio::ip::tcp::acceptor socket_acceptor;
typedef asio::io_service io_service;
typedef asio::error_code error_code;
using asio::async_write;
namespace asio = ::asio;
typedef asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
#else
using boost::system::error_code;
using boost::asio::ip::tcp;
using boost::asio::ip::udp;
using boost::asio::async_write;
using boost::asio::async_read;
typedef boost::asio::ip::tcp::socket stream_socket;
typedef boost::asio::ip::address address;
typedef boost::asio::ip::address_v4 address_v4;
typedef boost::asio::ip::address_v6 address_v6;
typedef boost::asio::ip::udp::socket datagram_socket;
typedef boost::asio::ip::tcp::acceptor socket_acceptor;
typedef boost::asio::io_service io_service;
namespace asio = boost::asio;
typedef boost::asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
#endif
inline std::ostream& print_address(std::ostream& os, address const& addr)
{
asio::error_code ec;
error_code ec;
std::string a = addr.to_string(ec);
if (ec) return os;
os << a;
@ -109,7 +127,7 @@ namespace libtorrent
inline std::ostream& print_endpoint(std::ostream& os, tcp::endpoint const& ep)
{
address const& addr = ep.address();
asio::error_code ec;
error_code ec;
std::string a = addr.to_string(ec);
if (ec) return os;
@ -132,7 +150,7 @@ namespace libtorrent
}
else if (a.is_v6())
{
asio::ip::address_v6::bytes_type bytes
address_v6::bytes_type bytes
= a.to_v6().to_bytes();
std::copy(bytes.begin(), bytes.end(), out);
}
@ -142,18 +160,18 @@ namespace libtorrent
address read_v4_address(InIt& in)
{
unsigned long ip = read_uint32(in);
return asio::ip::address_v4(ip);
return address_v4(ip);
}
template<class InIt>
address read_v6_address(InIt& in)
{
typedef asio::ip::address_v6::bytes_type bytes_t;
typedef address_v6::bytes_type bytes_t;
bytes_t bytes;
for (bytes_t::iterator i = bytes.begin()
, end(bytes.end()); i != end; ++i)
*i = read_uint8(in);
return asio::ip::address_v6(bytes);
return address_v6(bytes);
}
template<class Endpoint, class OutIt>

View File

@ -41,8 +41,8 @@ class socks4_stream : public proxy_base
{
public:
explicit socks4_stream(asio::io_service& io_service)
: proxy_base(io_service)
explicit socks4_stream(io_service& io_service_)
: proxy_base(io_service_)
{}
void set_username(std::string const& user)
@ -50,7 +50,7 @@ public:
m_user = user;
}
typedef boost::function<void(asio::error_code const&)> handler_type;
typedef boost::function<void(error_code const&)> handler_type;
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
@ -74,11 +74,11 @@ public:
private:
void name_lookup(asio::error_code const& e, tcp::resolver::iterator i
void name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h);
void connected(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
// send and receive buffer
std::vector<char> m_buffer;

View File

@ -41,7 +41,7 @@ class socks5_stream : public proxy_base
{
public:
explicit socks5_stream(asio::io_service& io_service)
explicit socks5_stream(io_service& io_service)
: proxy_base(io_service)
{}
@ -52,7 +52,7 @@ public:
m_password = password;
}
typedef boost::function<void(asio::error_code const&)> handler_type;
typedef boost::function<void(error_code const&)> handler_type;
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
@ -79,17 +79,17 @@ public:
private:
void name_lookup(asio::error_code const& e, tcp::resolver::iterator i
void name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h);
void connected(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void handshake3(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void handshake4(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake3(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake4(error_code const& e, boost::shared_ptr<handler_type> h);
void socks_connect(boost::shared_ptr<handler_type> h);
void connect1(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void connect2(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void connect3(asio::error_code const& e, boost::shared_ptr<handler_type> h);
void connect1(error_code const& e, boost::shared_ptr<handler_type> h);
void connect2(error_code const& e, boost::shared_ptr<handler_type> h);
void connect3(error_code const& e, boost::shared_ptr<handler_type> h);
// send and receive buffer
std::vector<char> m_buffer;

View File

@ -34,8 +34,11 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_SSL_STREAM_HPP_INCLUDED
#include "libtorrent/socket.hpp"
#if BOOST_VERSION < 103500
#include <asio/ssl.hpp>
#else
#include <boost/asio/ssl.hpp>
#endif
// openssl seems to believe it owns
// this name in every single scope
#undef set_key
@ -47,7 +50,7 @@ class ssl_stream
{
public:
explicit ssl_stream(asio::io_service& io_service)
explicit ssl_stream(io_service& io_service)
: m_context(io_service, asio::ssl::context::sslv23_client)
, m_sock(io_service, m_context)
{
@ -60,7 +63,7 @@ public:
typedef typename Stream::protocol_type protocol_type;
typedef typename asio::ssl::stream<Stream> sock_type;
typedef boost::function<void(asio::error_code const&)> handler_type;
typedef boost::function<void(error_code const&)> handler_type;
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
@ -70,7 +73,7 @@ public:
// 2. perform SSL client handshake
// to avoid unnecessary copying of the handler,
// store it in a shaed_ptr
// store it in a shared_ptr
boost::shared_ptr<handler_type> h(new handler_type(handler));
m_sock.next_layer().async_connect(endpoint
@ -84,7 +87,7 @@ public:
}
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
{
return m_sock.read_some(buffers, ec);
}
@ -104,7 +107,7 @@ public:
#endif
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc, asio::error_code& ec)
void io_control(IO_Control_Command& ioc, error_code& ec)
{
m_sock.next_layer().io_control(ioc, ec);
}
@ -122,7 +125,7 @@ public:
}
#endif
void bind(endpoint_type const& endpoint, asio::error_code& ec)
void bind(endpoint_type const& endpoint, error_code& ec)
{
m_sock.next_layer().bind(endpoint, ec);
}
@ -134,7 +137,7 @@ public:
}
#endif
void open(protocol_type const& p, asio::error_code& ec)
void open(protocol_type const& p, error_code& ec)
{
m_sock.next_layer().open(p, ec);
}
@ -151,7 +154,7 @@ public:
}
#endif
void close(asio::error_code& ec)
void close(error_code& ec)
{
m_sock.next_layer().close(ec);
}
@ -163,7 +166,7 @@ public:
}
#endif
endpoint_type remote_endpoint(asio::error_code& ec) const
endpoint_type remote_endpoint(error_code& ec) const
{
return const_cast<sock_type&>(m_sock).next_layer().remote_endpoint(ec);
}
@ -175,14 +178,14 @@ public:
}
#endif
endpoint_type local_endpoint(asio::error_code& ec) const
endpoint_type local_endpoint(error_code& ec) const
{
return const_cast<sock_type&>(m_sock).next_layer().local_endpoint(ec);
}
asio::io_service& io_service()
io_service& get_io_service()
{
return m_sock.io_service();
return m_sock.get_io_service();
}
lowest_layer_type& lowest_layer()
@ -197,7 +200,7 @@ public:
private:
void connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void connected(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
@ -209,7 +212,7 @@ private:
, boost::bind(&ssl_stream::handshake, this, _1, h));
}
void handshake(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void handshake(error_code const& e, boost::shared_ptr<handler_type> h)
{
(*h)(e);
}

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <vector>
#include <assert.h>
#include <cstring>
#include "libtorrent/size_type.hpp"
#include "libtorrent/invariant_check.hpp"
@ -44,88 +45,162 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
class TORRENT_EXPORT stat
class TORRENT_EXPORT stat_channel
{
friend class invariant_access;
public:
enum { history = 10 };
stat()
: m_downloaded_payload(0)
, m_uploaded_payload(0)
, m_downloaded_protocol(0)
, m_uploaded_protocol(0)
, m_total_download_payload(0)
, m_total_upload_payload(0)
, m_total_download_protocol(0)
, m_total_upload_protocol(0)
, m_mean_download_rate(0)
, m_mean_upload_rate(0)
, m_mean_download_payload_rate(0)
, m_mean_upload_payload_rate(0)
stat_channel()
: m_counter(0)
, m_total_counter(0)
, m_rate_sum(0)
{
std::fill(m_download_rate_history, m_download_rate_history+history, 0.f);
std::fill(m_upload_rate_history, m_upload_rate_history+history, 0.f);
std::fill(m_download_payload_rate_history, m_download_payload_rate_history+history, 0.f);
std::fill(m_upload_payload_rate_history, m_upload_payload_rate_history+history, 0.f);
std::memset(m_rate_history, 0, sizeof(m_rate_history));
}
void operator+=(const stat& s)
void operator+=(stat_channel const& s)
{
INVARIANT_CHECK;
m_downloaded_payload += s.m_downloaded_payload;
m_total_download_payload += s.m_downloaded_payload;
m_downloaded_protocol += s.m_downloaded_protocol;
m_total_download_protocol += s.m_downloaded_protocol;
m_uploaded_payload += s.m_uploaded_payload;
m_total_upload_payload += s.m_uploaded_payload;
m_uploaded_protocol += s.m_uploaded_protocol;
m_total_upload_protocol += s.m_uploaded_protocol;
m_counter += s.m_counter;
m_total_counter += s.m_counter;
}
void received_bytes(int bytes_payload, int bytes_protocol)
void add(int count)
{
INVARIANT_CHECK;
TORRENT_ASSERT(count >= 0);
TORRENT_ASSERT(bytes_payload >= 0);
TORRENT_ASSERT(bytes_protocol >= 0);
m_downloaded_payload += bytes_payload;
m_total_download_payload += bytes_payload;
m_downloaded_protocol += bytes_protocol;
m_total_download_protocol += bytes_protocol;
}
void sent_bytes(int bytes_payload, int bytes_protocol)
{
INVARIANT_CHECK;
TORRENT_ASSERT(bytes_payload >= 0);
TORRENT_ASSERT(bytes_protocol >= 0);
m_uploaded_payload += bytes_payload;
m_total_upload_payload += bytes_payload;
m_uploaded_protocol += bytes_protocol;
m_total_upload_protocol += bytes_protocol;
m_counter += count;
m_total_counter += count;
}
// should be called once every second
void second_tick(float tick_interval);
float rate() const { return m_rate_sum / float(history); }
size_type rate_sum() const { return m_rate_sum; }
size_type total() const { return m_total_counter; }
float upload_rate() const { return m_mean_upload_rate; }
float download_rate() const { return m_mean_download_rate; }
void offset(size_type counter)
{
TORRENT_ASSERT(counter >= 0);
m_total_counter += counter;
}
float upload_payload_rate() const { return m_mean_upload_payload_rate; }
float download_payload_rate() const { return m_mean_download_payload_rate; }
size_type counter() const { return m_counter; }
size_type total_payload_upload() const { return m_total_upload_payload; }
size_type total_payload_download() const { return m_total_download_payload; }
private:
size_type total_protocol_upload() const { return m_total_upload_protocol; }
size_type total_protocol_download() const { return m_total_download_protocol; }
#ifndef NDEBUG
void check_invariant() const
{
int sum = 0;
for (int i = 0; i < history; ++i) sum += m_rate_history[i];
TORRENT_ASSERT(m_rate_sum == sum);
TORRENT_ASSERT(m_total_counter >= 0);
}
#endif
// history of rates a few seconds back
int m_rate_history[history];
// the accumulator for this second.
int m_counter;
// total counters
size_type m_total_counter;
// sum of all elements in m_rate_history
size_type m_rate_sum;
};
class TORRENT_EXPORT stat
{
friend class invariant_access;
public:
void operator+=(const stat& s)
{
for (int i = 0; i < num_channels; ++i)
m_stat[i] += s.m_stat[i];
}
void received_bytes(int bytes_payload, int bytes_protocol)
{
TORRENT_ASSERT(bytes_payload >= 0);
TORRENT_ASSERT(bytes_protocol >= 0);
m_stat[download_payload].add(bytes_payload);
m_stat[download_protocol].add(bytes_protocol);
}
void sent_bytes(int bytes_payload, int bytes_protocol)
{
TORRENT_ASSERT(bytes_payload >= 0);
TORRENT_ASSERT(bytes_protocol >= 0);
m_stat[upload_payload].add(bytes_payload);
m_stat[upload_protocol].add(bytes_protocol);
}
// calculate ip protocol overhead
void calc_ip_overhead()
{
int uploaded = m_stat[upload_protocol].counter()
+ m_stat[upload_payload].counter();
int downloaded = m_stat[download_protocol].counter()
+ m_stat[download_payload].counter();
// IP + TCP headers are 40 bytes per MTU (1460)
// bytes of payload, but at least 40 bytes
m_stat[upload_ip_protocol].add((std::max)(uploaded / 1460, uploaded>0?40:0));
m_stat[download_ip_protocol].add((std::max)(downloaded / 1460, downloaded>0?40:0));
// also account for ACK traffic. That adds to the transfers
// in the opposite direction. Even on connections with symmetric
// transfer rates, it seems to add a penalty.
m_stat[upload_ip_protocol].add((std::max)(downloaded * 40 / 1460, downloaded>0?40:0));
m_stat[download_ip_protocol].add((std::max)(uploaded * 40 / 1460, uploaded>0?40:0));
}
int upload_ip_overhead() const { return m_stat[upload_ip_protocol].counter(); }
int download_ip_overhead() const { return m_stat[download_ip_protocol].counter(); }
// should be called once every second
void second_tick(float tick_interval)
{
for (int i = 0; i < num_channels; ++i)
m_stat[i].second_tick(tick_interval);
}
float upload_rate() const
{
return (m_stat[upload_payload].rate_sum()
+ m_stat[upload_protocol].rate_sum()
+ m_stat[upload_ip_protocol].rate_sum())
/ float(stat_channel::history);
}
float download_rate() const
{
return (m_stat[download_payload].rate_sum()
+ m_stat[download_protocol].rate_sum()
+ m_stat[download_ip_protocol].rate_sum())
/ float(stat_channel::history);
}
float upload_payload_rate() const
{ return m_stat[upload_payload].rate(); }
float download_payload_rate() const
{ return m_stat[download_payload].rate(); }
size_type total_payload_upload() const
{ return m_stat[upload_payload].total(); }
size_type total_payload_download() const
{ return m_stat[download_payload].total(); }
size_type total_protocol_upload() const
{ return m_stat[upload_protocol].total(); }
size_type total_protocol_download() const
{ return m_stat[download_protocol].total(); }
// this is used to offset the statistics when a
// peer_connection is opened and have some previous
@ -134,66 +209,33 @@ namespace libtorrent
{
TORRENT_ASSERT(downloaded >= 0);
TORRENT_ASSERT(uploaded >= 0);
m_total_download_payload += downloaded;
m_total_upload_payload += uploaded;
m_stat[download_payload].offset(downloaded);
m_stat[upload_payload].offset(uploaded);
}
size_type last_payload_downloaded() const { return m_downloaded_payload; }
size_type last_payload_uploaded() const { return m_uploaded_payload; }
size_type last_payload_downloaded() const
{ return m_stat[download_payload].counter(); }
size_type last_payload_uploaded() const
{ return m_stat[upload_payload].counter(); }
private:
#ifndef NDEBUG
void check_invariant() const
// these are the channels we keep stats for
enum
{
TORRENT_ASSERT(m_mean_upload_rate >= 0);
TORRENT_ASSERT(m_mean_download_rate >= 0);
TORRENT_ASSERT(m_mean_upload_payload_rate >= 0);
TORRENT_ASSERT(m_mean_download_payload_rate >= 0);
TORRENT_ASSERT(m_total_upload_payload >= 0);
TORRENT_ASSERT(m_total_download_payload >= 0);
TORRENT_ASSERT(m_total_upload_protocol >= 0);
TORRENT_ASSERT(m_total_download_protocol >= 0);
}
#endif
upload_payload,
upload_protocol,
upload_ip_protocol,
download_payload,
download_protocol,
download_ip_protocol,
num_channels
};
// history of download/upload speeds a few seconds back
float m_download_rate_history[history];
float m_upload_rate_history[history];
float m_download_payload_rate_history[history];
float m_upload_payload_rate_history[history];
// the accumulators we are adding the downloads/uploads
// to this second. This only counts the actual payload
// and ignores the bytes sent as protocol chatter.
int m_downloaded_payload;
int m_uploaded_payload;
// the accumulators we are adding the downloads/uploads
// to this second. This only counts the protocol
// chatter and ignores the actual payload
int m_downloaded_protocol;
int m_uploaded_protocol;
// total download/upload counters
// only counting payload data
size_type m_total_download_payload;
size_type m_total_upload_payload;
// total download/upload counters
// only counting protocol chatter
size_type m_total_download_protocol;
size_type m_total_upload_protocol;
// current mean download/upload rates
float m_mean_download_rate;
float m_mean_upload_rate;
float m_mean_download_payload_rate;
float m_mean_upload_payload_rate;
stat_channel m_stat[num_channels];
};
}
#endif // TORRENT_STAT_HPP_INCLUDED

View File

@ -86,7 +86,11 @@ namespace libtorrent
#else
#if BOOST_VERSION < 103500
#include <asio/time_traits.hpp>
#else
#include <boost/asio/time_traits.hpp>
#endif
#include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp"
@ -152,6 +156,9 @@ namespace libtorrent
}
// asio time_traits
#if BOOST_VERSION >= 103500
namespace boost {
#endif
namespace asio
{
template<>
@ -172,6 +179,9 @@ namespace asio
{ return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
};
}
#if BOOST_VERSION >= 103500
}
#endif
#if defined(__MACH__)

View File

@ -151,8 +151,7 @@ namespace libtorrent
void files_checked();
void start_checking();
float seed_cycles(session_settings const& s) const;
int seed_cycles_int(session_settings const& s) const { return int(seed_cycles(s)); }
int seed_rank(session_settings const& s) const;
storage_mode_t storage_mode() const { return m_storage_mode; }
// this will flag the torrent as aborted. The main
@ -356,6 +355,7 @@ namespace libtorrent
void force_tracker_request();
void force_tracker_request(ptime);
void scrape_tracker();
ptime const& last_scrape() const { return m_last_scrape; }
// sets the username and password that will be sent to
// the tracker
@ -453,6 +453,7 @@ namespace libtorrent
void announce_piece(int index);
void disconnect_all();
int disconnect_peers(int num);
// this is called wheh the torrent has completed
// the download. It will post an event, disconnect
@ -461,17 +462,17 @@ namespace libtorrent
// this is the asio callback that is called when a name
// lookup for a PEER is completed.
void on_peer_name_lookup(asio::error_code const& e, tcp::resolver::iterator i
void on_peer_name_lookup(error_code const& e, tcp::resolver::iterator i
, peer_id pid);
// this is the asio callback that is called when a name
// lookup for a WEB SEED is completed.
void on_name_lookup(asio::error_code const& e, tcp::resolver::iterator i
void on_name_lookup(error_code const& e, tcp::resolver::iterator i
, std::string url, tcp::endpoint proxy);
// this is the asio callback that is called when a name
// lookup for a proxy for a web seed is completed.
void on_proxy_name_lookup(asio::error_code const& e, tcp::resolver::iterator i
void on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator i
, std::string url);
// this is called when the torrent has finished. i.e.
@ -480,6 +481,11 @@ namespace libtorrent
// completed() is called immediately after it.
void finished();
// This is the opposite of finished. It is called if we used
// to be finished but enabled some files for download so that
// we wasn't finished anymore.
void resume_download();
void async_verify_piece(int piece_index, boost::function<void(int)> const&);
// this is called from the peer_connection
@ -570,7 +576,7 @@ namespace libtorrent
// to the checker thread for initial checking
// of the storage.
// a return value of false indicates an error
bool set_metadata(entry const& metadata, std::string& error);
bool set_metadata(lazy_entry const& metadata, std::string& error);
int sequence_number() const { return m_sequence_number; }
@ -587,40 +593,43 @@ namespace libtorrent
void try_next_tracker();
int prioritize_tracker(int tracker_index);
void on_country_lookup(asio::error_code const& error, tcp::resolver::iterator i
void on_country_lookup(error_code const& error, tcp::resolver::iterator i
, boost::intrusive_ptr<peer_connection> p) const;
bool request_bandwidth_from_session(int channel) const;
void update_peer_interest(bool was_finished);
policy m_policy;
// total time we've been available on this torrent
// does not count when the torrent is stopped or paused
time_duration m_active_time;
// total time we've been available as a seed on this torrent
// does not count when the torrent is stopped or paused
time_duration m_seeding_time;
// all time totals of uploaded and downloaded payload
// stored in resume data
size_type m_total_uploaded;
size_type m_total_downloaded;
// if this torrent is running, this was the time
// when it was started. This is used to have a
// bias towards keeping seeding torrents that
// recently was started, to avoid oscillation
ptime m_started;
// the last time we initiated a scrape request to
// one of the trackers in this torrent
ptime m_last_scrape;
boost::intrusive_ptr<torrent_info> m_torrent_file;
// is set to true when the torrent has
// been aborted.
bool m_abort;
// is true if this torrent has been paused
bool m_paused;
// this is true from the time when the torrent was
// paused to the time should_request() is called
bool m_just_paused;
// if this is true, libtorrent may pause and resume
// this torrent depending on queuing rules. Torrents
// started with auto_managed flag set may be added in
// a paused state in case there are no available
// slots.
bool m_auto_managed;
tracker_request::event_t m_event;
void parse_response(const entry& e, std::vector<peer_entry>& peer_list);
// the size of a request block
// each piece is divided into these
// blocks when requested
int m_block_size;
// if this pointer is 0, the torrent is in
// a state where the metadata hasn't been
// received yet.
@ -649,18 +658,6 @@ namespace libtorrent
// the time of next tracker request
ptime m_next_request;
// -----------------------------
// DATA FROM TRACKER RESPONSE
// the number number of seconds between requests
// from the tracker
int m_duration;
// the scrape data from the tracker response, this
// is optional and may be -1.
int m_complete;
int m_incomplete;
#ifndef NDEBUG
public:
#endif
@ -681,28 +678,21 @@ namespace libtorrent
// resolving the address for
std::set<std::string> m_resolving_web_seeds;
#ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;
extension_list_t m_extensions;
#endif
// used to resolve the names of web seeds
mutable tcp::resolver m_host_resolver;
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
// this is true while there is a country
// resolution in progress. To avoid flodding
// the DNS request queue, only one ip is resolved
// at a time.
mutable bool m_resolving_country;
// this is true if the user has enabled
// country resolution in this torrent
bool m_resolve_countries;
#endif
// this announce timer is used both
// by Local service discovery and
// by the DHT.
deadline_timer m_announce_timer;
static void on_announce_disp(boost::weak_ptr<torrent> p
, asio::error_code const& e);
, error_code const& e);
// this is called once per announce interval
void on_announce();
@ -737,41 +727,9 @@ namespace libtorrent
std::vector<announce_entry> m_trackers;
// this is an index into m_trackers
int m_last_working_tracker;
int m_currently_trying_tracker;
// the number of connection attempts that has
// failed in a row, this is currently used to
// determine the timeout until next try.
int m_failed_trackers;
// this is a counter that is decreased every
// second, and when it reaches 0, the policy::pulse()
// is called and the time scaler is reset to 10.
int m_time_scaler;
// the bitmask that says which pieces we have
std::vector<bool> m_have_pieces;
// the number of pieces we have. The same as
// std::accumulate(m_have_pieces.begin(),
// m_have_pieces.end(), 0)
int m_num_pieces;
// in case the piece picker hasn't been constructed
// when this settings is set, this variable will keep
// its value until the piece picker is created
bool m_sequential_download;
// is false by default and set to
// true when the first tracker reponse
// is received
bool m_got_tracker_response;
// the upload/download ratio that each peer
// tries to maintain.
// 0 is infinite
float m_ratio;
// the number of bytes that has been
// downloaded that failed the hash-test
size_type m_total_failed_bytes;
@ -791,25 +749,9 @@ namespace libtorrent
// the state of this torrent (queued, checking, downloading)
torrent_status::state_t m_state;
float m_progress;
entry m_resume_data;
// defaults to 16 kiB, but can be set by the user
// when creating the torrent
const int m_default_block_size;
// this is set to false as long as the connections
// of this torrent hasn't been initialized. If we
// have metadata from the start, connections are
// initialized immediately, if we didn't have metadata,
// they are initialized right after files_checked().
// valid_resume_data() will return false as long as
// the connections aren't initialized, to avoid
// them from altering the piece-picker before it
// has been initialized with files_checked().
bool m_connections_initialized;
// if the torrent is started without metadata, it may
// still be given a name until the metadata is received
// once the metadata is received this field will no
@ -820,6 +762,18 @@ namespace libtorrent
storage_constructor_type m_storage_constructor;
float m_progress;
// the number of pieces we have. The same as
// std::accumulate(m_have_pieces.begin(),
// m_have_pieces.end(), 0)
int m_num_pieces;
// the upload/download ratio that each peer
// tries to maintain.
// 0 is infinite
float m_ratio;
// the maximum number of uploads for this torrent
int m_max_uploads;
@ -829,14 +783,18 @@ namespace libtorrent
// the maximum number of connections for this torrent
int m_max_connections;
#ifndef NDEBUG
bool m_files_checked;
#endif
// the size of a request block
// each piece is divided into these
// 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;
#endif
// -----------------------------
// DATA FROM TRACKER RESPONSE
// the scrape data from the tracker response, this
// is optional and may be -1.
int m_complete;
int m_incomplete;
#ifndef NDEBUG
// this is the amount downloaded when this torrent
@ -858,24 +816,84 @@ namespace libtorrent
// torrent object, these points are called connect_points.
int m_deficit_counter;
policy m_policy;
// the number number of seconds between requests
// from the tracker
boost::int16_t m_duration;
// the sequence number for this torrent, this is a
// monotonically increasing number for each added torrent
int m_sequence_number;
boost::int16_t m_sequence_number;
// total time we've been available on this torrent
// does not count when the torrent is stopped or paused
time_duration m_active_time;
// the index to the last tracker that worked
boost::int8_t m_last_working_tracker;
// total time we've been available as a seed on this torrent
// does not count when the torrent is stopped or paused
time_duration m_seeding_time;
// the tracker that is currently (or was last)
// tried
boost::int8_t m_currently_trying_tracker;
// all time totals of uploaded and downloaded payload
// stored in resume data
size_type m_total_uploaded;
size_type m_total_downloaded;
// the number of connection attempts that has
// failed in a row, this is currently used to
// determine the timeout until next try.
boost::int8_t m_failed_trackers;
// this is a counter that is decreased every
// second, and when it reaches 0, the policy::pulse()
// is called and the time scaler is reset to 10.
boost::int8_t m_time_scaler;
// is set to true when the torrent has
// been aborted.
bool m_abort:1;
// is true if this torrent has been paused
bool m_paused:1;
// this is true from the time when the torrent was
// paused to the time should_request() is called
bool m_just_paused:1;
// if this is true, libtorrent may pause and resume
// this torrent depending on queuing rules. Torrents
// started with auto_managed flag set may be added in
// a paused state in case there are no available
// slots.
bool m_auto_managed:1;
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
// this is true while there is a country
// resolution in progress. To avoid flodding
// the DNS request queue, only one ip is resolved
// at a time.
mutable bool m_resolving_country:1;
// this is true if the user has enabled
// country resolution in this torrent
bool m_resolve_countries:1;
#endif
// in case the piece picker hasn't been constructed
// when this settings is set, this variable will keep
// its value until the piece picker is created
bool m_sequential_download:1;
// is false by default and set to
// true when the first tracker reponse
// is received
bool m_got_tracker_response:1;
// this is set to false as long as the connections
// of this torrent hasn't been initialized. If we
// have metadata from the start, connections are
// initialized immediately, if we didn't have metadata,
// they are initialized right after files_checked().
// valid_resume_data() will return false as long as
// the connections aren't initialized, to avoid
// them from altering the piece-picker before it
// has been initialized with files_checked().
bool m_connections_initialized:1;
#ifndef NDEBUG
bool m_files_checked:1;
#endif
};
inline ptime torrent::next_announce() const

View File

@ -118,7 +118,8 @@ namespace libtorrent
, all_time_download(0)
, active_time(0)
, seeding_time(0)
, seed_cycles(0.f)
, seed_rank(0)
, last_scrape(0)
{}
enum state_t
@ -257,7 +258,12 @@ namespace libtorrent
int active_time;
int seeding_time;
float seed_cycles;
// higher value means more important to seed
int seed_rank;
// number of seconds since last scrape, or -1 if
// there hasn't been a scrape
int last_scrape;
};
struct TORRENT_EXPORT block_info

View File

@ -45,12 +45,14 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/optional.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/entry.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/size_type.hpp"
@ -110,18 +112,12 @@ namespace libtorrent
torrent_info();
torrent_info(sha1_hash const& info_hash);
torrent_info(entry const& torrent_file);
torrent_info(lazy_entry const& torrent_file);
torrent_info(char const* buffer, int size);
torrent_info(char const* filename);
~torrent_info();
entry create_torrent() const;
entry create_info_metadata() const;
void set_comment(char const* str);
void set_creator(char const* str);
void set_piece_size(int size);
void set_hash(int index, sha1_hash const& h);
void add_tracker(std::string const& url, int tier = 0);
void add_file(fs::path file, size_type size);
void add_url_seed(std::string const& url);
bool remap_files(std::vector<file_entry> const& map);
@ -131,10 +127,9 @@ namespace libtorrent
, bool storage = false) const;
std::vector<std::string> const& url_seeds() const
{
TORRENT_ASSERT(!m_half_metadata);
return m_url_seeds;
}
{ return m_url_seeds; }
void add_url_seed(std::string const& url)
{ m_url_seeds.push_back(url); }
typedef std::vector<file_entry>::const_iterator file_iterator;
typedef std::vector<file_entry>::const_reverse_iterator reverse_file_iterator;
@ -176,12 +171,12 @@ namespace libtorrent
{
TORRENT_ASSERT(m_piece_length > 0);
if (!storage || m_remapped_files.empty())
return (int)m_files.size();
return int(m_files.size());
else
return (int)m_remapped_files.size();
return int(m_remapped_files.size());
}
const file_entry& file_at(int index, bool storage = false) const
file_entry const& file_at(int index, bool storage = false) const
{
if (!storage || m_remapped_files.empty())
{
@ -195,7 +190,7 @@ namespace libtorrent
}
}
const std::vector<announce_entry>& trackers() const { return m_urls; }
std::vector<announce_entry> const& trackers() const { return m_urls; }
size_type total_size() const { TORRENT_ASSERT(m_piece_length > 0); return m_total_size; }
int piece_length() const { TORRENT_ASSERT(m_piece_length > 0); return m_piece_length; }
@ -204,25 +199,30 @@ namespace libtorrent
const std::string& name() const { TORRENT_ASSERT(m_piece_length > 0); return m_name; }
// ------- start deprecation -------
// this functionaily will be removed in a future version
// these functions will be removed in a future version
torrent_info(entry const& torrent_file) TORRENT_DEPRECATED;
void print(std::ostream& os) const TORRENT_DEPRECATED;
// ------- end deprecation -------
bool is_valid() const { return m_piece_length > 0; }
bool priv() const { return m_private; }
void set_priv(bool v) { m_private = v; }
void convert_file_names();
int piece_size(int index) const;
const sha1_hash& hash_for_piece(int index) const
sha1_hash hash_for_piece(int index) const
{
return sha1_hash(hash_for_piece_ptr(index));
}
char const* hash_for_piece_ptr(int index) const
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < (int)m_piece_hash.size());
TORRENT_ASSERT(!m_half_metadata);
return m_piece_hash[index];
TORRENT_ASSERT(index < m_num_pieces);
TORRENT_ASSERT(m_piece_hashes);
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
return &m_piece_hashes[index*20];
}
boost::optional<pt::ptime> creation_date() const;
@ -237,27 +237,30 @@ namespace libtorrent
typedef std::vector<std::pair<std::string, int> > nodes_t;
nodes_t const& nodes() const
{ return m_nodes; }
void add_node(std::pair<std::string, int> const& node)
{ m_nodes.push_back(node); }
bool parse_info_section(lazy_entry const& e, std::string& error);
lazy_entry const* info(char const* key) const
{
TORRENT_ASSERT(!m_half_metadata);
return m_nodes;
if (m_info_dict.type() == lazy_entry::none_t)
lazy_bdecode(m_info_section.get(), m_info_section.get()
+ m_info_section_size, m_info_dict);
return m_info_dict.dict_find(key);
}
void add_node(std::pair<std::string, int> const& node);
bool parse_info_section(entry const& e, std::string& error);
entry const* extra(char const* key) const
{ return m_extra_info.find_key(key); }
// frees parts of the metadata that isn't
// used by seeds
void seed_free();
void swap(torrent_info& ti);
boost::shared_array<char> metadata() const
{ return m_info_section; }
int metadata_size() const { return m_info_section_size; }
private:
bool read_torrent_info(const entry& libtorrent, std::string& error);
bool parse_torrent_file(lazy_entry const& libtorrent, std::string& error);
// the urls to the trackers
std::vector<announce_entry> m_urls;
@ -269,9 +272,6 @@ namespace libtorrent
// in an uninitialized state
int m_piece_length;
// the sha-1 hashes of each piece
std::vector<sha1_hash> m_piece_hash;
// the list of files that this torrent consists of
std::vector<file_entry> m_files;
@ -293,7 +293,7 @@ namespace libtorrent
// the hash that identifies this torrent
// is mutable because it's calculated
// lazily
mutable sha1_hash m_info_hash;
sha1_hash m_info_hash;
std::string m_name;
@ -321,18 +321,19 @@ namespace libtorrent
// be announced on the dht
bool m_private;
// contains any non-parsed entries from the info-section
// these are kept in order to be able to accurately
// reproduce the info-section when sending the metadata
// to peers.
entry m_extra_info;
// this is a copy of the info section from the torrent.
// it use maintained in this flat format in order to
// make it available through the metadata extension
boost::shared_array<char> m_info_section;
int m_info_section_size;
#ifndef NDEBUG
public:
// this is set to true when seed_free() is called
bool m_half_metadata;
private:
#endif
// this is a pointer into the m_info_section buffer
// pointing to the first byte of the first sha-1 hash
char const* m_piece_hashes;
// the info section parsed. points into m_info_section
// parsed lazily
mutable lazy_entry m_info_dict;
};
}

View File

@ -74,9 +74,6 @@ namespace libtorrent
// returns -1 if gzip header is invalid or the header size in bytes
TORRENT_EXPORT int gzip_header(const char* buf, int size);
TORRENT_EXPORT boost::tuple<std::string, std::string, std::string, int, std::string>
parse_url_components(std::string url);
struct TORRENT_EXPORT tracker_request
{
tracker_request()
@ -160,7 +157,7 @@ namespace libtorrent
private:
void timeout_callback(asio::error_code const&);
void timeout_callback(error_code const&);
boost::intrusive_ptr<timeout_handler> self()
{ return boost::intrusive_ptr<timeout_handler>(this); }

View File

@ -46,16 +46,16 @@ namespace libtorrent
class udp_socket
{
public:
typedef boost::function<void(asio::error_code const& ec
typedef boost::function<void(error_code const& ec
, udp::endpoint const&, char const* buf, int size)> callback_t;
udp_socket(asio::io_service& ios, callback_t const& c, connection_queue& cc);
udp_socket(io_service& ios, callback_t const& c, connection_queue& cc);
bool is_open() const { return m_ipv4_sock.is_open() || m_ipv6_sock.is_open(); }
asio::io_service& get_io_service() { return m_ipv4_sock.get_io_service(); }
io_service& get_io_service() { return m_ipv4_sock.get_io_service(); }
void send(udp::endpoint const& ep, char const* p, int len, asio::error_code& ec);
void bind(udp::endpoint const& ep, asio::error_code& ec);
void send(udp::endpoint const& ep, char const* p, int len, error_code& ec);
void bind(udp::endpoint const& ep, error_code& ec);
void bind(int port);
void close();
int local_port() const { return m_bind_port; }
@ -67,21 +67,21 @@ namespace libtorrent
callback_t m_callback;
void on_read(udp::socket* sock, asio::error_code const& e, std::size_t bytes_transferred);
void on_name_lookup(asio::error_code const& e, tcp::resolver::iterator i);
void on_read(udp::socket* sock, error_code const& e, std::size_t bytes_transferred);
void on_name_lookup(error_code const& e, tcp::resolver::iterator i);
void on_timeout();
void on_connect(int ticket);
void on_connected(asio::error_code const& ec);
void handshake1(asio::error_code const& e);
void handshake2(asio::error_code const& e);
void handshake3(asio::error_code const& e);
void handshake4(asio::error_code const& e);
void on_connected(error_code const& ec);
void handshake1(error_code const& e);
void handshake2(error_code const& e);
void handshake3(error_code const& e);
void handshake4(error_code const& e);
void socks_forward_udp();
void connect1(asio::error_code const& e);
void connect2(asio::error_code const& e);
void connect1(error_code const& e);
void connect2(error_code const& e);
void wrap(udp::endpoint const& ep, char const* p, int len, asio::error_code& ec);
void unwrap(asio::error_code const& e, char const* buf, int size);
void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec);
void unwrap(error_code const& e, char const* buf, int size);
udp::socket m_ipv4_sock;
udp::socket m_ipv6_sock;

View File

@ -89,10 +89,10 @@ namespace libtorrent
boost::intrusive_ptr<udp_tracker_connection> self()
{ return boost::intrusive_ptr<udp_tracker_connection>(this); }
void name_lookup(asio::error_code const& error, udp::resolver::iterator i);
void timeout(asio::error_code const& error);
void name_lookup(error_code const& error, udp::resolver::iterator i);
void timeout(error_code const& error);
void on_receive(asio::error_code const& e, udp::endpoint const& ep
void on_receive(error_code const& e, udp::endpoint const& ep
, char const* buf, int size);
void on_connect_response(char const* buf, int size);
void on_announce_response(char const* buf, int size);

View File

@ -93,7 +93,7 @@ private:
enum { default_lease_time = 3600 };
void resend_request(asio::error_code const& e);
void resend_request(error_code const& e);
void on_reply(udp::endpoint const& from, char* buffer
, std::size_t bytes_transferred);
@ -102,15 +102,16 @@ private:
void update_map(rootdevice& d, int i);
void on_upnp_xml(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d);
void on_upnp_map_response(asio::error_code const& e
void on_upnp_xml(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d
, int mapping);
void on_upnp_unmap_response(asio::error_code const& e
, http_connection& c);
void on_upnp_map_response(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d
, int mapping);
void on_expire(asio::error_code const& e);
, int mapping, http_connection& c);
void on_upnp_unmap_response(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d
, int mapping, http_connection& c);
void on_expire(error_code const& e);
void disable(char const* msg);
void return_error(int mapping, int code);
@ -237,7 +238,7 @@ private:
// current retry count
int m_retry_count;
asio::io_service& m_io_service;
io_service& m_io_service;
// the udp socket used to send and receive
// multicast messages on the network
@ -252,7 +253,7 @@ private:
bool m_disabled;
bool m_closing;
bool m_ignore_outside_network;
bool m_ignore_non_routers;
connection_queue& m_cc;

View File

@ -21,7 +21,11 @@
# include <boost/type_traits/add_pointer.hpp>
# include <boost/noncopyable.hpp>
#if BOOST_VERSION < 103500
#include <asio/io_service.hpp>
#else
#include <boost/asio/io_service.hpp>
#endif
# define NETWORK_VARIANT_STREAM_LIMIT 5
@ -48,7 +52,7 @@ namespace aux
template<class IO_Control_Command>
struct io_control_visitor_ec: boost::static_visitor<>
{
io_control_visitor_ec(IO_Control_Command& ioc, asio::error_code& ec_)
io_control_visitor_ec(IO_Control_Command& ioc, error_code& ec_)
: ioc(ioc), ec(ec_) {}
template <class T>
@ -61,7 +65,7 @@ namespace aux
{}
IO_Control_Command& ioc;
asio::error_code& ec;
error_code& ec;
};
template<class IO_Control_Command>
@ -112,7 +116,7 @@ namespace aux
struct bind_visitor_ec
: boost::static_visitor<>
{
bind_visitor_ec(EndpointType const& ep, asio::error_code& ec_)
bind_visitor_ec(EndpointType const& ep, error_code& ec_)
: endpoint(ep)
, ec(ec_)
{}
@ -124,7 +128,7 @@ namespace aux
void operator()(boost::blank) const {}
EndpointType const& endpoint;
asio::error_code& ec;
error_code& ec;
};
template <class EndpointType>
@ -150,7 +154,7 @@ namespace aux
struct open_visitor_ec
: boost::static_visitor<>
{
open_visitor_ec(Protocol const& p, asio::error_code& ec_)
open_visitor_ec(Protocol const& p, error_code& ec_)
: proto(p)
, ec(ec_)
{}
@ -162,7 +166,7 @@ namespace aux
void operator()(boost::blank) const {}
Protocol const& proto;
asio::error_code& ec;
error_code& ec;
};
template <class Protocol>
@ -201,7 +205,7 @@ namespace aux
struct close_visitor_ec
: boost::static_visitor<>
{
close_visitor_ec(asio::error_code& ec_)
close_visitor_ec(error_code& ec_)
: ec(ec_)
{}
@ -211,7 +215,7 @@ namespace aux
void operator()(boost::blank) const {}
asio::error_code& ec;
error_code& ec;
};
struct close_visitor
@ -230,18 +234,18 @@ namespace aux
struct remote_endpoint_visitor_ec
: boost::static_visitor<EndpointType>
{
remote_endpoint_visitor_ec(asio::error_code& ec)
: error_code(ec)
remote_endpoint_visitor_ec(error_code& ec_)
: ec(ec_)
{}
template <class T>
EndpointType operator()(T const* p) const
{ return p->remote_endpoint(error_code); }
{ return p->remote_endpoint(ec); }
EndpointType operator()(boost::blank) const
{ return EndpointType(); }
asio::error_code& error_code;
error_code& ec;
};
template <class EndpointType>
@ -270,29 +274,29 @@ namespace aux
void operator()(T* p) const
{ p->set_option(opt_); }
void operator()(boost::blank) const {}
void operator()(boost::blank) const {}
SettableSocketOption const& opt_;
};
template <class SettableSocketOption>
struct set_option_visitor_ec
: boost::static_visitor<asio::error_code>
: boost::static_visitor<error_code>
{
set_option_visitor_ec(SettableSocketOption const& opt, asio::error_code& ec)
set_option_visitor_ec(SettableSocketOption const& opt, error_code& ec)
: opt_(opt)
, ec_(ec)
{}
template <class T>
asio::error_code operator()(T* p) const
error_code operator()(T* p) const
{ return p->set_option(opt_, ec_); }
asio::error_code operator()(boost::blank) const
error_code operator()(boost::blank) const
{ return ec_; }
SettableSocketOption const& opt_;
asio::error_code& ec_;
error_code& ec_;
};
// -------------- local_endpoint -----------
@ -301,14 +305,14 @@ namespace aux
struct local_endpoint_visitor_ec
: boost::static_visitor<EndpointType>
{
local_endpoint_visitor_ec(asio::error_code& ec)
: error_code(ec)
local_endpoint_visitor_ec(error_code& ec_)
: ec(ec_)
{}
template <class T>
EndpointType operator()(T const* p) const
{
return p->local_endpoint(error_code);
return p->local_endpoint(ec);
}
EndpointType operator()(boost::blank) const
@ -316,7 +320,7 @@ namespace aux
return EndpointType();
}
asio::error_code& error_code;
error_code& ec;
};
template <class EndpointType>
@ -372,7 +376,7 @@ namespace aux
std::size_t operator()(T* p) const
{ return p->read_some(buffers); }
std::size_t operator()(boost::blank) const
std::size_t operator()(boost::blank) const
{ return 0; }
Mutable_Buffers const& buffers;
@ -382,7 +386,7 @@ namespace aux
struct read_some_visitor_ec
: boost::static_visitor<std::size_t>
{
read_some_visitor_ec(Mutable_Buffers const& buffers, asio::error_code& ec_)
read_some_visitor_ec(Mutable_Buffers const& buffers, error_code& ec_)
: buffers(buffers)
, ec(ec_)
{}
@ -391,11 +395,11 @@ namespace aux
std::size_t operator()(T* p) const
{ return p->read_some(buffers, ec); }
std::size_t operator()(boost::blank) const
std::size_t operator()(boost::blank) const
{ return 0; }
Mutable_Buffers const& buffers;
asio::error_code& ec;
error_code& ec;
};
// -------------- async_write_some -----------
@ -427,7 +431,7 @@ namespace aux
struct in_avail_visitor_ec
: boost::static_visitor<std::size_t>
{
in_avail_visitor_ec(asio::error_code& ec_)
in_avail_visitor_ec(error_code& ec_)
: ec(ec_)
{}
@ -442,7 +446,7 @@ namespace aux
return 0;
}
asio::error_code& ec;
error_code& ec;
};
struct in_avail_visitor
@ -524,11 +528,11 @@ public:
typedef typename S0::endpoint_type endpoint_type;
typedef typename S0::protocol_type protocol_type;
explicit variant_stream(asio::io_service& ios)
explicit variant_stream(io_service& ios)
: m_io_service(ios), m_variant(boost::blank()) {}
template <class S>
void instantiate(asio::io_service& ios)
void instantiate(io_service& ios)
{
TORRENT_ASSERT(&ios == &m_io_service);
std::auto_ptr<S> owned(new S(ios));
@ -540,7 +544,7 @@ public:
template <class S>
S& get()
{
return *boost::get<S*>(m_variant);
return *boost::get<S*>(m_variant);
}
bool instantiated() const
@ -554,7 +558,7 @@ public:
}
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(
@ -612,7 +616,7 @@ public:
}
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc, asio::error_code& ec)
void io_control(IO_Control_Command& ioc, error_code& ec)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(
@ -627,7 +631,7 @@ public:
boost::apply_visitor(aux::bind_visitor<endpoint_type>(endpoint), m_variant);
}
void bind(endpoint_type const& endpoint, asio::error_code& ec)
void bind(endpoint_type const& endpoint, error_code& ec)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(
@ -641,7 +645,7 @@ public:
boost::apply_visitor(aux::open_visitor<protocol_type>(p), m_variant);
}
void open(protocol_type const& p, asio::error_code& ec)
void open(protocol_type const& p, error_code& ec)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(
@ -660,7 +664,7 @@ public:
boost::apply_visitor(aux::close_visitor(), m_variant);
}
void close(asio::error_code& ec)
void close(error_code& ec)
{
if (!instantiated()) return;
boost::apply_visitor(
@ -674,7 +678,7 @@ public:
return boost::apply_visitor(aux::in_avail_visitor(), m_variant);
}
std::size_t in_avail(asio::error_code& ec) const
std::size_t in_avail(error_code& ec) const
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(
@ -688,7 +692,7 @@ public:
return boost::apply_visitor(aux::remote_endpoint_visitor<endpoint_type>(), m_variant);
}
endpoint_type remote_endpoint(asio::error_code& ec) const
endpoint_type remote_endpoint(error_code& ec) const
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(
@ -705,7 +709,7 @@ public:
}
template <class SettableSocketOption>
asio::error_code set_option(SettableSocketOption const& opt, asio::error_code& ec)
error_code set_option(SettableSocketOption const& opt, error_code& ec)
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(aux::set_option_visitor_ec<SettableSocketOption>(opt, ec)
@ -718,7 +722,7 @@ public:
return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_type>(), m_variant);
}
endpoint_type local_endpoint(asio::error_code& ec) const
endpoint_type local_endpoint(error_code& ec) const
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(
@ -726,7 +730,7 @@ public:
);
}
asio::io_service& get_io_service()
io_service& get_io_service()
{
return m_io_service;
}
@ -740,7 +744,7 @@ public:
}
private:
asio::io_service& m_io_service;
io_service& m_io_service;
variant_type m_variant;
};

View File

@ -102,9 +102,9 @@ namespace libtorrent
// called from the main loop when this connection has any
// work to do.
void on_sent(asio::error_code const& error
void on_sent(error_code const& error
, std::size_t bytes_transferred);
void on_receive(asio::error_code const& error
void on_receive(error_code const& error
, std::size_t bytes_transferred);
std::string const& url() const { return m_url; }

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "GeoIP.h"
#include "libtorrent/GeoIP.h"
#ifndef WIN32
#include <netdb.h>

View File

@ -30,8 +30,14 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#if BOOST_VERSION < 103500
#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#else
#include <boost/asio/ip/host_name.hpp>
#include <boost/asio/ip/multicast.hpp>
#endif
#include <boost/bind.hpp>
#include "libtorrent/socket.hpp"
@ -75,10 +81,10 @@ namespace libtorrent
return addr.to_v6() == address_v6::any();
}
address guess_local_address(asio::io_service& ios)
address guess_local_address(io_service& ios)
{
// make a best guess of the interface we're using and its IP
asio::error_code ec;
error_code ec;
std::vector<ip_interface> const& interfaces = enum_net_interfaces(ios, ec);
address ret = address_v4::any();
for (std::vector<ip_interface>::const_iterator i = interfaces.begin()
@ -137,7 +143,7 @@ namespace libtorrent
- common_bits(b1.c_array(), b2.c_array(), b1.size());
}
broadcast_socket::broadcast_socket(asio::io_service& ios
broadcast_socket::broadcast_socket(io_service& ios
, udp::endpoint const& multicast_endpoint
, receive_handler_t const& handler
, bool loopback)
@ -148,7 +154,7 @@ namespace libtorrent
using namespace asio::ip::multicast;
asio::error_code ec;
error_code ec;
std::vector<ip_interface> interfaces = enum_net_interfaces(ios, ec);
if (multicast_endpoint.address().is_v4())
@ -179,7 +185,7 @@ namespace libtorrent
{
using namespace asio::ip::multicast;
asio::error_code ec;
error_code ec;
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
if (addr.is_v4())
s->open(udp::v4(), ec);
@ -205,7 +211,7 @@ namespace libtorrent
void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr)
{
using namespace asio::ip::multicast;
asio::error_code ec;
error_code ec;
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
s->open(addr.is_v4() ? udp::v4() : udp::v6(), ec);
if (ec) return;
@ -220,13 +226,13 @@ namespace libtorrent
, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
}
void broadcast_socket::send(char const* buffer, int size, asio::error_code& ec)
void broadcast_socket::send(char const* buffer, int size, error_code& ec)
{
for (std::list<socket_entry>::iterator i = m_unicast_sockets.begin()
, end(m_unicast_sockets.end()); i != end; ++i)
{
if (!i->socket) continue;
asio::error_code e;
error_code e;
i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
#ifndef NDEBUG
// std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << " to: " << m_multicast_endpoint << std::endl;
@ -239,7 +245,7 @@ namespace libtorrent
}
}
void broadcast_socket::on_receive(socket_entry* s, asio::error_code const& ec
void broadcast_socket::on_receive(socket_entry* s, error_code const& ec
, std::size_t bytes_transferred)
{
if (ec || bytes_transferred == 0 || !m_on_receive) return;

View File

@ -125,8 +125,9 @@ namespace libtorrent
bt_peer_connection::bt_peer_connection(
session_impl& ses
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo)
: peer_connection(ses, s, peerinfo)
: peer_connection(ses, s, remote, peerinfo)
, m_state(read_protocol_identifier)
#ifndef TORRENT_DISABLE_EXTENSIONS
, m_supports_extensions(false)
@ -800,13 +801,14 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 1)
{
disconnect("'choke' message size != 1");
disconnect("'choke' message size != 1", 2);
return;
}
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
incoming_choke();
if (is_disconnecting()) return;
if (!m_supports_fast)
{
boost::shared_ptr<torrent> t = associated_torrent().lock();
@ -834,7 +836,7 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 1)
{
disconnect("'unchoke' message size != 1");
disconnect("'unchoke' message size != 1", 2);
return;
}
m_statistics.received_bytes(0, received);
@ -854,7 +856,7 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 1)
{
disconnect("'interested' message size != 1");
disconnect("'interested' message size != 1", 2);
return;
}
m_statistics.received_bytes(0, received);
@ -874,7 +876,7 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 1)
{
disconnect("'not interested' message size != 1");
disconnect("'not interested' message size != 1", 2);
return;
}
m_statistics.received_bytes(0, received);
@ -894,7 +896,7 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 5)
{
disconnect("'have' message size != 5");
disconnect("'have' message size != 5", 2);
return;
}
m_statistics.received_bytes(0, received);
@ -926,7 +928,7 @@ namespace libtorrent
if (t->valid_metadata()
&& packet_size() - 1 != ((int)get_bitfield().size() + 7) / 8)
{
disconnect("bitfield with invalid size");
disconnect("bitfield with invalid size", 2);
return;
}
@ -963,7 +965,7 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 13)
{
disconnect("'request' message size != 13");
disconnect("'request' message size != 13", 2);
return;
}
m_statistics.received_bytes(0, received);
@ -1021,6 +1023,7 @@ namespace libtorrent
}
incoming_piece_fragment();
if (is_disconnecting()) return;
if (!packet_finished()) return;
const char* ptr = recv_buffer.begin + 1;
@ -1044,7 +1047,7 @@ namespace libtorrent
TORRENT_ASSERT(received > 0);
if (packet_size() != 13)
{
disconnect("'cancel' message size != 13");
disconnect("'cancel' message size != 13", 2);
return;
}
m_statistics.received_bytes(0, received);
@ -1071,14 +1074,14 @@ namespace libtorrent
if (!m_supports_dht_port)
{
disconnect("got 'dht_port' message from peer that doesn't support it");
disconnect("got 'dht_port' message from peer that doesn't support it", 2);
return;
}
TORRENT_ASSERT(received > 0);
if (packet_size() != 3)
{
disconnect("'dht_port' message size != 3");
disconnect("'dht_port' message size != 3", 2);
return;
}
m_statistics.received_bytes(0, received);
@ -1098,7 +1101,7 @@ namespace libtorrent
if (!m_supports_fast)
{
disconnect("got 'suggest_piece' without FAST excension support");
disconnect("got 'suggest_piece' without FAST excension support", 2);
return;
}
@ -1118,7 +1121,7 @@ namespace libtorrent
if (!m_supports_fast)
{
disconnect("got 'have_all' without FAST extension support");
disconnect("got 'have_all' without FAST extension support", 2);
return;
}
m_statistics.received_bytes(0, received);
@ -1131,7 +1134,7 @@ namespace libtorrent
if (!m_supports_fast)
{
disconnect("got 'have_none' without FAST extension support");
disconnect("got 'have_none' without FAST extension support", 2);
return;
}
m_statistics.received_bytes(0, received);
@ -1144,7 +1147,7 @@ namespace libtorrent
if (!m_supports_fast)
{
disconnect("got 'reject_request' without FAST extension support");
disconnect("got 'reject_request' without FAST extension support", 2);
return;
}
@ -1168,7 +1171,7 @@ namespace libtorrent
if (!m_supports_fast)
{
disconnect("got 'allowed_fast' without FAST extension support");
disconnect("got 'allowed_fast' without FAST extension support", 2);
return;
}
@ -1193,13 +1196,13 @@ namespace libtorrent
m_statistics.received_bytes(0, received);
if (packet_size() < 2)
{
disconnect("'extended' message smaller than 2 bytes");
disconnect("'extended' message smaller than 2 bytes", 2);
return;
}
if (associated_torrent().expired())
{
disconnect("'extended' message sent before proper handshake");
disconnect("'extended' message sent before proper handshake", 2);
return;
}
@ -1229,7 +1232,7 @@ namespace libtorrent
std::stringstream msg;
msg << "unknown extended message id: " << extended_id;
disconnect(msg.str().c_str());
disconnect(msg.str().c_str(), 2);
return;
}
@ -1298,6 +1301,12 @@ namespace libtorrent
m_max_out_request_queue = 1;
}
if (entry* upload_only = root.find_key("upload_only"))
{
if (upload_only->type() == entry::int_t && upload_only->integer() != 0)
set_upload_only(true);
}
if (entry* myip = root.find_key("yourip"))
{
// TODO: don't trust this blindly
@ -1318,6 +1327,11 @@ namespace libtorrent
}
}
}
// if we're finished and this peer is uploading only
// disconnect it
if (t->is_finished() && upload_only())
disconnect("upload to upload connection, closing");
}
bool bt_peer_connection::dispatch_message(int received)
@ -1350,7 +1364,7 @@ namespace libtorrent
std::stringstream msg;
msg << "unkown message id: " << packet_type << " size: " << packet_size();
disconnect(msg.str().c_str());
disconnect(msg.str().c_str(), 2);
return packet_finished();
}
@ -1553,6 +1567,9 @@ namespace libtorrent
detail::write_address(remote().address(), out);
handshake["yourip"] = remote_address;
handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue;
boost::shared_ptr<torrent> t = associated_torrent().lock();
TORRENT_ASSERT(t);
if (t->is_finished()) handshake["upload_only"] = 1;
tcp::endpoint ep = m_ses.get_ipv6_interface();
if (ep != tcp::endpoint())
@ -1671,7 +1688,7 @@ namespace libtorrent
detail::write_int32(r.start, ptr);
send_buffer(msg, sizeof(msg));
append_send_buffer(buffer.buffer(), r.length
append_send_buffer(buffer.get(), r.length
, boost::bind(&session_impl::free_disk_buffer
, boost::ref(m_ses), _1));
buffer.release();
@ -1707,7 +1724,7 @@ namespace libtorrent
// --------------------------
// throws exception when the client should be disconnected
void bt_peer_connection::on_receive(asio::error_code const& error
void bt_peer_connection::on_receive(error_code const& error
, std::size_t bytes_transferred)
{
INVARIANT_CHECK;
@ -1802,7 +1819,7 @@ namespace libtorrent
if (recv_buffer.left() < 20)
{
if (packet_finished())
disconnect("sync hash not found");
disconnect("sync hash not found", 2);
return;
}
@ -1828,7 +1845,7 @@ namespace libtorrent
m_sync_bytes_read += bytes_processed;
if (m_sync_bytes_read >= 512)
{
disconnect("sync hash not found within 532 bytes");
disconnect("sync hash not found within 532 bytes", 2);
return;
}
@ -1913,7 +1930,7 @@ namespace libtorrent
if (!m_RC4_handler.get())
{
disconnect("invalid streamkey identifier (info hash) in encrypted handshake");
disconnect("invalid streamkey identifier (info hash) in encrypted handshake", 2);
return;
}
@ -1925,7 +1942,7 @@ namespace libtorrent
const char sh_vc[] = {0,0,0,0, 0,0,0,0};
if (!std::equal(sh_vc, sh_vc+8, recv_buffer.begin + 20))
{
disconnect("unable to verify constant");
disconnect("unable to verify constant", 2);
return;
}
@ -1947,7 +1964,7 @@ namespace libtorrent
if (recv_buffer.left() < 8)
{
if (packet_finished())
disconnect("sync verification constant not found");
disconnect("sync verification constant not found", 2);
return;
}
@ -1972,7 +1989,7 @@ namespace libtorrent
m_sync_bytes_read += bytes_processed;
if (m_sync_bytes_read >= 512)
{
disconnect("sync verification constant not found within 520 bytes");
disconnect("sync verification constant not found within 520 bytes", 2);
return;
}
@ -2035,7 +2052,7 @@ namespace libtorrent
case pe_settings::plaintext:
if (!(crypto_field & 0x01))
{
disconnect("plaintext not provided");
disconnect("plaintext not provided", 1);
return;
}
crypto_select = 0x01;
@ -2043,7 +2060,7 @@ namespace libtorrent
case pe_settings::rc4:
if (!(crypto_field & 0x02))
{
disconnect("rc4 not provided");
disconnect("rc4 not provided", 1);
return;
}
crypto_select = 0x02;
@ -2065,7 +2082,7 @@ namespace libtorrent
}
if (!crypto_select)
{
disconnect("rc4/plaintext not provided");
disconnect("rc4/plaintext not provided", 1);
return;
}
break;
@ -2083,7 +2100,7 @@ namespace libtorrent
{
if (allowed_enc_level == pe_settings::plaintext)
{
disconnect("rc4 selected by peer when not provided");
disconnect("rc4 selected by peer when not provided", 2);
return;
}
m_rc4_encrypted = true;
@ -2092,14 +2109,14 @@ namespace libtorrent
{
if (allowed_enc_level == pe_settings::rc4)
{
disconnect("plaintext selected by peer when not provided");
disconnect("plaintext selected by peer when not provided", 2);
return;
}
m_rc4_encrypted = false;
}
else
{
disconnect("unsupported crypto method selected by peer");
disconnect("unsupported crypto method selected by peer", 2);
return;
}
}
@ -2107,7 +2124,7 @@ namespace libtorrent
int len_pad = detail::read_int16(recv_buffer.begin);
if (len_pad < 0 || len_pad > 512)
{
disconnect("invalid pad length");
disconnect("invalid pad length", 2);
return;
}
@ -2145,7 +2162,7 @@ namespace libtorrent
if (len_ia < 0)
{
disconnect("invalid len_ia in handshake");
disconnect("invalid len_ia in handshake", 2);
return;
}
@ -2277,7 +2294,7 @@ namespace libtorrent
TORRENT_ASSERT((!is_local() && m_encrypted) || is_local());
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
disconnect("incorrect protocol identifier");
disconnect("incorrect protocol identifier", 2);
return;
}
@ -2329,6 +2346,7 @@ namespace libtorrent
#endif
#ifndef DISABLE_EXTENSIONS
std::memcpy(m_reserved_bits, recv_buffer.begin, 20);
if ((recv_buffer[5] & 0x10))
m_supports_extensions = true;
#endif
@ -2360,7 +2378,7 @@ namespace libtorrent
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << " received invalid info_hash\n";
#endif
disconnect("invalid info-hash in handshake");
disconnect("invalid info-hash in handshake", 2);
return;
}
@ -2449,8 +2467,7 @@ namespace libtorrent
if (pid == m_ses.get_peer_id())
{
set_failed();
disconnect("closing connection to ourself");
disconnect("closing connection to ourself", 1);
return;
}
@ -2466,8 +2483,7 @@ namespace libtorrent
// since it most likely is ourself then
if (pid == m_ses.get_peer_id())
{
set_failed();
disconnect("closing connection to ourself");
disconnect("closing connection to ourself", 1);
return;
}
@ -2475,7 +2491,7 @@ namespace libtorrent
for (extension_list_t::iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end;)
{
if (!(*i)->on_handshake())
if (!(*i)->on_handshake(m_reserved_bits))
{
i = m_extensions.erase(i);
}
@ -2484,6 +2500,7 @@ namespace libtorrent
++i;
}
}
if (is_disconnecting()) return;
if (m_supports_extensions) write_extensions();
#endif
@ -2542,13 +2559,14 @@ namespace libtorrent
// packet too large
std::stringstream msg;
msg << "packet > 1 MB (" << (unsigned int)packet_size << " bytes)";
disconnect(msg.str().c_str());
disconnect(msg.str().c_str(), 2);
return;
}
if (packet_size == 0)
{
incoming_keepalive();
if (is_disconnecting()) return;
// keepalive message
m_state = read_packet_size;
cut_receive_buffer(4, 4);
@ -2586,8 +2604,7 @@ namespace libtorrent
// SEND DATA
// --------------------------
// throws exception when the client should be disconnected
void bt_peer_connection::on_sent(asio::error_code const& error
void bt_peer_connection::on_sent(error_code const& error
, std::size_t bytes_transferred)
{
INVARIANT_CHECK;

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/bind.hpp>
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/connection_queue.hpp"
#include "libtorrent/socket.hpp"
namespace libtorrent
{
@ -112,7 +113,7 @@ namespace libtorrent
void connection_queue::close()
{
asio::error_code ec;
error_code ec;
m_timer.cancel(ec);
}
@ -153,7 +154,7 @@ namespace libtorrent
if (m_queue.empty())
{
asio::error_code ec;
error_code ec;
m_timer.cancel(ec);
return;
}
@ -166,7 +167,7 @@ namespace libtorrent
ptime expire = time_now() + i->timeout;
if (m_num_connecting == 0)
{
asio::error_code ec;
error_code ec;
m_timer.expires_at(expire, ec);
m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
}
@ -206,7 +207,7 @@ namespace libtorrent
};
#endif
void connection_queue::on_timeout(asio::error_code const& e)
void connection_queue::on_timeout(error_code const& e)
{
mutex_t::scoped_lock l(m_mutex);
@ -251,7 +252,7 @@ namespace libtorrent
if (next_expire < max_time())
{
asio::error_code ec;
error_code ec;
m_timer.expires_at(next_expire, ec);
m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
}

View File

@ -49,6 +49,12 @@ namespace libtorrent
TORRENT_ASSERT(buf == 0 || m_iothread.is_disk_buffer(buf));
}
void disk_buffer_holder::reset(char* buf)
{
if (m_buf) m_iothread.free_buffer(m_buf);
m_buf = buf;
}
char* disk_buffer_holder::release()
{
char* ret = m_buf;

View File

@ -182,7 +182,6 @@ namespace libtorrent
disk_io_thread::cache_t& cache
, disk_io_job const& j, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
for (cache_t::iterator i = cache.begin()
, end(cache.end()); i != end; ++i)
{
@ -196,7 +195,6 @@ namespace libtorrent
{
ptime now = time_now();
TORRENT_ASSERT(l.locked());
INVARIANT_CHECK;
for (;;)
{
@ -213,7 +211,6 @@ namespace libtorrent
void disk_io_thread::free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
int piece_size = p.storage->info()->piece_size(p.piece);
int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size;
@ -251,7 +248,6 @@ namespace libtorrent
void disk_io_thread::flush_oldest_piece(mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
INVARIANT_CHECK;
// first look if there are any read cache entries that can
// be cleared
@ -275,7 +271,6 @@ namespace libtorrent
void disk_io_thread::flush(disk_io_thread::cache_t::iterator e
, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
INVARIANT_CHECK;
cached_piece_entry& p = *e;
int piece_size = p.storage->info()->piece_size(p.piece);
@ -340,7 +335,6 @@ namespace libtorrent
void disk_io_thread::cache_block(disk_io_job& j, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
INVARIANT_CHECK;
TORRENT_ASSERT(find_cached_piece(m_pieces, j, l) == m_pieces.end());
cached_piece_entry p;
@ -365,8 +359,6 @@ namespace libtorrent
// read or -1 if there was an error
int disk_io_thread::read_into_piece(cached_piece_entry& p, int start_block, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
int piece_size = p.storage->info()->piece_size(p.piece);
int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size;
@ -436,8 +428,6 @@ namespace libtorrent
, cache_t::iterator ignore
, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
if (m_cache_size - m_cache_stats.cache_size < num_blocks)
{
// there's not enough room in the cache, clear a piece
@ -452,8 +442,6 @@ namespace libtorrent
// or the number of bytes read
int disk_io_thread::cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
INVARIANT_CHECK;
int piece_size = j.storage->info()->piece_size(j.piece);
@ -543,7 +531,6 @@ namespace libtorrent
int disk_io_thread::try_read_from_cache(disk_io_job const& j, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
TORRENT_ASSERT(j.buffer);
if (!m_use_read_cache) return -2;
@ -707,7 +694,6 @@ namespace libtorrent
char* disk_io_thread::allocate_buffer(mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
#ifdef TORRENT_STATS
++m_allocations;
#endif
@ -720,7 +706,6 @@ namespace libtorrent
void disk_io_thread::free_buffer(char* buf, mutex_t::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
#ifdef TORRENT_STATS
--m_allocations;
#endif

View File

@ -35,8 +35,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <boost/bind.hpp>
#include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/escape_string.hpp"
#if defined(_MSC_VER)
namespace std
@ -54,19 +56,6 @@ namespace
TORRENT_ASSERT(o);
o->~T();
}
struct compare_string
{
compare_string(char const* s): m_str(s) {}
bool operator()(
std::pair<std::string
, libtorrent::entry> const& e) const
{
return m_str && e.first == m_str;
}
char const* m_str;
};
}
namespace libtorrent
@ -94,6 +83,16 @@ namespace libtorrent
}
entry& entry::operator[](char const* key)
{
dictionary_type::iterator i = dict().find(key);
if (i != dict().end()) return i->second;
dictionary_type::iterator ret = dict().insert(
dict().begin()
, std::make_pair(key, entry()));
return ret->second;
}
entry& entry::operator[](std::string const& key)
{
dictionary_type::iterator i = dict().find(key);
if (i != dict().end()) return i->second;
@ -103,21 +102,11 @@ namespace libtorrent
return ret->second;
}
entry& entry::operator[](std::string const& key)
{
return (*this)[key.c_str()];
}
entry* entry::find_key(char const* key)
{
dictionary_type::iterator i = std::find_if(
dict().begin()
, dict().end()
, compare_string(key));
dictionary_type::iterator i = dict().find(key);
if (i == dict().end()) return 0;
return &i->second;
}
entry const* entry::find_key(char const* key) const
@ -127,6 +116,20 @@ namespace libtorrent
return &i->second;
}
entry* entry::find_key(std::string const& key)
{
dictionary_type::iterator i = dict().find(key);
if (i == dict().end()) return 0;
return &i->second;
}
entry const* entry::find_key(std::string const& key) const
{
dictionary_type::const_iterator i = dict().find(key);
if (i == dict().end()) return 0;
return &i->second;
}
#ifndef BOOST_NO_EXCEPTIONS
const entry& entry::operator[](char const* key) const
{
@ -370,21 +373,8 @@ namespace libtorrent
break;
}
}
if (binary_string)
{
os.unsetf(std::ios_base::dec);
os.setf(std::ios_base::hex);
for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
os << std::setfill('0') << std::setw(2)
<< static_cast<unsigned int>((unsigned char)*i);
os.unsetf(std::ios_base::hex);
os.setf(std::ios_base::dec);
os << "\n";
}
else
{
os << string() << "\n";
}
if (binary_string) os << to_hex(string()) << "\n";
else os << string() << "\n";
} break;
case list_t:
{
@ -399,8 +389,21 @@ namespace libtorrent
os << "dictionary\n";
for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
{
bool binary_string = false;
for (std::string::const_iterator k = i->first.begin(); k != i->first.end(); ++k)
{
if (!std::isprint(static_cast<unsigned char>(*k)))
{
binary_string = true;
break;
}
}
for (int j = 0; j < indent+1; ++j) os << " ";
os << "[" << i->first << "]";
os << "[";
if (binary_string) os << to_hex(i->first);
else os << i->first;
os << "]";
if (i->second.type() != entry::string_t
&& i->second.type() != entry::int_t)
os << "\n";

View File

@ -35,8 +35,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include "libtorrent/enum_net.hpp"
#include "libtorrent/broadcast_socket.hpp"
#if BOOST_VERSION < 103500
#include <asio/ip/host_name.hpp>
#else
#include <boost/asio/ip/host_name.hpp>
#endif
#if defined TORRENT_BSD
#include <sys/ioctl.h>
@ -225,7 +228,7 @@ namespace libtorrent
== (iface.interface_address.to_v4().to_ulong() & iface.netmask.to_v4().to_ulong());
}
bool in_local_network(asio::io_service& ios, address const& addr, asio::error_code& ec)
bool in_local_network(io_service& ios, address const& addr, error_code& ec)
{
std::vector<ip_interface> const& net = enum_net_interfaces(ios, ec);
if (ec) return false;
@ -237,7 +240,7 @@ namespace libtorrent
return false;
}
std::vector<ip_interface> enum_net_interfaces(asio::io_service& ios, asio::error_code& ec)
std::vector<ip_interface> enum_net_interfaces(io_service& ios, error_code& ec)
{
std::vector<ip_interface> ret;
// covers linux, MacOS X and BSD distributions
@ -254,7 +257,7 @@ namespace libtorrent
ifc.ifc_buf = buf;
if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
{
ec = asio::error_code(errno, asio::error::system_category);
ec = error_code(errno, asio::error::system_category);
close(s);
return ret;
}
@ -283,7 +286,7 @@ namespace libtorrent
}
else
{
ec = asio::error_code(errno, asio::error::system_category);
ec = error_code(errno, asio::error::system_category);
close(s);
return ret;
}
@ -310,7 +313,7 @@ namespace libtorrent
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == SOCKET_ERROR)
{
ec = asio::error_code(WSAGetLastError(), asio::error::system_category);
ec = error_code(WSAGetLastError(), asio::error::system_category);
return ret;
}
@ -320,7 +323,7 @@ namespace libtorrent
if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, 0, 0, buffer,
sizeof(buffer), &size, 0, 0) != 0)
{
ec = asio::error_code(WSAGetLastError(), asio::error::system_category);
ec = error_code(WSAGetLastError(), asio::error::system_category);
closesocket(s);
return ret;
}
@ -356,16 +359,21 @@ namespace libtorrent
return ret;
}
address get_default_gateway(asio::io_service& ios, asio::error_code& ec)
address get_default_gateway(io_service& ios, error_code& ec)
{
std::vector<ip_route> ret = enum_routes(ios, ec);
#ifdef TORRENT_WINDOWS
std::vector<ip_route>::iterator i = std::find_if(ret.begin(), ret.end()
, boost::bind(&is_loopback, boost::bind(&ip_route::destination, _1)));
#else
std::vector<ip_route>::iterator i = std::find_if(ret.begin(), ret.end()
, boost::bind(&ip_route::destination, _1) == address());
#endif
if (i == ret.end()) return address();
return i->gateway;
}
std::vector<ip_route> enum_routes(asio::io_service& ios, asio::error_code& ec)
std::vector<ip_route> enum_routes(io_service& ios, error_code& ec)
{
std::vector<ip_route> ret;
@ -390,14 +398,14 @@ namespace libtorrent
int s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
if (s == -1)
{
ec = asio::error_code(errno, asio::error::system_category);
ec = error_code(errno, asio::error::system_category);
return std::vector<ip_route>();
}
int n = write(s, &m, len);
if (n == -1)
{
ec = asio::error_code(errno, asio::error::system_category);
ec = error_code(errno, asio::error::system_category);
close(s);
return std::vector<ip_route>();
}
@ -412,7 +420,7 @@ namespace libtorrent
n = read(s, &m, len);
if (n == -1)
{
ec = asio::error_code(errno, asio::error::system_category);
ec = error_code(errno, asio::error::system_category);
close(s);
return std::vector<ip_route>();
}
@ -423,7 +431,7 @@ namespace libtorrent
std::cout << " rtm_type: " << ptr->rtm_type << std::endl;
if (ptr->rtm_errno)
{
ec = asio::error_code(ptr->rtm_errno, asio::error::system_category);
ec = error_code(ptr->rtm_errno, asio::error::system_category);
return std::vector<ip_route>();
}
if (m.m_rtm.rtm_flags & RTF_UP == 0
@ -475,7 +483,7 @@ namespace libtorrent
size_t needed = 0;
if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
{
ec = asio::error_code(errno, asio::error::system_category);
ec = error_code(errno, asio::error::system_category);
return std::vector<ip_route>();
}
@ -493,7 +501,7 @@ namespace libtorrent
if (sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0)
{
ec = asio::error_code(errno, asio::error::system_category);
ec = error_code(errno, asio::error::system_category);
return std::vector<ip_route>();
}
@ -547,7 +555,6 @@ namespace libtorrent
return std::vector<ip_route>();
}
address ret;
if (GetAdaptersInfo(adapter_info, &out_buf_size) == NO_ERROR)
{
for (PIP_ADAPTER_INFO adapter = adapter_info;
@ -555,14 +562,14 @@ namespace libtorrent
{
ip_route r;
r.source = address::from_string(adapter->IpAddressList.IpAddress.String, ec);
r.destination = address::from_string(adapter->IpAddressList.IpAddress.String, ec);
r.gateway = address::from_string(adapter->GatewayList.IpAddress.String, ec);
r.netmask = address::from_string(adapter->IpAddressList.IpMask.String, ec);
strcpy(r.name, adapter->AdapterName);
strncpy(r.name, adapter->AdapterName, sizeof(r.name));
if (ec)
{
ec = asio::error_code();
ec = error_code();
continue;
}
ret.push_back(r);
@ -573,8 +580,6 @@ namespace libtorrent
free(adapter_info);
FreeLibrary(iphlp);
return ret;
#elif defined TORRENT_LINUX
enum { BUFSIZE = 8192 };
@ -582,7 +587,7 @@ namespace libtorrent
int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE);
if (sock < 0)
{
ec = asio::error_code(errno, asio::error::system_category);
ec = error_code(errno, asio::error::system_category);
return std::vector<ip_route>();
}
@ -600,7 +605,7 @@ namespace libtorrent
if (send(sock, nl_msg, nl_msg->nlmsg_len, 0) < 0)
{
ec = asio::error_code(errno, asio::error::system_category);
ec = error_code(errno, asio::error::system_category);
close(sock);
return std::vector<ip_route>();
}
@ -608,7 +613,7 @@ namespace libtorrent
int len = read_nl_sock(sock, msg, BUFSIZE, seq, getpid());
if (len < 0)
{
ec = asio::error_code(errno, asio::error::system_category);
ec = error_code(errno, asio::error::system_category);
close(sock);
return std::vector<ip_route>();
}

View File

@ -352,5 +352,17 @@ namespace libtorrent
return url.substr(pos, url.find('&', pos) - pos);
}
TORRENT_EXPORT std::string to_hex(std::string const& s)
{
std::string ret;
char* digits = "0123456789abcdef";
for (std::string::const_iterator i = s.begin(); i != s.end(); ++i)
{
ret += digits[((unsigned char)*i) >> 4];
ret += digits[((unsigned char)*i) & 0xf];
}
return ret;
}
}

View File

@ -34,12 +34,14 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/escape_string.hpp"
#include "libtorrent/instantiate_connection.hpp"
#include "libtorrent/gzip.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/parse_url.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/connection_queue.hpp"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <asio/ip/tcp.hpp>
#include <string>
#include <algorithm>
using boost::bind;
@ -56,8 +58,17 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri
std::string auth;
std::string hostname;
std::string path;
char const* error;
int port;
boost::tie(protocol, auth, hostname, port, path) = parse_url_components(url);
boost::tie(protocol, auth, hostname, port, path, error)
= parse_url_components(url);
if (error)
{
callback(asio::error::socket_type_not_supported);
return;
}
TORRENT_ASSERT(prio >= 0 && prio < 2);
@ -104,6 +115,7 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri
"\r\n";
sendbuffer = headers.str();
m_url = url;
start(hostname, boost::lexical_cast<std::string>(port), timeout, prio
, ps, ssl, handle_redirects, bind_addr);
}
@ -118,7 +130,7 @@ void http_connection::start(std::string const& hostname, std::string const& port
if (ps) m_proxy = *ps;
m_timeout = timeout;
asio::error_code ec;
error_code ec;
m_timer.expires_from_now(m_timeout, ec);
m_timer.async_wait(bind(&http_connection::on_timeout
, boost::weak_ptr<http_connection>(shared_from_this()), _1));
@ -137,14 +149,14 @@ void http_connection::start(std::string const& hostname, std::string const& port
if (m_sock.is_open() && m_hostname == hostname && m_port == port
&& m_ssl == ssl && m_bind_addr == bind_addr)
{
asio::async_write(m_sock, asio::buffer(sendbuffer)
async_write(m_sock, asio::buffer(sendbuffer)
, bind(&http_connection::on_write, shared_from_this(), _1));
}
else
{
m_ssl = ssl;
m_bind_addr = bind_addr;
asio::error_code ec;
error_code ec;
m_sock.close(ec);
#ifdef TORRENT_USE_OPENSSL
@ -168,7 +180,7 @@ void http_connection::start(std::string const& hostname, std::string const& port
#endif
if (m_bind_addr != address_v4::any())
{
asio::error_code ec;
error_code ec;
m_sock.bind(tcp::endpoint(m_bind_addr, 0), ec);
if (ec)
{
@ -187,52 +199,65 @@ void http_connection::start(std::string const& hostname, std::string const& port
void http_connection::on_connect_timeout()
{
TORRENT_ASSERT(m_connection_ticket >= 0);
if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
m_connection_ticket = -1;
callback(asio::error::timed_out);
close();
if (!m_endpoints.empty())
{
m_sock.close();
}
else
{
callback(asio::error::timed_out);
close();
}
}
void http_connection::on_timeout(boost::weak_ptr<http_connection> p
, asio::error_code const& e)
, error_code const& e)
{
boost::shared_ptr<http_connection> c = p.lock();
if (!c) return;
if (c->m_connection_ticket > -1) c->m_cc.done(c->m_connection_ticket);
c->m_connection_ticket = -1;
if (e == asio::error::operation_aborted) return;
if (c->m_last_receive + c->m_timeout < time_now())
{
c->callback(asio::error::timed_out);
c->close();
if (c->m_connection_ticket > -1 && !c->m_endpoints.empty())
{
c->m_sock.close();
error_code ec;
c->m_timer.expires_at(c->m_last_receive + c->m_timeout, ec);
c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1));
}
else
{
c->callback(asio::error::timed_out);
c->close();
}
return;
}
if (!c->m_sock.is_open()) return;
asio::error_code ec;
error_code ec;
c->m_timer.expires_at(c->m_last_receive + c->m_timeout, ec);
c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1));
}
void http_connection::close()
{
asio::error_code ec;
error_code ec;
m_timer.cancel(ec);
m_limiter_timer.cancel(ec);
m_sock.close(ec);
m_hostname.clear();
m_port.clear();
if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
m_connection_ticket = -1;
m_handler.clear();
m_abort = true;
}
void http_connection::on_resolve(asio::error_code const& e
void http_connection::on_resolve(error_code const& e
, tcp::resolver::iterator i)
{
if (e)
@ -243,21 +268,26 @@ void http_connection::on_resolve(asio::error_code const& e
}
TORRENT_ASSERT(i != tcp::resolver::iterator());
// look for an address that has the same kind as the one
// we're binding to. To make sure a tracker get our
// correct listening address.
tcp::resolver::iterator target = i;
tcp::resolver::iterator end;
tcp::endpoint target_address = *i;
for (; target != end && target->endpoint().address().is_v4()
!= m_bind_addr.is_v4(); ++target);
std::transform(i, tcp::resolver::iterator(), std::back_inserter(m_endpoints)
, boost::bind(&tcp::resolver::iterator::value_type::endpoint, _1));
if (target != end)
{
target_address = *target;
}
// sort the endpoints so that the ones with the same IP version as our
// bound listen socket are first. So that when contacting a tracker,
// we'll talk to it from the same IP that we're listening on
m_endpoints.sort(
(bind(&address::is_v4, bind(&tcp::endpoint::address, _1)) == m_bind_addr.is_v4())
> (bind(&address::is_v4, bind(&tcp::endpoint::address, _2)) == m_bind_addr.is_v4()));
m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, target_address)
queue_connect();
}
void http_connection::queue_connect()
{
TORRENT_ASSERT(!m_endpoints.empty());
tcp::endpoint target = m_endpoints.front();
m_endpoints.pop_front();
m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, target)
, bind(&http_connection::on_connect_timeout, shared_from_this())
, m_timeout, m_priority);
}
@ -266,35 +296,35 @@ void http_connection::connect(int ticket, tcp::endpoint target_address)
{
m_connection_ticket = ticket;
m_sock.async_connect(target_address, boost::bind(&http_connection::on_connect
, shared_from_this(), _1/*, ++i*/));
, shared_from_this(), _1));
}
void http_connection::on_connect(asio::error_code const& e
/*, tcp::resolver::iterator i*/)
void http_connection::on_connect(error_code const& e)
{
TORRENT_ASSERT(m_connection_ticket >= 0);
m_cc.done(m_connection_ticket);
m_last_receive = time_now();
if (!e)
{
m_last_receive = time_now();
if (m_connect_handler) m_connect_handler(*this);
asio::async_write(m_sock, asio::buffer(sendbuffer)
async_write(m_sock, asio::buffer(sendbuffer)
, bind(&http_connection::on_write, shared_from_this(), _1));
}
/* else if (i != tcp::resolver::iterator())
else if (!m_endpoints.empty() && !m_abort)
{
// The connection failed. Try the next endpoint in the list.
m_sock.close();
m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i)
, bind(&http_connection::on_connect_timeout, shared_from_this())
, m_timeout, m_priority);
queue_connect();
}
*/ else
else
{
callback(e);
close();
}
}
void http_connection::callback(asio::error_code const& e, char const* data, int size)
void http_connection::callback(error_code const& e, char const* data, int size)
{
if (!m_bottled || !m_called)
{
@ -307,7 +337,7 @@ void http_connection::callback(asio::error_code const& e, char const* data, int
std::string error;
if (inflate_gzip(data, size, buf, max_bottled_buffer, error))
{
callback(asio::error::fault, data, size);
if (m_handler) m_handler(asio::error::fault, m_parser, data, size, *this);
close();
return;
}
@ -317,11 +347,11 @@ void http_connection::callback(asio::error_code const& e, char const* data, int
}
m_called = true;
m_timer.cancel();
if (m_handler) m_handler(e, m_parser, data, size);
if (m_handler) m_handler(e, m_parser, data, size, *this);
}
}
void http_connection::on_write(asio::error_code const& e)
void http_connection::on_write(error_code const& e)
{
if (e)
{
@ -340,7 +370,7 @@ void http_connection::on_write(asio::error_code const& e)
if (m_download_quota == 0)
{
if (!m_limiter_timer_active)
on_assign_bandwidth(asio::error_code());
on_assign_bandwidth(error_code());
return;
}
}
@ -350,7 +380,7 @@ void http_connection::on_write(asio::error_code const& e)
, shared_from_this(), _1, _2));
}
void http_connection::on_read(asio::error_code const& e
void http_connection::on_read(error_code const& e
, std::size_t bytes_transferred)
{
if (m_rate_limit)
@ -394,7 +424,7 @@ void http_connection::on_read(asio::error_code const& e
if (error)
{
// HTTP parse error
asio::error_code ec = asio::error::fault;
error_code ec = asio::error::fault;
callback(ec, 0, 0);
return;
}
@ -407,17 +437,44 @@ void http_connection::on_read(asio::error_code const& e
if (code >= 300 && code < 400)
{
// attempt a redirect
std::string const& url = m_parser.header("location");
if (url.empty())
std::string const& location = m_parser.header("location");
if (location.empty())
{
// missing location header
callback(e);
callback(asio::error::fault);
close();
return;
}
asio::error_code ec;
error_code ec;
m_sock.close(ec);
get(url, m_timeout, m_priority, &m_proxy, m_redirects - 1);
using boost::tuples::ignore;
char const* error;
boost::tie(ignore, ignore, ignore, ignore, ignore, error)
= parse_url_components(location);
if (error == 0)
{
get(location, m_timeout, m_priority, &m_proxy, m_redirects - 1);
}
else
{
// some broken web servers send out relative paths
// in the location header.
std::string url = m_url;
// remove the leaf filename
std::size_t i = url.find_last_of('/');
if (i == std::string::npos)
{
url += '/';
}
else
{
url.resize(i + 1);
}
url += location;
get(url, m_timeout, m_priority, &m_proxy, m_redirects - 1);
}
return;
}
@ -434,7 +491,7 @@ void http_connection::on_read(asio::error_code const& e
}
else if (m_bottled && m_parser.finished())
{
asio::error_code ec;
error_code ec;
m_timer.cancel(ec);
callback(e, m_parser.get_body().begin, m_parser.get_body().left());
}
@ -462,7 +519,7 @@ void http_connection::on_read(asio::error_code const& e
if (m_download_quota == 0)
{
if (!m_limiter_timer_active)
on_assign_bandwidth(asio::error_code());
on_assign_bandwidth(error_code());
return;
}
}
@ -472,7 +529,7 @@ void http_connection::on_read(asio::error_code const& e
, shared_from_this(), _1, _2));
}
void http_connection::on_assign_bandwidth(asio::error_code const& e)
void http_connection::on_assign_bandwidth(error_code const& e)
{
if ((e == asio::error::operation_aborted
&& m_limiter_timer_active)
@ -499,7 +556,7 @@ void http_connection::on_assign_bandwidth(asio::error_code const& e)
, bind(&http_connection::on_read
, shared_from_this(), _1, _2));
asio::error_code ec;
error_code ec;
m_limiter_timer_active = true;
m_limiter_timer.expires_from_now(milliseconds(250), ec);
m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth
@ -512,7 +569,7 @@ void http_connection::rate_limit(int limit)
if (!m_limiter_timer_active)
{
asio::error_code ec;
error_code ec;
m_limiter_timer_active = true;
m_limiter_timer.expires_from_now(milliseconds(250), ec);
m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth

View File

@ -38,13 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
void http_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i
void http_stream::name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h)
{
if (e || i == tcp::resolver::iterator())
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -53,12 +53,12 @@ namespace libtorrent
&http_stream::connected, this, _1, h));
}
void http_stream::connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void http_stream::connected(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -82,32 +82,32 @@ namespace libtorrent
m_user + ":" + m_password) + "\r\n", p);
}
write_string("\r\n", p);
asio::async_write(m_sock, asio::buffer(m_buffer)
async_write(m_sock, asio::buffer(m_buffer)
, boost::bind(&http_stream::handshake1, this, _1, h));
}
void http_stream::handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void http_stream::handshake1(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
// read one byte from the socket
m_buffer.resize(1);
asio::async_read(m_sock, asio::buffer(m_buffer)
async_read(m_sock, asio::buffer(m_buffer)
, boost::bind(&http_stream::handshake2, this, _1, h));
}
void http_stream::handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void http_stream::handshake2(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -138,7 +138,7 @@ namespace libtorrent
if (status == 0)
{
(*h)(asio::error::operation_not_supported);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -148,7 +148,7 @@ namespace libtorrent
if (code != 200)
{
(*h)(asio::error::operation_not_supported);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -160,7 +160,7 @@ namespace libtorrent
// read another byte from the socket
m_buffer.resize(read_pos + 1);
asio::async_read(m_sock, asio::buffer(&m_buffer[0] + read_pos, 1)
async_read(m_sock, asio::buffer(&m_buffer[0] + read_pos, 1)
, boost::bind(&http_stream::handshake2, this, _1, h));
}

View File

@ -194,7 +194,7 @@ namespace libtorrent
tracker_connection::close();
}
void http_tracker_connection::on_response(asio::error_code const& ec
void http_tracker_connection::on_response(error_code const& ec
, http_parser const& parser, char const* data, int size)
{
// keep this alive
@ -313,9 +313,7 @@ namespace libtorrent
if (tracker_req().kind == tracker_request::scrape_request)
{
std::string ih;
std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end()
, std::back_inserter(ih));
std::string ih = tracker_req().info_hash.to_string();
entry const* files = e.find_key("files");
if (files == 0 || files->type() != entry::dictionary_t)
@ -324,7 +322,7 @@ namespace libtorrent
return;
}
entry const* scrape_data = e.find_key(ih.c_str());
entry const* scrape_data = files->find_key(ih);
if (scrape_data == 0 || scrape_data->type() != entry::dictionary_t)
{
fail(-1, "missing or invalid info-hash entry in scrape response");

View File

@ -37,12 +37,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket_type.hpp"
#include <boost/shared_ptr.hpp>
#include <stdexcept>
#include <asio/io_service.hpp>
namespace libtorrent
{
bool instantiate_connection(asio::io_service& ios
bool instantiate_connection(io_service& ios
, proxy_settings const& ps, socket_type& s)
{
if (ps.type == proxy_settings::none)

View File

@ -40,8 +40,6 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent { namespace dht
{
using asio::ip::udp;
closest_nodes_observer::~closest_nodes_observer()
{
if (m_algorithm) m_algorithm->failed(m_self, true);

View File

@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/bencode.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/version.hpp"
#include "libtorrent/escape_string.hpp"
using boost::ref;
using boost::lexical_cast;
@ -66,9 +67,6 @@ enum
key_refresh = 5 // generate a new write token key every 5 minutes
};
using asio::ip::udp;
typedef asio::ip::address_v4 address;
namespace
{
const int tick_period = 1; // minutes
@ -228,7 +226,7 @@ namespace libtorrent { namespace dht
s.dht_global_nodes = m_dht.num_global_nodes();
}
void dht_tracker::connection_timeout(asio::error_code const& e)
void dht_tracker::connection_timeout(error_code const& e)
try
{
mutex_t::scoped_lock l(m_mutex);
@ -247,7 +245,7 @@ namespace libtorrent { namespace dht
#endif
};
void dht_tracker::refresh_timeout(asio::error_code const& e)
void dht_tracker::refresh_timeout(error_code const& e)
try
{
mutex_t::scoped_lock l(m_mutex);
@ -263,7 +261,7 @@ namespace libtorrent { namespace dht
TORRENT_ASSERT(false);
};
void dht_tracker::tick(asio::error_code const& e)
void dht_tracker::tick(error_code const& e)
try
{
mutex_t::scoped_lock l(m_mutex);
@ -375,6 +373,12 @@ namespace libtorrent { namespace dht
m_dht.announce(ih, listen_port, f);
}
void dht_tracker::on_unreachable(udp::endpoint const& ep)
{
m_dht.unreachable(ep);
}
// translate bittorrent kademlia message into the generice kademlia message
// used by the library
void dht_tracker::on_receive(udp::endpoint const& ep, char const* buf, int bytes_transferred)
@ -404,8 +408,8 @@ namespace libtorrent { namespace dht
if (match->count == 20)
{
TORRENT_LOG(dht_tracker) << time_now_string() << " BANNING PEER [ ip: "
<< ep << " | time: " << total_milliseconds((now - match->limit) + seconds(5)) / 1000.f
<< " | count: " << match->count << " ]";
<< ep << " time: " << total_milliseconds((now - match->limit) + seconds(5)) / 1000.f
<< " count: " << match->count << " ]";
}
#endif
// we've received 20 messages in less than 5 seconds from
@ -442,8 +446,9 @@ namespace libtorrent { namespace dht
entry e = bdecode(buf, buf + bytes_transferred);
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << time_now_string() << " RECEIVED ["
<< ep << "]:";
std::stringstream log_line;
log_line << time_now_string() << " RECEIVED ["
" ip: " << ep;
#endif
libtorrent::dht::msg m;
@ -461,36 +466,36 @@ namespace libtorrent { namespace dht
if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "UT"))
{
++m_ut_message_input;
TORRENT_LOG(dht_tracker) << " client: uTorrent";
log_line << " c: uTorrent";
}
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "LT"))
{
++m_lt_message_input;
TORRENT_LOG(dht_tracker) << " client: libtorrent";
log_line << " c: libtorrent";
}
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MP"))
{
++m_mp_message_input;
TORRENT_LOG(dht_tracker) << " client: MooPolice";
log_line << " c: MooPolice";
}
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "GR"))
{
++m_gr_message_input;
TORRENT_LOG(dht_tracker) << " client: GetRight";
log_line << " c: GetRight";
}
else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MO"))
{
++m_mo_message_input;
TORRENT_LOG(dht_tracker) << " client: Mono Torrent";
log_line << " c: Mono Torrent";
}
else
{
TORRENT_LOG(dht_tracker) << " client: " << client;
log_line << " c: " << client;
}
}
catch (std::exception&)
{
TORRENT_LOG(dht_tracker) << " client: generic";
log_line << " c: generic";
};
#endif
@ -499,8 +504,8 @@ namespace libtorrent { namespace dht
if (msg_type == "r")
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " reply: transaction: "
<< m.transaction_id;
log_line << " r: " << messages::ids[m.message_id]
<< " t: " << to_hex(m.transaction_id);
#endif
m.reply = true;
@ -528,7 +533,7 @@ namespace libtorrent { namespace dht
read_endpoint_list<tcp::endpoint>(n, m.peers);
}
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size();
log_line << " p: " << m.peers.size();
#endif
}
@ -548,7 +553,7 @@ namespace libtorrent { namespace dht
id, read_v4_endpoint<udp::endpoint>(i)));
}
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " nodes: " << m.nodes.size();
log_line << " n: " << m.nodes.size();
#endif
}
@ -573,7 +578,7 @@ namespace libtorrent { namespace dht
id, read_v6_endpoint<udp::endpoint>(in)));
}
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " nodes2 + nodes: " << m.nodes.size();
log_line << " n2: " << m.nodes.size();
#endif
}
@ -590,7 +595,7 @@ namespace libtorrent { namespace dht
std::string request_kind(e["q"].string());
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " query: " << request_kind;
log_line << " q: " << request_kind;
#endif
if (request_kind == "ping")
@ -603,8 +608,7 @@ namespace libtorrent { namespace dht
if (target.size() != 20) throw std::runtime_error("invalid size of target id");
std::copy(target.begin(), target.end(), m.info_hash.begin());
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " target: "
<< boost::lexical_cast<std::string>(m.info_hash);
log_line << " t: " << boost::lexical_cast<std::string>(m.info_hash);
#endif
m.message_id = libtorrent::dht::messages::find_node;
@ -616,8 +620,7 @@ namespace libtorrent { namespace dht
std::copy(info_hash.begin(), info_hash.end(), m.info_hash.begin());
m.message_id = libtorrent::dht::messages::get_peers;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " info_hash: "
<< boost::lexical_cast<std::string>(m.info_hash);
log_line << " ih: " << boost::lexical_cast<std::string>(m.info_hash);
#endif
}
else if (request_kind == "announce_peer")
@ -633,9 +636,8 @@ namespace libtorrent { namespace dht
m.write_token = a["token"];
m.message_id = libtorrent::dht::messages::announce_peer;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " info_hash: "
<< boost::lexical_cast<std::string>(m.info_hash);
TORRENT_LOG(dht_tracker) << " port: " << m.port;
log_line << " ih: " << boost::lexical_cast<std::string>(m.info_hash);
log_line << " p: " << m.port;
if (!m_dht.verify_token(m))
++m_failed_announces;
@ -657,8 +659,8 @@ namespace libtorrent { namespace dht
m.error_msg = list.back().string();
m.error_code = list.front().integer();
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " incoming error: " << m.error_code << " "
<< m.error_msg;
log_line << " incoming error: " << m.error_code
<< " " << m.error_msg;
#endif
throw std::runtime_error("DHT error message");
}
@ -677,7 +679,7 @@ namespace libtorrent { namespace dht
++m_queries_received[m.message_id];
m_queries_bytes_received[m.message_id] += int(bytes_transferred);
}
TORRENT_LOG(dht_tracker) << e;
TORRENT_LOG(dht_tracker) << log_line.str() << " ]";
#endif
TORRENT_ASSERT(m.message_id != messages::error);
m_dht.incoming(m);
@ -739,7 +741,7 @@ namespace libtorrent { namespace dht
bind(&dht_tracker::on_name_lookup, self(), _1, _2));
}
void dht_tracker::on_name_lookup(asio::error_code const& e
void dht_tracker::on_name_lookup(error_code const& e
, udp::resolver::iterator host) try
{
if (e || host == udp::resolver::iterator()) return;
@ -757,7 +759,7 @@ namespace libtorrent { namespace dht
bind(&dht_tracker::on_router_name_lookup, self(), _1, _2));
}
void dht_tracker::on_router_name_lookup(asio::error_code const& e
void dht_tracker::on_router_name_lookup(error_code const& e
, udp::resolver::iterator host) try
{
if (e || host == udp::resolver::iterator()) return;
@ -809,9 +811,6 @@ namespace libtorrent { namespace dht
p.list().push_back(entry(endpoint));
}
}
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " nodes: " << m.nodes.size();
#endif
}
}
@ -828,9 +827,10 @@ namespace libtorrent { namespace dht
e["v"] = std::string(version_str, version_str + 4);
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << time_now_string()
<< " SENDING [" << m.addr << "]:";
TORRENT_LOG(dht_tracker) << " transaction: " << m.transaction_id;
std::stringstream log_line;
log_line << time_now_string()
<< " SENDING [ ip: " << m.addr
<< " t: " << to_hex(m.transaction_id);
#endif
if (m.message_id == messages::error)
@ -843,8 +843,8 @@ namespace libtorrent { namespace dht
error_list.list().push_back(entry(m.error_msg));
e["e"] = error_list;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << time_now_string()
<< " outgoing error: " << m.error_code << " " << m.error_msg;
log_line << " err: " << m.error_code
<< " msg: " << m.error_msg;
#endif
}
else if (m.reply)
@ -855,8 +855,7 @@ namespace libtorrent { namespace dht
r["id"] = std::string(m.id.begin(), m.id.end());
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << time_now_string()
<< " reply: " << messages::ids[m.message_id];
log_line << " r: " << messages::ids[m.message_id];
#endif
if (m.write_token.type() != entry::undefined_t)
@ -892,7 +891,7 @@ namespace libtorrent { namespace dht
p.list().push_back(entry(endpoint));
}
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size();
log_line << " p: " << m.peers.size();
#endif
}
break;
@ -916,8 +915,7 @@ namespace libtorrent { namespace dht
e["q"] = messages::ids[m.message_id];
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " query: "
<< messages::ids[m.message_id];
log_line << " q: " << messages::ids[m.message_id];
#endif
switch (m.message_id)
@ -926,8 +924,7 @@ namespace libtorrent { namespace dht
{
a["target"] = std::string(m.info_hash.begin(), m.info_hash.end());
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " target: "
<< boost::lexical_cast<std::string>(m.info_hash);
log_line << " target: " << boost::lexical_cast<std::string>(m.info_hash);
#endif
break;
}
@ -935,8 +932,7 @@ namespace libtorrent { namespace dht
{
a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end());
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker) << " info_hash: "
<< boost::lexical_cast<std::string>(m.info_hash);
log_line << " ih: " << boost::lexical_cast<std::string>(m.info_hash);
#endif
break;
}
@ -945,9 +941,8 @@ namespace libtorrent { namespace dht
a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end());
a["token"] = m.write_token;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(dht_tracker)
<< " port: " << m.port
<< " info_hash: " << boost::lexical_cast<std::string>(m.info_hash);
log_line << " p: " << m.port
<< " ih: " << boost::lexical_cast<std::string>(m.info_hash);
#endif
break;
default: break;
@ -957,7 +952,7 @@ namespace libtorrent { namespace dht
m_send_buf.clear();
bencode(std::back_inserter(m_send_buf), e);
asio::error_code ec;
error_code ec;
m_sock.send(m.addr, &m_send_buf[0], (int)m_send_buf.size(), ec);
#ifdef TORRENT_DHT_VERBOSE_LOGGING
@ -972,7 +967,7 @@ namespace libtorrent { namespace dht
{
m_queries_out_bytes += m_send_buf.size();
}
TORRENT_LOG(dht_tracker) << e;
TORRENT_LOG(dht_tracker) << log_line.str() << " ]";
#endif
if (!m.piggy_backed_ping) return;

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include <libtorrent/io.hpp>
#include <libtorrent/socket.hpp>
namespace libtorrent { namespace dht
{
@ -101,7 +102,7 @@ find_data::find_data(
add_requests();
}
void find_data::invoke(node_id const& id, asio::ip::udp::endpoint addr)
void find_data::invoke(node_id const& id, udp::endpoint addr)
{
if (m_done)
{

View File

@ -65,8 +65,6 @@ namespace
// TODO: configurable?
enum { announce_interval = 30 };
using asio::ip::udp;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DEFINE_LOG(node)
#endif
@ -245,6 +243,11 @@ void node_impl::refresh_bucket(int bucket) try
}
catch (std::exception&) {}
void node_impl::unreachable(udp::endpoint const& ep)
{
m_rpc.unreachable(ep);
}
void node_impl::incoming(msg const& m)
{
if (m_rpc.incoming(m))
@ -269,6 +272,9 @@ namespace
for (std::vector<node_entry>::const_iterator i = v.begin()
, end(v.end()); i != end; ++i)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(node) << " distance: " << (160 - distance_exp(ih, i->id));
#endif
observer_ptr o(new (rpc.allocator().malloc()) get_peers_observer(ih, listen_port, rpc, f));
#ifndef NDEBUG
o->m_in_constructor = false;

View File

@ -47,8 +47,6 @@ using boost::bind;
namespace libtorrent { namespace dht
{
using asio::ip::udp;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DEFINE_LOG(refresh)
#endif

View File

@ -50,8 +50,9 @@ using boost::uint8_t;
namespace libtorrent { namespace dht
{
using asio::ip::udp;
typedef asio::ip::address_v4 address;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DEFINE_LOG(table)
#endif
routing_table::routing_table(node_id const& id, int bucket_size
, dht_settings const& settings)
@ -225,6 +226,15 @@ void routing_table::node_failed(node_id const& id)
if (rb.empty())
{
++i->fail_count;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(table) << " NODE FAILED"
" id: " << id <<
" ip: " << i->addr <<
" fails: " << i->fail_count <<
" up-time: " << total_seconds(time_now() - i->first_seen);
#endif
if (i->fail_count >= m_settings.max_fail_count)
{
b.erase(i);

View File

@ -159,6 +159,39 @@ void rpc_manager::check_invariant() const
}
#endif
void rpc_manager::unreachable(udp::endpoint const& ep)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(rpc) << time_now_string() << " PORT_UNREACHABLE [ ip: " << ep << " ]";
#endif
int num_active = m_oldest_transaction_id < m_next_transaction_id
? m_next_transaction_id - m_oldest_transaction_id
: max_transactions - m_next_transaction_id + m_oldest_transaction_id;
TORRENT_ASSERT((m_oldest_transaction_id + num_active) % max_transactions
== m_next_transaction_id);
int tid = m_oldest_transaction_id;
for (int i = 0; i < num_active; ++i, ++tid)
{
if (tid >= max_transactions) tid = 0;
observer_ptr const& o = m_transactions[tid];
if (!o) continue;
if (o->target_addr != ep) continue;
observer_ptr ptr = m_transactions[tid];
m_transactions[tid] = 0;
if (tid == m_oldest_transaction_id)
{
++m_oldest_transaction_id;
if (m_oldest_transaction_id >= max_transactions)
m_oldest_transaction_id = 0;
}
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(rpc) << " found transaction [ tid: " << tid << " ]";
#endif
ptr->timeout();
return;
}
}
bool rpc_manager::incoming(msg const& m)
{
INVARIANT_CHECK;

View File

@ -39,7 +39,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/bind.hpp>
using boost::bind;
using asio::ip::udp;
namespace libtorrent { namespace dht
{
@ -89,7 +88,8 @@ boost::pool<>& traversal_algorithm::allocator() const
void traversal_algorithm::traverse(node_id const& id, udp::endpoint addr)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(traversal) << "node returned a list which included a node with id 0";
if (id.is_all_zeros())
TORRENT_LOG(traversal) << time_now_string() << " WARNING: node returned a list which included a node with id 0";
#endif
add_entry(id, addr, 0);
}

View File

@ -187,6 +187,7 @@ namespace libtorrent
std::pair<char const*, lazy_entry>* tmp = new (std::nothrow) std::pair<char const*, lazy_entry>[capacity];
if (tmp == 0) return 0;
std::memcpy(tmp, m_data.dict, sizeof(std::pair<char const*, lazy_entry>) * m_size);
for (int i = 0; i < m_size; ++i) m_data.dict[i].second.release();
delete[] m_data.dict;
m_data.dict = tmp;
m_capacity = capacity;
@ -299,6 +300,7 @@ namespace libtorrent
lazy_entry* tmp = new (std::nothrow) lazy_entry[capacity];
if (tmp == 0) return 0;
std::memcpy(tmp, m_data.list, sizeof(lazy_entry) * m_size);
for (int i = 0; i < m_size; ++i) m_data.list[i].release();
delete[] m_data.list;
m_data.list = tmp;
m_capacity = capacity;
@ -330,6 +332,7 @@ namespace libtorrent
case dict_t: delete[] m_data.dict; break;
default: break;
}
m_data.start = 0;
m_size = 0;
m_capacity = 0;
m_type = none_t;
@ -370,7 +373,8 @@ namespace libtorrent
bool one_liner = (e.list_size() == 0
|| e.list_at(0)->type() == lazy_entry::int_t
|| (e.list_at(0)->type() == lazy_entry::string_t
&& e.list_at(0)->string_length() < 10))
&& (e.list_at(0)->string_length() < 10
|| e.list_size() < 2)))
&& e.list_size() < 5;
if (!one_liner) os << "\n";
for (int i = 0; i < e.list_size(); ++i)
@ -388,7 +392,7 @@ namespace libtorrent
bool one_liner = (e.dict_size() == 0
|| e.dict_at(0).second->type() == lazy_entry::int_t
|| (e.dict_at(0).second->type() == lazy_entry::string_t
&& e.dict_at(0).second->string_length() < 10)
&& e.dict_at(0).second->string_length() < 30)
|| e.dict_at(0).first.size() < 10)
&& e.dict_size() < 5;

View File

@ -40,8 +40,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#if BOOST_VERSION < 103500
#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#else
#include <boost/asio/ip/host_name.hpp>
#include <boost/asio/ip/multicast.hpp>
#endif
#include <boost/thread/mutex.hpp>
#include <cstdlib>
#include <boost/config.hpp>
@ -52,7 +57,7 @@ using namespace libtorrent;
namespace libtorrent
{
// defined in broadcast_socket.cpp
address guess_local_address(asio::io_service&);
address guess_local_address(io_service&);
}
lsd::lsd(io_service& ios, address const& listen_interface
@ -84,7 +89,7 @@ void lsd::announce(sha1_hash const& ih, int listen_port)
std::string const& msg = btsearch.str();
m_retry_count = 1;
asio::error_code ec;
error_code ec;
m_socket.send(msg.c_str(), int(msg.size()), ec);
if (ec)
{
@ -101,11 +106,11 @@ void lsd::announce(sha1_hash const& ih, int listen_port)
m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
}
void lsd::resend_announce(asio::error_code const& e, std::string msg)
void lsd::resend_announce(error_code const& e, std::string msg)
{
if (e) return;
asio::error_code ec;
error_code ec;
m_socket.send(msg.c_str(), int(msg.size()), ec);
++m_retry_count;
@ -192,7 +197,7 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
void lsd::close()
{
m_socket.close();
asio::error_code ec;
error_code ec;
m_broadcast_timer.cancel(ec);
m_disabled = true;
m_callback.clear();

View File

@ -47,6 +47,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/utility.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#if BOOST_VERSION >= 103500
#include <boost/system/error_code.hpp>
#endif
#include <boost/version.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
@ -57,8 +62,10 @@ using boost::iostreams::mapped_file_params;
namespace libtorrent
{
namespace fs = boost::filesystem;
#if BOOST_VERSION >= 103500
using boost::system::error_code;
#endif
struct mapped_file_pool
{
@ -78,7 +85,7 @@ namespace libtorrent
#ifndef NDEBUG
if (file_size > 0)
{
fs::system_error_type ec;
error_code ec;
fs::file_status st = fs::status(path, ec);
TORRENT_ASSERT(!fs::exists(st));
}
@ -197,7 +204,11 @@ namespace libtorrent
size_type start = (offset / view_size) * view_size;
TORRENT_ASSERT(start + view_size >= offset + length);
#if BOOST_VERSION < 103500
fs::system_error_type ec;
#else
error_code ec;
#endif
fs::file_status st = fs::status(p, ec);
m_files.push_back(file_entry());

View File

@ -55,6 +55,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/extensions.hpp"
#include "libtorrent/extensions/metadata_transfer.hpp"
#include "libtorrent/alert_types.hpp"
#include "libtorrent/buffer.hpp"
namespace libtorrent { namespace
{
@ -107,40 +108,37 @@ namespace libtorrent { namespace
virtual void on_files_checked()
{
// if the torrent is a seed, copy the metadata from
// the torrent before it is deallocated
if (m_torrent.is_seed())
metadata();
// if the torrent is a seed, make a reference to
// the metadata from the torrent before it is deallocated
if (m_torrent.is_seed()) metadata();
}
virtual boost::shared_ptr<peer_plugin> new_connection(
peer_connection* pc);
std::vector<char> const& metadata() const
buffer::const_interval metadata() const
{
if (m_metadata.empty())
if (!m_metadata)
{
bencode(std::back_inserter(m_metadata)
, m_torrent.torrent_file().create_info_metadata());
TORRENT_ASSERT(hasher(&m_metadata[0], m_metadata.size()).final()
m_metadata = m_torrent.torrent_file().metadata();
m_metadata_size = m_torrent.torrent_file().metadata_size();
TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final()
== m_torrent.torrent_file().info_hash());
}
TORRENT_ASSERT(!m_metadata.empty());
return m_metadata;
return buffer::const_interval(m_metadata.get(), m_metadata.get()
+ m_metadata_size);
}
bool received_metadata(char const* buf, int size, int offset, int total_size)
{
if (m_torrent.valid_metadata()) return false;
if ((int)m_metadata.size() < total_size)
m_metadata.resize(total_size);
std::copy(
buf
, buf + size
, &m_metadata[offset]);
if (!m_metadata || m_metadata_size < total_size)
{
m_metadata.reset(new char[total_size]);
m_metadata_size = total_size;
}
std::copy(buf, buf + size, &m_metadata[offset]);
if (m_have_metadata.empty())
m_have_metadata.resize(256, false);
@ -163,7 +161,7 @@ namespace libtorrent { namespace
if (!have_all) return false;
hasher h;
h.update(&m_metadata[0], (int)m_metadata.size());
h.update(&m_metadata[0], m_metadata_size);
sha1_hash info_hash = h.final();
if (info_hash != m_torrent.torrent_file().info_hash())
@ -184,9 +182,10 @@ namespace libtorrent { namespace
return false;
}
entry metadata = bdecode(m_metadata.begin(), m_metadata.end());
lazy_entry e;
lazy_bdecode(m_metadata.get(), m_metadata.get() + m_metadata_size, e);
std::string error;
if (!m_torrent.set_metadata(metadata, error))
if (!m_torrent.set_metadata(e, error))
{
// this means the metadata is correct, since we
// verified it against the info-hash, but we
@ -240,10 +239,10 @@ namespace libtorrent { namespace
// the metadata file while downloading it from
// peers, and while sending it.
// it is mutable because it's generated lazily
mutable std::vector<char> m_metadata;
mutable boost::shared_array<char> m_metadata;
int m_metadata_progress;
int m_metadata_size;
mutable int m_metadata_size;
// this is a bitfield of size 256, each bit represents
// a piece of the metadata. It is set to one if we
@ -333,7 +332,7 @@ namespace libtorrent { namespace
if (m_torrent.valid_metadata() && !m_torrent.torrent_file().priv())
{
std::pair<int, int> offset
= req_to_offset(req, (int)m_tp.metadata().size());
= req_to_offset(req, (int)m_tp.metadata().left());
buffer::interval i = m_pc.allocate_send_buffer(15 + offset.second);
@ -343,11 +342,11 @@ namespace libtorrent { namespace
detail::write_uint8(m_message_index, i.begin);
// means 'data packet'
detail::write_uint8(1, i.begin);
detail::write_uint32((int)m_tp.metadata().size(), i.begin);
detail::write_uint32((int)m_tp.metadata().left(), i.begin);
detail::write_uint32(offset.first, i.begin);
std::vector<char> const& metadata = m_tp.metadata();
std::copy(metadata.begin() + offset.first
, metadata.begin() + offset.first + offset.second, i.begin);
char const* metadata = m_tp.metadata().begin;
std::copy(metadata + offset.first
, metadata + offset.first + offset.second, i.begin);
i.begin += offset.second;
TORRENT_ASSERT(i.begin == i.end);
}

View File

@ -33,7 +33,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/pch.hpp"
#include <boost/bind.hpp>
#if BOOST_VERSION < 103500
#include <asio/ip/host_name.hpp>
#else
#include <boost/asio/ip/host_name.hpp>
#endif
#include "libtorrent/natpmp.hpp"
#include "libtorrent/io.hpp"
@ -63,7 +67,7 @@ void natpmp::rebind(address const& listen_interface)
{
mutex_t::scoped_lock l(m_mutex);
asio::error_code ec;
error_code ec;
address gateway = get_default_gateway(m_socket.get_io_service(), ec);
if (ec)
{
@ -198,7 +202,7 @@ void natpmp::try_next_mapping(int i)
{
if (m_abort)
{
asio::error_code ec;
error_code ec;
m_send_timer.cancel(ec);
m_socket.close(ec);
}
@ -264,7 +268,7 @@ void natpmp::send_map_request(int i)
<< " ttl: " << ttl << " ]" << std::endl;
#endif
asio::error_code ec;
error_code ec;
m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint, 0, ec);
// linear back-off instead of exponential
++m_retry_count;
@ -272,7 +276,7 @@ void natpmp::send_map_request(int i)
m_send_timer.async_wait(bind(&natpmp::resend_request, self(), i, _1));
}
void natpmp::resend_request(int i, asio::error_code const& e)
void natpmp::resend_request(int i, error_code const& e)
{
if (e) return;
@ -290,7 +294,7 @@ void natpmp::resend_request(int i, asio::error_code const& e)
send_map_request(i);
}
void natpmp::on_reply(asio::error_code const& e
void natpmp::on_reply(error_code const& e
, std::size_t bytes_transferred)
{
using namespace libtorrent::detail;
@ -305,7 +309,7 @@ void natpmp::on_reply(asio::error_code const& e
mutex_t::scoped_lock l(m_mutex);
asio::error_code ec;
error_code ec;
m_send_timer.cancel(ec);
TORRENT_ASSERT(m_currently_mapping >= 0);
@ -439,7 +443,7 @@ void natpmp::update_expiration_timer()
<< " ttl: " << total_seconds(min_expire - time_now())
<< " ]" << std::endl;
#endif
asio::error_code ec;
error_code ec;
if (m_next_refresh >= 0) m_refresh_timer.cancel(ec);
m_refresh_timer.expires_from_now(min_expire - now, ec);
m_refresh_timer.async_wait(bind(&natpmp::mapping_expired, self(), _1, min_index));
@ -447,7 +451,7 @@ void natpmp::update_expiration_timer()
}
}
void natpmp::mapping_expired(asio::error_code const& e, int i)
void natpmp::mapping_expired(error_code const& e, int i)
{
if (e) return;
mutex_t::scoped_lock l(m_mutex);
@ -463,7 +467,7 @@ void natpmp::close()
{
mutex_t::scoped_lock l(m_mutex);
m_abort = true;
asio::error_code ec;
error_code ec;
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
m_log << time_now_string() << " close" << std::endl;
#endif

View File

@ -64,7 +64,7 @@ namespace libtorrent
session_impl& ses
, boost::weak_ptr<torrent> tor
, shared_ptr<socket_type> s
, tcp::endpoint const& remote
, tcp::endpoint const& endp
, policy::peer* peerinfo)
:
#ifndef NDEBUG
@ -73,41 +73,28 @@ namespace libtorrent
#endif
m_ses(ses)
, m_max_out_request_queue(m_ses.settings().max_out_request_queue)
, m_timeout(m_ses.settings().peer_timeout)
, m_last_piece(time_now())
, m_last_request(time_now())
, m_last_incoming_request(min_time())
, m_last_unchoke(min_time())
, m_last_receive(time_now())
, m_last_sent(time_now())
, m_remote_dl_update(time_now())
, m_became_uninterested(time_now())
, m_became_uninteresting(time_now())
, m_free_upload(0)
, m_downloaded_at_last_unchoke(0)
, m_disk_recv_buffer(ses, 0)
, m_socket(s)
, m_remote(endp)
, m_torrent(tor)
, m_num_pieces(0)
, m_timeout(m_ses.settings().peer_timeout)
, m_packet_size(0)
, m_recv_pos(0)
, m_disk_recv_buffer_size(0)
, m_disk_recv_buffer(0)
, m_reading_bytes(0)
, m_last_receive(time_now())
, m_last_sent(time_now())
, m_socket(s)
, m_remote(remote)
, m_torrent(tor)
, m_active(true)
, m_peer_interested(false)
, m_peer_choked(true)
, m_interesting(false)
, m_choked(true)
, m_failed(false)
, m_ignore_bandwidth_limits(false)
, m_have_all(false)
, m_num_pieces(0)
, m_desired_queue_size(2)
, m_free_upload(0)
, m_assume_fifo(false)
, m_num_invalid_requests(0)
, m_disconnecting(false)
, m_became_uninterested(time_now())
, m_became_uninteresting(time_now())
, m_connecting(true)
, m_queued(true)
, m_prefer_whole_pieces(false)
, m_request_large_blocks(false)
, m_priority(1)
, m_upload_limit(bandwidth_limit::inf)
, m_download_limit(bandwidth_limit::inf)
@ -116,13 +103,27 @@ namespace libtorrent
, m_connection_ticket(-1)
, m_remote_bytes_dled(0)
, m_remote_dl_rate(0)
, m_remote_dl_update(time_now())
, m_outstanding_writing_bytes(0)
, m_fast_reconnect(false)
, m_rtt(0)
, m_downloaded_at_last_unchoke(0)
, m_download_rate_peak(0)
, m_upload_rate_peak(0)
, m_rtt(0)
, m_prefer_whole_pieces(0)
, m_desired_queue_size(2)
, m_fast_reconnect(false)
, m_active(true)
, m_peer_interested(false)
, m_peer_choked(true)
, m_interesting(false)
, m_choked(true)
, m_failed(false)
, m_ignore_bandwidth_limits(false)
, m_have_all(false)
, m_assume_fifo(false)
, m_disconnecting(false)
, m_connecting(true)
, m_queued(true)
, m_request_large_blocks(false)
, m_upload_only(false)
#ifndef NDEBUG
, m_in_constructor(true)
#endif
@ -164,6 +165,7 @@ namespace libtorrent
peer_connection::peer_connection(
session_impl& ses
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& endp
, policy::peer* peerinfo)
:
#ifndef NDEBUG
@ -172,39 +174,27 @@ namespace libtorrent
#endif
m_ses(ses)
, m_max_out_request_queue(m_ses.settings().max_out_request_queue)
, m_timeout(m_ses.settings().peer_timeout)
, m_last_piece(time_now())
, m_last_request(time_now())
, m_last_incoming_request(min_time())
, m_last_unchoke(min_time())
, m_last_receive(time_now())
, m_last_sent(time_now())
, m_remote_dl_update(time_now())
, m_became_uninterested(time_now())
, m_became_uninteresting(time_now())
, m_free_upload(0)
, m_downloaded_at_last_unchoke(0)
, m_disk_recv_buffer(ses, 0)
, m_socket(s)
, m_remote(endp)
, m_num_pieces(0)
, m_timeout(m_ses.settings().peer_timeout)
, m_packet_size(0)
, m_recv_pos(0)
, m_disk_recv_buffer_size(0)
, m_disk_recv_buffer(0)
, m_reading_bytes(0)
, m_last_receive(time_now())
, m_last_sent(time_now())
, m_socket(s)
, m_active(false)
, m_peer_interested(false)
, m_peer_choked(true)
, m_interesting(false)
, m_choked(true)
, m_failed(false)
, m_ignore_bandwidth_limits(false)
, m_have_all(false)
, m_num_pieces(0)
, m_desired_queue_size(2)
, m_free_upload(0)
, m_assume_fifo(false)
, m_num_invalid_requests(0)
, m_disconnecting(false)
, m_became_uninterested(time_now())
, m_became_uninteresting(time_now())
, m_connecting(false)
, m_queued(false)
, m_prefer_whole_pieces(false)
, m_request_large_blocks(false)
, m_priority(1)
, m_upload_limit(bandwidth_limit::inf)
, m_download_limit(bandwidth_limit::inf)
@ -213,13 +203,27 @@ namespace libtorrent
, m_connection_ticket(-1)
, m_remote_bytes_dled(0)
, m_remote_dl_rate(0)
, m_remote_dl_update(time_now())
, m_outstanding_writing_bytes(0)
, m_fast_reconnect(false)
, m_rtt(0)
, m_downloaded_at_last_unchoke(0)
, m_download_rate_peak(0)
, m_upload_rate_peak(0)
, m_rtt(0)
, m_prefer_whole_pieces(0)
, m_desired_queue_size(2)
, m_fast_reconnect(false)
, m_active(false)
, m_peer_interested(false)
, m_peer_choked(true)
, m_interesting(false)
, m_choked(true)
, m_failed(false)
, m_ignore_bandwidth_limits(false)
, m_have_all(false)
, m_assume_fifo(false)
, m_disconnecting(false)
, m_connecting(false)
, m_queued(false)
, m_request_large_blocks(false)
, m_upload_only(false)
#ifndef NDEBUG
, m_in_constructor(true)
#endif
@ -243,8 +247,8 @@ namespace libtorrent
#endif
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
asio::error_code ec;
TORRENT_ASSERT(m_socket->remote_endpoint() == remote() || ec);
error_code ec;
TORRENT_ASSERT(m_socket->remote_endpoint(ec) == m_remote || ec);
m_logger = m_ses.create_log(remote().address().to_string(ec) + "_"
+ boost::lexical_cast<std::string>(remote().port()), m_ses.listen_port());
(*m_logger) << "*** INCOMING CONNECTION\n";
@ -286,12 +290,13 @@ namespace libtorrent
void peer_connection::start()
{
TORRENT_ASSERT(m_peer_info == 0 || m_peer_info->connection == this);
boost::shared_ptr<torrent> t = m_torrent.lock();
if (!t)
{
tcp::socket::non_blocking_io ioc(true);
asio::error_code ec;
error_code ec;
m_socket->io_control(ioc, ec);
if (ec)
{
@ -439,7 +444,7 @@ namespace libtorrent
// if this is a web seed. we don't have a peer_info struct
if (m_peer_info) m_peer_info->seed = true;
// if we're a seed too, disconnect
if (t->is_finished())
if (t->is_finished() && m_ses.settings().close_redundant_connections)
{
disconnect("seed to seed connection redundant");
return;
@ -476,12 +481,7 @@ namespace libtorrent
TORRENT_ASSERT(!m_in_constructor);
TORRENT_ASSERT(m_disconnecting);
if (m_disk_recv_buffer)
{
m_ses.free_disk_buffer(m_disk_recv_buffer);
m_disk_recv_buffer = 0;
m_disk_recv_buffer_size = 0;
}
m_disk_recv_buffer_size = 0;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
if (m_logger)
@ -616,6 +616,7 @@ namespace libtorrent
#endif
}
#endif
if (is_disconnecting()) return;
if (peer_info_struct())
{
@ -701,7 +702,7 @@ namespace libtorrent
(*m_logger) << " " << i->second->torrent_file().info_hash() << "\n";
}
#endif
disconnect("got invalid info-hash");
disconnect("got invalid info-hash", 2);
return;
}
@ -785,6 +786,7 @@ namespace libtorrent
if ((*i)->on_choke()) return;
}
#endif
if (is_disconnecting()) return;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " <== CHOKE\n";
@ -838,6 +840,8 @@ namespace libtorrent
}
#endif
if (is_disconnecting()) return;
std::deque<piece_block>::iterator i = std::find_if(
m_download_queue.begin(), m_download_queue.end()
, bind(match_request, boost::cref(r), _1, t->block_size()));
@ -921,6 +925,7 @@ namespace libtorrent
}
#endif
if (is_disconnecting()) return;
if (t->have_piece(index)) return;
if (m_suggested_pieces.size() > 9)
@ -956,6 +961,8 @@ namespace libtorrent
(*m_logger) << time_now_string() << " <== UNCHOKE\n";
#endif
m_peer_choked = false;
if (is_disconnecting()) return;
t->get_policy().unchoked(*this);
}
@ -982,6 +989,7 @@ namespace libtorrent
(*m_logger) << time_now_string() << " <== INTERESTED\n";
#endif
m_peer_interested = true;
if (is_disconnecting()) return;
t->get_policy().interested(*this);
}
@ -1006,11 +1014,12 @@ namespace libtorrent
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " <== NOT_INTERESTED\n";
#endif
m_peer_interested = false;
if (is_disconnecting()) return;
boost::shared_ptr<torrent> t = m_torrent.lock();
TORRENT_ASSERT(t);
m_peer_interested = false;
t->get_policy().not_interested(*this);
}
@ -1033,6 +1042,8 @@ namespace libtorrent
}
#endif
if (is_disconnecting()) return;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string()
<< " <== HAVE [ piece: " << index << "]\n";
@ -1059,7 +1070,7 @@ namespace libtorrent
// if we got an invalid message, abort
if (index >= int(m_have_piece.size()) || index < 0)
{
disconnect("got 'have'-message with higher index than the number of pieces");
disconnect("got 'have'-message with higher index than the number of pieces", 2);
return;
}
@ -1099,11 +1110,11 @@ namespace libtorrent
}
}
if (is_seed())
if (upload_only())
{
TORRENT_ASSERT(m_peer_info);
m_peer_info->seed = true;
if (t->is_finished())
if (is_seed()) m_peer_info->seed = true;
if (t->is_finished() && m_ses.settings().close_redundant_connections)
{
disconnect("seed to seed connection redundant");
return;
@ -1131,6 +1142,8 @@ namespace libtorrent
}
#endif
if (is_disconnecting()) return;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " <== BITFIELD ";
@ -1151,7 +1164,7 @@ namespace libtorrent
msg << "got bitfield with invalid size: " << (bitfield.size() / 8)
<< "bytes. expected: " << (m_have_piece.size() / 8)
<< " bytes";
disconnect(msg.str().c_str());
disconnect(msg.str().c_str(), 2);
return;
}
@ -1178,7 +1191,7 @@ namespace libtorrent
// if this is a web seed. we don't have a peer_info struct
if (m_peer_info) m_peer_info->seed = true;
// if we're a seed too, disconnect
if (t->is_finished())
if (t->is_finished() && m_ses.settings().close_redundant_connections)
{
disconnect("seed to seed connection redundant, disconnecting");
return;
@ -1220,6 +1233,7 @@ namespace libtorrent
m_num_pieces = num_pieces;
if (interesting) t->get_policy().peer_is_interesting(*this);
else if (upload_only()) disconnect("upload to upload connections");
}
// -----------------------------
@ -1240,6 +1254,7 @@ namespace libtorrent
if ((*i)->on_request(r)) return;
}
#endif
if (is_disconnecting()) return;
if (!t->valid_metadata())
{
@ -1426,7 +1441,7 @@ namespace libtorrent
boost::shared_ptr<torrent> t = m_torrent.lock();
TORRENT_ASSERT(t);
TORRENT_ASSERT(m_disk_recv_buffer == 0);
TORRENT_ASSERT(!m_disk_recv_buffer);
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
#ifndef TORRENT_DISABLE_EXTENSIONS
@ -1436,6 +1451,7 @@ namespace libtorrent
if ((*i)->on_piece(p, data)) return;
}
#endif
if (is_disconnecting()) return;
#ifndef NDEBUG
check_postcondition post_checker_(t);
@ -1461,7 +1477,7 @@ namespace libtorrent
"start: " << p.start << " | "
"length: " << p.length << " ]\n";
#endif
disconnect("got invalid piece packet");
disconnect("got invalid piece packet", 2);
return;
}
@ -1648,6 +1664,7 @@ namespace libtorrent
if ((*i)->on_cancel(r)) return;
}
#endif
if (is_disconnecting()) return;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string()
@ -1717,6 +1734,7 @@ namespace libtorrent
if ((*i)->on_have_all()) return;
}
#endif
if (is_disconnecting()) return;
m_have_all = true;
@ -1739,7 +1757,7 @@ namespace libtorrent
#endif
// if we're a seed too, disconnect
if (t->is_finished())
if (t->is_finished() && m_ses.settings().close_redundant_connections)
{
disconnect("seed to seed connection redundant, disconnecting");
return;
@ -1762,13 +1780,13 @@ namespace libtorrent
{
INVARIANT_CHECK;
boost::shared_ptr<torrent> t = m_torrent.lock();
TORRENT_ASSERT(t);
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " <== HAVE_NONE\n";
#endif
boost::shared_ptr<torrent> t = m_torrent.lock();
TORRENT_ASSERT(t);
#ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i)
@ -1776,8 +1794,9 @@ namespace libtorrent
if ((*i)->on_have_none()) return;
}
#endif
if (is_disconnecting()) return;
if (m_peer_info) m_peer_info->seed = false;
TORRENT_ASSERT(!m_have_piece.empty() || !t->ready_for_connections());
}
@ -1803,6 +1822,7 @@ namespace libtorrent
if ((*i)->on_allowed_fast(index)) return;
}
#endif
if (is_disconnecting()) return;
if (index < 0 || index >= int(m_have_piece.size()))
{
@ -2109,6 +2129,7 @@ namespace libtorrent
{
if (handled = (*i)->write_request(r)) break;
}
if (is_disconnecting()) return;
if (!handled)
{
write_request(r);
@ -2141,24 +2162,38 @@ namespace libtorrent
(*m_ses.m_logger) << time_now_string() << " CONNECTION TIMED OUT: " << m_remote.address().to_string()
<< "\n";
#endif
set_failed();
disconnect("timed out");
disconnect("timed out: connect", 1);
}
void peer_connection::disconnect(char const* message)
// the error argument defaults to 0, which means deliberate disconnect
// 1 means unexpected disconnect/error
// 2 protocol error (client sent something invalid)
void peer_connection::disconnect(char const* message, int error)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
(*m_logger) << "*** CONNECTION FAILED " << message << "\n";
switch (error)
{
case 0:
(*m_logger) << "*** CONNECTION CLOSED " << message << "\n";
break;
case 1:
(*m_logger) << "*** CONNECTION FAILED " << message << "\n";
break;
case 2:
(*m_logger) << "*** PEER ERROR " << message << "\n";
break;
}
#endif
// we cannot do this in a constructor
TORRENT_ASSERT(m_in_constructor == false);
if (error > 0) m_failed = true;
if (m_disconnecting) return;
boost::intrusive_ptr<peer_connection> me(this);
INVARIANT_CHECK;
if (m_disconnecting) return;
if (m_connecting && m_connection_ticket >= 0)
{
m_ses.m_half_open.done(m_connection_ticket);
@ -2167,13 +2202,18 @@ namespace libtorrent
boost::shared_ptr<torrent> t = m_torrent.lock();
if (message && m_ses.m_alerts.should_post(alert::debug))
if (message)
{
m_ses.m_alerts.post_alert(
peer_error_alert(
remote()
, pid()
, message));
if (error > 1 && m_ses.m_alerts.should_post(alert::info))
{
m_ses.m_alerts.post_alert(
peer_error_alert(remote(), pid(), message));
}
else if (error <= 1 && m_ses.m_alerts.should_post(alert::debug))
{
m_ses.m_alerts.post_alert(
peer_disconnected_alert(remote(), pid(), message));
}
}
if (t)
@ -2207,7 +2247,7 @@ namespace libtorrent
#endif
m_disconnecting = true;
asio::error_code ec;
error_code ec;
m_socket->close(ec);
m_ses.close_connection(this, message);
}
@ -2372,17 +2412,17 @@ namespace libtorrent
TORRENT_ASSERT(m_packet_size > 0);
TORRENT_ASSERT(m_recv_pos <= m_packet_size - disk_buffer_size);
TORRENT_ASSERT(m_disk_recv_buffer == 0);
TORRENT_ASSERT(!m_disk_recv_buffer);
TORRENT_ASSERT(disk_buffer_size <= 16 * 1024);
if (disk_buffer_size > 16 * 1024)
{
disconnect("invalid piece size");
disconnect("invalid piece size", 2);
return false;
}
m_disk_recv_buffer = m_ses.allocate_disk_buffer();
if (m_disk_recv_buffer == 0)
m_disk_recv_buffer.reset(m_ses.allocate_disk_buffer());
if (!m_disk_recv_buffer)
{
disconnect("out of memory");
return false;
@ -2393,10 +2433,8 @@ namespace libtorrent
char* peer_connection::release_disk_receive_buffer()
{
char* ret = m_disk_recv_buffer;
m_disk_recv_buffer = 0;
m_disk_recv_buffer_size = 0;
return ret;
return m_disk_recv_buffer.release();
}
void peer_connection::cut_receive_buffer(int size, int packet_size)
@ -2420,11 +2458,17 @@ namespace libtorrent
m_packet_size = packet_size;
}
void peer_connection::calc_ip_overhead()
{
m_statistics.calc_ip_overhead();
}
void peer_connection::second_tick(float tick_interval)
{
INVARIANT_CHECK;
ptime now(time_now());
boost::intrusive_ptr<peer_connection> me(self());
boost::shared_ptr<torrent> t = m_torrent.lock();
if (!t || m_disconnecting)
@ -2466,6 +2510,7 @@ namespace libtorrent
}
#endif
}
if (is_disconnecting()) return;
if (!t->valid_metadata()) return;
@ -2829,7 +2874,7 @@ namespace libtorrent
if (int(m_recv_buffer.size()) < regular_buffer_size)
m_recv_buffer.resize(regular_buffer_size);
if (m_disk_recv_buffer == 0 || regular_buffer_size >= m_recv_pos + max_receive)
if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos + max_receive)
{
// only receive into regular buffer
TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size()));
@ -2841,7 +2886,7 @@ namespace libtorrent
// only receive into disk buffer
TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0);
TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size);
m_socket->async_read_some(asio::buffer(m_disk_recv_buffer + m_recv_pos - regular_buffer_size
m_socket->async_read_some(asio::buffer(m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size
, max_receive)
, bind(&peer_connection::on_receive_data, self(), _1, _2));
}
@ -2856,7 +2901,7 @@ namespace libtorrent
boost::array<asio::mutable_buffer, 2> vec;
vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos]
, regular_buffer_size - m_recv_pos);
vec[1] = asio::buffer(m_disk_recv_buffer
vec[1] = asio::buffer(m_disk_recv_buffer.get()
, max_receive - regular_buffer_size + m_recv_pos);
m_socket->async_read_some(vec, bind(&peer_connection::on_receive_data
, self(), _1, _2));
@ -2874,7 +2919,7 @@ namespace libtorrent
std::pair<buffer::interval, buffer::interval> vec;
int regular_buffer_size = m_packet_size - m_disk_recv_buffer_size;
TORRENT_ASSERT(regular_buffer_size >= 0);
if (m_disk_recv_buffer == 0 || regular_buffer_size >= m_recv_pos)
if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos)
{
vec.first = buffer::interval(&m_recv_buffer[0]
+ m_recv_pos - bytes, &m_recv_buffer[0] + m_recv_pos);
@ -2882,8 +2927,8 @@ namespace libtorrent
}
else if (m_recv_pos - bytes >= regular_buffer_size)
{
vec.first = buffer::interval(m_disk_recv_buffer + m_recv_pos
- regular_buffer_size - bytes, m_disk_recv_buffer + m_recv_pos
vec.first = buffer::interval(m_disk_recv_buffer.get() + m_recv_pos
- regular_buffer_size - bytes, m_disk_recv_buffer.get() + m_recv_pos
- regular_buffer_size);
vec.second = buffer::interval(0,0);
}
@ -2893,8 +2938,8 @@ namespace libtorrent
TORRENT_ASSERT(m_recv_pos > regular_buffer_size);
vec.first = buffer::interval(&m_recv_buffer[0] + m_recv_pos - bytes
, &m_recv_buffer[0] + regular_buffer_size);
vec.second = buffer::interval(m_disk_recv_buffer
, m_disk_recv_buffer + m_recv_pos - regular_buffer_size);
vec.second = buffer::interval(m_disk_recv_buffer.get()
, m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size);
}
TORRENT_ASSERT(vec.first.left() + vec.second.left() == bytes);
return vec;
@ -2998,7 +3043,7 @@ namespace libtorrent
// --------------------------
// throws exception when the client should be disconnected
void peer_connection::on_receive_data(const asio::error_code& error
void peer_connection::on_receive_data(const error_code& error
, std::size_t bytes_transferred)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
@ -3014,7 +3059,6 @@ namespace libtorrent
(*m_logger) << time_now_string() << " **ERROR**: "
<< error.message() << "[in peer_connection::on_receive_data]\n";
#endif
set_failed();
on_receive(error, bytes_transferred);
disconnect(error.message().c_str());
return;
@ -3063,8 +3107,8 @@ namespace libtorrent
if (int(m_recv_buffer.size()) < regular_buffer_size)
m_recv_buffer.resize(regular_buffer_size);
asio::error_code ec;
if (m_disk_recv_buffer == 0 || regular_buffer_size >= m_recv_pos + max_receive)
error_code ec;
if (!m_disk_recv_buffer || regular_buffer_size >= m_recv_pos + max_receive)
{
// only receive into regular buffer
TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size()));
@ -3076,7 +3120,7 @@ namespace libtorrent
// only receive into disk buffer
TORRENT_ASSERT(m_recv_pos - regular_buffer_size >= 0);
TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size);
bytes_transferred = m_socket->read_some(asio::buffer(m_disk_recv_buffer
bytes_transferred = m_socket->read_some(asio::buffer(m_disk_recv_buffer.get()
+ m_recv_pos - regular_buffer_size, (std::min)(m_packet_size
- m_recv_pos, max_receive)), ec);
}
@ -3091,7 +3135,7 @@ namespace libtorrent
boost::array<asio::mutable_buffer, 2> vec;
vec[0] = asio::buffer(&m_recv_buffer[m_recv_pos]
, regular_buffer_size - m_recv_pos);
vec[1] = asio::buffer(m_disk_recv_buffer
vec[1] = asio::buffer(m_disk_recv_buffer.get()
, (std::min)(m_disk_recv_buffer_size
, max_receive - regular_buffer_size + m_recv_pos));
bytes_transferred = m_socket->read_some(vec, ec);
@ -3107,27 +3151,6 @@ namespace libtorrent
setup_receive();
}
/*
catch (file_error& e)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
boost::shared_ptr<torrent> t = m_torrent.lock();
if (!t)
{
disconnect(e.what());
return;
}
if (t->alerts().should_post(alert::fatal))
{
t->alerts().post_alert(
file_error_alert(t->get_handle()
, std::string("torrent paused: ") + e.what()));
}
t->pause();
}
*/
bool peer_connection::can_write() const
{
@ -3158,7 +3181,7 @@ namespace libtorrent
{
INVARIANT_CHECK;
asio::error_code ec;
error_code ec;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
(*m_ses.m_logger) << time_now_string() << " CONNECTING: " << m_remote.address().to_string(ec)
<< ":" << m_remote.port() << "\n";
@ -3209,7 +3232,7 @@ namespace libtorrent
}
}
void peer_connection::on_connection_complete(asio::error_code const& e)
void peer_connection::on_connection_complete(error_code const& e)
{
ptime completed = time_now();
@ -3230,8 +3253,7 @@ namespace libtorrent
(*m_ses.m_logger) << time_now_string() << " CONNECTION FAILED: " << m_remote.address().to_string()
<< ": " << e.message() << "\n";
#endif
set_failed();
disconnect(e.message().c_str());
disconnect(e.message().c_str(), 1);
return;
}
@ -3247,7 +3269,7 @@ namespace libtorrent
if (m_remote.address().is_v4())
{
asio::error_code ec;
error_code ec;
m_socket->set_option(type_of_service(m_ses.settings().peer_tos), ec);
}
@ -3261,7 +3283,7 @@ namespace libtorrent
// --------------------------
// throws exception when the client should be disconnected
void peer_connection::on_send_data(asio::error_code const& error
void peer_connection::on_send_data(error_code const& error
, std::size_t bytes_transferred)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
@ -3286,7 +3308,6 @@ namespace libtorrent
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
(*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n";
#endif
set_failed();
disconnect(error.message().c_str());
return;
}
@ -3306,7 +3327,7 @@ namespace libtorrent
#ifndef NDEBUG
void peer_connection::check_invariant() const
{
TORRENT_ASSERT((m_disk_recv_buffer != 0) == (m_disk_recv_buffer_size > 0));
TORRENT_ASSERT(bool(m_disk_recv_buffer) == (m_disk_recv_buffer_size > 0));
boost::shared_ptr<torrent> t = m_torrent.lock();
if (m_disconnecting)

View File

@ -133,22 +133,8 @@ namespace libtorrent
{
int index = static_cast<int>(i - pieces.begin());
piece_pos& p = m_piece_map[index];
if (*i)
{
if (m_sequential_download == index) ++m_sequential_download;
++m_num_have;
p.set_have();
if (p.filtered())
{
++m_num_have_filtered;
TORRENT_ASSERT(m_num_filtered > 0);
--m_num_filtered;
}
}
else
{
p.index = 0;
}
if (*i) we_have(index);
else TORRENT_ASSERT(p.index == 0);
}
}

View File

@ -225,7 +225,7 @@ namespace libtorrent
// blocks be from whole pieces, possibly by returning more blocks
// than we requested.
#ifndef NDEBUG
asio::error_code ec;
error_code ec;
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
#endif
@ -348,6 +348,7 @@ namespace libtorrent
, m_torrent(t)
, m_available_free_upload(0)
, m_num_connect_candidates(0)
, m_num_seeds(0)
{ TORRENT_ASSERT(t); }
// disconnects and removes all peers that are now filtered
@ -420,49 +421,6 @@ namespace libtorrent
return true;
}
policy::iterator policy::find_disconnect_candidate()
{
INVARIANT_CHECK;
iterator disconnect_peer = m_peers.end();
double slowest_transfer_rate = (std::numeric_limits<double>::max)();
ptime now = time_now();
for (iterator i = m_peers.begin();
i != m_peers.end(); ++i)
{
peer_connection* c = i->second.connection;
if (c == 0) continue;
if (c->is_disconnecting()) continue;
// never disconnect an interesting peer if we have a candidate that
// isn't interesting
if (disconnect_peer != m_peers.end()
&& c->is_interesting()
&& !disconnect_peer->second.connection->is_interesting())
continue;
double transferred_amount
= (double)c->statistics().total_payload_download();
time_duration connected_time = now - i->second.connected;
double connected_time_in_seconds = total_seconds(connected_time);
double transfer_rate
= transferred_amount / (connected_time_in_seconds + 1);
// prefer to disconnect uninteresting peers, and secondly slow peers
if (transfer_rate <= slowest_transfer_rate)
{
slowest_transfer_rate = transfer_rate;
disconnect_peer = i;
}
}
return disconnect_peer;
}
policy::iterator policy::find_connect_candidate()
{
// too expensive
@ -625,7 +583,7 @@ namespace libtorrent
// TODO: only allow _one_ connection to use this
// override at a time
asio::error_code ec;
error_code ec;
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
aux::session_impl& ses = m_torrent->session();
@ -697,7 +655,7 @@ namespace libtorrent
{
// we don't have any info about this peer.
// add a new entry
asio::error_code ec;
error_code ec;
TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec);
peer p(c.remote(), peer::not_connectable, 0);
@ -1073,19 +1031,6 @@ namespace libtorrent
return true;
}
bool policy::disconnect_one_peer()
{
iterator p = find_disconnect_candidate();
if (p == m_peers.end())
return false;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
(*p->second.connection->m_logger) << "*** CLOSING CONNECTION 'too many connections'\n";
#endif
p->second.connection->disconnect("too many connections, closing");
return true;
}
// this is called whenever a peer connection is closed
void policy::connection_closed(const peer_connection& c)
{
@ -1156,7 +1101,7 @@ namespace libtorrent
// INVARIANT_CHECK;
TORRENT_ASSERT(c);
asio::error_code ec;
error_code ec;
TORRENT_ASSERT(c->remote() == c->get_socket()->remote_endpoint(ec) || ec);
return std::find_if(

View File

@ -253,7 +253,6 @@ namespace libtorrent
, bool paused
, storage_constructor_type sc)
{
TORRENT_ASSERT(!ti.m_half_metadata);
boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti));
add_torrent_params p(sc);
p.ti = tip;
@ -273,7 +272,6 @@ namespace libtorrent
, storage_constructor_type sc
, void* userdata)
{
TORRENT_ASSERT(!ti->m_half_metadata);
add_torrent_params p(sc);
p.ti = ti;
p.save_path = save_path;

View File

@ -76,6 +76,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/enum_net.hpp"
#include "libtorrent/config.hpp"
#ifndef TORRENT_WINDOWS
#include <sys/resource.h>
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
#include <openssl/crypto.h>
@ -162,6 +166,7 @@ namespace aux {
, m_auto_manage_time_scaler(0)
, m_optimistic_unchoke_time_scaler(0)
, m_disconnect_time_scaler(90)
, m_auto_scrape_time_scaler(180)
, m_incoming_connection(false)
, m_last_tick(time_now())
, m_torrent_sequence(0)
@ -207,6 +212,11 @@ namespace aux {
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
m_logger = create_log("main_session", listen_port(), false);
(*m_logger) << time_now_string() << "\n";
(*m_logger) << "sizeof(torrent): " << sizeof(torrent) << "\n";
(*m_logger) << "sizeof(peer_connection): " << sizeof(peer_connection) << "\n";
(*m_logger) << "sizeof(bt_peer_connection): " << sizeof(bt_peer_connection) << "\n";
(*m_logger) << "sizeof(policy::peer): " << sizeof(policy::peer) << "\n";
#endif
#ifdef TORRENT_STATS
@ -250,7 +260,7 @@ namespace aux {
*i = printable[rand() % (sizeof(printable)-1)];
}
asio::error_code ec;
error_code ec;
m_timer.expires_from_now(seconds(1), ec);
m_timer.async_wait(
bind(&session_impl::second_tick, this, _1));
@ -396,7 +406,7 @@ namespace aux {
if (m_dht) m_dht->stop();
m_dht_socket.close();
#endif
asio::error_code ec;
error_code ec;
m_timer.cancel(ec);
// close the listen sockets
@ -535,7 +545,7 @@ namespace aux {
session_impl::listen_socket_t session_impl::setup_listener(tcp::endpoint ep
, int retries, bool v6_only)
{
asio::error_code ec;
error_code ec;
listen_socket_t s;
s.sock.reset(new socket_acceptor(m_io_service));
s.sock->open(ep.protocol(), ec);
@ -544,7 +554,7 @@ namespace aux {
s.sock->bind(ep, ec);
while (ec && retries > 0)
{
ec = asio::error_code();
ec = error_code();
TORRENT_ASSERT(!ec);
--retries;
ep.port(ep.port() + 1);
@ -555,7 +565,7 @@ namespace aux {
// instead of giving up, try
// let the OS pick a port
ep.port(0);
ec = asio::error_code();
ec = error_code();
s.sock->bind(ep, ec);
}
if (ec)
@ -661,7 +671,7 @@ namespace aux {
for (std::list<listen_socket_t>::const_iterator i = m_listen_sockets.begin()
, end(m_listen_sockets.end()); i != end; ++i)
{
asio::error_code ec;
error_code ec;
tcp::endpoint ep = i->sock->local_endpoint(ec);
if (ec || ep.address().is_v4()) continue;
@ -691,7 +701,7 @@ namespace aux {
if (!m_listen_sockets.empty())
{
asio::error_code ec;
error_code ec;
tcp::endpoint local = m_listen_sockets.front().sock->local_endpoint(ec);
if (!ec)
{
@ -713,11 +723,16 @@ namespace aux {
#ifndef TORRENT_DISABLE_DHT
void session_impl::on_receive_udp(asio::error_code const& e
void session_impl::on_receive_udp(error_code const& e
, udp::endpoint const& ep, char const* buf, int len)
{
if (e)
{
if (e == asio::error::connection_refused
|| e == asio::error::connection_reset
|| e == asio::error::connection_aborted)
m_dht->on_unreachable(ep);
if (m_alerts.should_post(alert::info))
{
std::string msg = "UDP socket error from '"
@ -746,7 +761,7 @@ namespace aux {
}
void session_impl::on_incoming_connection(shared_ptr<socket_type> const& s
, weak_ptr<socket_acceptor> listen_socket, asio::error_code const& e)
, weak_ptr<socket_acceptor> listen_socket, error_code const& e)
{
boost::shared_ptr<socket_acceptor> listener = listen_socket.lock();
if (!listener) return;
@ -756,7 +771,7 @@ namespace aux {
mutex_t::scoped_lock l(m_mutex);
if (m_abort) return;
asio::error_code ec;
error_code ec;
if (e)
{
tcp::endpoint ep = listener->local_endpoint(ec);
@ -842,7 +857,13 @@ namespace aux {
// check if we have any active torrents
// if we don't reject the connection
if (m_torrents.empty()) return;
if (m_torrents.empty())
{
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << " There are no torrents, disconnect\n";
#endif
return;
}
bool has_active_torrent = false;
for (torrent_map::iterator i = m_torrents.begin()
@ -854,10 +875,16 @@ namespace aux {
break;
}
}
if (!has_active_torrent) return;
if (!has_active_torrent)
{
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << " There are no _active_ torrents, disconnect\n";
#endif
return;
}
boost::intrusive_ptr<peer_connection> c(
new bt_peer_connection(*this, s, 0));
new bt_peer_connection(*this, s, endp, 0));
#ifndef NDEBUG
c->m_in_constructor = false;
#endif
@ -926,7 +953,7 @@ namespace aux {
return port;
}
void session_impl::second_tick(asio::error_code const& e)
void session_impl::second_tick(error_code const& e)
{
session_impl::mutex_t::scoped_lock l(m_mutex);
@ -947,7 +974,7 @@ namespace aux {
float tick_interval = total_microseconds(time_now() - m_last_tick) / 1000000.f;
m_last_tick = time_now();
asio::error_code ec;
error_code ec;
m_timer.expires_from_now(seconds(1), ec);
m_timer.async_wait(
bind(&session_impl::second_tick, this, _1));
@ -986,7 +1013,6 @@ namespace aux {
<< m_disk_thread.disk_allocations() << "\t"
<< std::endl;
#endif
// --------------------------------------------------------------
// second_tick every torrent
// --------------------------------------------------------------
@ -1002,6 +1028,9 @@ namespace aux {
// count the number of peers of downloading torrents
int num_downloads_peers = 0;
torrent_map::iterator least_recently_scraped = m_torrents.begin();
int num_paused_auto_managed = 0;
// check each torrent for tracker updates
// TODO: do this in a timer-event in each torrent instead
for (torrent_map::iterator i = m_torrents.begin();
@ -1014,6 +1043,17 @@ namespace aux {
else
++uncongested_torrents;
if (t.is_auto_managed() && t.is_paused())
{
++num_paused_auto_managed;
if (!least_recently_scraped->second->is_auto_managed()
|| !least_recently_scraped->second->is_paused()
|| least_recently_scraped->second->last_scrape() > t.last_scrape())
{
least_recently_scraped = i;
}
}
if (t.is_finished())
{
++num_seeds;
@ -1046,8 +1086,28 @@ namespace aux {
++i;
}
// drain the IP overhead from the bandwidth limiters
m_download_channel.drain(m_stat.download_ip_overhead());
m_upload_channel.drain(m_stat.upload_ip_overhead());
m_stat.second_tick(tick_interval);
// --------------------------------------------------------------
// scrape paused torrents that are auto managed
// --------------------------------------------------------------
--m_auto_scrape_time_scaler;
if (m_auto_scrape_time_scaler <= 0)
{
m_auto_scrape_time_scaler = m_settings.auto_scrape_interval
/ (std::max)(1, num_paused_auto_managed);
if (m_auto_scrape_time_scaler < m_settings.auto_scrape_min_interval)
m_auto_scrape_time_scaler = m_settings.auto_scrape_min_interval;
if (least_recently_scraped != m_torrents.end())
{
least_recently_scraped->second->scrape_tracker();
}
}
// --------------------------------------------------------------
// connect new peers
@ -1156,20 +1216,10 @@ namespace aux {
peer_connection& c = *j->get();
if (c.has_timed_out())
{
if (m_alerts.should_post(alert::debug))
{
m_alerts.post_alert(
peer_error_alert(
c.remote()
, c.pid()
, "connection timed out"));
}
#if defined(TORRENT_VERBOSE_LOGGING)
(*c.m_logger) << "*** CONNECTION TIMED OUT\n";
#endif
c.set_failed();
c.disconnect("timed out");
c.disconnect("timed out: inactive", 1);
continue;
}
@ -1205,17 +1255,37 @@ namespace aux {
{
m_disconnect_time_scaler = 90;
// every 90 seconds, disconnect the worst peer
// every 90 seconds, disconnect the worst peers
// if we have reached the connection limit
if (num_connections() >= max_connections() && !m_torrents.empty())
if (num_connections() >= max_connections() * m_settings.peer_turnover_cutoff
&& !m_torrents.empty())
{
torrent_map::iterator i = std::max_element(m_torrents.begin(), m_torrents.end()
, bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _1))
< bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _2)));
TORRENT_ASSERT(i != m_torrents.end());
// TODO: make the number of peers a percentage of the number of connected peers
i->second->get_policy().disconnect_one_peer();
int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers()
* m_settings.peer_turnover), 1)
, i->second->get_policy().num_connect_candidates());
i->second->disconnect_peers(peers_to_disconnect);
}
else
{
// if we haven't reached the global max. see if any torrent
// has reached its local limit
for (torrent_map::iterator i = m_torrents.begin()
, end(m_torrents.end()); i != end; ++i)
{
boost::shared_ptr<torrent> t = i->second;
if (t->num_peers() < t->max_connections() * m_settings.peer_turnover_cutoff)
continue;
int peers_to_disconnect = (std::min)((std::max)(int(i->second->num_peers()
* m_settings.peer_turnover), 1)
, i->second->get_policy().num_connect_candidates());
t->disconnect_peers(peers_to_disconnect);
}
}
}
}
@ -1276,8 +1346,8 @@ namespace aux {
, bind(&torrent::sequence_number, _1) < bind(&torrent::sequence_number, _2));
std::sort(seeds.begin(), seeds.end()
, bind(&torrent::seed_cycles_int, _1, boost::ref(m_settings))
< bind(&torrent::seed_cycles_int, _2, boost::ref(m_settings)));
, bind(&torrent::seed_rank, _1, boost::ref(m_settings))
> bind(&torrent::seed_rank, _2, boost::ref(m_settings)));
}
for (std::vector<torrent*>::iterator i = downloaders.begin()
@ -2111,7 +2181,19 @@ namespace aux {
INVARIANT_CHECK;
if (limit <= 0) limit = (std::numeric_limits<int>::max)();
if (limit <= 0)
{
limit = (std::numeric_limits<int>::max)();
#ifndef TORRENT_WINDOWS
rlimit l;
if (getrlimit(RLIMIT_NOFILE, &l) == 0
&& l.rlim_cur != RLIM_INFINITY)
{
limit = l.rlim_cur - m_settings.file_pool_size;
if (limit < 5) limit = 5;
}
#endif
}
m_max_connections = limit;
}

View File

@ -37,13 +37,13 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
void socks4_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i
void socks4_stream::name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -54,7 +54,7 @@ namespace libtorrent
if (i == tcp::resolver::iterator())
{
asio::error_code ec = asio::error::operation_not_supported;
error_code ec = asio::error::operation_not_supported;
(*h)(ec);
close(ec);
return;
@ -64,12 +64,12 @@ namespace libtorrent
&socks4_stream::connected, this, _1, h));
}
void socks4_stream::connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void socks4_stream::connected(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -86,31 +86,31 @@ namespace libtorrent
p += m_user.size();
write_uint8(0, p); // NULL terminator
asio::async_write(m_sock, asio::buffer(m_buffer)
async_write(m_sock, asio::buffer(m_buffer)
, boost::bind(&socks4_stream::handshake1, this, _1, h));
}
void socks4_stream::handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void socks4_stream::handshake1(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
m_buffer.resize(8);
asio::async_read(m_sock, asio::buffer(m_buffer)
async_read(m_sock, asio::buffer(m_buffer)
, boost::bind(&socks4_stream::handshake2, this, _1, h));
}
void socks4_stream::handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void socks4_stream::handshake2(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -123,7 +123,7 @@ namespace libtorrent
if (reply_version != 0)
{
asio::error_code ec = asio::error::operation_not_supported;
error_code ec = asio::error::operation_not_supported;
(*h)(ec);
close(ec);
return;
@ -137,7 +137,7 @@ namespace libtorrent
return;
}
asio::error_code ec = asio::error::fault;
error_code ec = asio::error::fault;
switch (status_code)
{
case 91: ec = asio::error::connection_refused; break;

View File

@ -38,13 +38,13 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
void socks5_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i
void socks5_stream::name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h)
{
if (e || i == tcp::resolver::iterator())
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -53,12 +53,12 @@ namespace libtorrent
&socks5_stream::connected, this, _1, h));
}
void socks5_stream::connected(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void socks5_stream::connected(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -79,31 +79,31 @@ namespace libtorrent
write_uint8(0, p); // no authentication
write_uint8(2, p); // username/password
}
asio::async_write(m_sock, asio::buffer(m_buffer)
async_write(m_sock, asio::buffer(m_buffer)
, boost::bind(&socks5_stream::handshake1, this, _1, h));
}
void socks5_stream::handshake1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void socks5_stream::handshake1(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
m_buffer.resize(2);
asio::async_read(m_sock, asio::buffer(m_buffer)
async_read(m_sock, asio::buffer(m_buffer)
, boost::bind(&socks5_stream::handshake2, this, _1, h));
}
void socks5_stream::handshake2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void socks5_stream::handshake2(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -117,7 +117,7 @@ namespace libtorrent
if (version < 5)
{
(*h)(asio::error::operation_not_supported);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -131,7 +131,7 @@ namespace libtorrent
if (m_user.empty())
{
(*h)(asio::error::operation_not_supported);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -144,41 +144,41 @@ namespace libtorrent
write_string(m_user, p);
write_uint8(m_password.size(), p);
write_string(m_password, p);
asio::async_write(m_sock, asio::buffer(m_buffer)
async_write(m_sock, asio::buffer(m_buffer)
, boost::bind(&socks5_stream::handshake3, this, _1, h));
}
else
{
(*h)(asio::error::operation_not_supported);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
}
void socks5_stream::handshake3(asio::error_code const& e
void socks5_stream::handshake3(error_code const& e
, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
m_buffer.resize(2);
asio::async_read(m_sock, asio::buffer(m_buffer)
async_read(m_sock, asio::buffer(m_buffer)
, boost::bind(&socks5_stream::handshake4, this, _1, h));
}
void socks5_stream::handshake4(asio::error_code const& e
void socks5_stream::handshake4(error_code const& e
, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -192,7 +192,7 @@ namespace libtorrent
if (version != 1)
{
(*h)(asio::error::operation_not_supported);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -200,7 +200,7 @@ namespace libtorrent
if (status != 0)
{
(*h)(asio::error::operation_not_supported);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -223,31 +223,31 @@ namespace libtorrent
write_endpoint(m_remote_endpoint, p);
TORRENT_ASSERT(p - &m_buffer[0] == int(m_buffer.size()));
asio::async_write(m_sock, asio::buffer(m_buffer)
async_write(m_sock, asio::buffer(m_buffer)
, boost::bind(&socks5_stream::connect1, this, _1, h));
}
void socks5_stream::connect1(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void socks5_stream::connect1(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
m_buffer.resize(6 + 4); // assume an IPv4 address
asio::async_read(m_sock, asio::buffer(m_buffer)
async_read(m_sock, asio::buffer(m_buffer)
, boost::bind(&socks5_stream::connect2, this, _1, h));
}
void socks5_stream::connect2(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void socks5_stream::connect2(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -260,14 +260,14 @@ namespace libtorrent
if (version < 5)
{
(*h)(asio::error::operation_not_supported);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
int response = read_uint8(p);
if (response != 0)
{
asio::error_code e = asio::error::fault;
error_code e = asio::error::fault;
switch (response)
{
case 1: e = asio::error::fault; break;
@ -280,7 +280,7 @@ namespace libtorrent
case 8: e = asio::error::address_family_not_supported; break;
}
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
@ -305,22 +305,22 @@ namespace libtorrent
else
{
(*h)(asio::error::operation_not_supported);
asio::error_code ec;
error_code ec;
close(ec);
return;
}
m_buffer.resize(skip_bytes);
asio::async_read(m_sock, asio::buffer(m_buffer)
async_read(m_sock, asio::buffer(m_buffer)
, boost::bind(&socks5_stream::connect3, this, _1, h));
}
void socks5_stream::connect3(asio::error_code const& e, boost::shared_ptr<handler_type> h)
void socks5_stream::connect3(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
asio::error_code ec;
error_code ec;
close(ec);
return;
}

View File

@ -47,47 +47,23 @@ POSSIBILITY OF SUCH DAMAGE.
#define for if (false) {} else for
#endif
using namespace libtorrent;
namespace libtorrent
{
void libtorrent::stat::second_tick(float tick_interval)
void stat_channel::second_tick(float tick_interval)
{
INVARIANT_CHECK;
m_rate_sum -= m_rate_history[history-1];
for (int i = history - 2; i >= 0; --i)
{
m_download_rate_history[i + 1] = m_download_rate_history[i];
m_upload_rate_history[i + 1] = m_upload_rate_history[i];
m_download_payload_rate_history[i + 1] = m_download_payload_rate_history[i];
m_upload_payload_rate_history[i + 1] = m_upload_payload_rate_history[i];
}
m_rate_history[i + 1] = m_rate_history[i];
m_download_rate_history[0] = (m_downloaded_payload + m_downloaded_protocol)
/ tick_interval;
m_upload_rate_history[0] = (m_uploaded_payload + m_uploaded_protocol)
/ tick_interval;
m_download_payload_rate_history[0] = m_downloaded_payload / tick_interval;
m_upload_payload_rate_history[0] = m_uploaded_payload / tick_interval;
m_downloaded_payload = 0;
m_uploaded_payload = 0;
m_downloaded_protocol = 0;
m_uploaded_protocol = 0;
m_mean_download_rate = 0;
m_mean_upload_rate = 0;
m_mean_download_payload_rate = 0;
m_mean_upload_payload_rate = 0;
for (int i = 0; i < history; ++i)
{
m_mean_download_rate += m_download_rate_history[i];
m_mean_upload_rate += m_upload_rate_history[i];
m_mean_download_payload_rate += m_download_payload_rate_history[i];
m_mean_upload_payload_rate += m_upload_payload_rate_history[i];
}
m_mean_download_rate /= history;
m_mean_upload_rate /= history;
m_mean_download_payload_rate /= history;
m_mean_upload_payload_rate /= history;
m_rate_history[0] = m_counter / tick_interval;
m_rate_sum += m_rate_history[0];
m_counter = 0;
}
}

View File

@ -527,12 +527,23 @@ namespace libtorrent
std::pair<iter_t, bool> ret = directories.insert((m_save_path / bp).string());
bp = bp.branch_path();
}
#if defined(_WIN32) && defined(UNICODE)
try
{ fs::remove(safe_convert(p)); }
catch (std::exception& e)
{
error = e.what();
error_file = p;
result = 1;
}
#else
if (std::remove(p.c_str()) != 0 && errno != ENOENT)
{
error = std::strerror(errno);
error_file = p;
result = errno;
}
#endif
}
// remove the directories. Reverse order to delete
@ -541,12 +552,23 @@ namespace libtorrent
for (std::set<std::string>::reverse_iterator i = directories.rbegin()
, end(directories.rend()); i != end; ++i)
{
#if defined(_WIN32) && defined(UNICODE)
try
{ fs::remove(safe_convert(*i)); }
catch (std::exception& e)
{
error = e.what();
error_file = *i;
result = 1;
}
#else
if (std::remove(i->c_str()) != 0 && errno != ENOENT)
{
error = std::strerror(errno);
error_file = *i;
result = errno;
}
#endif
}
if (!error.empty())
@ -1230,7 +1252,7 @@ namespace libtorrent
{
TORRENT_ASSERT(r.length <= 16 * 1024);
// the buffer needs to be allocated through the io_thread
TORRENT_ASSERT(m_io_thread.is_disk_buffer(buffer.buffer()));
TORRENT_ASSERT(m_io_thread.is_disk_buffer(buffer.get()));
disk_io_job j;
j.storage = this;
@ -1238,7 +1260,7 @@ namespace libtorrent
j.piece = r.piece;
j.offset = r.start;
j.buffer_size = r.length;
j.buffer = buffer.buffer();
j.buffer = buffer.get();
m_io_thread.add_job(j, handler);
buffer.release();
}
@ -2465,7 +2487,8 @@ namespace libtorrent
&& m_free_slots.empty()
&& m_state == state_finished)
{
TORRENT_ASSERT(m_storage_mode != storage_mode_compact);
TORRENT_ASSERT(m_storage_mode != storage_mode_compact
|| m_info->num_pieces() == 0);
}
if (m_storage_mode != storage_mode_compact)

View File

@ -59,6 +59,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/session.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/parse_url.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/entry.hpp"
@ -95,20 +96,6 @@ namespace
, tracker_failed_max = 5
};
int calculate_block_size(const torrent_info& i, int default_block_size)
{
if (default_block_size < 1024) default_block_size = 1024;
// if pieces are too small, adjust the block size
if (i.piece_length() < default_block_size)
{
return i.piece_length();
}
// otherwise, go with the default
return default_block_size;
}
struct find_peer_by_ip
{
find_peer_by_ip(tcp::endpoint const& a, const torrent* t)
@ -160,23 +147,18 @@ namespace libtorrent
, entry const* resume_data
, int seq
, bool auto_managed)
: m_torrent_file(tf)
, m_abort(false)
, m_paused(paused)
, m_just_paused(false)
, m_auto_managed(auto_managed)
: m_policy(this)
, m_active_time(seconds(0))
, m_seeding_time(seconds(0))
, m_total_uploaded(0)
, m_total_downloaded(0)
, m_started(time_now())
, m_last_scrape(min_time())
, m_torrent_file(tf)
, m_event(tracker_request::started)
, m_block_size(0)
, m_storage(0)
, m_next_request(time_now())
, m_duration(1800)
, m_complete(-1)
, m_incomplete(-1)
, m_host_resolver(ses.m_io_service)
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
, m_resolving_country(false)
, m_resolve_countries(false)
#endif
, m_announce_timer(ses.m_io_service)
#ifndef TORRENT_DISABLE_DHT
, m_last_dht_announce(time_now() - minutes(15))
@ -184,35 +166,41 @@ namespace libtorrent
, m_ses(ses)
, m_picker(0)
, m_trackers(m_torrent_file->trackers())
, m_last_working_tracker(-1)
, m_currently_trying_tracker(0)
, m_failed_trackers(0)
, m_time_scaler(0)
, m_num_pieces(0)
, m_sequential_download(false)
, m_got_tracker_response(false)
, m_ratio(0.f)
, m_total_failed_bytes(0)
, m_total_redundant_bytes(0)
, m_net_interface(net_interface.address(), 0)
, m_save_path(complete(save_path))
, m_storage_mode(storage_mode)
, m_state(torrent_status::queued_for_checking)
, m_progress(0.f)
, m_default_block_size(block_size)
, m_connections_initialized(true)
, m_settings(ses.settings())
, m_storage_constructor(sc)
, m_progress(0.f)
, m_num_pieces(0)
, m_ratio(0.f)
, m_max_uploads((std::numeric_limits<int>::max)())
, m_num_uploads(0)
, m_max_connections((std::numeric_limits<int>::max)())
, m_block_size(block_size)
, m_complete(-1)
, m_incomplete(-1)
, m_deficit_counter(0)
, m_policy(this)
, m_duration(1800)
, m_sequence_number(seq)
, m_active_time(seconds(0))
, m_seeding_time(seconds(0))
, m_total_uploaded(0)
, m_total_downloaded(0)
, m_last_working_tracker(-1)
, m_currently_trying_tracker(0)
, m_failed_trackers(0)
, m_time_scaler(0)
, m_abort(false)
, m_paused(paused)
, m_just_paused(false)
, m_auto_managed(auto_managed)
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
, m_resolving_country(false)
, m_resolve_countries(false)
#endif
, m_sequential_download(false)
, m_got_tracker_response(false)
, m_connections_initialized(true)
{
if (resume_data) m_resume_data = *resume_data;
#ifndef NDEBUG
@ -234,58 +222,59 @@ namespace libtorrent
, entry const* resume_data
, int seq
, bool auto_managed)
: m_torrent_file(new torrent_info(info_hash))
, m_abort(false)
, m_paused(paused)
, m_just_paused(false)
, m_auto_managed(auto_managed)
: m_policy(this)
, m_active_time(seconds(0))
, m_seeding_time(seconds(0))
, m_total_uploaded(0)
, m_total_downloaded(0)
, m_started(time_now())
, m_last_scrape(min_time())
, m_torrent_file(new torrent_info(info_hash))
, m_event(tracker_request::started)
, m_block_size(0)
, m_storage(0)
, m_next_request(time_now())
, m_duration(1800)
, m_complete(-1)
, m_incomplete(-1)
, m_host_resolver(ses.m_io_service)
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
, m_resolving_country(false)
, m_resolve_countries(false)
#endif
, m_announce_timer(ses.m_io_service)
#ifndef TORRENT_DISABLE_DHT
, m_last_dht_announce(time_now() - minutes(15))
#endif
, m_ses(ses)
, m_picker(0)
, m_last_working_tracker(-1)
, m_currently_trying_tracker(0)
, m_failed_trackers(0)
, m_time_scaler(0)
, m_num_pieces(0)
, m_sequential_download(false)
, m_got_tracker_response(false)
, m_ratio(0.f)
, m_total_failed_bytes(0)
, m_total_redundant_bytes(0)
, m_net_interface(net_interface.address(), 0)
, m_save_path(complete(save_path))
, m_storage_mode(storage_mode)
, m_state(torrent_status::queued_for_checking)
, m_progress(0.f)
, m_default_block_size(block_size)
, m_connections_initialized(false)
, m_settings(ses.settings())
, m_storage_constructor(sc)
, m_progress(0.f)
, m_num_pieces(0)
, m_ratio(0.f)
, m_max_uploads((std::numeric_limits<int>::max)())
, m_num_uploads(0)
, m_max_connections((std::numeric_limits<int>::max)())
, m_block_size(block_size)
, m_complete(-1)
, m_incomplete(-1)
, m_deficit_counter(0)
, m_policy(this)
, m_duration(1800)
, m_sequence_number(seq)
, m_active_time(seconds(0))
, m_seeding_time(seconds(0))
, m_total_uploaded(0)
, m_total_downloaded(0)
, m_last_working_tracker(-1)
, m_currently_trying_tracker(0)
, m_failed_trackers(0)
, m_time_scaler(0)
, m_abort(false)
, m_paused(paused)
, m_just_paused(false)
, m_auto_managed(auto_managed)
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
, m_resolving_country(false)
, m_resolve_countries(false)
#endif
, m_sequential_download(false)
, m_got_tracker_response(false)
, m_connections_initialized(false)
{
if (resume_data) m_resume_data = *resume_data;
#ifndef NDEBUG
@ -307,7 +296,7 @@ namespace libtorrent
boost::weak_ptr<torrent> self(shared_from_this());
if (m_torrent_file->is_valid()) init();
if (m_abort) return;
asio::error_code ec;
error_code ec;
m_announce_timer.expires_from_now(seconds(1), ec);
m_announce_timer.async_wait(
bind(&torrent::on_announce_disp, self, _1));
@ -425,7 +414,6 @@ namespace libtorrent
, m_save_path, m_ses.m_files, m_ses.m_disk_thread, m_storage_constructor
, m_storage_mode);
m_storage = m_owning_storage.get();
m_block_size = calculate_block_size(*m_torrent_file, m_default_block_size);
m_picker.reset(new piece_picker(
m_torrent_file->piece_length() / m_block_size
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size)));
@ -603,6 +591,13 @@ namespace libtorrent
}
}
}
int index = 0;
for (std::vector<bool>::iterator i = m_have_pieces.begin()
, end(m_have_pieces.end()); i != end; ++i, ++index)
{
if (*i) m_picker->we_have(index);
}
}
files_checked();
@ -654,6 +649,8 @@ namespace libtorrent
{
m_have_pieces[j.offset] = true;
++m_num_pieces;
TORRENT_ASSERT(m_picker);
m_picker->we_have(j.offset);
}
// we're not done checking yet
@ -673,7 +670,7 @@ namespace libtorrent
}
void torrent::on_announce_disp(boost::weak_ptr<torrent> p
, asio::error_code const& e)
, error_code const& e)
{
if (e) return;
boost::shared_ptr<torrent> t = p.lock();
@ -687,7 +684,7 @@ namespace libtorrent
boost::weak_ptr<torrent> self(shared_from_this());
asio::error_code ec;
error_code ec;
if (!m_torrent_file->priv())
{
// announce on local network every 5 minutes
@ -759,6 +756,8 @@ namespace libtorrent
req.url = m_trackers[m_currently_trying_tracker].url;
m_ses.m_tracker_manager.queue_request(m_ses.m_io_service, m_ses.m_half_open, req
, tracker_login(), m_ses.m_listen_interface.address(), shared_from_this());
m_last_scrape = time_now();
}
// returns true if it is time for this torrent to make another
@ -837,6 +836,8 @@ namespace libtorrent
if (complete >= 0) m_complete = complete;
if (incomplete >= 0) m_incomplete = incomplete;
if (complete >= 0 && incomplete >= 0)
m_last_scrape = time_now();
// connect to random peers from the list
std::random_shuffle(peer_list.begin(), peer_list.end());
@ -865,7 +866,7 @@ namespace libtorrent
if (i->pid == m_ses.get_peer_id())
continue;
asio::error_code ec;
error_code ec;
tcp::endpoint a(address::from_string(i->ip, ec), i->port);
if (ec)
@ -875,7 +876,7 @@ namespace libtorrent
tcp::resolver::query q(i->ip, boost::lexical_cast<std::string>(i->port));
m_host_resolver.async_resolve(q,
bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid));
bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid));
}
else
{
@ -905,7 +906,7 @@ namespace libtorrent
m_got_tracker_response = true;
}
void torrent::on_peer_name_lookup(asio::error_code const& e, tcp::resolver::iterator host
void torrent::on_peer_name_lookup(error_code const& e, tcp::resolver::iterator host
, peer_id pid)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
@ -1369,7 +1370,7 @@ namespace libtorrent
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
m_owning_storage = 0;
asio::error_code ec;
error_code ec;
m_announce_timer.cancel(ec);
m_host_resolver.cancel();
}
@ -1487,9 +1488,8 @@ namespace libtorrent
#endif
if (is_seed())
{
m_state = torrent_status::seeding;
m_picker.reset();
if (m_ses.settings().free_torrent_hashes)
m_torrent_file->seed_free();
}
}
@ -1653,6 +1653,8 @@ namespace libtorrent
// the torrent just became finished
if (is_finished() && !was_finished)
finished();
else if (!is_finished() && was_finished)
resume_download();
}
void torrent::filter_piece(int index, bool filter)
@ -1912,9 +1914,20 @@ namespace libtorrent
std::string hostname;
int port;
std::string path;
boost::tie(protocol, auth, hostname, port, path)
char const* error;
boost::tie(protocol, auth, hostname, port, path, error)
= parse_url_components(url);
if (error)
{
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
(*m_ses.m_logger) << time_now_string() << " failed to parse web seed url: " << error << "\n";
#endif
// never try it again
remove_url_seed(url);
return;
}
#ifdef TORRENT_USE_OPENSSL
if (protocol != "http" && protocol != "https")
#else
@ -1968,6 +1981,18 @@ namespace libtorrent
}
else
{
if (m_ses.m_port_filter.access(port) & port_filter::blocked)
{
if (m_ses.m_alerts.should_post(alert::warning))
{
m_ses.m_alerts.post_alert(
url_seed_alert(get_handle(), url, "port blocked by port-filter"));
}
// never try it again
remove_url_seed(url);
return;
}
tcp::resolver::query q(hostname, boost::lexical_cast<std::string>(port));
m_host_resolver.async_resolve(q,
bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url
@ -1976,7 +2001,7 @@ namespace libtorrent
}
void torrent::on_proxy_name_lookup(asio::error_code const& e, tcp::resolver::iterator host
void torrent::on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator host
, std::string url)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
@ -1991,10 +2016,8 @@ namespace libtorrent
{
if (m_ses.m_alerts.should_post(alert::warning))
{
std::stringstream msg;
msg << "HTTP seed proxy hostname lookup failed: " << e.message();
m_ses.m_alerts.post_alert(
url_seed_alert(get_handle(), url, msg.str()));
url_seed_alert(get_handle(), url, e.message()));
}
// the name lookup failed for the http host. Don't try
@ -2010,9 +2033,21 @@ namespace libtorrent
using boost::tuples::ignore;
std::string hostname;
int port;
boost::tie(ignore, ignore, hostname, port, ignore)
char const* error;
boost::tie(ignore, ignore, hostname, port, ignore, error)
= parse_url_components(url);
if (error)
{
if (m_ses.m_alerts.should_post(alert::warning))
{
m_ses.m_alerts.post_alert(
url_seed_alert(get_handle(), url, error));
}
remove_url_seed(url);
return;
}
if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked)
{
if (m_ses.m_alerts.should_post(alert::info))
@ -2028,7 +2063,7 @@ namespace libtorrent
bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url, a));
}
void torrent::on_name_lookup(asio::error_code const& e, tcp::resolver::iterator host
void torrent::on_name_lookup(error_code const& e, tcp::resolver::iterator host
, std::string url, tcp::endpoint proxy)
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
@ -2090,7 +2125,7 @@ namespace libtorrent
}
std::pair<int, int> const& out_ports = m_settings.outgoing_ports;
asio::error_code ec;
error_code ec;
if (out_ports.first > 0 && out_ports.second >= out_ports.first)
s->bind(tcp::endpoint(address(), m_ses.next_port()), ec);
@ -2135,9 +2170,7 @@ namespace libtorrent
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
(*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << e.what() << "\n";
#endif
// TODO: post an error alert!
c->disconnect(e.what());
c->disconnect(e.what(), 1);
}
#endif
}
@ -2176,7 +2209,7 @@ namespace libtorrent
};
}
void torrent::on_country_lookup(asio::error_code const& error, tcp::resolver::iterator i
void torrent::on_country_lookup(error_code const& error, tcp::resolver::iterator i
, intrusive_ptr<peer_connection> p) const
{
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
@ -2287,6 +2320,19 @@ namespace libtorrent
m_active_time = seconds((e != 0 && e->type() == entry::int_t)?e->integer():0);
e = rd.find_key("seeding_time");
m_seeding_time = seconds((e != 0 && e->type() == entry::int_t)?e->integer():0);
e = rd.find_key("num_seeds");
m_complete = (e != 0 && e->type() == entry::int_t)?e->integer():-1;
e = rd.find_key("num_downloaders");
m_incomplete = (e != 0 && e->type() == entry::int_t)?e->integer():-1;
/*
m_total_uploaded = rd.find_int_value("total_uploaded");
m_total_downloaded = rd.find_inte_value("total_downloaded");
m_active_time = rd.find_int_value("active_time");
m_seeding_time = rd.find_int_value("seeding_time");
m_complete = rd.find_int_value("num_seeds", -1);
m_incomplete = rd.find_int_value("num_downloaders", -1);
*/
}
void torrent::write_resume_data(entry& ret) const
@ -2300,6 +2346,16 @@ namespace libtorrent
ret["active_time"] = total_seconds(m_active_time);
ret["seeding_time"] = total_seconds(m_seeding_time);
int seeds = 0;
int downloaders = 0;
if (m_complete >= 0) seeds = m_complete;
else seeds = m_policy.num_seeds();
if (m_incomplete >= 0) downloaders = m_incomplete;
else downloaders = m_policy.num_peers() - m_policy.num_seeds();
ret["num_seeds"] = seeds;
ret["num_downloaders"] = downloaders;
ret["allocation"] = m_storage_mode == storage_mode_sparse?"sparse"
:m_storage_mode == storage_mode_allocate?"full":"compact";
@ -2369,7 +2425,7 @@ namespace libtorrent
for (policy::const_iterator i = m_policy.begin_peer()
, end(m_policy.end_peer()); i != end; ++i)
{
asio::error_code ec;
error_code ec;
if (i->second.banned)
{
tcp::endpoint ip = i->second.ip;
@ -2538,7 +2594,7 @@ namespace libtorrent
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s);
TORRENT_ASSERT(ret);
std::pair<int, int> const& out_ports = m_ses.settings().outgoing_ports;
asio::error_code ec;
error_code ec;
if (out_ports.first > 0 && out_ports.second >= out_ports.first)
s->bind(tcp::endpoint(address(), m_ses.next_port()), ec);
@ -2571,6 +2627,7 @@ namespace libtorrent
// add the newly connected peer to this torrent's peer list
m_connections.insert(boost::get_pointer(c));
m_ses.m_connections.insert(c);
peerinfo->connection = c.get();
c->start();
int timeout = settings().peer_connect_timeout;
@ -2595,11 +2652,10 @@ namespace libtorrent
return false;
}
#endif
peerinfo->connection = c.get();
return true;
}
bool torrent::set_metadata(entry const& metadata, std::string& error)
bool torrent::set_metadata(lazy_entry const& metadata, std::string& error)
{
INVARIANT_CHECK;
@ -2683,7 +2739,7 @@ namespace libtorrent
TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
peer_iterator ci = m_connections.insert(p).first;
#ifndef NDEBUG
asio::error_code ec;
error_code ec;
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint(ec) || ec);
#endif
@ -2698,7 +2754,8 @@ namespace libtorrent
return int(m_connections.size()) < m_max_connections
&& !m_paused
&& m_state != torrent_status::checking_files
&& m_state != torrent_status::queued_for_checking
&& (m_state != torrent_status::queued_for_checking
|| !valid_metadata())
&& m_policy.num_connect_candidates() > 0;
}
@ -2730,6 +2787,71 @@ namespace libtorrent
}
}
namespace
{
// this returns true if lhs is a better disconnect candidate than rhs
bool compare_disconnect_peer(peer_connection const* lhs, peer_connection const* rhs)
{
// prefer to disconnect peers we're not interested in
if (lhs->is_interesting() != rhs->is_interesting())
return rhs->is_interesting();
// prefer to disconnect peers that are not seeds
if (lhs->is_seed() != rhs->is_seed())
return rhs->is_seed();
// prefer to disconnect peers that are on parole
if (lhs->on_parole() != rhs->on_parole())
return lhs->on_parole();
// prefer to disconnect peers that send data at a lower rate
size_type lhs_transferred = lhs->statistics().total_payload_download();
size_type rhs_transferred = rhs->statistics().total_payload_download();
if (lhs_transferred != rhs_transferred
&& lhs_transferred > 0
&& rhs_transferred > 0)
{
ptime now = time_now();
size_type lhs_time_connected = total_seconds(now - lhs->connected_time());
size_type rhs_time_connected = total_seconds(now - rhs->connected_time());
double lhs_rate = double(lhs_transferred) / (lhs_time_connected + 1);
double rhs_rate = double(rhs_transferred) / (rhs_time_connected + 1);
return lhs_rate < rhs_rate;
}
// prefer to disconnect peers that chokes us
if (lhs->is_choked() != rhs->is_choked())
return lhs->is_choked();
return lhs->last_received() < rhs->last_received();
}
}
int torrent::disconnect_peers(int num)
{
int ret = 0;
// buils a list of all connected peers and sort it by 'disconnectability'.
std::vector<peer_connection*> peers(m_connections.size());
std::copy(m_connections.begin(), m_connections.end(), peers.begin());
std::sort(peers.begin(), peers.end(), boost::bind(&compare_disconnect_peer, _1, _2));
// never disconnect peers that connected less than 90 seconds ago
ptime cut_off = time_now() - seconds(90);
for (std::vector<peer_connection*>::iterator i = peers.begin()
, end(peers.end()); i != end && ret < num; ++i)
{
peer_connection* p = *i;
if (p->connected_time() > cut_off) continue;
++ret;
p->disconnect("optimistic disconnect");
}
return ret;
}
int torrent::bandwidth_throttle(int channel) const
{
return m_bandwidth_limit[channel].throttle();
@ -2844,7 +2966,7 @@ namespace libtorrent
{
peer_connection* p = *i;
TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
if (p->is_seed())
if (p->upload_only())
{
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
(*p->m_logger) << "*** SEED, CLOSING CONNECTION\n";
@ -2853,7 +2975,7 @@ namespace libtorrent
}
}
std::for_each(seeds.begin(), seeds.end()
, bind(&peer_connection::disconnect, _1, "torrent finished, disconnecting seed"));
, bind(&peer_connection::disconnect, _1, "torrent finished, disconnecting seed", 0));
TORRENT_ASSERT(m_storage);
// we need to keep the object alive during this operation
@ -2861,6 +2983,15 @@ namespace libtorrent
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
}
// this is called when we were finished, but some files were
// marked for downloading, and we are no longer finished
void torrent::resume_download()
{
INVARIANT_CHECK;
m_state = torrent_status::downloading;
}
// called when torrent is complete (all pieces downloaded)
void torrent::completed()
{
@ -2900,7 +3031,7 @@ namespace libtorrent
if ((unsigned)m_currently_trying_tracker >= m_trackers.size())
{
int delay = tracker_retry_delay_min
+ (std::min)(m_failed_trackers, (int)tracker_failed_max)
+ (std::min)(int(m_failed_trackers), int(tracker_failed_max))
* (tracker_retry_delay_max - tracker_retry_delay_min)
/ tracker_failed_max;
@ -2968,8 +3099,6 @@ namespace libtorrent
{
m_state = torrent_status::seeding;
m_picker.reset();
if (m_ses.settings().free_torrent_hashes)
m_torrent_file->seed_free();
}
if (!m_connections_initialized)
@ -3285,27 +3414,59 @@ namespace libtorrent
m_ses.m_auto_manage_time_scaler = 0;
}
float torrent::seed_cycles(session_settings const& s) const
// the higher seed rank, the more important to seed
int torrent::seed_rank(session_settings const& s) const
{
if (!is_seed()) return 0.f;
enum flags
{
seed_ratio_not_met = 0x400000,
recently_started = 0x200000,
no_seeds = 0x100000,
prio_mask = 0xfffff
};
int seeding = total_seconds(m_seeding_time);
int downloading = total_seconds(m_active_time) - seeding;
if (!is_seed()) return 0;
// if the seed time limit is set to less than 60 minutes
// use 60 minutes, to avoid oscillation
float ret = seeding / float((std::max)(s.seed_time_limit, 60 * 60));
int ret = 0;
// if it took less than 30 minutes to download, disregard the
// seed_time_ratio_limit, since it would make it oscillate too frequent
if (downloading > 30 * 60 && s.seed_time_ratio_limit >= 1.f)
ret = (std::max)(ret, (seeding / downloading
/ s.seed_time_ratio_limit));
ptime now(time_now());
int seed_time = total_seconds(m_seeding_time);
int download_time = total_seconds(m_active_time) - seed_time;
// if we haven't yet met the seed limits, set the seed_ratio_not_met
// flag. That will make this seed prioritized
size_type downloaded = (std::max)(m_total_downloaded, m_torrent_file->total_size());
if (downloaded > 0 && s.share_ratio_limit >= 1.f)
ret = (std::max)(ret, float(m_total_uploaded) / downloaded
/ s.share_ratio_limit);
if (seed_time < s.seed_time_limit
&& (seed_time > 1 && download_time / float(seed_time) < s.seed_time_ratio_limit)
&& m_total_uploaded / downloaded < s.share_ratio_limit)
ret |= seed_ratio_not_met;
// if this torrent is running, and it was started less
// than 30 minutes ago, give it priority, to avoid oscillation
if (!is_paused() && now - m_started < minutes(30))
ret |= recently_started;
// if we have any scrape data, use it to calculate
// seed rank
int seeds = 0;
int downloaders = 0;
if (m_complete >= 0) seeds = m_complete;
else seeds = m_policy.num_seeds();
if (m_incomplete >= 0) downloaders = m_incomplete;
else downloaders = m_policy.num_peers() - m_policy.num_seeds();
if (seeds == 0)
{
ret |= no_seeds;
ret |= downloaders & prio_mask;
}
else
{
ret |= (downloaders * 100 / seeds) & prio_mask;
}
return ret;
}
@ -3402,6 +3563,7 @@ namespace libtorrent
#endif
m_paused = false;
m_started = time_now();
// tell the tracker that we're back
m_event = tracker_request::started;
@ -3489,6 +3651,7 @@ namespace libtorrent
{
peer_connection* p = *i;
++i;
p->calc_ip_overhead();
m_stat += p->statistics();
// updates the peer connection's ul/dl bandwidth
// resource requests
@ -3504,8 +3667,7 @@ namespace libtorrent
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
(*p->m_logger) << "**ERROR**: " << e.what() << "\n";
#endif
p->set_failed();
p->disconnect(e.what());
p->disconnect(e.what(), 1);
}
#endif
}
@ -3643,8 +3805,18 @@ namespace libtorrent
, m_have_pieces.end()
, 0) == m_num_pieces);
ptime now = time_now();
torrent_status st;
if (m_last_scrape == min_time())
{
st.last_scrape = -1;
}
else
{
st.last_scrape = total_seconds(now - m_last_scrape);
}
st.up_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::upload_channel].size();
st.down_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::download_channel].size();
@ -3654,7 +3826,7 @@ namespace libtorrent
st.list_peers = m_policy.num_peers();
st.list_seeds = m_policy.num_seeds();
st.connect_candidates = m_policy.num_connect_candidates();
st.seed_cycles = seed_cycles(m_ses.m_settings);
st.seed_rank = seed_rank(m_ses.m_settings);
st.all_time_upload = m_total_uploaded;
st.all_time_download = m_total_downloaded;
@ -3668,6 +3840,7 @@ namespace libtorrent
st.num_incomplete = m_incomplete;
st.paused = m_paused;
boost::tie(st.total_done, st.total_wanted_done) = bytes_done();
TORRENT_ASSERT(st.total_wanted_done >= 0);
TORRENT_ASSERT(st.total_done >= st.total_wanted_done);
// payload transfer
@ -3691,7 +3864,7 @@ namespace libtorrent
st.upload_payload_rate = m_stat.upload_payload_rate();
st.next_announce = boost::posix_time::seconds(
total_seconds(next_announce() - time_now()));
total_seconds(next_announce() - now));
if (st.next_announce.is_negative())
st.next_announce = boost::posix_time::seconds(0);
@ -3713,7 +3886,7 @@ namespace libtorrent
if (!valid_metadata())
{
if (m_got_tracker_response == false)
if (m_got_tracker_response == false && m_connections.empty())
st.state = torrent_status::connecting_to_tracker;
else
st.state = torrent_status::downloading_metadata;
@ -3728,6 +3901,7 @@ namespace libtorrent
// fill in status that depends on metadata
st.total_wanted = m_torrent_file->total_size();
TORRENT_ASSERT(st.total_wanted >= 0);
if (m_picker.get() && (m_picker->num_filtered() > 0
|| m_picker->num_have_filtered() > 0))

View File

@ -1,6 +1,6 @@
/*
Copyright (c) 2003, Arvid Norberg
Copyright (c) 2008, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/lexical_cast.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem.hpp>
#include <boost/next_prior.hpp>
#include <boost/bind.hpp>
@ -159,13 +160,13 @@ namespace
}
}
bool extract_single_file(entry const& dict, file_entry& target
bool extract_single_file(lazy_entry const& dict, file_entry& target
, std::string const& root_dir)
{
entry const* length = dict.find_key("length");
if (length == 0 || length->type() != entry::int_t)
lazy_entry const* length = dict.dict_find("length");
if (length == 0 || length->type() != lazy_entry::int_t)
return false;
target.size = length->integer();
target.size = length->int_value();
target.path = root_dir;
target.file_base = 0;
@ -173,27 +174,19 @@ namespace
// because if it exists, it is more
// likely to be correctly encoded
const entry::list_type* list = 0;
entry const* p8 = dict.find_key("path.utf-8");
if (p8 != 0 && p8->type() == entry::list_t)
{
list = &p8->list();
}
else
{
entry const* p = dict.find_key("path");
if (p == 0 || p->type() != entry::list_t)
return false;
list = &p->list();
}
lazy_entry const* p = dict.dict_find("path.utf-8");
if (p == 0 || p->type() != lazy_entry::list_t)
p = dict.dict_find("path");
if (p == 0 || p->type() != lazy_entry::list_t)
return false;
for (entry::list_type::const_iterator i = list->begin();
i != list->end(); ++i)
for (int i = 0, end(p->list_size()); i < end; ++i)
{
if (i->type() != entry::string_t)
if (p->list_at(i)->type() != lazy_entry::string_t)
return false;
if (i->string() != "..")
target.path /= i->string();
std::string path_element = p->list_at(i)->string_value();
if (path_element != "..")
target.path /= path_element;
}
verify_encoding(target);
if (target.path.is_complete())
@ -201,14 +194,15 @@ namespace
return true;
}
bool extract_files(const entry::list_type& list, std::vector<file_entry>& target
bool extract_files(lazy_entry const& list, std::vector<file_entry>& target
, std::string const& root_dir)
{
size_type offset = 0;
for (entry::list_type::const_iterator i = list.begin(); i != list.end(); ++i)
if (list.type() != lazy_entry::list_t) return false;
for (int i = 0, end(list.list_size()); i < end; ++i)
{
target.push_back(file_entry());
if (!extract_single_file(*i, target.back(), root_dir))
if (!extract_single_file(*list.list_at(i), target.back(), root_dir))
return false;
target.back().offset = offset;
offset += target.back().size;
@ -231,25 +225,65 @@ namespace libtorrent
{
// standard constructor that parses a torrent file
torrent_info::torrent_info(const entry& torrent_file)
torrent_info::torrent_info(entry const& torrent_file)
: m_num_pieces(0)
, m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
, m_extra_info(entry::dictionary_t)
#ifndef NDEBUG
, m_half_metadata(false)
, m_info_section_size(0)
, m_piece_hashes(0)
{
std::vector<char> tmp;
std::back_insert_iterator<std::vector<char> > out(tmp);
bencode(out, torrent_file);
lazy_entry e;
lazy_bdecode(&tmp[0], &tmp[0] + tmp.size(), e);
std::string error;
#ifndef BOOST_NO_EXCEPTIONS
if (!parse_torrent_file(e, error))
throw invalid_torrent_file();
#else
read_torrent_info(e, error);
#endif
}
torrent_info::torrent_info(lazy_entry const& torrent_file)
: m_num_pieces(0)
, m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
, m_info_section_size(0)
, m_piece_hashes(0)
{
std::string error;
#ifndef BOOST_NO_EXCEPTIONS
if (!read_torrent_info(torrent_file, error))
if (!parse_torrent_file(torrent_file, error))
throw invalid_torrent_file();
#else
read_torrent_info(torrent_file, error);
#endif
}
torrent_info::torrent_info(char const* buffer, int size)
: m_num_pieces(0)
, m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
, m_info_section_size(0)
, m_piece_hashes(0)
{
std::string error;
lazy_entry e;
lazy_bdecode(buffer, buffer + size, e);
#ifndef BOOST_NO_EXCEPTIONS
if (!parse_torrent_file(e, error))
throw invalid_torrent_file();
#else
read_torrent_info(e, error);
#endif
}
// constructor used for creating new torrents
// will not contain any hashes, comments, creation date
// just the necessary to use it with piece manager
@ -263,10 +297,8 @@ namespace libtorrent
, m_creation_date(pt::second_clock::universal_time())
, m_multifile(false)
, m_private(false)
, m_extra_info(entry::dictionary_t)
#ifndef NDEBUG
, m_half_metadata(false)
#endif
, m_info_section_size(0)
, m_piece_hashes(0)
{
}
@ -279,13 +311,35 @@ namespace libtorrent
, m_creation_date(pt::second_clock::universal_time())
, m_multifile(false)
, m_private(false)
, m_extra_info(entry::dictionary_t)
#ifndef NDEBUG
, m_half_metadata(false)
#endif
, m_info_section_size(0)
, m_piece_hashes(0)
{
}
torrent_info::torrent_info(char const* filename)
: m_num_pieces(0)
, m_creation_date(pt::ptime(pt::not_a_date_time))
, m_multifile(false)
, m_private(false)
{
size_type s = fs::file_size(fs::path(filename));
// don't load torrent files larger than 2 MB
if (s > 2000000) return;
std::vector<char> buf(s);
std::ifstream f(filename);
f.read(&buf[0], s);
std::string error;
lazy_entry e;
lazy_bdecode(&buf[0], &buf[0] + buf.size(), e);
#ifndef BOOST_NO_EXCEPTIONS
if (!parse_torrent_file(e, error))
throw invalid_torrent_file();
#else
read_torrent_info(e, error);
#endif
}
torrent_info::~torrent_info()
{}
@ -294,9 +348,8 @@ namespace libtorrent
using std::swap;
m_urls.swap(ti.m_urls);
m_url_seeds.swap(ti.m_url_seeds);
swap(m_piece_length, ti.m_piece_length);
m_piece_hash.swap(ti.m_piece_hash);
m_files.swap(ti.m_files);
m_files.swap(ti.m_remapped_files);
m_nodes.swap(ti.m_nodes);
swap(m_num_pieces, ti.m_num_pieces);
swap(m_info_hash, ti.m_info_hash);
@ -306,81 +359,49 @@ namespace libtorrent
m_created_by.swap(ti.m_created_by);
swap(m_multifile, ti.m_multifile);
swap(m_private, ti.m_private);
m_extra_info.swap(ti.m_extra_info);
#ifndef NDEBUG
swap(m_half_metadata, ti.m_half_metadata);
#endif
swap(m_info_section, ti.m_info_section);
swap(m_info_section_size, ti.m_info_section_size);
swap(m_piece_hashes, ti.m_piece_hashes);
swap(m_info_dict, ti.m_info_dict);
}
void torrent_info::set_piece_size(int size)
bool torrent_info::parse_info_section(lazy_entry const& info, std::string& error)
{
// make sure the size is an even power of 2
#ifndef NDEBUG
for (int i = 0; i < 32; ++i)
{
if (size & (1 << i))
{
TORRENT_ASSERT((size & ~(1 << i)) == 0);
break;
}
}
#endif
TORRENT_ASSERT(!m_half_metadata);
m_piece_length = size;
m_num_pieces = static_cast<int>(
(m_total_size + m_piece_length - 1) / m_piece_length);
int old_num_pieces = static_cast<int>(m_piece_hash.size());
m_piece_hash.resize(m_num_pieces);
for (int i = old_num_pieces; i < m_num_pieces; ++i)
{
m_piece_hash[i].clear();
}
}
bool torrent_info::parse_info_section(entry const& info, std::string& error)
{
if (info.type() != entry::dictionary_t)
if (info.type() != lazy_entry::dict_t)
{
error = "'info' entry is not a dictionary";
return false;
}
// encode the info-field in order to calculate it's sha1-hash
std::vector<char> buf;
bencode(std::back_inserter(buf), info);
// hash the info-field to calculate info-hash
hasher h;
h.update(&buf[0], (int)buf.size());
std::pair<char const*, int> section = info.data_section();
h.update(section.first, section.second);
m_info_hash = h.final();
// copy the info section
m_info_section_size = section.second;
m_info_section.reset(new char[m_info_section_size]);
memcpy(m_info_section.get(), section.first, m_info_section_size);
TORRENT_ASSERT(section.first[0] == 'd');
TORRENT_ASSERT(section.first[m_info_section_size-1] == 'e');
// extract piece length
entry const* piece_length = info.find_key("piece length");
if (piece_length == 0 || piece_length->type() != entry::int_t)
m_piece_length = info.dict_find_int_value("piece length", -1);
if (m_piece_length <= 0)
{
error = "invalid or missing 'piece length' entry in torrent file";
return false;
}
m_piece_length = int(piece_length->integer());
if (m_piece_length <= 0)
{
error = "invalid torrent. piece length <= 0";
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
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())
{
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();
error = "invalid name in torrent file";
return false;
}
fs::path tmp = m_name;
@ -401,32 +422,31 @@ namespace libtorrent
}
if (m_name == ".." || m_name == ".")
{
error = "invalid 'name' of torrent (possible exploit attempt)";
return false;
}
// extract file list
entry const* i = info.find_key("files");
lazy_entry const* i = info.dict_find_list("files");
if (i == 0)
{
entry const* length = info.find_key("length");
if (length == 0 || length->type() != entry::int_t)
{
error = "invalid length of torrent";
return false;
}
// if there's no list of files, there has to be a length
// field.
file_entry e;
e.path = m_name;
e.offset = 0;
e.size = length->integer();
e.size = info.dict_find_int_value("length", -1);
if (e.size < 0)
{
error = "invalid length of torrent";
return false;
}
m_files.push_back(e);
m_multifile = false;
}
else
{
if (!extract_files(i->list(), m_files, m_name))
if (!extract_files(*i, m_files, m_name))
{
error = "failed to parse files from torrent file";
return false;
@ -443,84 +463,51 @@ namespace libtorrent
// we want this division to round upwards, that's why we have the
// extra addition
entry const* pieces_ent = info.find_key("pieces");
if (pieces_ent == 0 || pieces_ent->type() != entry::string_t)
m_num_pieces = static_cast<int>((m_total_size + m_piece_length - 1) / m_piece_length);
lazy_entry const* pieces = info.dict_find("pieces");
if (pieces == 0 || pieces->type() != lazy_entry::string_t)
{
error = "invalid or missing 'pieces' entry in torrent file";
return false;
}
m_num_pieces = static_cast<int>((m_total_size + m_piece_length - 1) / m_piece_length);
m_piece_hash.resize(m_num_pieces);
const std::string& hash_string = pieces_ent->string();
if ((int)hash_string.length() != m_num_pieces * 20)
if (pieces->string_length() != m_num_pieces * 20)
{
error = "incorrect number of piece hashes in torrent file";
return false;
}
for (int i = 0; i < m_num_pieces; ++i)
std::copy(
hash_string.begin() + i*20
, hash_string.begin() + (i+1)*20
, m_piece_hash[i].begin());
m_piece_hashes = m_info_section.get() + (pieces->string_ptr() - section.first);
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
for (entry::dictionary_type::const_iterator i = info.dict().begin()
, end(info.dict().end()); i != end; ++i)
{
if (i->first == "pieces"
|| i->first == "piece length"
|| i->first == "length")
continue;
m_extra_info[i->first] = i->second;
}
if (entry const* priv = info.find_key("private"))
{
if (priv->type() != entry::int_t
|| priv->integer() != 0)
{
// this key exists and it's not 0.
// consider the torrent private
m_private = true;
}
}
#ifndef NDEBUG
std::vector<char> info_section_buf;
entry gen_info_section = create_info_metadata();
bencode(std::back_inserter(info_section_buf), gen_info_section);
TORRENT_ASSERT(hasher(&info_section_buf[0], info_section_buf.size()).final()
== m_info_hash);
#endif
m_private = info.dict_find_int_value("private", 0);
return true;
}
// extracts information from a libtorrent file and fills in the structures in
// the torrent object
bool torrent_info::read_torrent_info(const entry& torrent_file, std::string& error)
bool torrent_info::parse_torrent_file(lazy_entry const& torrent_file, std::string& error)
{
if (torrent_file.type() != entry::dictionary_t)
if (torrent_file.type() != lazy_entry::dict_t)
{
error = "torrent file is not a dictionary";
return false;
}
// extract the url of the tracker
entry const* i = torrent_file.find_key("announce-list");
if (i && i->type() == entry::list_t)
lazy_entry const* i = torrent_file.dict_find_list("announce-list");
if (i)
{
const entry::list_type& l = i->list();
for (entry::list_type::const_iterator j = l.begin(); j != l.end(); ++j)
m_urls.reserve(i->list_size());
for (int j = 0, end(i->list_size()); j < end; ++j)
{
if (j->type() != entry::list_t) break;
const entry::list_type& ll = j->list();
for (entry::list_type::const_iterator k = ll.begin(); k != ll.end(); ++k)
lazy_entry const* tier = i->list_at(j);
if (tier->type() != lazy_entry::list_t) continue;
for (int k = 0, end(tier->list_size()); k < end; ++k)
{
if (k->type() != entry::string_t) break;
announce_entry e(k->string());
e.tier = (int)std::distance(l.begin(), j);
announce_entry e(tier->list_string_value_at(k));
if (e.url.empty()) continue;
e.tier = j;
m_urls.push_back(e);
}
}
@ -541,71 +528,62 @@ namespace libtorrent
std::random_shuffle(start, stop);
}
entry const* announce = torrent_file.find_key("announce");
if (m_urls.empty() && announce && announce->type() == entry::string_t)
if (m_urls.empty())
{
m_urls.push_back(announce_entry(announce->string()));
announce_entry e(torrent_file.dict_find_string_value("announce"));
if (!e.url.empty()) m_urls.push_back(e);
}
entry const* nodes = torrent_file.find_key("nodes");
if (nodes && nodes->type() == entry::list_t)
lazy_entry const* nodes = torrent_file.dict_find_list("nodes");
if (nodes)
{
entry::list_type const& list = nodes->list();
for (entry::list_type::const_iterator i(list.begin())
, end(list.end()); i != end; ++i)
for (int i = 0, end(nodes->list_size()); i < end; ++i)
{
if (i->type() != entry::list_t) continue;
entry::list_type const& l = i->list();
entry::list_type::const_iterator iter = l.begin();
if (l.size() < 1) continue;
if (iter->type() != entry::string_t) continue;
std::string const& hostname = iter->string();
++iter;
int port = 6881;
if (iter->type() != entry::int_t) continue;
if (l.end() != iter) port = int(iter->integer());
m_nodes.push_back(std::make_pair(hostname, port));
lazy_entry const* n = nodes->list_at(i);
if (n->type() != lazy_entry::list_t
|| n->list_size() < 2
|| n->list_at(0)->type() != lazy_entry::string_t
|| n->list_at(1)->type() != lazy_entry::int_t)
continue;
m_nodes.push_back(std::make_pair(
n->list_at(0)->string_value()
, int(n->list_at(1)->int_value())));
}
}
// extract creation date
entry const* creation_date = torrent_file.find_key("creation date");
if (creation_date && creation_date->type() == entry::int_t)
size_type cd = torrent_file.dict_find_int_value("creation date", -1);
if (cd >= 0)
{
m_creation_date = pt::ptime(gr::date(1970, gr::Jan, 1))
+ pt::seconds(long(creation_date->integer()));
+ pt::seconds(long(cd));
}
// if there are any url-seeds, extract them
entry const* url_seeds = torrent_file.find_key("url-list");
if (url_seeds && url_seeds->type() == entry::string_t)
lazy_entry const* url_seeds = torrent_file.dict_find("url-list");
if (url_seeds && url_seeds->type() == lazy_entry::string_t)
{
m_url_seeds.push_back(url_seeds->string());
m_url_seeds.push_back(url_seeds->string_value());
}
else if (url_seeds && url_seeds->type() == entry::list_t)
else if (url_seeds && url_seeds->type() == lazy_entry::list_t)
{
entry::list_type const& l = url_seeds->list();
for (entry::list_type::const_iterator i = l.begin();
i != l.end(); ++i)
for (int i = 0, end(url_seeds->list_size()); i < end; ++i)
{
if (i->type() != entry::string_t) continue;
m_url_seeds.push_back(i->string());
lazy_entry const* url = url_seeds->list_at(i);
if (url->type() != lazy_entry::string_t) continue;
m_url_seeds.push_back(url->string_value());
}
}
// extract comment
if (entry const* e = torrent_file.find_key("comment.utf-8"))
{ m_comment = e->string(); }
else if (entry const* e = torrent_file.find_key("comment"))
{ m_comment = e->string(); }
m_comment = torrent_file.dict_find_string_value("comment.utf-8");
if (m_comment.empty()) m_comment = torrent_file.dict_find_string_value("comment");
if (entry const* e = torrent_file.find_key("created by.utf-8"))
{ m_created_by = e->string(); }
else if (entry const* e = torrent_file.find_key("created by"))
{ m_created_by = e->string(); }
m_created_by = torrent_file.dict_find_string_value("created by.utf-8");
if (m_created_by.empty()) m_created_by = torrent_file.dict_find_string_value("created by");
entry const* info = torrent_file.find_key("info");
if (info == 0 || info->type() != entry::dictionary_t)
lazy_entry const* info = torrent_file.dict_find_dict("info");
if (info == 0)
{
error = "missing or invalid 'info' section in torrent file";
return false;
@ -634,234 +612,6 @@ namespace libtorrent
, bind(&announce_entry::tier, _1), bind(&announce_entry::tier, _2)));
}
void torrent_info::add_file(fs::path file, size_type size)
{
// TORRENT_ASSERT(file.begin() != file.end());
if (!file.has_branch_path())
{
// you have already added at least one file with a
// path to the file (branch_path), which means that
// all the other files need to be in the same top
// directory as the first file.
TORRENT_ASSERT(m_files.empty());
TORRENT_ASSERT(!m_multifile);
m_name = file.string();
}
else
{
#ifndef NDEBUG
if (!m_files.empty())
TORRENT_ASSERT(m_name == *file.begin());
#endif
m_multifile = true;
m_name = *file.begin();
}
file_entry e;
e.path = file;
e.size = size;
e.offset = m_files.empty() ? 0 : m_files.back().offset
+ m_files.back().size;
m_files.push_back(e);
m_total_size += size;
if (m_piece_length == 0)
m_piece_length = 256 * 1024;
m_num_pieces = static_cast<int>(
(m_total_size + m_piece_length - 1) / m_piece_length);
int old_num_pieces = static_cast<int>(m_piece_hash.size());
m_piece_hash.resize(m_num_pieces);
if (m_num_pieces > old_num_pieces)
std::for_each(m_piece_hash.begin() + old_num_pieces
, m_piece_hash.end(), boost::bind(&sha1_hash::clear, _1));
}
void torrent_info::add_url_seed(std::string const& url)
{
m_url_seeds.push_back(url);
}
void torrent_info::set_comment(char const* str)
{
m_comment = str;
}
void torrent_info::set_creator(char const* str)
{
m_created_by = str;
}
entry torrent_info::create_info_metadata() const
{
// you have to add files to the torrent first
TORRENT_ASSERT(!m_files.empty());
entry info(m_extra_info);
if (!info.find_key("name"))
info["name"] = m_name;
if (m_private) info["private"] = 1;
if (!m_multifile)
{
info["length"] = m_files.front().size;
}
else
{
if (!info.find_key("files"))
{
entry& files = info["files"];
for (std::vector<file_entry>::const_iterator i = m_files.begin();
i != m_files.end(); ++i)
{
files.list().push_back(entry());
entry& file_e = files.list().back();
file_e["length"] = i->size;
entry& path_e = file_e["path"];
fs::path const* file_path;
if (i->orig_path) file_path = &(*i->orig_path);
else file_path = &i->path;
TORRENT_ASSERT(file_path->has_branch_path());
TORRENT_ASSERT(*file_path->begin() == m_name);
for (fs::path::iterator j = boost::next(file_path->begin());
j != file_path->end(); ++j)
{
path_e.list().push_back(entry(*j));
}
}
}
}
info["piece length"] = piece_length();
entry& pieces = info["pieces"];
std::string& p = pieces.string();
for (std::vector<sha1_hash>::const_iterator i = m_piece_hash.begin();
i != m_piece_hash.end(); ++i)
{
p.append((char*)i->begin(), (char*)i->end());
}
return info;
}
entry torrent_info::create_torrent() const
{
TORRENT_ASSERT(m_piece_length > 0);
if (m_files.empty())
{
// TODO: throw something here
// throw
return entry();
}
entry dict;
if (!m_urls.empty())
dict["announce"] = m_urls.front().url;
if (!m_nodes.empty())
{
entry& nodes = dict["nodes"];
entry::list_type& nodes_list = nodes.list();
for (nodes_t::const_iterator i = m_nodes.begin()
, end(m_nodes.end()); i != end; ++i)
{
entry::list_type node;
node.push_back(entry(i->first));
node.push_back(entry(i->second));
nodes_list.push_back(entry(node));
}
}
if (m_urls.size() > 1)
{
entry trackers(entry::list_t);
entry tier(entry::list_t);
int current_tier = m_urls.front().tier;
for (std::vector<announce_entry>::const_iterator i = m_urls.begin();
i != m_urls.end(); ++i)
{
if (i->tier != current_tier)
{
current_tier = i->tier;
trackers.list().push_back(tier);
tier.list().clear();
}
tier.list().push_back(entry(i->url));
}
trackers.list().push_back(tier);
dict["announce-list"] = trackers;
}
if (!m_comment.empty())
dict["comment"] = m_comment;
dict["creation date"] =
(m_creation_date - pt::ptime(gr::date(1970, gr::Jan, 1))).total_seconds();
if (!m_created_by.empty())
dict["created by"] = m_created_by;
if (!m_url_seeds.empty())
{
if (m_url_seeds.size() == 1)
{
dict["url-list"] = m_url_seeds.front();
}
else
{
entry& list = dict["url-list"];
for (std::vector<std::string>::const_iterator i
= m_url_seeds.begin(); i != m_url_seeds.end(); ++i)
{
list.list().push_back(entry(*i));
}
}
}
dict["info"] = create_info_metadata();
entry const& info_section = dict["info"];
std::vector<char> buf;
bencode(std::back_inserter(buf), info_section);
m_info_hash = hasher(&buf[0], buf.size()).final();
return dict;
}
void torrent_info::set_hash(int index, const sha1_hash& h)
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < (int)m_piece_hash.size());
m_piece_hash[index] = h;
}
void torrent_info::convert_file_names()
{
TORRENT_ASSERT(false);
}
void torrent_info::seed_free()
{
std::vector<std::string>().swap(m_url_seeds);
nodes_t().swap(m_nodes);
std::vector<sha1_hash>().swap(m_piece_hash);
#ifndef NDEBUG
m_half_metadata = true;
#endif
}
// ------- start deprecation -------
void torrent_info::print(std::ostream& os) const
@ -901,11 +651,6 @@ namespace libtorrent
return piece_length();
}
void torrent_info::add_node(std::pair<std::string, int> const& node)
{
m_nodes.push_back(node);
}
bool torrent_info::remap_files(std::vector<file_entry> const& map)
{
size_type offset = 0;

View File

@ -84,7 +84,7 @@ namespace libtorrent
int timeout = (std::min)(
m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
asio::error_code ec;
error_code ec;
m_timeout.expires_at(m_read_time + seconds(timeout), ec);
m_timeout.async_wait(bind(
&timeout_handler::timeout_callback, self(), _1));
@ -99,11 +99,11 @@ namespace libtorrent
{
m_abort = true;
m_completion_timeout = 0;
asio::error_code ec;
error_code ec;
m_timeout.cancel(ec);
}
void timeout_handler::timeout_callback(asio::error_code const& error)
void timeout_handler::timeout_callback(error_code const& error)
{
if (error) return;
if (m_completion_timeout == 0) return;
@ -125,7 +125,7 @@ namespace libtorrent
int timeout = (std::min)(
m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
asio::error_code ec;
error_code ec;
m_timeout.expires_at(m_read_time + seconds(timeout), ec);
m_timeout.async_wait(
bind(&timeout_handler::timeout_callback, self(), _1));
@ -180,83 +180,6 @@ namespace libtorrent
m_connections.erase(i);
}
// returns protocol, auth, hostname, port, path
tuple<std::string, std::string, std::string, int, std::string>
parse_url_components(std::string url)
{
std::string hostname; // hostname only
std::string auth; // user:pass
std::string protocol; // http or https for instance
int port = 80;
std::string::iterator at;
std::string::iterator colon;
std::string::iterator port_pos;
// PARSE URL
std::string::iterator start = url.begin();
// remove white spaces in front of the url
while (start != url.end() && (*start == ' ' || *start == '\t'))
++start;
std::string::iterator end
= std::find(url.begin(), url.end(), ':');
protocol.assign(start, end);
if (protocol == "https") port = 443;
if (end == url.end()) goto exit;
++end;
if (end == url.end()) goto exit;
if (*end != '/') goto exit;
++end;
if (end == url.end()) goto exit;
if (*end != '/') goto exit;
++end;
start = end;
at = std::find(start, url.end(), '@');
colon = std::find(start, url.end(), ':');
end = std::find(start, url.end(), '/');
if (at != url.end()
&& colon != url.end()
&& colon < at
&& at < end)
{
auth.assign(start, at);
start = at;
++start;
}
// this is for IPv6 addresses
if (start != url.end() && *start == '[')
{
port_pos = std::find(start, url.end(), ']');
if (port_pos == url.end()) goto exit;
port_pos = std::find(port_pos, url.end(), ':');
}
else
{
port_pos = std::find(start, url.end(), ':');
}
if (port_pos < end)
{
hostname.assign(start, port_pos);
++port_pos;
port = atoi(std::string(port_pos, end).c_str());
}
else
{
hostname.assign(start, end);
}
start = end;
exit:
return make_tuple(protocol, auth, hostname, port
, std::string(start, url.end()));
}
void tracker_manager::queue_request(
io_service& ios
, connection_queue& cc

View File

@ -4,7 +4,11 @@
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/array.hpp>
#if BOOST_VERSION < 103500
#include <asio/read.hpp>
#else
#include <boost/asio/read.hpp>
#endif
using namespace libtorrent;
@ -22,7 +26,7 @@ udp_socket::udp_socket(asio::io_service& ios, udp_socket::callback_t const& c
{
}
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, asio::error_code& ec)
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec)
{
if (ec == asio::error::operation_aborted) return;
@ -39,7 +43,7 @@ void udp_socket::send(udp::endpoint const& ep, char const* p, int len, asio::err
m_ipv6_sock.send_to(asio::buffer(p, len), ep, 0, ec);
}
void udp_socket::on_read(udp::socket* s, asio::error_code const& e, std::size_t bytes_transferred)
void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_transferred)
{
if (e == asio::error::operation_aborted) return;
@ -113,7 +117,7 @@ void udp_socket::on_read(udp::socket* s, asio::error_code const& e, std::size_t
}
}
void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, asio::error_code& ec)
void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec)
{
using namespace libtorrent::detail;
@ -137,7 +141,7 @@ void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, asio::err
}
// unwrap the UDP packet from the SOCKS5 header
void udp_socket::unwrap(asio::error_code const& e, char const* buf, int size)
void udp_socket::unwrap(error_code const& e, char const* buf, int size)
{
using namespace libtorrent::detail;
@ -174,7 +178,7 @@ void udp_socket::unwrap(asio::error_code const& e, char const* buf, int size)
void udp_socket::close()
{
asio::error_code ec;
error_code ec;
m_ipv4_sock.close(ec);
m_ipv6_sock.close(ec);
m_socks5_sock.close(ec);
@ -186,7 +190,7 @@ void udp_socket::close()
}
}
void udp_socket::bind(udp::endpoint const& ep, asio::error_code& ec)
void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
{
if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec);
@ -214,7 +218,7 @@ void udp_socket::bind(udp::endpoint const& ep, asio::error_code& ec)
void udp_socket::bind(int port)
{
asio::error_code ec;
error_code ec;
if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec);
@ -239,7 +243,7 @@ void udp_socket::bind(int port)
void udp_socket::set_proxy_settings(proxy_settings const& ps)
{
asio::error_code ec;
error_code ec;
m_socks5_sock.close(ec);
m_tunnel_packets = false;
@ -256,7 +260,7 @@ void udp_socket::set_proxy_settings(proxy_settings const& ps)
}
}
void udp_socket::on_name_lookup(asio::error_code const& e, tcp::resolver::iterator i)
void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i)
{
if (e) return;
m_proxy_addr.address(i->endpoint().address());
@ -267,7 +271,7 @@ void udp_socket::on_name_lookup(asio::error_code const& e, tcp::resolver::iterat
void udp_socket::on_timeout()
{
asio::error_code ec;
error_code ec;
m_socks5_sock.close(ec);
m_connection_ticket = -1;
}
@ -275,13 +279,13 @@ void udp_socket::on_timeout()
void udp_socket::on_connect(int ticket)
{
m_connection_ticket = ticket;
asio::error_code ec;
error_code ec;
m_socks5_sock.open(m_proxy_addr.address().is_v4()?tcp::v4():tcp::v6(), ec);
m_socks5_sock.async_connect(tcp::endpoint(m_proxy_addr.address(), m_proxy_addr.port())
, boost::bind(&udp_socket::on_connected, this, _1));
}
void udp_socket::on_connected(asio::error_code const& e)
void udp_socket::on_connected(error_code const& e)
{
m_cc.done(m_connection_ticket);
m_connection_ticket = -1;
@ -308,7 +312,7 @@ void udp_socket::on_connected(asio::error_code const& e)
, boost::bind(&udp_socket::handshake1, this, _1));
}
void udp_socket::handshake1(asio::error_code const& e)
void udp_socket::handshake1(error_code const& e)
{
if (e) return;
@ -316,7 +320,7 @@ void udp_socket::handshake1(asio::error_code const& e)
, boost::bind(&udp_socket::handshake2, this, _1));
}
void udp_socket::handshake2(asio::error_code const& e)
void udp_socket::handshake2(error_code const& e)
{
if (e) return;
@ -336,7 +340,7 @@ void udp_socket::handshake2(asio::error_code const& e)
{
if (m_proxy_settings.username.empty())
{
asio::error_code ec;
error_code ec;
m_socks5_sock.close(ec);
return;
}
@ -353,13 +357,13 @@ void udp_socket::handshake2(asio::error_code const& e)
}
else
{
asio::error_code ec;
error_code ec;
m_socks5_sock.close(ec);
return;
}
}
void udp_socket::handshake3(asio::error_code const& e)
void udp_socket::handshake3(error_code const& e)
{
if (e) return;
@ -367,7 +371,7 @@ void udp_socket::handshake3(asio::error_code const& e)
, boost::bind(&udp_socket::handshake4, this, _1));
}
void udp_socket::handshake4(asio::error_code const& e)
void udp_socket::handshake4(error_code const& e)
{
if (e) return;
@ -400,7 +404,7 @@ void udp_socket::socks_forward_udp()
, boost::bind(&udp_socket::connect1, this, _1));
}
void udp_socket::connect1(asio::error_code const& e)
void udp_socket::connect1(error_code const& e)
{
if (e) return;
@ -408,7 +412,7 @@ void udp_socket::connect1(asio::error_code const& e)
, boost::bind(&udp_socket::connect2, this, _1));
}
void udp_socket::connect2(asio::error_code const& e)
void udp_socket::connect2(error_code const& e)
{
if (e) return;

View File

@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/parse_url.hpp"
#include "libtorrent/udp_tracker_connection.hpp"
#include "libtorrent/io.hpp"
@ -95,9 +96,17 @@ namespace libtorrent
std::string hostname;
int port;
char const* error;
using boost::tuples::ignore;
boost::tie(ignore, ignore, hostname, port, ignore) = parse_url_components(req.url);
boost::tie(ignore, ignore, hostname, port, ignore, error)
= parse_url_components(req.url);
if (error)
{
fail(-1, error);
return;
}
udp::resolver::query q(hostname, boost::lexical_cast<std::string>(port));
m_name_lookup.async_resolve(q
@ -113,7 +122,7 @@ namespace libtorrent
#endif
}
void udp_tracker_connection::name_lookup(asio::error_code const& error
void udp_tracker_connection::name_lookup(error_code const& error
, udp::resolver::iterator i)
{
if (error == asio::error::operation_aborted) return;
@ -156,7 +165,7 @@ namespace libtorrent
if (cb) cb->m_tracker_address = tcp::endpoint(target_address.address(), target_address.port());
m_target = target_address;
asio::error_code ec;
error_code ec;
m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
if (ec)
{
@ -179,13 +188,13 @@ namespace libtorrent
void udp_tracker_connection::close()
{
asio::error_code ec;
error_code ec;
m_socket.close();
m_name_lookup.cancel();
tracker_connection::close();
}
void udp_tracker_connection::on_receive(asio::error_code const& e
void udp_tracker_connection::on_receive(error_code const& e
, udp::endpoint const& ep, char const* buf, int size)
{
// ignore resposes before we've sent any requests
@ -305,7 +314,7 @@ namespace libtorrent
detail::write_int32(m_transaction_id, ptr); // transaction_id
TORRENT_ASSERT(ptr - buf == sizeof(buf));
asio::error_code ec;
error_code ec;
m_socket.send(m_target, buf, 16, ec);
m_state = action_connect;
++m_attempts;
@ -334,7 +343,7 @@ namespace libtorrent
out += 20;
TORRENT_ASSERT(out - buf == sizeof(buf));
asio::error_code ec;
error_code ec;
m_socket.send(m_target, buf, sizeof(buf), ec);
m_state = action_scrape;
++m_attempts;
@ -494,7 +503,7 @@ namespace libtorrent
}
#endif
asio::error_code ec;
error_code ec;
m_socket.send(m_target, buf, sizeof(buf), ec);
m_state = action_announce;
++m_attempts;

View File

@ -35,15 +35,20 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp"
#include "libtorrent/upnp.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/parse_url.hpp"
#include "libtorrent/xml_parse.hpp"
#include "libtorrent/connection_queue.hpp"
#include "libtorrent/enum_net.hpp"
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#if BOOST_VERSION < 103500
#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#else
#include <boost/asio/ip/host_name.hpp>
#include <boost/asio/ip/multicast.hpp>
#endif
#include <boost/thread/mutex.hpp>
#include <cstdlib>
@ -54,12 +59,6 @@ POSSIBILITY OF SUCH DAMAGE.
using boost::bind;
using namespace libtorrent;
namespace libtorrent
{
bool is_local(address const& a);
address guess_local_address(asio::io_service&);
}
upnp::upnp(io_service& ios, connection_queue& cc
, address const& listen_interface, std::string const& user_agent
, portmap_callback_t const& cb, bool ignore_nonrouters)
@ -73,7 +72,7 @@ upnp::upnp(io_service& ios, connection_queue& cc
, m_refresh_timer(ios)
, m_disabled(false)
, m_closing(false)
, m_ignore_outside_network(ignore_nonrouters)
, m_ignore_non_routers(ignore_nonrouters)
, m_cc(cc)
{
#ifdef TORRENT_UPNP_LOGGING
@ -103,7 +102,7 @@ void upnp::discover_device_impl()
"MX:3\r\n"
"\r\n\r\n";
asio::error_code ec;
error_code ec;
#ifdef TORRENT_DEBUG_UPNP
// simulate packet loss
if (m_retry_count & 1)
@ -215,7 +214,7 @@ void upnp::delete_mapping(int mapping)
}
}
void upnp::resend_request(asio::error_code const& e)
void upnp::resend_request(error_code const& e)
{
if (e) return;
@ -254,9 +253,10 @@ void upnp::resend_request(asio::error_code const& e)
m_log << time_now_string()
<< " ==> connecting to " << d.url << std::endl;
#endif
if (d.upnp_connection) d.upnp_connection->close();
d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2
, boost::ref(d))));
, boost::ref(d), _5)));
d.upnp_connection->get(d.url, seconds(30), 1);
}
catch (std::exception& e)
@ -306,8 +306,34 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0
*/
asio::error_code ec;
if (m_ignore_outside_network && !in_local_network(m_io_service, from.address(), ec))
error_code ec;
if (!in_local_network(m_io_service, from.address(), ec))
{
#ifdef TORRENT_UPNP_LOGGING
if (ec)
{
m_log << time_now_string() << " <== (" << from << ") error: "
<< ec.message() << std::endl;
}
else
{
m_log << time_now_string() << " <== (" << from << ") UPnP device "
"ignored because it's not on our local network ";
std::vector<ip_interface> const& net = enum_net_interfaces(m_io_service, ec);
for (std::vector<ip_interface>::const_iterator i = net.begin()
, end(net.end()); i != end; ++i)
{
m_log << "(" << i->interface_address << ", " << i->netmask << ") ";
}
m_log << std::endl;
}
#endif
return;
}
std::vector<ip_route> routes = enum_routes(m_io_service, ec);
if (m_ignore_non_routers && std::find_if(routes.begin(), routes.end()
, bind(&ip_route::gateway, _1) == from.address()) == routes.end())
{
// this upnp device is filtered because it's not in the
// list of configured routers
@ -319,13 +345,12 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
}
else
{
std::vector<ip_interface> const& net = enum_net_interfaces(m_io_service, ec);
m_log << time_now_string() << " <== (" << from << ") UPnP device "
"ignored because it's not on our network ";
for (std::vector<ip_interface>::const_iterator i = net.begin()
, end(net.end()); i != end; ++i)
"ignored because it's not a router on our network ";
for (std::vector<ip_route>::const_iterator i = routes.begin()
, end(routes.end()); i != end; ++i)
{
m_log << "(" << i->interface_address << ", " << i->netmask << ") ";
m_log << "(" << i->gateway << ", " << i->netmask << ") ";
}
m_log << std::endl;
}
@ -392,10 +417,21 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
std::string protocol;
std::string auth;
char const* error;
// we don't have this device in our list. Add it
boost::tie(protocol, auth, d.hostname, d.port, d.path)
boost::tie(protocol, auth, d.hostname, d.port, d.path, error)
= parse_url_components(d.url);
if (error)
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== (" << from << ") Rootdevice advertized an invalid url: '" << d.url
<< "'. " << error << ". Ignoring device" << std::endl;
#endif
return;
}
// ignore the auth here. It will be re-parsed
// by the http connection later
@ -453,7 +489,7 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
// just to make sure we find all devices
if (m_retry_count >= 4 && !m_devices.empty())
{
asio::error_code ec;
error_code ec;
m_broadcast_timer.cancel(ec);
for (std::set<rootdevice>::iterator i = m_devices.begin()
@ -473,9 +509,10 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
m_log << time_now_string()
<< " ==> connecting to " << d.url << std::endl;
#endif
if (d.upnp_connection) d.upnp_connection->close();
d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2
, boost::ref(d))));
, boost::ref(d), _5)));
d.upnp_connection->get(d.url, seconds(30), 1);
#ifndef BOOST_NO_EXCEPTIONS
}
@ -543,7 +580,7 @@ void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i)
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<s:Body><u:" << soap_action << " xmlns:u=\"" << d.service_namespace << "\">";
asio::error_code ec;
error_code ec;
soap << "<NewRemoteHost></NewRemoteHost>"
"<NewExternalPort>" << d.mapping[i].external_port << "</NewExternalPort>"
"<NewProtocol>" << (d.mapping[i].protocol == udp ? "UDP" : "TCP") << "</NewProtocol>"
@ -612,9 +649,10 @@ void upnp::update_map(rootdevice& d, int i)
return;
}
if (d.upnp_connection) d.upnp_connection->close();
d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, bind(&upnp::on_upnp_map_response, self(), _1, _2
, boost::ref(d), i), true
, boost::ref(d), i, _5), true
, bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i)));
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
@ -622,9 +660,10 @@ void upnp::update_map(rootdevice& d, int i)
}
else if (m.action == mapping_t::action_delete)
{
if (d.upnp_connection) d.upnp_connection->close();
d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, bind(&upnp::on_upnp_unmap_response, self(), _1, _2
, boost::ref(d), i), true
, boost::ref(d), i, _5), true
, bind(&upnp::delete_port_mapping, self(), boost::ref(d), i)));
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
, seconds(10), 1);
@ -732,13 +771,14 @@ namespace
}
void upnp::on_upnp_xml(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d)
void upnp::on_upnp_xml(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d
, http_connection& c)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(d.magic == 1337);
if (d.upnp_connection)
if (d.upnp_connection && d.upnp_connection.get() == &c)
{
d.upnp_connection->close();
d.upnp_connection.reset();
@ -816,7 +856,7 @@ void upnp::on_upnp_xml(asio::error_code const& e
d.control_url = s.control_url;
update_map(d, 0);
if (num_mappings() > 0) update_map(d, 0);
}
void upnp::disable(char const* msg)
@ -833,7 +873,7 @@ void upnp::disable(char const* msg)
}
m_devices.clear();
asio::error_code ec;
error_code ec;
m_broadcast_timer.cancel(ec);
m_refresh_timer.cancel(ec);
m_socket.close();
@ -891,13 +931,14 @@ namespace
}
void upnp::on_upnp_map_response(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d, int mapping)
void upnp::on_upnp_map_response(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d, int mapping
, http_connection& c)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(d.magic == 1337);
if (d.upnp_connection)
if (d.upnp_connection && d.upnp_connection.get() == &c)
{
d.upnp_connection->close();
d.upnp_connection.reset();
@ -1014,7 +1055,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
if (next_expire < time_now()
|| next_expire > m.expires)
{
asio::error_code ec;
error_code ec;
m_refresh_timer.expires_at(m.expires, ec);
m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1));
}
@ -1046,13 +1087,14 @@ void upnp::return_error(int mapping, int code)
m_callback(mapping, 0, error_string);
}
void upnp::on_upnp_unmap_response(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d, int mapping)
void upnp::on_upnp_unmap_response(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d, int mapping
, http_connection& c)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(d.magic == 1337);
if (d.upnp_connection)
if (d.upnp_connection && d.upnp_connection.get() == &c)
{
d.upnp_connection->close();
d.upnp_connection.reset();
@ -1093,7 +1135,7 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e
next(d, mapping);
}
void upnp::on_expire(asio::error_code const& e)
void upnp::on_expire(error_code const& e)
{
if (e) return;
@ -1125,7 +1167,7 @@ void upnp::on_expire(asio::error_code const& e)
}
if (next_expire != max_time())
{
asio::error_code ec;
error_code ec;
m_refresh_timer.expires_at(next_expire, ec);
m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1));
}
@ -1135,7 +1177,7 @@ void upnp::close()
{
mutex_t::scoped_lock l(m_mutex);
asio::error_code ec;
error_code ec;
m_refresh_timer.cancel(ec);
m_broadcast_timer.cancel(ec);
m_closing = true;
@ -1159,7 +1201,7 @@ void upnp::close()
j->action = mapping_t::action_delete;
m_mappings[j - d.mapping.begin()].protocol = none;
}
update_map(d, 0);
if (num_mappings() > 0) update_map(d, 0);
}
}

View File

@ -54,7 +54,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/extensions.hpp"
#include "libtorrent/extensions/metadata_transfer.hpp"
#include "libtorrent/extensions/ut_metadata.hpp"
#include "libtorrent/alert_types.hpp"
#ifdef TORRENT_STATS
#include "libtorrent/aux_/session_impl.hpp"
@ -89,39 +89,38 @@ namespace libtorrent { namespace
virtual boost::shared_ptr<peer_plugin> new_connection(
peer_connection* pc);
std::vector<char> const& metadata() const
buffer::const_interval metadata() const
{
TORRENT_ASSERT(m_torrent.valid_metadata());
if (m_metadata.empty())
if (!m_metadata)
{
bencode(std::back_inserter(m_metadata)
, m_torrent.torrent_file().create_info_metadata());
TORRENT_ASSERT(hasher(&m_metadata[0], m_metadata.size()).final()
m_metadata = m_torrent.torrent_file().metadata();
m_metadata_size = m_torrent.torrent_file().metadata_size();
TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final()
== m_torrent.torrent_file().info_hash());
}
TORRENT_ASSERT(!m_metadata.empty());
return m_metadata;
return buffer::const_interval(m_metadata.get(), m_metadata.get()
+ m_metadata_size);
}
bool received_metadata(char const* buf, int size, int piece, int total_size)
{
if (m_torrent.valid_metadata()) return false;
if (m_metadata.empty())
if (!m_metadata)
{
// verify the total_size
if (total_size <= 0 || total_size > 500 * 1024) return false;
m_metadata.resize(total_size);
m_metadata.reset(new char[total_size]);
m_requested_metadata.resize(div_round_up(total_size, 16 * 1024), 0);
m_metadata_size = total_size;
}
if (piece < 0 || piece >= int(m_requested_metadata.size()))
return false;
TORRENT_ASSERT(piece * 16 * 1024 + size <= int(m_metadata.size()));
TORRENT_ASSERT(piece * 16 * 1024 + size <= m_metadata_size);
std::memcpy(&m_metadata[piece * 16 * 1024], buf, size);
// mark this piece has 'have'
m_requested_metadata[piece] = (std::numeric_limits<int>::max)();
@ -133,7 +132,7 @@ namespace libtorrent { namespace
if (!have_all) return false;
hasher h;
h.update(&m_metadata[0], (int)m_metadata.size());
h.update(&m_metadata[0], m_metadata_size);
sha1_hash info_hash = h.final();
if (info_hash != m_torrent.torrent_file().info_hash())
@ -149,7 +148,8 @@ namespace libtorrent { namespace
return false;
}
entry metadata = bdecode(m_metadata.begin(), m_metadata.end());
lazy_entry metadata;
int ret = lazy_bdecode(m_metadata.get(), m_metadata.get() + m_metadata_size, metadata);
std::string error;
if (!m_torrent.set_metadata(metadata, error))
{
@ -191,7 +191,7 @@ namespace libtorrent { namespace
{
if (m_metadata_size > 0 || size <= 0 || size > 500 * 1024) return;
m_metadata_size = size;
m_metadata.resize(size);
m_metadata.reset(new char[size]);
m_requested_metadata.resize(div_round_up(size, 16 * 1024), 0);
}
@ -202,10 +202,10 @@ namespace libtorrent { namespace
// the metadata file while downloading it from
// peers, and while sending it.
// it is mutable because it's generated lazily
mutable std::vector<char> m_metadata;
mutable boost::shared_array<char> m_metadata;
int m_metadata_progress;
int m_metadata_size;
mutable int m_metadata_size;
// this vector keeps track of how many times each meatdata
// block has been requested
@ -231,7 +231,7 @@ namespace libtorrent { namespace
entry& messages = h["m"];
messages["ut_metadata"] = 15;
if (m_torrent.valid_metadata())
h["metadata_size"] = m_tp.metadata().size();
h["metadata_size"] = m_tp.metadata().left();
}
// called when the extension handshake from the other end is received
@ -273,14 +273,14 @@ namespace libtorrent { namespace
if (type == 1)
{
TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata());
e["total_size"] = m_tp.metadata().size();
e["total_size"] = m_tp.metadata().left();
int offset = piece * 16 * 1024;
metadata = &m_tp.metadata()[0] + offset;
metadata = m_tp.metadata().begin + offset;
metadata_piece_size = (std::min)(
int(m_tp.metadata().size() - offset), 16 * 1024);
int(m_tp.metadata().left() - offset), 16 * 1024);
TORRENT_ASSERT(metadata_piece_size > 0);
TORRENT_ASSERT(offset >= 0);
TORRENT_ASSERT(offset + metadata_piece_size <= int(m_tp.metadata().size()));
TORRENT_ASSERT(offset + metadata_piece_size <= int(m_tp.metadata().left()));
}
char msg[200];

View File

@ -113,7 +113,7 @@ namespace libtorrent { namespace
for (torrent::peer_iterator i = m_torrent.begin()
, end(m_torrent.end()); i != end; ++i)
{
peer_connection* peer = *i;
peer_connection* peer = *i;
if (!send_peer(*peer)) continue;
tcp::endpoint const& remote = peer->remote();

View File

@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/io.hpp"
#include "libtorrent/version.hpp"
#include "libtorrent/aux_/session_impl.hpp"
#include "libtorrent/parse_url.hpp"
using boost::bind;
using boost::shared_ptr;
@ -72,6 +73,8 @@ namespace libtorrent
// we want large blocks as well, so
// we can request more bytes at once
request_large_blocks(true);
set_upload_only(true);
// we only want left-over bandwidth
set_priority(0);
shared_ptr<torrent> tor = t.lock();
@ -95,8 +98,10 @@ namespace libtorrent
#endif
std::string protocol;
boost::tie(protocol, m_auth, m_host, m_port, m_path)
char const* error;
boost::tie(protocol, m_auth, m_host, m_port, m_path, error)
= parse_url_components(url);
TORRENT_ASSERT(error == 0);
if (!m_auth.empty())
m_auth = base64encode(m_auth);
@ -315,7 +320,7 @@ namespace libtorrent
}
}
void web_peer_connection::on_receive(asio::error_code const& error
void web_peer_connection::on_receive(error_code const& error
, std::size_t bytes_transferred)
{
INVARIANT_CHECK;
@ -349,7 +354,7 @@ namespace libtorrent
if (error)
{
disconnect("failed to parse HTTP response");
disconnect("failed to parse HTTP response", 2);
return;
}
@ -380,7 +385,7 @@ namespace libtorrent
m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url()
, error_msg));
}
disconnect(error_msg.c_str());
disconnect(error_msg.c_str(), 1);
return;
}
if (!m_parser.header_finished()) break;
@ -406,7 +411,7 @@ namespace libtorrent
{
// we should not try this server again.
t->remove_url_seed(m_url);
disconnect("got HTTP redirection status without location header");
disconnect("got HTTP redirection status without location header", 2);
return;
}
@ -430,7 +435,7 @@ namespace libtorrent
std::stringstream msg;
msg << "got invalid HTTP redirection location (\"" << location << "\") "
"expected it to end with: " << path;
disconnect(msg.str().c_str());
disconnect(msg.str().c_str(), 2);
return;
}
location.resize(i);
@ -475,7 +480,7 @@ namespace libtorrent
t->remove_url_seed(m_url);
std::stringstream msg;
msg << "invalid range in HTTP response: " << range_str.str();
disconnect(msg.str().c_str());
disconnect(msg.str().c_str(), 2);
return;
}
// the http range is inclusive
@ -489,7 +494,7 @@ namespace libtorrent
{
// we should not try this server again.
t->remove_url_seed(m_url);
disconnect("no content-length in HTTP response");
disconnect("no content-length in HTTP response", 2);
return;
}
}
@ -501,7 +506,7 @@ namespace libtorrent
if (m_requests.empty() || m_file_requests.empty())
{
disconnect("unexpected HTTP response");
disconnect("unexpected HTTP response", 2);
return;
}
@ -534,7 +539,7 @@ namespace libtorrent
{
// this means the end of the incoming request ends _before_ the
// first expected byte (fs + m_piece.size())
disconnect("invalid range in HTTP response");
disconnect("invalid range in HTTP response", 2);
return;
}
@ -662,7 +667,7 @@ namespace libtorrent
}
// throws exception when the client should be disconnected
void web_peer_connection::on_sent(asio::error_code const& error
void web_peer_connection::on_sent(error_code const& error
, std::size_t bytes_transferred)
{
INVARIANT_CHECK;

View File

@ -85,15 +85,10 @@ if not os.environ.has_key("CPP"):
# The libtorrent extension
_extra_compile_args = [
"-DHAVE_INCLUDE_LIBTORRENT_ASIO____ASIO_HPP=1",
"-DHAVE_INCLUDE_LIBTORRENT_ASIO_SSL_STREAM_HPP=1",
"-DHAVE_INCLUDE_LIBTORRENT_ASIO_IP_TCP_HPP=1",
"-DHAVE_PTHREAD=1",
"-DTORRENT_USE_OPENSSL=1",
"-DHAVE_SSL=1",
"-O2",
"-D_FILE_OFFSET_BITS=64",
"-DNDEBUG"
"-DNDEBUG",
]
if windows_check():