added the ability to limit the number of half-open tcp connections

This commit is contained in:
Arvid Norberg 2005-11-02 16:28:39 +00:00
parent 3f36dd0395
commit bcbe165aee
15 changed files with 351 additions and 154 deletions

View File

@ -1,3 +1,8 @@
* added the ability to limit the number of simultaneous half-open
TCP connections. Flags in peer_info has been added.
release 0.9.1
* strings that are invalid utf-8 strings are now decoded with the * strings that are invalid utf-8 strings are now decoded with the
local codepage on windows local codepage on windows
* added the ability to build libtorrent both as a shared library * added the ability to build libtorrent both as a shared library

View File

@ -1,41 +1,14 @@
<!DOCTYPE html PUBLIC <?xml version="1.0" encoding="utf-8" ?>
"-//W3C//DTD XHTML 1.0 Strict//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<html>
<head> <head>
<title>Rasterbar Software | Products | libtorrent</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta name="generator" content="Docutils 0.3.8: http://docutils.sourceforge.net/" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" /> <title>libtorrent manual</title>
<link rel="stylesheet" type="text/css" href="../../css/rst.css" /> <meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head> </head>
<body> <body>
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
<!-- <li><a href="/about.html">About</a></li> -->
</ul>
</div>
<div id="header">
<h1><span>Rasterbar Software</span></h1>
<h2><span>Software developement and consulting</span></h2>
<span>
</span>
</div>
<div id="main">
<div class="document" id="libtorrent-manual"> <div class="document" id="libtorrent-manual">
<h1 class="title">libtorrent manual</h1> <h1 class="title">libtorrent manual</h1>
<table class="docinfo" frame="void" rules="none"> <table class="docinfo" frame="void" rules="none">
@ -1800,7 +1773,9 @@ struct peer_info
remote_interested = 0x4, remote_interested = 0x4,
remote_choked = 0x8, remote_choked = 0x8,
supports_extensions = 0x10, supports_extensions = 0x10,
local_connection = 0x20 local_connection = 0x20,
connecting = 0x40,
queued = 0x80
}; };
unsigned int flags; unsigned int flags;
address ip; address ip;
@ -1858,6 +1833,15 @@ listen port open, and that port is the same as in the
peer connection was opened by this peer connecting to peer connection was opened by this peer connecting to
us.</td> us.</td>
</tr> </tr>
<tr><td><tt class="docutils literal"><span class="pre">connecting</span></tt></td>
<td>The connection is in a half-open state (i.e. it is
being connected).</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">queued</span></tt></td>
<td>The connection is currently queued for a connection
attempt. This may happen if there is a limit set on
the number of half-open TCP connections.</td>
</tr>
</tbody> </tbody>
</table> </table>
<p>The <tt class="docutils literal"><span class="pre">ip</span></tt> field is the IP-address to this peer. Its type is a wrapper around the <p>The <tt class="docutils literal"><span class="pre">ip</span></tt> field is the IP-address to this peer. Its type is a wrapper around the
@ -3266,13 +3250,5 @@ scripts.</p>
<p><a class="reference" href="http://sourceforge.net"><img alt="sf_logo" src="http://sourceforge.net/sflogo.php?group_id=7994" /></a></p> <p><a class="reference" href="http://sourceforge.net"><img alt="sf_logo" src="http://sourceforge.net/sflogo.php?group_id=7994" /></a></p>
</div> </div>
</div> </div>
</div>
<div id="footer">
<span>Copyright &copy; 2005 Rasterbar Software.</span>
</div>
</div>
</body> </body>
</html> </html>

View File

@ -1744,7 +1744,9 @@ It contains the following fields::
remote_interested = 0x4, remote_interested = 0x4,
remote_choked = 0x8, remote_choked = 0x8,
supports_extensions = 0x10, supports_extensions = 0x10,
local_connection = 0x20 local_connection = 0x20,
connecting = 0x40,
queued = 0x80
}; };
unsigned int flags; unsigned int flags;
address ip; address ip;
@ -1792,6 +1794,13 @@ any combination of the enums above. The following table describes each flag:
| | peer connection was opened by this peer connecting to | | | peer connection was opened by this peer connecting to |
| | us. | | | us. |
+-------------------------+-------------------------------------------------------+ +-------------------------+-------------------------------------------------------+
| ``connecting`` | The connection is in a half-open state (i.e. it is |
| | being connected). |
+-------------------------+-------------------------------------------------------+
| ``queued`` | The connection is currently queued for a connection |
| | attempt. This may happen if there is a limit set on |
| | the number of half-open TCP connections. |
+-------------------------+-------------------------------------------------------+
__ extension_protocol.html __ extension_protocol.html

View File

@ -1,41 +1,14 @@
<!DOCTYPE html PUBLIC <?xml version="1.0" encoding="utf-8" ?>
"-//W3C//DTD XHTML 1.0 Strict//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<html>
<head> <head>
<title>Rasterbar Software | Products | libtorrent</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta name="generator" content="Docutils 0.3.8: http://docutils.sourceforge.net/" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" /> <title>Bittorrent udp-tracker protocol extension</title>
<link rel="stylesheet" type="text/css" href="../../css/rst.css" /> <meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head> </head>
<body> <body>
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
<!-- <li><a href="/about.html">About</a></li> -->
</ul>
</div>
<div id="header">
<h1><span>Rasterbar Software</span></h1>
<h2><span>Software developement and consulting</span></h2>
<span>
</span>
</div>
<div id="main">
<div class="document" id="bittorrent-udp-tracker-protocol-extension"> <div class="document" id="bittorrent-udp-tracker-protocol-extension">
<h1 class="title">Bittorrent udp-tracker protocol extension</h1> <h1 class="title">Bittorrent udp-tracker protocol extension</h1>
<table class="docinfo" frame="void" rules="none"> <table class="docinfo" frame="void" rules="none">
@ -529,13 +502,5 @@ from the 20 bytes hash calculated.</td>
<p>Protocol designed by Olaf van der Spek</p> <p>Protocol designed by Olaf van der Spek</p>
</div> </div>
</div> </div>
</div>
<div id="footer">
<span>Copyright &copy; 2005 Rasterbar Software.</span>
</div>
</div>
</body> </body>
</html> </html>

