diff --git a/ChangeLog b/ChangeLog index e082d1c23..865ef595f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ + * deprecated setters for max connections, max half-open, upload and download + rates and unchoke slots. These are now set through session_settings * added functions to query an individual peer's upload and download limit * full support for BEP 21 (event=paused) * added share-mode feature for improving share ratios diff --git a/docs/manual.rst b/docs/manual.rst index d84595570..c2893ba08 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -547,116 +547,6 @@ See ``torrent_handle::is_valid()`` to know if the torrent was found or not. ``get_torrents()`` returns a vector of torrent_handles to all the torrents currently in the session. - -set_upload_rate_limit() set_download_rate_limit() upload_rate_limit() download_rate_limit() -------------------------------------------------------------------------------------------- - - :: - - void set_upload_rate_limit(int bytes_per_second); - void set_download_rate_limit(int bytes_per_second); - int upload_rate_limit() const; - int download_rate_limit() const; - -``set_upload_rate_limit()`` set the maximum number of bytes allowed to be -sent to peers per second. This bandwidth is distributed among all the peers. If -you don't want to limit upload rate, you can set this to 0 (the default). -``set_download_rate_limit()`` works the same way but for download rate instead -of upload rate. -``download_rate_limit()`` and ``upload_rate_limit()`` returns the previously -set limits. - -A rate limit of 0 means infinite. - -Upload and download rate limits are not applied to peers on the local network -by default. To change that, see ``session_settings::ignore_limits_on_local_network``. - - -set_local_upload_rate_limit() set_local_download_rate_limit() local_upload_rate_limit() local_download_rate_limit() -------------------------------------------------------------------------------------------------------------------- - - :: - - void set_local_upload_rate_limit(int bytes_per_second); - void set_local_download_rate_limit(int bytes_per_second); - int local_upload_rate_limit() const; - int local_download_rate_limit() const; - -These rate limits are only used for local peers (peers within the same subnet as -the client itself) and it is only used when ``session_settings::ignore_limits_on_local_network`` -is set to true (which it is by default). These rate limits default to unthrottled, -but can be useful in case you want to treat local peers preferentially, but not -quite unthrottled. - -A rate limit of 0 means infinite. - - -set_max_uploads() max_uploads() -------------------------------- - - :: - - void set_max_uploads(int limit); - int max_uploads() const; - -``set_max_uploads`` sets a global limit on the number of unchoked peers (uploads). -The number of uploads is at least one per torrent. - -``max_uploads()`` returns the current settings. - -The number of unchoke slots may be ignored depending on what -``session_settings::choking_algorithm`` is set to. - - -set_max_connections() max_connections() ---------------------------------------- - - :: - - void set_max_connections(int limit); - int max_connections() const; - -``set_max_connections`` sets a global limit on the number of connections -opened. The number of connections is set to a hard minimum of at least two per -torrent, so if you set a too low connections limit, and open too many torrents, -the limit will not be met. - -``max_connections()`` returns the current settings. - - -num_uploads() num_connections() -------------------------------- - - :: - - int num_uploads() const; - int num_connections() const; - -Returns the number of currently unchoked peers and the number of connections -(including half-open ones) respectively. - - -set_max_half_open_connections() max_half_open_connections() ------------------------------------------------------------ - - :: - - void set_max_half_open_connections(int limit); - int max_half_open_connections() const; - -Sets the maximum number of half-open connections libtorrent will have when -connecting to peers. A half-open connection is one where connect() has been -called, but the connection still hasn't been established (nor failed). Windows -XP Service Pack 2 sets a default, system wide, limit of the number of half-open -connections to 10. So, this limit can be used to work nicer together with -other network applications on that system. The default is to have no limit, -and passing -1 as the limit, means to have no limit. When limiting the number -of simultaneous connection attempts, peers will be put in a queue waiting for -their turn to get connected. - -``max_half_open_connections()`` returns the set limit. This limit defaults -to 8 on windows. - load_asnum_db() load_country_db() as_for_ip() --------------------------------------------- @@ -3929,6 +3819,13 @@ session_settings bool anonymous_mode; int tick_interval; int share_mode_target; + int upload_rate_limit; + int download_rate_limit; + int local_upload_rate_limit; + int local_download_rate_limit; + int unchoke_slots_limit; + int half_open_limit; + int connections_limit; }; ``version`` is automatically set to the libtorrent version you're using @@ -4599,6 +4496,40 @@ need to download the rarest piece, it's impossible to download a single piece and upload it more than 3 times. If the share_mode_target is set to more than 3, nothing is downloaded. +``upload_rate_limit``, ``download_rate_limit``, ``local_upload_rate_limit`` +and ``local_download_rate_limit`` sets the session-global limits of upload +and download rate limits, in bytes per second. The local rates refer to peers +on the local network. By default peers on the local network are not rate limited. + +These rate limits are only used for local peers (peers within the same subnet as +the client itself) and it is only used when ``session_settings::ignore_limits_on_local_network`` +is set to true (which it is by default). These rate limits default to unthrottled, +but can be useful in case you want to treat local peers preferentially, but not +quite unthrottled. + +A value of 0 means unlimited. + +``unchoke_slots_limit`` is the mac number of unchoked peers in the session. + +The number of unchoke slots may be ignored depending on what +``choking_algorithm`` is set to. + +``half_open_limit`` sets the maximum number of half-open connections +libtorrent will have when connecting to peers. A half-open connection is one +where connect() has been called, but the connection still hasn't been established +(nor failed). Windows XP Service Pack 2 sets a default, system wide, limit of +the number of half-open connections to 10. So, this limit can be used to work +nicer together with other network applications on that system. The default is +to have no limit, and passing -1 as the limit, means to have no limit. When +limiting the number of simultaneous connection attempts, peers will be put in +a queue waiting for their turn to get connected. + +``connections_limit`` sets a global limit on the number of connections +opened. The number of connections is set to a hard minimum of at least two per +torrent, so if you set a too low connections limit, and open too many torrents, +the limit will not be met. + + pe_settings =========== diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 3b9556f98..c883809af 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -893,7 +893,7 @@ int main(int argc, char* argv[]) switch (argv[i][1]) { case 'f': g_log_file = fopen(arg, "w+"); break; - case 'o': ses.set_max_half_open_connections(atoi(arg)); break; + case 'o': settings.half_open_limit = atoi(arg); break; case 'h': settings.allow_multiple_connections_per_ip = true; --i; break; case 'p': listen_port = atoi(arg); break; case 'r': @@ -901,9 +901,9 @@ int main(int argc, char* argv[]) if (preferred_ratio != 0 && preferred_ratio < 1.f) preferred_ratio = 1.f; break; case 'n': settings.announce_to_all_tiers = true; --i; break; - case 'd': ses.set_download_rate_limit(atoi(arg) * 1000); break; - case 'u': ses.set_upload_rate_limit(atoi(arg) * 1000); break; - case 'S': ses.set_max_uploads(atoi(arg)); break; + case 'd': settings.download_rate_limit = atoi(arg) * 1000; break; + case 'u': settings.upload_rate_limit = atoi(arg) * 1000; break; + case 'S': settings.unchoke_slots_limit = atoi(arg); break; case 'a': if (strcmp(arg, "allocate") == 0) allocation_mode = storage_mode_allocate; if (strcmp(arg, "compact") == 0) allocation_mode = storage_mode_compact; @@ -942,7 +942,7 @@ int main(int argc, char* argv[]) } } break; - case 'c': ses.set_max_connections(atoi(arg)); break; + case 'c': settings.connections_limit = atoi(arg); break; case 'T': max_connections_per_torrent = atoi(arg); break; #if TORRENT_USE_I2P case 'i': diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 933b26675..2d1ae599a 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -266,6 +266,7 @@ namespace libtorrent alert const* wait_for_alert(time_duration max_wait); +#ifndef TORRENT_NO_DEPRECATE int upload_rate_limit() const; int download_rate_limit() const; int local_upload_rate_limit() const; @@ -273,16 +274,17 @@ namespace libtorrent void set_local_download_rate_limit(int bytes_per_second); void set_local_upload_rate_limit(int bytes_per_second); - void set_download_rate_limit(int bytes_per_second); void set_upload_rate_limit(int bytes_per_second); void set_max_half_open_connections(int limit); void set_max_connections(int limit); void set_max_uploads(int limit); - int max_connections() const { return m_max_connections; } - int max_uploads() const { return m_max_uploads; } - int max_half_open_connections() const { return m_half_open.limit(); } + int max_connections() const; + int max_uploads() const; + int max_half_open_connections() const; + +#endif int num_uploads() const { return m_num_unchoked; } int num_connections() const @@ -395,6 +397,10 @@ namespace libtorrent // private: + void update_connections_limit(); + void update_unchoke_limit(); + void update_rate_settings(); + void update_disk_thread_settings(); void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih); void setup_socket_buffers(socket_type& s); @@ -605,16 +611,10 @@ namespace libtorrent // is true if the session is paused bool m_paused; - // 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 int m_num_unchoked; diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index 851df550d..bb3534f7f 100644 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -392,22 +392,39 @@ namespace libtorrent proxy_settings i2p_proxy() const; #endif - int upload_rate_limit() const; - int download_rate_limit() const; - int local_upload_rate_limit() const; - int local_download_rate_limit() const; - int max_half_open_connections() const; +#ifndef TORRENT_NO_DEPRECATE + // deprecated in 0.16 + TORRENT_DEPRECATED_PREFIX + int upload_rate_limit() const TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + int download_rate_limit() const TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + int local_upload_rate_limit() const TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + int local_download_rate_limit() const TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + int max_half_open_connections() const TORRENT_DEPRECATED; - void set_local_upload_rate_limit(int bytes_per_second); - void set_local_download_rate_limit(int bytes_per_second); - void set_upload_rate_limit(int bytes_per_second); - void set_download_rate_limit(int bytes_per_second); - void set_max_uploads(int limit); - void set_max_connections(int limit); - void set_max_half_open_connections(int limit); + TORRENT_DEPRECATED_PREFIX + void set_local_upload_rate_limit(int bytes_per_second) TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + void set_local_download_rate_limit(int bytes_per_second) TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + void set_upload_rate_limit(int bytes_per_second) TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + void set_download_rate_limit(int bytes_per_second) TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + void set_max_uploads(int limit) TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + void set_max_connections(int limit) TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + void set_max_half_open_connections(int limit) TORRENT_DEPRECATED; - int max_connections() const; - int max_uploads() const; + TORRENT_DEPRECATED_PREFIX + int max_connections() const TORRENT_DEPRECATED; + TORRENT_DEPRECATED_PREFIX + int max_uploads() const TORRENT_DEPRECATED; +#endif std::auto_ptr pop_alert(); #ifndef TORRENT_NO_DEPRECATE diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index f0ac941e3..8151799a5 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -222,6 +222,14 @@ namespace libtorrent , tick_interval(100) , report_web_seed_downloads(true) , share_mode_target(3) + + , upload_rate_limit(0) + , download_rate_limit(0) + , local_upload_rate_limit(0) + , local_download_rate_limit(0) + , unchoke_slots_limit(8) + , half_open_limit(0) + , connections_limit(200) {} // libtorrent version. Used for forward binary compatibility @@ -847,6 +855,30 @@ namespace libtorrent // this is the target share ratio for share-mode torrents int share_mode_target; + + // max upload rate in bytes per second for the session + int upload_rate_limit; + + // max download rate in bytes per second for the session + int download_rate_limit; + + // max upload rate in bytes per second for peers on the local + // network, in the session + int local_upload_rate_limit; + + // max download rate in bytes per second for peers on the local + // network, in the session + int local_download_rate_limit; + + // the max number of unchoke slots in the session (might be + // overridden by unchoke algorithm) + int unchoke_slots_limit; + + // the max number of half-open TCP connections + int half_open_limit; + + // the max number of connections in the session + int connections_limit; }; #ifndef TORRENT_DISABLE_DHT diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 8f97c41ec..84467bf26 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -1435,7 +1435,7 @@ namespace libtorrent // just unchoke it immediately send_unchoke(); } - else if (m_ses.num_uploads() < m_ses.max_uploads() + else if (m_ses.num_uploads() < m_ses.settings().unchoke_slots_limit && (t->ratio() == 0 || share_diff() >= size_type(-free_upload_amount) || t->is_finished())) @@ -1456,12 +1456,12 @@ namespace libtorrent else { std::string reason; - if (m_ses.num_uploads() >= m_ses.max_uploads()) + if (m_ses.num_uploads() >= m_ses.settings().unchoke_slots_limit) { (*m_logger) << time_now_string() << " DID NOT UNCHOKE [ " "the number of uploads (" << m_ses.num_uploads() << ") is more than or equal to the limit (" - << m_ses.max_uploads() << ") ]\n"; + << m_ses.settings().unchoke_slots_limit << ") ]\n"; } else { @@ -3511,7 +3511,7 @@ namespace libtorrent } p.estimated_reciprocation_rate = m_est_reciprocation_rate; - int upload_capacity = m_ses.upload_rate_limit(); + int upload_capacity = m_ses.settings().upload_rate_limit; if (upload_capacity == 0) upload_capacity = (std::max)(20000, m_ses.m_peak_up_rate + 10000); @@ -3767,7 +3767,7 @@ namespace libtorrent && !m_peer_interested && d1 > time_limit && d2 > time_limit - && (m_ses.num_connections() >= m_ses.max_connections() + && (m_ses.num_connections() >= m_ses.settings().connections_limit || (t && t->num_peers() >= t->max_connections()))) { #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING @@ -4199,7 +4199,7 @@ namespace libtorrent // is decided based on the estimated reciprocation rate and // the share it represents of the total upload rate capacity // the torrent priority is taken into account when unchoking peers - int upload_capacity = m_ses.upload_rate_limit(); + int upload_capacity = m_ses.settings().upload_rate_limit; if (upload_capacity == 0) { // we don't know at what rate we can upload. If we have a diff --git a/src/policy.cpp b/src/policy.cpp index e74905ea9..7b52130d2 100644 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -686,7 +686,7 @@ namespace libtorrent aux::session_impl& ses = m_torrent->session(); if (m_torrent->num_peers() >= m_torrent->max_connections() - && ses.num_connections() >= ses.max_connections() + && ses.num_connections() >= ses.settings().connections_limit && c.remote().address() != m_torrent->current_tracker().address()) { c.disconnect(errors::too_many_connections); diff --git a/src/session.cpp b/src/session.cpp index 8f729b0f3..8c91c8395 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -804,6 +804,7 @@ namespace libtorrent } #endif +#ifndef TORRENT_NO_DEPRECATE int session::max_uploads() const { TORRENT_SYNC_CALL_RET(int, max_uploads); @@ -892,6 +893,7 @@ namespace libtorrent TORRENT_SYNC_CALL_RET(int, num_connections); return r; } +#endif // TORRENT_NO_DEPRECATE std::auto_ptr session::pop_alert() { diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 753b9641a..28d0f9680 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -319,6 +319,13 @@ namespace aux { TORRENT_SETTING(boolean, ignore_resume_timestamps) TORRENT_SETTING(boolean, anonymous_mode) TORRENT_SETTING(integer, tick_interval) + TORRENT_SETTING(integer, upload_rate_limit) + TORRENT_SETTING(integer, download_rate_limit) + TORRENT_SETTING(integer, local_upload_rate_limit) + TORRENT_SETTING(integer, local_download_rate_limit) + TORRENT_SETTING(integer, unchoke_slots_limit) + TORRENT_SETTING(integer, half_open_limit) + TORRENT_SETTING(integer, connections_limit) }; #undef TORRENT_SETTING @@ -486,9 +493,7 @@ namespace aux { #endif , m_abort(false) , m_paused(false) - , m_max_uploads(8) , m_allowed_upload_slots(8) - , m_max_connections(200) , m_num_unchoked(0) , m_unchoke_time_scaler(0) , m_auto_manage_time_scaler(0) @@ -617,6 +622,7 @@ namespace aux { // before XP SP2, there was no limit m_half_open.limit(0); } + m_settings.half_open_limit = m_half_open.limit(); #endif m_bandwidth_channel[peer_connection::download_channel] = &m_download_channel; @@ -724,11 +730,12 @@ namespace aux { rl.rlim_cur -= 20; // 80% of the available file descriptors should go - m_max_connections = (std::min)(m_max_connections, int(rl.rlim_cur * 8 / 10)); + m_settings.connections_limit = (std::min)(m_settings.connections_limit + , int(rl.rlim_cur * 8 / 10)); // 20% goes towards regular files m_files.resize((std::min)(m_files.size_limit(), int(rl.rlim_cur * 2 / 10))); #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_logger) << time_now_string() << " max connections: " << m_max_connections << "\n"; + (*m_logger) << time_now_string() << " max connections: " << m_settings.connections_limit << "\n"; (*m_logger) << time_now_string() << " max files: " << m_files.size_limit() << "\n"; #endif } @@ -750,6 +757,10 @@ namespace aux { url_random((char*)&m_peer_id[print.length()], (char*)&m_peer_id[0] + 20); + update_rate_settings(); + update_connections_limit(); + update_unchoke_limit(); + m_thread.reset(new thread(boost::bind(&session_impl::main_thread, this))); } @@ -790,18 +801,6 @@ namespace aux { entry& e = *eptr; - if (flags & session::save_settings) - { - // TODO: move these to session_settings - e["upload_rate_limit"] = upload_rate_limit(); - e["download_rate_limit"] = download_rate_limit(); - e["local_upload_rate_limit"] = local_upload_rate_limit(); - e["local_download_rate_limit"] = local_download_rate_limit(); - e["max_uploads"] = max_uploads(); - e["max_half_open_connections"] = max_half_open_connections(); - e["max_connections"] = max_connections(); - } - for (int i = 0; i < sizeof(all_settings)/sizeof(all_settings[0]); ++i) { session_category const& c = all_settings[i]; @@ -866,14 +865,6 @@ namespace aux { if (e->type() != lazy_entry::dict_t) return; - set_upload_rate_limit(e->dict_find_int_value("upload_rate_limit", 0)); - set_download_rate_limit(e->dict_find_int_value("download_rate_limit", 0)); - set_local_upload_rate_limit(e->dict_find_int_value("local_upload_rate_limit", 0)); - set_local_download_rate_limit(e->dict_find_int_value("local_download_rate_limit", 0)); - set_max_uploads(e->dict_find_int_value("max_uploads", 0)); - set_max_half_open_connections(e->dict_find_int_value("max_half_open_connections", 0)); - set_max_connections(e->dict_find_int_value("max_connections", 0)); - for (int i = 0; i < sizeof(all_settings)/sizeof(all_settings[0]); ++i) { session_category const& c = all_settings[i]; @@ -881,6 +872,17 @@ namespace aux { if (!settings) continue; load_struct(*settings, reinterpret_cast(this) + c.offset, c.map, c.num_entries); } + + update_rate_settings(); + + update_connections_limit(); + update_unchoke_limit(); + + // in case we just set a socks proxy, we might have to + // open the socks incoming connection + if (!m_socks_listen_socket) open_new_incoming_socks_connection(); + m_udp_socket.set_proxy_settings(m_proxy); + #ifndef TORRENT_DISABLE_DHT settings = e->dict_find_dict("dht"); if (settings) @@ -1265,6 +1267,9 @@ namespace aux { || m_settings.low_prio_disk != s.low_prio_disk) update_disk_io_thread = true; + bool connections_limit_changed = m_settings.connections_limit != s.connections_limit; + bool unchoke_limit_changed = m_settings.unchoke_slots_limit != s.unchoke_slots_limit; + #ifndef TORRENT_NO_DEPRECATE // support deprecated choker settings if (s.choking_algorithm == session_settings::rate_based_choker) @@ -1342,6 +1347,11 @@ namespace aux { m_settings = s; + update_rate_settings(); + + if (connections_limit_changed) update_connections_limit(); + if (unchoke_limit_changed) update_unchoke_limit(); + // enable anonymous mode. We don't want to accept any incoming // connections, except through a proxy. if (anonymous) @@ -1376,10 +1386,10 @@ namespace aux { } if (s.choking_algorithm == session_settings::fixed_slots_choker) - m_allowed_upload_slots = m_max_uploads; + m_allowed_upload_slots = m_settings.unchoke_slots_limit; else if (s.choking_algorithm == session_settings::auto_expand_choker - && m_allowed_upload_slots < m_max_uploads) - m_allowed_upload_slots = m_max_uploads; + && m_allowed_upload_slots < m_settings.unchoke_slots_limit) + m_allowed_upload_slots = m_settings.unchoke_slots_limit; // replace all occurances of '\n' with ' '. std::string::iterator i = m_settings.user_agent.begin(); @@ -1791,8 +1801,8 @@ namespace aux { // because we have too many files open, try again // and lower the number of file descriptors used // elsewere. - if (m_max_connections > 10) - --m_max_connections; + if (m_settings.connections_limit > 10) + --m_settings.connections_limit; // try again, but still alert the user of the problem async_accept(listener); } @@ -1844,10 +1854,10 @@ namespace aux { // don't allow more connections than the max setting bool reject = false; if (m_settings.ignore_limits_on_local_network && is_local(endp.address())) - reject = max_connections() < INT_MAX / 12 - && num_connections() >= max_connections() * 12 / 10; + reject = m_settings.connections_limit < INT_MAX / 12 + && num_connections() >= m_settings.connections_limit * 12 / 10; else - reject = num_connections() >= max_connections(); + reject = num_connections() >= m_settings.connections_limit; if (reject) { @@ -1859,7 +1869,7 @@ namespace aux { } #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << "number of connections limit exceeded (conns: " - << num_connections() << ", limit: " << max_connections() + << num_connections() << ", limit: " << m_settings.connections_limit << "), connection rejected\n"; #endif return; @@ -2393,7 +2403,7 @@ namespace aux { int free_slots = m_half_open.free_slots(); if (!m_torrents.empty() && free_slots > -m_half_open.limit() - && num_connections() < m_max_connections + && num_connections() < m_settings.connections_limit && !m_abort && m_settings.connection_speed > 0) { @@ -2446,8 +2456,8 @@ namespace aux { // we ran out of memory trying to connect to a peer // lower the global limit to the number of peers // we already have - m_max_connections = num_connections(); - if (m_max_connections < 2) m_max_connections = 2; + m_settings.connections_limit = num_connections(); + if (m_settings.connections_limit < 2) m_settings.connections_limit = 2; } #endif } @@ -2466,7 +2476,7 @@ namespace aux { // attempts this tick, abort if (max_connections == 0) break; // maintain the global limit on number of connections - if (num_connections() >= m_max_connections) break; + if (num_connections() >= m_settings.connections_limit) break; } } @@ -2510,7 +2520,7 @@ namespace aux { { m_disconnect_time_scaler = 90; - if (num_connections() >= max_connections() * m_settings.peer_turnover_cutoff + if (num_connections() >= m_settings.connections_limit * m_settings.peer_turnover_cutoff && !m_torrents.empty()) { // every 90 seconds, disconnect the worst peers @@ -2979,7 +2989,7 @@ namespace aux { ++m_allowed_upload_slots; } else if (m_upload_rate.queue_size() > 1 - && m_allowed_upload_slots > m_max_uploads) + && m_allowed_upload_slots > m_settings.unchoke_slots_limit) { --m_allowed_upload_slots; } @@ -3753,16 +3763,98 @@ namespace aux { TORRENT_ASSERT(m_connections.empty()); } +#ifndef TORRENT_NO_DEPRECATE + int session_impl::max_connections() const + { + return m_settings.connections_limit; + } + + int session_impl::max_uploads() const + { + return m_settings.unchoke_slots_limit; + } + + int session_impl::max_half_open_connections() const + { + return m_settings.half_open_limit; + } + + void session_impl::set_local_download_rate_limit(int bytes_per_second) + { + session_settings s = m_settings; + s.local_download_rate_limit = bytes_per_second; + set_settings(s); + } + + void session_impl::set_local_upload_rate_limit(int bytes_per_second) + { + session_settings s = m_settings; + s.local_upload_rate_limit = bytes_per_second; + set_settings(s); + } + + void session_impl::set_download_rate_limit(int bytes_per_second) + { + session_settings s = m_settings; + s.download_rate_limit = bytes_per_second; + set_settings(s); + } + + void session_impl::set_upload_rate_limit(int bytes_per_second) + { + session_settings s = m_settings; + s.upload_rate_limit = bytes_per_second; + set_settings(s); + } + + void session_impl::set_max_half_open_connections(int limit) + { + session_settings s = m_settings; + s.half_open_limit = limit; + set_settings(s); + } + + void session_impl::set_max_connections(int limit) + { + session_settings s = m_settings; + s.connections_limit = limit; + set_settings(s); + } + void session_impl::set_max_uploads(int limit) { - TORRENT_ASSERT(limit >= 0 || limit == -1); + session_settings s = m_settings; + s.unchoke_slots_limit = limit; + set_settings(s); + } - INVARIANT_CHECK; + int session_impl::local_upload_rate_limit() const + { + return m_local_upload_channel.throttle(); + } - if (limit < 0) limit = (std::numeric_limits::max)(); - if (m_max_uploads == limit) return; - m_max_uploads = limit; - m_allowed_upload_slots = limit; + int session_impl::local_download_rate_limit() const + { + return m_local_download_channel.throttle(); + } + + int session_impl::upload_rate_limit() const + { + return m_upload_channel.throttle(); + } + + int session_impl::download_rate_limit() const + { + return m_download_channel.throttle(); + } +#endif + + void session_impl::update_unchoke_limit() + { + if (m_settings.unchoke_slots_limit < 0) + m_settings.unchoke_slots_limit = (std::numeric_limits::max)(); + + m_allowed_upload_slots = m_settings.unchoke_slots_limit; if (m_settings.num_optimistic_unchoke_slots >= m_allowed_upload_slots / 2) { if (m_alerts.should_post()) @@ -3771,37 +3863,59 @@ namespace aux { } } - void session_impl::set_max_connections(int limit) + void session_impl::update_rate_settings() + { + if (m_settings.half_open_limit <= 0) m_settings.half_open_limit + = (std::numeric_limits::max)(); + m_half_open.limit(m_settings.half_open_limit); + + if (m_settings.local_download_rate_limit < 0) + m_settings.local_download_rate_limit = 0; + m_local_download_channel.throttle(m_settings.local_download_rate_limit); + + if (m_settings.local_upload_rate_limit < 0) + m_settings.local_upload_rate_limit = 0; + m_local_upload_channel.throttle(m_settings.local_upload_rate_limit); + + if (m_settings.download_rate_limit < 0) + m_settings.download_rate_limit = 0; + m_download_channel.throttle(m_settings.download_rate_limit); + + if (m_settings.upload_rate_limit < 0) + m_settings.upload_rate_limit = 0; + m_upload_channel.throttle(m_settings.upload_rate_limit); + } + + void session_impl::update_connections_limit() { INVARIANT_CHECK; - if (limit <= 0) + if (m_settings.connections_limit <= 0) { - limit = (std::numeric_limits::max)(); + m_settings.connections_limit = (std::numeric_limits::max)(); #if TORRENT_USE_RLIMIT 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; + m_settings.connections_limit = l.rlim_cur - m_settings.file_pool_size; + if (m_settings.connections_limit < 5) m_settings.connections_limit = 5; } #endif } - m_max_connections = limit; - if (num_connections() > max_connections() && !m_torrents.empty()) + if (num_connections() > m_settings.connections_limit && !m_torrents.empty()) { // if we have more connections that we're allowed, disconnect // peers from the torrents so that they are all as even as possible - int to_disconnect = num_connections() - max_connections(); + int to_disconnect = num_connections() - m_settings.connections_limit; int last_average = 0; - int average = max_connections() / m_torrents.size(); + int average = m_settings.connections_limit / m_torrents.size(); // the number of slots that are unused by torrents - int extra = max_connections() % m_torrents.size(); + int extra = m_settings.connections_limit % m_torrents.size(); // run 3 iterations of this, then we're probably close enough for (int iter = 0; iter < 4; ++iter) @@ -3848,46 +3962,6 @@ namespace aux { } } - void session_impl::set_max_half_open_connections(int limit) - { - INVARIANT_CHECK; - - if (limit <= 0) limit = (std::numeric_limits::max)(); - m_half_open.limit(limit); - } - - void session_impl::set_local_download_rate_limit(int bytes_per_second) - { - INVARIANT_CHECK; - - if (bytes_per_second <= 0) bytes_per_second = 0; - m_local_download_channel.throttle(bytes_per_second); - } - - void session_impl::set_local_upload_rate_limit(int bytes_per_second) - { - INVARIANT_CHECK; - - if (bytes_per_second <= 0) bytes_per_second = 0; - m_local_upload_channel.throttle(bytes_per_second); - } - - void session_impl::set_download_rate_limit(int bytes_per_second) - { - INVARIANT_CHECK; - - if (bytes_per_second <= 0) bytes_per_second = 0; - m_download_channel.throttle(bytes_per_second); - } - - void session_impl::set_upload_rate_limit(int bytes_per_second) - { - INVARIANT_CHECK; - - if (bytes_per_second <= 0) bytes_per_second = 0; - m_upload_channel.throttle(bytes_per_second); - } - void session_impl::set_alert_dispatch(boost::function)> const& fun) { m_alerts.set_dispatch_function(fun); @@ -3916,26 +3990,6 @@ namespace aux { return m_alerts.set_alert_queue_size_limit(queue_size_limit_); } - int session_impl::local_upload_rate_limit() const - { - return m_local_upload_channel.throttle(); - } - - int session_impl::local_download_rate_limit() const - { - return m_local_download_channel.throttle(); - } - - int session_impl::upload_rate_limit() const - { - return m_upload_channel.throttle(); - } - - int session_impl::download_rate_limit() const - { - return m_download_channel.throttle(); - } - void session_impl::start_lsd() { INVARIANT_CHECK; @@ -4155,10 +4209,10 @@ namespace aux { TORRENT_ASSERT(int(unique.size()) == total_downloaders); std::set unique_peers; - TORRENT_ASSERT(m_max_connections > 0); - TORRENT_ASSERT(m_max_uploads >= 0); + TORRENT_ASSERT(m_settings.connections_limit > 0); + TORRENT_ASSERT(m_settings.unchoke_slots_limit >= 0); if (m_settings.choking_algorithm == session_settings::auto_expand_choker) - TORRENT_ASSERT(m_allowed_upload_slots >= m_max_uploads); + TORRENT_ASSERT(m_allowed_upload_slots >= m_settings.unchoke_slots_limit); int unchokes = 0; int num_optimistic = 0; for (connection_map::const_iterator i = m_connections.begin(); diff --git a/src/torrent.cpp b/src/torrent.cpp index 167cdb5f4..603ebad2b 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -4328,7 +4328,7 @@ namespace libtorrent #endif TORRENT_ASSERT(want_more_peers()); - TORRENT_ASSERT(m_ses.num_connections() < m_ses.max_connections()); + TORRENT_ASSERT(m_ses.num_connections() < m_ses.settings().connections_limit); tcp::endpoint a(peerinfo->ip()); TORRENT_ASSERT((m_ses.m_ip_filter.access(peerinfo->address()) & ip_filter::blocked) == 0); diff --git a/test/test_auto_unchoke.cpp b/test/test_auto_unchoke.cpp index 63d9787d9..1b4cf3845 100644 --- a/test/test_auto_unchoke.cpp +++ b/test/test_auto_unchoke.cpp @@ -25,18 +25,18 @@ void test_swarm() // immediately. To make the swarm actually connect all // three peers before finishing. float rate_limit = 100000; - ses1.set_upload_rate_limit(int(rate_limit)); - ses1.set_max_uploads(1); - ses2.set_download_rate_limit(int(rate_limit / 5)); - ses3.set_download_rate_limit(int(rate_limit / 5)); - ses2.set_upload_rate_limit(int(rate_limit / 10)); - ses3.set_upload_rate_limit(int(rate_limit / 10)); session_settings settings; settings.allow_multiple_connections_per_ip = true; settings.ignore_limits_on_local_network = false; settings.choking_algorithm = session_settings::auto_expand_choker; + settings.upload_rate_limit = rate_limit; + settings.unchoke_slots_limit = 1; ses1.set_settings(settings); + + settings.upload_rate_limit = rate_limit / 10; + settings.download_rate_limit = rate_limit / 5; + settings.unchoke_slots_limit = 0; ses2.set_settings(settings); ses3.set_settings(settings); diff --git a/test/test_pex.cpp b/test/test_pex.cpp index edf48ceff..57a95cee7 100644 --- a/test/test_pex.cpp +++ b/test/test_pex.cpp @@ -53,13 +53,21 @@ void test_pex() // immediately. To make the swarm actually connect all // three peers before finishing. float rate_limit = 1000; - ses1.set_upload_rate_limit(int(rate_limit)); - ses2.set_download_rate_limit(int(rate_limit)); - ses3.set_download_rate_limit(int(rate_limit)); + session_settings set = ses1.settings(); + set.upload_rate_limit = rate_limit; + ses1.set_settings(set); + // make the peer connecting the two worthless to transfer // data, to force peer 3 to connect directly to peer 1 through pex - ses2.set_upload_rate_limit(2000); - ses3.set_upload_rate_limit(int(rate_limit / 2)); + set = ses2.settings(); + set.download_rate_limit = rate_limit; + set.upload_rate_limit = 2000; + ses2.set_settings(set); + + set = ses3.settings(); + set.download_rate_limit = rate_limit; + set.upload_rate_limit = rate_limit / 2; + ses3.set_settings(set); ses1.add_extension(&create_ut_pex_plugin); ses2.add_extension(&create_ut_pex_plugin); diff --git a/test/test_swarm.cpp b/test/test_swarm.cpp index e141d0849..90fc4a441 100644 --- a/test/test_swarm.cpp +++ b/test/test_swarm.cpp @@ -60,17 +60,17 @@ void test_swarm(bool super_seeding = false, bool strict = false, bool seed_mode // immediately. To make the swarm actually connect all // three peers before finishing. float rate_limit = 100000; - ses1.set_upload_rate_limit(int(rate_limit)); - ses2.set_download_rate_limit(int(rate_limit)); - ses3.set_download_rate_limit(int(rate_limit)); - ses2.set_upload_rate_limit(int(rate_limit / 2)); - ses3.set_upload_rate_limit(int(rate_limit / 2)); session_settings settings; settings.allow_multiple_connections_per_ip = true; settings.ignore_limits_on_local_network = false; settings.strict_super_seeding = strict; + + settings.upload_rate_limit = rate_limit; ses1.set_settings(settings); + + settings.download_rate_limit = rate_limit / 2; + settings.upload_rate_limit = rate_limit; ses2.set_settings(settings); ses3.set_settings(settings); diff --git a/test/test_transfer.cpp b/test/test_transfer.cpp index 6a3c1881f..70ea0aa7b 100644 --- a/test/test_transfer.cpp +++ b/test/test_transfer.cpp @@ -82,7 +82,7 @@ void test_rate() ptime start = time_now(); - for (int i = 0; i < 70; ++i) + for (int i = 0; i < 7; ++i) { print_alerts(ses1, "ses1"); print_alerts(ses2, "ses2"); @@ -97,7 +97,7 @@ void test_rate() << std::endl; if (tor2.is_seed()) break; - test_sleep(100); + test_sleep(1000); } TEST_CHECK(tor2.is_seed()); @@ -263,7 +263,7 @@ void test_transfer(int proxy_type, bool test_disk_full = false, bool test_allowe if (test_allowed_fast) { sett.allowed_fast_set_size = 2000; - ses1.set_max_uploads(0); + sett.unchoke_slots_limit = 0; } sett.min_reconnect_time = 1; @@ -324,7 +324,9 @@ void test_transfer(int proxy_type, bool test_disk_full = false, bool test_allowe & ~alert::stats_notification); // ses1.set_alert_dispatch(&print_alert); - ses2.set_download_rate_limit(tor2.get_torrent_info().piece_length() * 5); + sett = ses2.settings(); + sett.download_rate_limit = tor2.get_torrent_info().piece_length() * 5; + ses2.set_settings(sett); // also test to move the storage of the downloader and the uploader // to make sure it can handle switching paths