From 297b8943d0a9f1ff8ff90cd1369b089b3aa1444d Mon Sep 17 00:00:00 2001 From: arvidn Date: Sun, 17 Jan 2016 15:09:27 -0500 Subject: [PATCH] move the DHT rate limiter into the dht_tracker class and remove the rate_limited_udp_socket type. This further simplifies the udp socket (preparing for moving it into the listen_socket structure) --- include/libtorrent/aux_/session_impl.hpp | 4 +- include/libtorrent/kademlia/dht_tracker.hpp | 8 +++- include/libtorrent/session_settings.hpp | 6 +++ include/libtorrent/settings_pack.hpp | 4 ++ include/libtorrent/udp_socket.hpp | 15 -------- src/kademlia/dht_tracker.cpp | 39 +++++++++++++++++--- src/session.cpp | 4 -- src/session_impl.cpp | 8 +++- src/settings_pack.cpp | 2 +- src/udp_socket.cpp | 41 --------------------- 10 files changed, 59 insertions(+), 72 deletions(-) diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 6ebfbffbc..40747feb4 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -635,7 +635,9 @@ namespace libtorrent void update_connection_speed(); void update_queued_disk_bytes(); void update_alert_queue_size(); +#ifndef TORRENT_NO_DEPRECATE void update_dht_upload_rate_limit(); +#endif void update_disk_threads(); void update_network_threads(); void update_cache_buffer_chunk_size(); @@ -1031,7 +1033,7 @@ namespace libtorrent // but for the udp port used by the DHT. int m_external_udp_port; - rate_limited_udp_socket m_udp_socket; + udp_socket m_udp_socket; libtorrent::utp_socket_manager m_utp_socket_manager; #ifdef TORRENT_USE_OPENSSL diff --git a/include/libtorrent/kademlia/dht_tracker.hpp b/include/libtorrent/kademlia/dht_tracker.hpp index 7474b6204..e2cc65c38 100644 --- a/include/libtorrent/kademlia/dht_tracker.hpp +++ b/include/libtorrent/kademlia/dht_tracker.hpp @@ -71,7 +71,7 @@ namespace libtorrent { namespace dht , udp_socket_observer , boost::enable_shared_from_this { - dht_tracker(dht_observer* observer, rate_limited_udp_socket& sock + dht_tracker(dht_observer* observer, udp_socket& sock , dht_settings const& settings, counters& cnt , dht_storage_constructor_type storage_constructor , entry const& state); @@ -155,7 +155,7 @@ namespace libtorrent { namespace dht counters& m_counters; node m_dht; - rate_limited_udp_socket& m_sock; + udp_socket& m_sock; dht_logger* m_log; std::vector m_send_buf; @@ -170,6 +170,10 @@ namespace libtorrent { namespace dht // used to resolve hostnames for nodes udp::resolver m_host_resolver; + + // state for the send rate limit + int m_send_quota; + time_point m_last_tick; }; }} diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index a65b73826..e69b8208c 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -1406,6 +1406,7 @@ namespace libtorrent , block_ratelimit(5) , read_only(false) , item_lifetime(0) + , upload_rate_limit(8000) {} // the maximum number of peers to send in a reply to ``get_peers`` @@ -1507,6 +1508,11 @@ namespace libtorrent // the number of seconds a immutable/mutable item will be expired. // default is 0, means never expires. int item_lifetime; + + // the number of bytes per second (on average) the DHT is allowed to send. + // If the incoming requests causes to many bytes to be sent in responses, + // incoming requests will be dropped until the quota has been replenished. + int upload_rate_limit; }; diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index 9531ecb9c..7575ab887 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -1248,11 +1248,15 @@ namespace libtorrent deprecated4, #endif +#ifndef TORRENT_NO_DEPRECATE // ``dht_upload_rate_limit`` sets the rate limit on the DHT. This is // specified in bytes per second and defaults to 4000. For busy boxes // with lots of torrents that requires more DHT traffic, this should // be raised. dht_upload_rate_limit, +#else + deprecated7, +#endif // ``unchoke_slots_limit`` is the max number of unchoked peers in the // session. The number of unchoke slots may be ignored depending on diff --git a/include/libtorrent/udp_socket.hpp b/include/libtorrent/udp_socket.hpp index 1b21cde01..4293b46b2 100644 --- a/include/libtorrent/udp_socket.hpp +++ b/include/libtorrent/udp_socket.hpp @@ -309,21 +309,6 @@ namespace libtorrent int m_outstanding_socks; #endif }; - - struct rate_limited_udp_socket : public udp_socket - { - rate_limited_udp_socket(io_service& ios); - void set_rate_limit(int limit) { m_rate_limit = limit; } - bool send(udp::endpoint const& ep, char const* p, int len - , error_code& ec, int flags = 0); - bool has_quota(); - - private: - - int m_rate_limit; - int m_quota; - time_point m_last_tick; - }; } #endif diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index 2f8d7e67c..98cf7c5be 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/version.hpp" #include "libtorrent/time.hpp" #include "libtorrent/performance_counters.hpp" // for counters +#include "libtorrent/aux_/time.hpp" #include "libtorrent/aux_/disable_warnings_push.hpp" @@ -89,7 +90,7 @@ namespace libtorrent { namespace dht // class that puts the networking and the kademlia node in a single // unit and connecting them together. dht_tracker::dht_tracker(dht_observer* observer - , rate_limited_udp_socket& sock + , udp_socket& sock , dht_settings const& settings , counters& cnt , dht_storage_constructor_type storage_constructor @@ -104,6 +105,8 @@ namespace libtorrent { namespace dht , m_settings(settings) , m_abort(false) , m_host_resolver(sock.get_io_service()) + , m_send_quota(settings.upload_rate_limit) + , m_last_tick(aux::time_now()) { #ifndef TORRENT_DISABLE_LOGGING m_log->log(dht_logger::tracker, "starting DHT tracker with node id: %s" @@ -406,10 +409,18 @@ namespace libtorrent { namespace dht bool dht_tracker::has_quota() { - return m_sock.has_quota(); + time_point now = clock_type::now(); + time_duration delta = now - m_last_tick; + m_last_tick = now; + // add any new quota we've accrued since last time + m_send_quota += boost::uint64_t(m_settings.upload_rate_limit) + * total_microseconds(delta) / 1000000; + return m_send_quota > 0; } - bool dht_tracker::send_packet(libtorrent::entry& e, udp::endpoint const& addr, int send_flags) + // TODO: 4 do we need the flags here? + bool dht_tracker::send_packet(libtorrent::entry& e, udp::endpoint const& addr + , int send_flags) { using libtorrent::bencode; using libtorrent::entry; @@ -420,10 +431,26 @@ namespace libtorrent { namespace dht m_send_buf.clear(); bencode(std::back_inserter(m_send_buf), e); - error_code ec; - bool ret = m_sock.send(addr, &m_send_buf[0], int(m_send_buf.size()), ec, send_flags); - if (!ret || ec) + // update the quota. We won't prevent the packet to be sent if we exceed + // the quota, we'll just (potentially) block the next incoming request. + time_point const now = clock_type::now(); + time_duration const delta = now - m_last_tick; + m_last_tick = now; + + // add any new quota we've accrued since last time + m_send_quota += boost::uint64_t(m_settings.upload_rate_limit) + * total_microseconds(delta) / 1000000; + + // allow 3 seconds worth of burst + if (m_send_quota > 3 * m_settings.upload_rate_limit) + m_send_quota = 3 * m_settings.upload_rate_limit; + + m_send_quota -= m_send_buf.size(); + + error_code ec; + m_sock.send(addr, &m_send_buf[0], int(m_send_buf.size()), ec, send_flags); + if (ec) { m_counters.inc_stats_counter(counters::dht_messages_out_dropped); #ifndef TORRENT_DISABLE_LOGGING diff --git a/src/session.cpp b/src/session.cpp index adacc0eb5..f89724a69 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -204,10 +204,6 @@ namespace libtorrent // unchoke many peers set.set_int(settings_pack::unchoke_slots_limit, 2000); - // we need more DHT capacity to ping more peers - // candidates before trying to connect - set.set_int(settings_pack::dht_upload_rate_limit, 20000); - // use 1 GB of cache set.set_int(settings_pack::cache_size, 32768 * 2); set.set_bool(settings_pack::use_read_cache, true); diff --git a/src/session_impl.cpp b/src/session_impl.cpp index fc128f79c..9b9fc0ab0 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -438,7 +438,6 @@ namespace aux { #if TORRENT_USE_ASSERTS m_posting_torrent_updates = false; #endif - m_udp_socket.set_rate_limit(m_settings.get_int(settings_pack::dht_upload_rate_limit)); m_udp_socket.subscribe(&m_utp_socket_manager); m_udp_socket.subscribe(this); @@ -6067,10 +6066,15 @@ retry: || m_settings.get_int(settings_pack::unchoke_slots_limit) < 0; } +#ifndef TORRENT_NO_DEPRECATE void session_impl::update_dht_upload_rate_limit() { - m_udp_socket.set_rate_limit(m_settings.get_int(settings_pack::dht_upload_rate_limit)); +#ifndef TORRENT_DISABLE_DHT + m_dht_settings.upload_rate_limit + = m_settings.get_int(settings_pack::dht_upload_rate_limit); +#endif } +#endif void session_impl::update_disk_threads() { diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index 9d34fa9f6..dabcb5e8b 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -297,7 +297,7 @@ namespace libtorrent SET(download_rate_limit, 0, &session_impl::update_download_rate), DEPRECATED_SET(local_upload_rate_limit, 0, &session_impl::update_local_upload_rate), DEPRECATED_SET(local_download_rate_limit, 0, &session_impl::update_local_download_rate), - SET(dht_upload_rate_limit, 4000, &session_impl::update_dht_upload_rate_limit), + DEPRECATED_SET(dht_upload_rate_limit, 4000, &session_impl::update_dht_upload_rate_limit), SET(unchoke_slots_limit, 8, &session_impl::update_unchoke_limit), DEPRECATED_SET(half_open_limit, 0, 0), SET(connections_limit, 200, &session_impl::update_connections_limit), diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index c3726b5ca..92586fc4e 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -1413,44 +1413,3 @@ void udp_socket::drain_queue() } } -rate_limited_udp_socket::rate_limited_udp_socket(io_service& ios) - : udp_socket(ios) - , m_rate_limit(8000) - , m_quota(8000) - , m_last_tick(aux::time_now()) -{ -} - -bool rate_limited_udp_socket::has_quota() -{ - time_point now = clock_type::now(); - time_duration delta = now - m_last_tick; - m_last_tick = now; - // add any new quota we've accrued since last time - m_quota += boost::uint64_t(m_rate_limit) * total_microseconds(delta) / 1000000; - return m_quota > 0; -} - -bool rate_limited_udp_socket::send(udp::endpoint const& ep, char const* p - , int len, error_code& ec, int flags) -{ - time_point now = clock_type::now(); - time_duration delta = now - m_last_tick; - m_last_tick = now; - - // add any new quota we've accrued since last time - m_quota += boost::uint64_t(m_rate_limit) * total_microseconds(delta) / 1000000; - - // allow 3 seconds worth of burst - if (m_quota > 3 * m_rate_limit) m_quota = 3 * m_rate_limit; - - // if there's no quota, and it's OK to drop, just - // drop the packet - if (m_quota < 0 && (flags & dont_drop) == 0) return false; - - m_quota -= len; - if (m_quota < 0) m_quota = 0; - udp_socket::send(ep, p, len, ec, flags); - return true; -} -