View File

@ -273,7 +273,18 @@ void print_peer_info(std::ostream& out, std::vector<libtorrent::peer_info> const
out << progress_bar(0.f, 15); out << progress_bar(0.f, 15);
} }
out << " " << identify_client(i->id) << "\n"; if (i->flags & peer_info::connecting)
{
out << esc("31") << " connecting to peer" << esc("0") << "\n";
}
else if (i->flags & peer_info::queued)
{
out << esc("33") << " queued" << esc("0") << "\n";
}
else
{
out << " " << identify_client(i->id) << "\n";
}
} }
} }
@ -403,6 +414,7 @@ int main(int ac, char* av[])
float preferred_ratio; float preferred_ratio;
int download_limit; int download_limit;
int upload_limit; int upload_limit;
int half_open_limit;
std::string save_path_str; std::string save_path_str;
std::string log_level; std::string log_level;
std::string ip_filter_file; std::string ip_filter_file;
@ -447,6 +459,8 @@ int main(int ac, char* av[])
("poll-interval,t", po::value<int>(&poll_interval)->default_value(2) ("poll-interval,t", po::value<int>(&poll_interval)->default_value(2)
, "if a directory is being monitored, this is the interval (given " , "if a directory is being monitored, this is the interval (given "
"in seconds) between two refreshes of the directory listing") "in seconds) between two refreshes of the directory listing")
("half-open-limit,a", po::value<int>(&half_open_limit)->default_value(-1)
, "Sets the maximum number of simultaneous half-open tcp connections")
; ;
po::positional_options_description p; po::positional_options_description p;
@ -466,6 +480,7 @@ int main(int ac, char* av[])
if (download_limit <= 0) download_limit = -1; if (download_limit <= 0) download_limit = -1;
if (upload_limit <= 0) upload_limit = -1; if (upload_limit <= 0) upload_limit = -1;
if (poll_interval < 2) poll_interval = 2; if (poll_interval < 2) poll_interval = 2;
if (half_open_limit < 1) half_open_limit = -1;
if (!monitor_dir.empty() && !exists(monitor_dir)) if (!monitor_dir.empty() && !exists(monitor_dir))
{ {
std::cerr << "The monitor directory doesn't exist: " << monitor_dir.string() << std::endl; std::cerr << "The monitor directory doesn't exist: " << monitor_dir.string() << std::endl;
@ -501,6 +516,7 @@ int main(int ac, char* av[])
handles_t handles; handles_t handles;
session ses; session ses;
ses.set_max_half_open_connections(half_open_limit);
ses.set_download_rate_limit(download_limit); ses.set_download_rate_limit(download_limit);
ses.set_upload_rate_limit(upload_limit); ses.set_upload_rate_limit(upload_limit);
ses.listen_on(std::make_pair(listen_port, listen_port + 10)); ses.listen_on(std::make_pair(listen_port, listen_port + 10));
@ -662,7 +678,7 @@ int main(int ac, char* av[])
if (torrent_finished_alert* p = dynamic_cast<torrent_finished_alert*>(a.get())) if (torrent_finished_alert* p = dynamic_cast<torrent_finished_alert*>(a.get()))
{ {
// limit the bandwidth for all seeding torrents // limit the bandwidth for all seeding torrents
p->handle.set_max_connections(10); p->handle.set_max_connections(60);
//p->handle.set_max_uploads(5); //p->handle.set_max_uploads(5);
//p->handle.set_upload_limit(10000); //p->handle.set_upload_limit(10000);
@ -755,7 +771,8 @@ int main(int ac, char* av[])
out << "info-hash: " << h.info_hash() << "\n"; out << "info-hash: " << h.info_hash() << "\n";
boost::posix_time::time_duration t = s.next_announce; boost::posix_time::time_duration t = s.next_announce;
out << "next announce: " << esc("37") << boost::posix_time::to_simple_string(t) << esc("0") << "\n"; out << "next announce: " << esc("37") <<
boost::posix_time::to_simple_string(t) << esc("0") << "\n";
out << "tracker: " << s.current_tracker << "\n"; out << "tracker: " << s.current_tracker << "\n";
} }

View File

@ -86,7 +86,9 @@ namespace libtorrent
protocol_error(const std::string& msg): std::runtime_error(msg) {}; protocol_error(const std::string& msg): std::runtime_error(msg) {};
}; };
class TORRENT_EXPORT peer_connection: public boost::noncopyable class TORRENT_EXPORT peer_connection
: public boost::noncopyable
, public boost::enable_shared_from_this<peer_connection>
{ {
friend class invariant_access; friend class invariant_access;
public: public:
@ -98,7 +100,8 @@ namespace libtorrent
detail::session_impl& ses detail::session_impl& ses
, selector& sel , selector& sel
, torrent* t , torrent* t
, boost::shared_ptr<libtorrent::socket> s); , boost::shared_ptr<libtorrent::socket> s
, address const& remote);
// with this constructor we have been contacted and we still don't // with this constructor we have been contacted and we still don't
// know which torrent the connection belongs to // know which torrent the connection belongs to
@ -123,7 +126,7 @@ namespace libtorrent
// work to do. // work to do.
void send_data(); void send_data();
void receive_data(); void receive_data();
// tells if this connection has data it want to send // tells if this connection has data it want to send
// and has enough upload bandwidth quota left to send it. // and has enough upload bandwidth quota left to send it.
bool can_write() const; bool can_write() const;
@ -171,6 +174,7 @@ namespace libtorrent
void second_tick(); void second_tick();
boost::shared_ptr<libtorrent::socket> get_socket() const { return m_socket; } boost::shared_ptr<libtorrent::socket> get_socket() const { return m_socket; }
address const& remote() const { return m_remote; }
const peer_id& get_peer_id() const { return m_peer_id; } const peer_id& get_peer_id() const { return m_peer_id; }
const std::vector<bool>& get_bitfield() const; const std::vector<bool>& get_bitfield() const;
@ -182,6 +186,27 @@ namespace libtorrent
void disconnect(); void disconnect();
bool is_disconnecting() const { return m_disconnecting; } 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 connection_complete();
// returns true if this connection is still waiting to
// finish the connection attempt
bool is_connecting() const { return m_connecting; }
// returns true if the socket of this peer hasn't been
// attempted to connect yet (i.e. it's queued for
// connection attempt).
bool is_queued() const { return m_queued; }
// called when it's time for this peer_conncetion to actually
// initiate the tcp connection. This may be postponed until
// the library isn't using up the limitation of half-open
// tcp connections.
void connect();
// This is called for every peer right after the upload // This is called for every peer right after the upload
// bandwidth has been distributed among them // bandwidth has been distributed among them
// It will reset the used bandwidth to 0 and // It will reset the used bandwidth to 0 and
@ -376,6 +401,7 @@ namespace libtorrent
// peer's socket from the writability monitor list. // peer's socket from the writability monitor list.
selector& m_selector; selector& m_selector;
boost::shared_ptr<libtorrent::socket> m_socket; boost::shared_ptr<libtorrent::socket> m_socket;
address m_remote;
// this is the torrent this connection is // this is the torrent this connection is
// associated with. If the connection is an // associated with. If the connection is an
@ -529,8 +555,9 @@ namespace libtorrent
// this was the request we sent // this was the request we sent
std::pair<int, int> m_last_metadata_request; std::pair<int, int> m_last_metadata_request;
// this is true until this socket has received // this is true until this socket has become
// data for the first time. While connecting // writable for the first time (i.e. the
// connection completed). While connecting
// the timeout will not be triggered. This is // the timeout will not be triggered. This is
// because windows XP SP2 may delay connection // because windows XP SP2 may delay connection
// attempts, which means that the connection // attempts, which means that the connection
@ -538,6 +565,11 @@ namespace libtorrent
// time out is reached. // time out is reached.
bool m_connecting; 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;
// the number of bytes of metadata we have received // the number of bytes of metadata we have received
// so far from this per, only counting the current // so far from this per, only counting the current
// request. Any previously finished requests // request. Any previously finished requests

