diff --git a/ChangeLog b/ChangeLog index 68a0ddee7..9a36cb84e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ + * Auto Upload slots. Automtically opens up more slots if + upload limit is not met. + * Improved NAT-PMP support by querying the default gateway (no + linux support yet) + * Improved UPnP support by ignoring routers not on the clients subnet. release 0.13 diff --git a/docs/manual.html b/docs/manual.html index e986501d3..35aa1b6c3 100644 --- a/docs/manual.html +++ b/docs/manual.html @@ -607,6 +607,8 @@ struct session_status size_type total_payload_upload; int num_peers; + int num_unchoked; + int allowed_upload_slots; int dht_nodes; int dht_cache_nodes; @@ -628,6 +630,8 @@ incoming connections that still hasn't sent their handshake or outgoing connecti that still hasn't completed the TCP connection. This number may be slightly higher than the sum of all peers of all torrents because the incoming connections may not be assigned a torrent yet.

+

num_unchoked is the current number of unchoked peers. +allowed_upload_slots is the current allowed number of unchoked peers.

dht_nodes, dht_cache_nodes and dht_torrents are only available when built with DHT support. They are all set to 0 if the DHT isn't running. When the DHT is running, dht_nodes is set to the number of nodes in the routing @@ -2499,6 +2503,7 @@ struct session_settings bool free_torrent_hashes; bool upnp_ignore_nonrouters; int send_buffer_watermark; + bool auto_upload_slots; };

user_agent this is the client identification to the tracker. @@ -2615,6 +2620,12 @@ if the send buffer has fewer bytes than this, we'll read another 16kB block onto it. If set too small, upload rate capacity will suffer. If set too high, memory will be wasted. The actual watermark may be lower than this in case the upload rate is low, this is the upper limit.

+

auto_upload_slots defaults to true. When true, if there is a global upload +limit set and the current upload rate is less than 90% of that, another upload +slot is opened. If the upload rate has been saturated for an extended period +of time, on upload slot is closed. The number of upload slots will never be +less than what has been set by session::set_max_uploads(). To query the +current number of upload slots, see session_status::allowed_upload_slots.

pe_settings