View File

@ -51,7 +51,9 @@ namespace libtorrent
remote_interested = 0x4, remote_interested = 0x4,
remote_choked = 0x8, remote_choked = 0x8,
supports_extensions = 0x10, supports_extensions = 0x10,
local_connection = 0x20 local_connection = 0x20,
connecting = 0x40,
queued = 0x80
}; };
unsigned int flags; unsigned int flags;
address ip; address ip;

View File

@ -172,8 +172,11 @@ namespace libtorrent
friend class invariant_access; friend class invariant_access;
// TODO: maybe this should be changed to a sorted vector // TODO: maybe this should be changed to a sorted vector
// using lower_bound? // using lower_bound?
typedef std::map<boost::shared_ptr<socket>, boost::shared_ptr<peer_connection> > connection_map; typedef std::map<boost::shared_ptr<socket>, boost::shared_ptr<peer_connection> >
connection_map;
typedef std::map<sha1_hash, boost::shared_ptr<torrent> > torrent_map; typedef std::map<sha1_hash, boost::shared_ptr<torrent> > torrent_map;
typedef std::deque<boost::shared_ptr<peer_connection> >
connection_queue;
session_impl( session_impl(
std::pair<int, int> listen_port_range std::pair<int, int> listen_port_range
@ -193,16 +196,31 @@ namespace libtorrent
tracker_manager m_tracker_manager; tracker_manager m_tracker_manager;
torrent_map m_torrents; torrent_map m_torrents;
// this will see if there are any pending connection attempts
// and in that case initiate new connections until the limit
// is reached.
void process_connection_queue();
// this maps sockets to their peer_connection // this maps sockets to their peer_connection
// object. It is the complete list of all connected // object. It is the complete list of all connected
// peers. // peers.
connection_map m_connections; connection_map m_connections;
// this is a list of half-open tcp connections
// (only outgoing connections)
connection_map m_half_open;
// this is a queue of pending outgoing connections. If the
// list of half-open connections is full (given the global
// limit), new outgoing connections are put on this queue,
// waiting for one slot in the half-open queue to open up.
connection_queue m_connection_queue;
// this is a list of iterators into the m_connections map // this is a list of iterators into the m_connections map
// that should be disconnected as soon as possible. // that should be disconnected as soon as possible.
// It is used to delay disconnections to avoid troubles // It is used to delay disconnections to avoid troubles
// in loops that iterate over them. // in loops that iterate over them.
std::vector<connection_map::iterator> m_disconnect_peer; std::vector<boost::shared_ptr<peer_connection> > m_disconnect_peer;
// filters incomming connections // filters incomming connections
ip_filter m_ip_filter; ip_filter m_ip_filter;
@ -253,6 +271,9 @@ namespace libtorrent
int m_download_rate; int m_download_rate;
int m_max_uploads; int m_max_uploads;
int m_max_connections; int m_max_connections;
// the number of simultaneous half-open tcp
// connections libtorrent will have.
int m_half_open_limit;
// statistics gathered from all torrents. // statistics gathered from all torrents.
stat m_stat; stat m_stat;
@ -379,6 +400,7 @@ namespace libtorrent
void set_download_rate_limit(int bytes_per_second); void set_download_rate_limit(int bytes_per_second);
void set_max_uploads(int limit); void set_max_uploads(int limit);
void set_max_connections(int limit); void set_max_connections(int limit);
void set_max_half_open_connections(int limit);
std::auto_ptr<alert> pop_alert(); std::auto_ptr<alert> pop_alert();
void set_severity_level(alert::severity_t s); void set_severity_level(alert::severity_t s);

View File

@ -133,7 +133,7 @@ namespace libtorrent
void set_blocking(bool blocking); void set_blocking(bool blocking);
bool is_blocking() { return m_blocking; } bool is_blocking() { return m_blocking; }
const address& sender() const { return m_sender; } const address& sender() const { assert(m_sender != address()); return m_sender; }
address name() const; address name() const;
void listen(libtorrent::address const& iface, int queue); void listen(libtorrent::address const& iface, int queue);

View File

@ -176,6 +176,7 @@ namespace libtorrent
torrent_status status() const; torrent_status status() const;
void use_interface(const char* net_interface); void use_interface(const char* net_interface);
address const& interface() const { return m_net_interface; }
peer_connection& connect_to_peer(const address& a); peer_connection& connect_to_peer(const address& a);
void set_ratio(float ratio) void set_ratio(float ratio)

View File

@ -77,7 +77,8 @@ namespace libtorrent
detail::session_impl& ses detail::session_impl& ses
, selector& sel , selector& sel
, torrent* t , torrent* t
, boost::shared_ptr<libtorrent::socket> s) , boost::shared_ptr<libtorrent::socket> s
, address const& remote)
: :
#ifndef NDEBUG #ifndef NDEBUG
m_last_choke(boost::posix_time::second_clock::universal_time() m_last_choke(boost::posix_time::second_clock::universal_time()
@ -92,11 +93,12 @@ namespace libtorrent
, m_last_sent(second_clock::universal_time()) , m_last_sent(second_clock::universal_time())
, m_selector(sel) , m_selector(sel)
, m_socket(s) , m_socket(s)
, m_remote(remote)
, m_torrent(t) , m_torrent(t)
, m_attached_to_torrent(true) , m_attached_to_torrent(true)
, m_ses(ses) , m_ses(ses)
, m_active(true) , m_active(true)
, m_writability_monitored(false) , m_writability_monitored(true)
, m_readability_monitored(true) , m_readability_monitored(true)
, m_peer_interested(false) , m_peer_interested(false)
, m_peer_choked(true) , m_peer_choked(true)
@ -119,9 +121,11 @@ namespace libtorrent
boost::gregorian::date(1970, boost::date_time::Jan, 1) boost::gregorian::date(1970, boost::date_time::Jan, 1)
, boost::posix_time::seconds(0)) , boost::posix_time::seconds(0))
, m_waiting_metadata_request(false) , m_waiting_metadata_request(false)
, m_connecting(false) , m_connecting(true)
, m_queued(true)
, m_metadata_progress(0) , m_metadata_progress(0)
{ {
m_selector.monitor_writability(m_socket);
INVARIANT_CHECK; INVARIANT_CHECK;
// these numbers are used the first second of connection. // these numbers are used the first second of connection.
@ -158,8 +162,8 @@ namespace libtorrent
assert(m_torrent != 0); assert(m_torrent != 0);
#ifdef TORRENT_VERBOSE_LOGGING #ifdef TORRENT_VERBOSE_LOGGING
m_logger = m_ses.create_log(s->sender().as_string() + "_" m_logger = m_ses.create_log(m_remote.as_string() + "_"
+ boost::lexical_cast<std::string>(s->sender().port)); + boost::lexical_cast<std::string>(m_remote.port));
(*m_logger) << "*** OUTGOING CONNECTION\n"; (*m_logger) << "*** OUTGOING CONNECTION\n";
#endif #endif
@ -202,6 +206,7 @@ namespace libtorrent
, m_last_sent(second_clock::universal_time()) , m_last_sent(second_clock::universal_time())
, m_selector(sel) , m_selector(sel)
, m_socket(s) , m_socket(s)
, m_remote(s->sender())
, m_torrent(0) , m_torrent(0)
, m_attached_to_torrent(false) , m_attached_to_torrent(false)
, m_ses(ses) , m_ses(ses)
@ -230,7 +235,8 @@ namespace libtorrent
boost::gregorian::date(1970, boost::date_time::Jan, 1) boost::gregorian::date(1970, boost::date_time::Jan, 1)
, boost::posix_time::seconds(0)) , boost::posix_time::seconds(0))
, m_waiting_metadata_request(false) , m_waiting_metadata_request(false)
, m_connecting(true) , m_connecting(false)
, m_queued(false)
, m_metadata_progress(0) , m_metadata_progress(0)
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
@ -274,8 +280,9 @@ namespace libtorrent
std::fill(m_peer_id.begin(), m_peer_id.end(), 0); std::fill(m_peer_id.begin(), m_peer_id.end(), 0);
#ifdef TORRENT_VERBOSE_LOGGING #ifdef TORRENT_VERBOSE_LOGGING
m_logger = m_ses.create_log(s->sender().as_string() + "_" assert(m_socket->sender() == remote());
+ boost::lexical_cast<std::string>(s->sender().port)); m_logger = m_ses.create_log(remote().as_string() + "_"
+ boost::lexical_cast<std::string>(remote().port));
(*m_logger) << "*** INCOMING CONNECTION\n"; (*m_logger) << "*** INCOMING CONNECTION\n";
#endif #endif
@ -374,7 +381,7 @@ namespace libtorrent
if (m_torrent) if (m_torrent)
{ {
torrent::peer_iterator i = m_torrent->m_connections.find( torrent::peer_iterator i = m_torrent->m_connections.find(
get_socket()->sender()); remote());
assert(i == m_torrent->m_connections.end()); assert(i == m_torrent->m_connections.end());
} }
} }
@ -939,7 +946,7 @@ namespace libtorrent
m_torrent->alerts().post_alert(invalid_request_alert( m_torrent->alerts().post_alert(invalid_request_alert(
r r
, m_torrent->get_handle() , m_torrent->get_handle()
, m_socket->sender() , m_remote
, m_peer_id , m_peer_id
, "peer sent an illegal request, ignoring")); , "peer sent an illegal request, ignoring"));
} }
@ -1058,7 +1065,7 @@ namespace libtorrent
{ {
m_torrent->alerts().post_alert( m_torrent->alerts().post_alert(
peer_error_alert( peer_error_alert(
m_socket->sender() m_remote
, m_peer_id , m_peer_id
, "got a block that was not requested")); , "got a block that was not requested"));
} }
@ -1077,7 +1084,7 @@ namespace libtorrent
bool was_finished = picker.num_filtered() + m_torrent->num_pieces() bool was_finished = picker.num_filtered() + m_torrent->num_pieces()
== m_torrent->torrent_file().num_pieces(); == m_torrent->torrent_file().num_pieces();
picker.mark_as_finished(block_finished, m_socket->sender()); picker.mark_as_finished(block_finished, m_remote);
m_torrent->get_policy().block_finished(*this, block_finished); m_torrent->get_policy().block_finished(*this, block_finished);
@ -1297,7 +1304,7 @@ namespace libtorrent
m_torrent->alerts().post_alert( m_torrent->alerts().post_alert(
chat_message_alert( chat_message_alert(
m_torrent->get_handle() m_torrent->get_handle()
, m_socket->sender(), str)); , m_remote, str));
} }
} }
@ -1435,7 +1442,7 @@ namespace libtorrent
<< "<== LISTEN_PORT [ port: " << port << " ]\n"; << "<== LISTEN_PORT [ port: " << port << " ]\n";
#endif #endif
address adr = m_socket->sender(); address adr = m_remote;
adr.port = port; adr.port = port;
m_torrent->get_policy().peer_from_tracker(adr, m_peer_id); m_torrent->get_policy().peer_from_tracker(adr, m_peer_id);
} }
@ -1450,14 +1457,17 @@ namespace libtorrent
void peer_connection::disconnect() void peer_connection::disconnect()
{ {
if (m_disconnecting) return; if (m_disconnecting) return;
detail::session_impl::connection_map::iterator i
= m_ses.m_connections.find(m_socket); assert((m_ses.m_connections.find(m_socket) != m_ses.m_connections.end())
== !m_connecting);
m_disconnecting = true; m_disconnecting = true;
assert(i != m_ses.m_connections.end());
assert(std::find(m_ses.m_disconnect_peer.begin() assert(std::find(m_ses.m_disconnect_peer.begin()
, m_ses.m_disconnect_peer.end(), i) , m_ses.m_disconnect_peer.end(), shared_from_this())
== m_ses.m_disconnect_peer.end()); == m_ses.m_disconnect_peer.end());
m_ses.m_disconnect_peer.push_back(i);
m_ses.m_disconnect_peer.push_back(shared_from_this());
} }
bool peer_connection::dispatch_message(int received) bool peer_connection::dispatch_message(int received)
@ -1634,7 +1644,7 @@ namespace libtorrent
assert(block.block_index < m_torrent->torrent_file().piece_size(block.piece_index)); assert(block.block_index < m_torrent->torrent_file().piece_size(block.piece_index));
assert(!m_torrent->picker().is_downloading(block)); assert(!m_torrent->picker().is_downloading(block));
m_torrent->picker().mark_as_downloading(block, m_socket->sender()); m_torrent->picker().mark_as_downloading(block, m_remote);
m_request_queue.push_back(block); m_request_queue.push_back(block);
send_block_requests(); send_block_requests();
} }
@ -2141,7 +2151,6 @@ namespace libtorrent
if (received > 0) if (received > 0)
{ {
m_connecting = false;
m_last_receive = second_clock::universal_time(); m_last_receive = second_clock::universal_time();
m_recv_pos += received; m_recv_pos += received;
@ -2426,6 +2435,46 @@ namespace libtorrent
return m_dl_bandwidth_quota.left() > 0; return m_dl_bandwidth_quota.left() > 0;
} }
void peer_connection::connect()
{
INVARIANT_CHECK;
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_ses.m_logger) << "CONNECT: " << m_remote.as_string() << "\n";
#endif
m_queued = false;
assert(m_connecting);
assert(associated_torrent());
m_socket->connect(m_remote, associated_torrent()->interface());
if (m_torrent->alerts().should_post(alert::debug))
{
m_torrent->alerts().post_alert(peer_error_alert(
m_remote, m_peer_id, "connecting to peer"));
}
}
void peer_connection::connection_complete()
{
INVARIANT_CHECK;
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_ses.m_logger) << "COMPLETED: " << m_remote.as_string() << "\n";
#endif
m_connecting = false;
// this means the connection just succeeded
// assert(!can_write());
// assert(m_writability_monitored);
if (!can_write() && m_writability_monitored)
{
m_writability_monitored = false;
m_selector.remove_writable(m_socket);
}
}
// -------------------------- // --------------------------
// SEND DATA // SEND DATA
// -------------------------- // --------------------------
@ -2435,6 +2484,7 @@ namespace libtorrent
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
assert(!m_connecting);
assert(!m_disconnecting); assert(!m_disconnecting);
assert(m_socket->is_writable()); assert(m_socket->is_writable());
assert(can_write()); assert(can_write());
@ -2585,7 +2635,7 @@ namespace libtorrent
#ifndef NDEBUG #ifndef NDEBUG
void peer_connection::check_invariant() const void peer_connection::check_invariant() const
{ {
assert(can_write() == m_selector.is_writability_monitored(m_socket)); assert((can_write() || m_connecting) == m_selector.is_writability_monitored(m_socket));
/* /*
assert(m_num_pieces == std::count( assert(m_num_pieces == std::count(

View File

@ -116,8 +116,9 @@ namespace
// the number of blocks we want, but it will try to make the picked // the number of blocks we want, but it will try to make the picked
// blocks be from whole pieces, possibly by returning more blocks // blocks be from whole pieces, possibly by returning more blocks
// than we requested. // than we requested.
assert(c.remote() == c.get_socket()->sender());
p.pick_pieces(c.get_bitfield(), interesting_pieces p.pick_pieces(c.get_bitfield(), interesting_pieces
, num_requests, prefer_whole_pieces, c.get_socket()->sender()); , num_requests, prefer_whole_pieces, c.remote());
// this vector is filled with the interesting pieces // this vector is filled with the interesting pieces
// that some other peer is currently downloading // that some other peer is currently downloading
@ -866,14 +867,15 @@ namespace libtorrent
// TODO: only allow _one_ connection to use this // TODO: only allow _one_ connection to use this
// override at a time // override at a time
assert(c.remote() == c.get_socket()->sender());
if (m_torrent->num_peers() >= m_torrent->m_connections_quota.given if (m_torrent->num_peers() >= m_torrent->m_connections_quota.given
&& c.get_socket()->sender().ip() != m_torrent->current_tracker().ip()) && c.remote().ip() != m_torrent->current_tracker().ip())
{ {
throw protocol_error("too many connections, refusing incoming connection"); // cause a disconnect throw protocol_error("too many connections, refusing incoming connection"); // cause a disconnect
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (c.get_socket()->sender().ip() == m_torrent->current_tracker().ip()) if (c.remote().ip() == m_torrent->current_tracker().ip())
{ {
m_torrent->debug_log("overriding connection limit for tracker NAT-check"); m_torrent->debug_log("overriding connection limit for tracker NAT-check");
} }
@ -882,7 +884,7 @@ namespace libtorrent
std::vector<peer>::iterator i = std::find_if( std::vector<peer>::iterator i = std::find_if(
m_peers.begin() m_peers.begin()
, m_peers.end() , m_peers.end()
, match_peer_ip(c.get_socket()->sender())); , match_peer_ip(c.remote()));
if (i == m_peers.end()) if (i == m_peers.end())
{ {
@ -892,8 +894,10 @@ namespace libtorrent
// we don't have ny info about this peer. // we don't have ny info about this peer.
// add a new entry // add a new entry
peer p(c.get_socket()->sender(), peer::not_connectable); assert(c.remote() == c.get_socket()->sender());
peer p(c.remote(), peer::not_connectable);
m_peers.push_back(p); m_peers.push_back(p);
check_invariant();
i = m_peers.end()-1; i = m_peers.end()-1;
} }
else else
@ -909,6 +913,7 @@ namespace libtorrent
i->prev_amount_download = 0; i->prev_amount_download = 0;
i->prev_amount_upload = 0; i->prev_amount_upload = 0;
i->connection = &c; i->connection = &c;
assert(i->connection);
i->connected = second_clock::universal_time(); i->connected = second_clock::universal_time();
m_last_optimistic_disconnect = second_clock::universal_time(); m_last_optimistic_disconnect = second_clock::universal_time();
} }
@ -939,7 +944,7 @@ namespace libtorrent
m_peers.push_back(p); m_peers.push_back(p);
// the iterator is invalid // the iterator is invalid
// because of the push_back() // because of the push_back()
i = m_peers.end()-1; i = m_peers.end() - 1;
} }
else else
{ {
@ -1157,7 +1162,9 @@ namespace libtorrent
{ {
try try
{ {
assert(!p->connection);
p->connection = &m_torrent->connect_to_peer(p->id); p->connection = &m_torrent->connect_to_peer(p->id);
assert(p->connection);
p->connection->add_stat(p->prev_amount_download, p->prev_amount_upload); p->connection->add_stat(p->prev_amount_download, p->prev_amount_upload);
p->prev_amount_download = 0; p->prev_amount_download = 0;
p->prev_amount_upload = 0; p->prev_amount_upload = 0;
@ -1166,8 +1173,11 @@ namespace libtorrent
second_clock::universal_time(); second_clock::universal_time();
return true; return true;
} }
catch (network_error&) catch (network_error& e)
{ {
// TODO: This path needs testing!
std::string msg = e.what();
assert(false);
// TODO: remove the peer // TODO: remove the peer
// m_peers.erase(std::find(m_peers.begin(), m_peers.end(), p)); // m_peers.erase(std::find(m_peers.begin(), m_peers.end(), p));
} }
@ -1253,10 +1263,11 @@ namespace libtorrent
bool policy::has_connection(const peer_connection* c) bool policy::has_connection(const peer_connection* c)
{ {
assert(c); assert(c);
assert(c->remote() == c->get_socket()->sender());
return std::find_if( return std::find_if(
m_peers.begin() m_peers.begin()
, m_peers.end() , m_peers.end()
, match_peer_ip(c->get_socket()->sender())) != m_peers.end(); , match_peer_ip(c->remote())) != m_peers.end();
} }
void policy::check_invariant() const void policy::check_invariant() const
@ -1264,10 +1275,17 @@ namespace libtorrent
if (m_torrent->is_aborted()) return; if (m_torrent->is_aborted()) return;
int actual_unchoked = 0; int actual_unchoked = 0;
int connected_peers = 0; int connected_peers = 0;
int total_connections = 0;
int nonempty_connections = 0;
for (std::vector<peer>::const_iterator i = m_peers.begin(); for (std::vector<peer>::const_iterator i = m_peers.begin();
i != m_peers.end(); ++i) i != m_peers.end(); ++i)
{ {
++total_connections;
if (!i->connection) continue; if (!i->connection) continue;
++nonempty_connections;
if (!i->connection->is_disconnecting()) if (!i->connection->is_disconnecting())
++connected_peers; ++connected_peers;
if (!i->connection->is_choked()) ++actual_unchoked; if (!i->connection->is_choked()) ++actual_unchoked;
@ -1291,6 +1309,7 @@ namespace libtorrent
// When there's an outgoing connection, it will first // When there's an outgoing connection, it will first
// be added to the torrent and then to the policy. // be added to the torrent and then to the policy.
// that's why the two second cases are in there. // that's why the two second cases are in there.
assert(connected_peers == num_torrent_peers assert(connected_peers == num_torrent_peers
|| (connected_peers == num_torrent_peers + 1 || (connected_peers == num_torrent_peers + 1
&& connected_peers > 0) && connected_peers > 0)

View File

@ -393,6 +393,7 @@ namespace libtorrent { namespace detail
, m_download_rate(-1) , m_download_rate(-1)
, m_max_uploads(-1) , m_max_uploads(-1)
, m_max_connections(-1) , m_max_connections(-1)
, m_half_open_limit(-1)
, m_incoming_connection(false) , m_incoming_connection(false)
{ {
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
@ -441,7 +442,34 @@ namespace libtorrent { namespace detail
{ {
while (!m_disconnect_peer.empty()) while (!m_disconnect_peer.empty())
{ {
m_connections.erase(m_disconnect_peer.back()); boost::shared_ptr<peer_connection>& p = m_disconnect_peer.back();
assert(p->is_disconnecting());
if (p->is_connecting())
{
// Since this peer is still connecting, will not be
// in the list of completed connections.
connection_map::iterator i = m_half_open.find(p->get_socket());
if (i == m_half_open.end())
{
// this connection is not in the half-open list, so it
// has to be in the queue, waiting to be connected.
connection_queue::iterator j = std::find(
m_connection_queue.begin(), m_connection_queue.end(), p);
assert(j != m_connection_queue.end());
if (j != m_connection_queue.end()) m_connection_queue.erase(j);
}
else
{
m_half_open.erase(i);
}
}
else
{
connection_map::iterator i = m_connections.find(p->get_socket());
assert(i != m_connections.end());
if (i != m_connections.end()) m_connections.erase(i);
}
m_disconnect_peer.pop_back(); m_disconnect_peer.pop_back();
} }
} }
@ -514,6 +542,21 @@ namespace libtorrent { namespace detail
} }
} }
void session_impl::process_connection_queue()
{
while (!m_connection_queue.empty())
{
if ((int)m_half_open.size() >= m_half_open_limit
&& m_half_open_limit > 0)
return;
connection_queue::value_type& c = m_connection_queue.front();
m_half_open.insert(std::make_pair(c->get_socket(), c));
assert(c->associated_torrent());
c->connect();
m_connection_queue.pop_front();
}
}
void session_impl::operator()() void session_impl::operator()()
{ {
@ -605,7 +648,24 @@ namespace libtorrent { namespace detail
// the connection may have been disconnected in the receive phase // the connection may have been disconnected in the receive phase
if (p == m_connections.end()) if (p == m_connections.end())
{ {
m_selector.remove(*i); // if we didn't find the socket among the
// connected connections, look among the
// half-open connections to see if some of
// them have finished.
p = m_half_open.find(*i);
if (p == m_half_open.end())
{
m_selector.remove(*i);
}
else
{
p->second->connection_complete();
assert(!p->second->is_connecting());
m_connections.insert(*p);
m_half_open.erase(p);
process_connection_queue();
}
} }
else else
{ {
@ -703,6 +763,7 @@ namespace libtorrent { namespace detail
boost::shared_ptr<peer_connection> c( boost::shared_ptr<peer_connection> c(
new peer_connection(*this, m_selector, s)); new peer_connection(*this, m_selector, s));
assert(!c->is_connecting());
m_connections.insert(std::make_pair(s, c)); m_connections.insert(std::make_pair(s, c));
m_selector.monitor_readability(s); m_selector.monitor_readability(s);
m_selector.monitor_errors(s); m_selector.monitor_errors(s);
@ -773,6 +834,9 @@ namespace libtorrent { namespace detail
i != error_clients.end(); ++i) i != error_clients.end(); ++i)
{ {
connection_map::iterator p = m_connections.find(*i); connection_map::iterator p = m_connections.find(*i);
m_selector.remove(*i);
// the connection may have been disconnected in the receive or send phase
if (p != m_connections.end()) if (p != m_connections.end())
{ {
if (m_alerts.should_post(alert::debug)) if (m_alerts.should_post(alert::debug))
@ -783,12 +847,7 @@ namespace libtorrent { namespace detail
, p->second->id() , p->second->id()
, "connection closed")); , "connection closed"));
} }
}
m_selector.remove(*i);
// the connection may have been disconnected in the receive or send phase
if (p != m_connections.end())
{
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*p->second->m_logger) << "*** CONNECTION EXCEPTION\n"; (*p->second->m_logger) << "*** CONNECTION EXCEPTION\n";
#endif #endif
@ -809,6 +868,32 @@ namespace libtorrent { namespace detail
assert(m_listen_socket.unique()); assert(m_listen_socket.unique());
m_listen_socket.reset(); m_listen_socket.reset();
} }
else
{
// the error was not in one of the connected
// conenctions. Look among the half-open ones.
p = m_half_open.find(*i);
if (p != m_half_open.end())
{
if (m_alerts.should_post(alert::debug))
{
m_alerts.post_alert(
peer_error_alert(
p->first->sender()
, p->second->id()
, "connection attempt failed"));
// TODO: TEMP!
#warning TEMP!
std::ofstream log("connect.log", std::ios::app);
log << boost::posix_time::microsec_clock::universal_time() << " FAILED: "
<< (*i)->sender().as_string() << std::endl;
p->second->set_failed();
m_half_open.erase(p);
}
}
}
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -1003,17 +1088,25 @@ namespace libtorrent { namespace detail
{ {
assert(place); assert(place);
for (connection_map::iterator i = m_half_open.begin();
i != m_half_open.end(); ++i)
{
assert(i->second->is_connecting());
}
for (connection_map::iterator i = m_connections.begin(); for (connection_map::iterator i = m_connections.begin();
i != m_connections.end(); ++i) i != m_connections.end(); ++i)
{ {
assert(i->second); assert(i->second);
if (i->second->can_write() != m_selector.is_writability_monitored(i->first) if (i->second->is_connecting()
|| i->second->can_write() != m_selector.is_writability_monitored(i->first)
|| i->second->can_read() != m_selector.is_readability_monitored(i->first)) || i->second->can_read() != m_selector.is_readability_monitored(i->first))
{ {
std::ofstream error_log("error.log", std::ios_base::app); std::ofstream error_log("error.log", std::ios_base::app);
boost::shared_ptr<peer_connection> p = i->second; boost::shared_ptr<peer_connection> p = i->second;
error_log << "selector::is_writability_monitored() " << m_selector.is_writability_monitored(i->first) << "\n"; error_log << "selector::is_writability_monitored() " << m_selector.is_writability_monitored(i->first) << "\n";
error_log << "selector::is_readability_monitored() " << m_selector.is_readability_monitored(i->first) << "\n"; error_log << "selector::is_readability_monitored() " << m_selector.is_readability_monitored(i->first) << "\n";
error_log << "peer_connection::is_connecting() " << p->is_connecting() << "\n";
error_log << "peer_connection::can_write() " << p->can_write() << "\n"; error_log << "peer_connection::can_write() " << p->can_write() << "\n";
error_log << "peer_connection::can_read() " << p->can_read() << "\n"; error_log << "peer_connection::can_read() " << p->can_read() << "\n";
error_log << "peer_connection::ul_quota_left " << p->m_ul_bandwidth_quota.left() << "\n"; error_log << "peer_connection::ul_quota_left " << p->m_ul_bandwidth_quota.left() << "\n";
@ -1406,6 +1499,13 @@ namespace libtorrent
m_impl.m_max_connections = limit; m_impl.m_max_connections = limit;
} }
void session::set_max_half_open_connections(int limit)
{
assert(limit > 0 || limit == -1);
boost::mutex::scoped_lock l(m_impl.m_mutex);
m_impl.m_half_open_limit = limit;
}
void session::set_upload_rate_limit(int bytes_per_second) void session::set_upload_rate_limit(int bytes_per_second)
{ {
assert(bytes_per_second > 0 || bytes_per_second == -1); assert(bytes_per_second > 0 || bytes_per_second == -1);

View File

@ -857,7 +857,7 @@ namespace libtorrent
{ {
assert(p != 0); assert(p != 0);
peer_iterator i = m_connections.find(p->get_socket()->sender()); peer_iterator i = m_connections.find(p->remote());
assert(i != m_connections.end()); assert(i != m_connections.end());
if (ready_for_connections()) if (ready_for_connections())
@ -903,25 +903,20 @@ namespace libtorrent
peer_connection& torrent::connect_to_peer(const address& a) peer_connection& torrent::connect_to_peer(const address& a)
{ {
boost::shared_ptr<socket> s(new socket(socket::tcp, false)); boost::shared_ptr<socket> s(new socket(socket::tcp, false));
s->connect(a, m_net_interface);
boost::shared_ptr<peer_connection> c(new peer_connection( boost::shared_ptr<peer_connection> c(new peer_connection(
m_ses, m_ses.m_selector, this, s)); m_ses, m_ses.m_selector, this, s, a));
detail::session_impl::connection_map::iterator p = m_ses.m_connection_queue.push_back(c);
m_ses.m_connections.insert(std::make_pair(s, c)).first;
// add the newly connected peer to this torrent's peer list assert(m_connections.find(a) == m_connections.end());
assert(m_connections.find(p->second->get_socket()->sender())
== m_connections.end());
#ifndef NDEBUG #ifndef NDEBUG
m_policy->check_invariant(); m_policy->check_invariant();
#endif #endif
// add the newly connected peer to this torrent's peer list
m_connections.insert( m_connections.insert(
std::make_pair( std::make_pair(a, boost::get_pointer(c)));
p->second->get_socket()->sender()
, boost::get_pointer(p->second)));
#ifndef NDEBUG #ifndef NDEBUG
m_policy->check_invariant(); m_policy->check_invariant();
@ -929,13 +924,14 @@ namespace libtorrent
m_ses.m_selector.monitor_readability(s); m_ses.m_selector.monitor_readability(s);
m_ses.m_selector.monitor_errors(s); m_ses.m_selector.monitor_errors(s);
m_ses.process_connection_queue();
return *c; return *c;
} }
void torrent::attach_peer(peer_connection* p) void torrent::attach_peer(peer_connection* p)
{ {
assert(p != 0); assert(p != 0);
assert(m_connections.find(p->get_socket()->sender()) == m_connections.end()); assert(m_connections.find(p->remote()) == m_connections.end());
assert(!p->is_local()); assert(!p->is_local());
detail::session_impl::connection_map::iterator i detail::session_impl::connection_map::iterator i
@ -950,7 +946,8 @@ namespace libtorrent
// connection list. // connection list.
m_policy->new_connection(*i->second); m_policy->new_connection(*i->second);
m_connections.insert(std::make_pair(p->get_socket()->sender(), p)); assert(p->remote() == p->get_socket()->sender());
m_connections.insert(std::make_pair(p->remote(), p));
#ifndef NDEBUG #ifndef NDEBUG
m_policy->check_invariant(); m_policy->check_invariant();

View File

@ -450,7 +450,7 @@ namespace libtorrent
// but still connectable // but still connectable
if (!i->second->is_local()) continue; if (!i->second->is_local()) continue;
address ip = i->second->get_socket()->sender(); address ip = i->second->remote();
entry peer(entry::dictionary_t); entry peer(entry::dictionary_t);
peer["ip"] = ip.as_string(); peer["ip"] = ip.as_string();
peer["port"] = ip.port; peer["port"] = ip.port;
@ -578,7 +578,7 @@ namespace libtorrent
p.payload_down_speed = statistics.download_payload_rate(); p.payload_down_speed = statistics.download_payload_rate();
p.payload_up_speed = statistics.upload_payload_rate(); p.payload_up_speed = statistics.upload_payload_rate();
p.id = peer->get_peer_id(); p.id = peer->get_peer_id();
p.ip = peer->get_socket()->sender(); p.ip = peer->remote();
p.total_download = statistics.total_payload_download(); p.total_download = statistics.total_payload_download();
p.total_upload = statistics.total_payload_upload(); p.total_upload = statistics.total_payload_upload();
@ -621,7 +621,9 @@ namespace libtorrent
if (peer->has_peer_choked()) p.flags |= peer_info::remote_choked; if (peer->has_peer_choked()) p.flags |= peer_info::remote_choked;
if (peer->support_extensions()) p.flags |= peer_info::supports_extensions; if (peer->support_extensions()) p.flags |= peer_info::supports_extensions;
if (peer->is_local()) p.flags |= peer_info::local_connection; if (peer->is_local()) p.flags |= peer_info::local_connection;
if (peer->is_connecting() && !peer->is_queued()) p.flags |= peer_info::connecting;
if (peer->is_queued()) p.flags |= peer_info::queued;
p.pieces = peer->get_bitfield(); p.pieces = peer->get_bitfield();
p.seed = peer->is_seed(); p.seed = peer->is_seed();
} }