diff --git a/docs/manual.rst b/docs/manual.rst index 2612e608c..3acbb91b2 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -447,6 +447,8 @@ struct has the following members:: size_type total_payload_upload; int num_peers; + int num_unchoked; + int allowed_upload_slots; int dht_nodes; int dht_cache_nodes; @@ -472,6 +474,9 @@ that still hasn't completed the TCP connection. This number may be slightly high than the sum of all peers of all torrents because the incoming connections may not be assigned a torrent yet. +``num_unchoked`` is the current number of unchoked peers. +``allowed_upload_slots`` is the current allowed number of unchoked peers. + ``dht_nodes``, ``dht_cache_nodes`` and ``dht_torrents`` are only available when built with DHT support. They are all set to 0 if the DHT isn't running. When the DHT is running, ``dht_nodes`` is set to the number of nodes in the routing @@ -2487,6 +2492,7 @@ that will be sent to the tracker. The user-agent is a good way to identify your bool free_torrent_hashes; bool upnp_ignore_nonrouters; int send_buffer_watermark; + bool auto_upload_slots; }; ``user_agent`` this is the client identification to the tracker. @@ -2630,6 +2636,13 @@ onto it. If set too small, upload rate capacity will suffer. If set too high, memory will be wasted. The actual watermark may be lower than this in case the upload rate is low, this is the upper limit. +``auto_upload_slots`` defaults to true. When true, if there is a global upload +limit set and the current upload rate is less than 90% of that, another upload +slot is opened. If the upload rate has been saturated for an extended period +of time, on upload slot is closed. The number of upload slots will never be +less than what has been set by ``session::set_max_uploads()``. To query the +current number of upload slots, see ``session_status::allowed_upload_slots``. + pe_settings =========== diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 7ed6eac91..5c146b9d4 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -1184,10 +1184,12 @@ int main(int ac, char* av[]) } - out << "conns: " << sess_stat.num_peers << " down: " << esc("32") << add_suffix(sess_stat.download_rate) << "/s" << esc("0") + out << "==== conns: " << sess_stat.num_peers << " down: " << esc("32") << add_suffix(sess_stat.download_rate) << "/s" << esc("0") << " (" << esc("32") << add_suffix(sess_stat.total_download) << esc("0") << ") " " up: " << esc("31") << add_suffix(sess_stat.upload_rate) << "/s " << esc("0") - << " (" << esc("31") << add_suffix(sess_stat.total_upload) << esc("0") << ")" << std::endl; + << " (" << esc("31") << add_suffix(sess_stat.total_upload) << esc("0") << ")" + " unchoked: " << sess_stat.num_unchoked << " / " << sess_stat.allowed_upload_slots + << " ====" << std::endl; if (print_log) { diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 9d232b644..916d842a2 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -503,7 +503,14 @@ namespace libtorrent // should exit volatile bool m_abort; + // the max number of unchoked peers as set by the user int m_max_uploads; + + // the number of unchoked peers as set by the auto-unchoker + // this should always be >= m_max_uploads + int m_allowed_upload_slots; + + // the max number of connections, as set by the user int m_max_connections; // the number of unchoked peers diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index 1b70f6c98..f2abe6b3c 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -119,6 +119,7 @@ namespace libtorrent , free_torrent_hashes(true) , upnp_ignore_nonrouters(true) , send_buffer_watermark(80 * 1024) + , auto_upload_slots(true) {} // this is the user agent that will be sent to the tracker @@ -307,6 +308,15 @@ namespace libtorrent // The actual watermark may be lower than this in case // the upload rate is low, this is the upper limit. int send_buffer_watermark; + + // if auto_upload_slots is true, and a global upload + // limit is set and the upload rate is less than 90% + // of the upload limit, on new slot is opened up. If + // the upload rate is >= upload limit for an extended + // period of time, one upload slot is closed. The + // upload slots are never automatically decreased below + // the manual settings, through max_uploads. + bool auto_upload_slots; }; #ifndef TORRENT_DISABLE_DHT diff --git a/include/libtorrent/session_status.hpp b/include/libtorrent/session_status.hpp index adbb1b57d..2c451a3c8 100644 --- a/include/libtorrent/session_status.hpp +++ b/include/libtorrent/session_status.hpp @@ -54,6 +54,8 @@ namespace libtorrent size_type total_payload_upload; int num_peers; + int num_unchoked; + int allowed_upload_slots; #ifndef TORRENT_DISABLE_DHT int dht_nodes; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 475897505..42bad0b43 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -564,6 +564,7 @@ namespace detail , m_listen_interface(address::from_string(listen_interface), listen_port_range.first) , m_abort(false) , m_max_uploads(8) + , m_allowed_upload_slots(8) , m_max_connections(200) , m_num_unchoked(0) , m_unchoke_time_scaler(0) @@ -808,6 +809,7 @@ namespace detail TORRENT_ASSERT(s.unchoke_interval >= 5); m_settings = s; m_files.resize(m_settings.file_pool_size); + if (!s.auto_upload_slots) m_allowed_upload_slots = m_max_uploads; // replace all occurances of '\n' with ' '. std::string::iterator i = m_settings.user_agent.begin(); while ((i = std::find(i, m_settings.user_agent.end(), '\n')) @@ -1420,8 +1422,25 @@ namespace detail , bind(&stat::download_payload_rate, bind(&peer_connection::statistics, _1)) > bind(&stat::download_payload_rate, bind(&peer_connection::statistics, _2))); + // auto unchoke + int upload_limit = m_bandwidth_manager[peer_connection::upload_channel]->throttle(); + if (m_settings.auto_upload_slots && upload_limit != bandwidth_limit::inf) + { + // if our current upload rate is less than 90% of our + if (m_stat.upload_rate() < upload_limit * 0.9f + && m_allowed_upload_slots < m_num_unchoked + 2) + { + ++m_allowed_upload_slots; + } + else if (m_stat.upload_rate() >= upload_limit + && m_allowed_upload_slots > m_max_uploads) + { + --m_allowed_upload_slots; + } + } + // reserve one upload slot for optimistic unchokes - int unchoke_set_size = m_max_uploads - 1; + int unchoke_set_size = m_allowed_upload_slots - 1; m_num_unchoked = 0; // go through all the peers and unchoke the first ones and choke @@ -2007,8 +2026,12 @@ namespace detail // INVARIANT_CHECK; session_status s; - s.has_incoming_connections = m_incoming_connection; + s.num_peers = (int)m_connections.size(); + s.num_unchoked = m_num_unchoked; + s.allowed_upload_slots = m_allowed_upload_slots; + + s.has_incoming_connections = m_incoming_connection; s.download_rate = m_stat.download_rate(); s.upload_rate = m_stat.upload_rate(); @@ -2213,6 +2236,7 @@ namespace detail if (limit <= 0) limit = (std::numeric_limits::max)(); m_max_uploads = limit; + if (m_allowed_upload_slots < limit) m_allowed_upload_slots = limit; } void session_impl::set_max_connections(int limit) @@ -2422,6 +2446,7 @@ namespace detail { TORRENT_ASSERT(m_max_connections > 0); TORRENT_ASSERT(m_max_uploads > 0); + TORRENT_ASSERT(m_allowed_upload_slots >= m_max_uploads); int unchokes = 0; int num_optimistic = 0; for (connection_map::const_iterator i = m_connections.begin();