2006-08-01 17:27:08 +02:00
|
|
|
/*
|
|
|
|
|
2016-01-18 00:57:46 +01:00
|
|
|
Copyright (c) 2006-2016, Arvid Norberg
|
2006-08-01 17:27:08 +02:00
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in
|
|
|
|
the documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of the author nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived
|
|
|
|
from this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <set>
|
|
|
|
#include <numeric>
|
2015-05-10 20:38:10 +02:00
|
|
|
|
|
|
|
#include "libtorrent/config.hpp"
|
2006-08-01 17:27:08 +02:00
|
|
|
|
|
|
|
#include "libtorrent/kademlia/node.hpp"
|
|
|
|
#include "libtorrent/kademlia/node_id.hpp"
|
|
|
|
#include "libtorrent/kademlia/traversal_algorithm.hpp"
|
|
|
|
#include "libtorrent/kademlia/dht_tracker.hpp"
|
2008-11-11 18:51:02 +01:00
|
|
|
#include "libtorrent/kademlia/msg.hpp"
|
2015-05-10 06:54:02 +02:00
|
|
|
#include "libtorrent/kademlia/dht_observer.hpp"
|
2006-08-01 17:27:08 +02:00
|
|
|
|
|
|
|
#include "libtorrent/socket.hpp"
|
2009-09-16 05:46:36 +02:00
|
|
|
#include "libtorrent/socket_io.hpp"
|
2006-08-01 17:27:08 +02:00
|
|
|
#include "libtorrent/bencode.hpp"
|
|
|
|
#include "libtorrent/io.hpp"
|
|
|
|
#include "libtorrent/version.hpp"
|
2015-05-09 20:06:02 +02:00
|
|
|
#include "libtorrent/time.hpp"
|
2014-07-06 21:18:00 +02:00
|
|
|
#include "libtorrent/performance_counters.hpp" // for counters
|
2016-01-17 21:09:27 +01:00
|
|
|
#include "libtorrent/aux_/time.hpp"
|
2016-06-04 20:04:29 +02:00
|
|
|
#include "libtorrent/session_status.hpp"
|
2006-08-01 17:27:08 +02:00
|
|
|
|
2016-05-23 14:15:39 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2016-06-04 16:01:43 +02:00
|
|
|
#include "libtorrent/hex.hpp" // to_hex
|
2016-05-23 14:15:39 +02:00
|
|
|
#endif
|
|
|
|
|
2015-05-09 21:00:22 +02:00
|
|
|
using libtorrent::dht::node;
|
2006-08-01 17:27:08 +02:00
|
|
|
using libtorrent::dht::node_id;
|
|
|
|
using libtorrent::dht::packet_t;
|
|
|
|
using libtorrent::dht::msg;
|
2015-07-04 04:33:17 +02:00
|
|
|
using libtorrent::detail::write_endpoint;
|
2016-05-25 06:31:52 +02:00
|
|
|
using namespace std::placeholders;
|
2006-08-01 17:27:08 +02:00
|
|
|
|
|
|
|
namespace libtorrent { namespace dht
|
|
|
|
{
|
2009-09-25 18:32:02 +02:00
|
|
|
void incoming_error(entry& e, char const* msg);
|
|
|
|
|
2015-04-20 06:52:49 +02:00
|
|
|
namespace {
|
|
|
|
|
2016-01-01 15:21:07 +01:00
|
|
|
// generate a new write token key every 5 minutes
|
|
|
|
time_duration const key_refresh
|
|
|
|
= duration_cast<time_duration>(minutes(5));
|
|
|
|
|
2015-11-14 06:08:57 +01:00
|
|
|
node_id extract_node_id(entry const& e, std::string const& key)
|
2008-11-11 09:33:34 +01:00
|
|
|
{
|
2016-01-01 15:21:07 +01:00
|
|
|
if (e.type() != entry::dictionary_t) return (node_id::min)();
|
2015-11-14 06:08:57 +01:00
|
|
|
entry const* nid = e.find_key(key);
|
2016-06-20 17:32:06 +02:00
|
|
|
if (nid == nullptr || nid->type() != entry::string_t || nid->string().length() != 20)
|
2009-11-23 09:38:50 +01:00
|
|
|
return (node_id::min)();
|
2015-08-22 22:01:53 +02:00
|
|
|
return node_id(nid->string().c_str());
|
2008-11-11 09:33:34 +01:00
|
|
|
}
|
|
|
|
|
2016-06-04 20:04:29 +02:00
|
|
|
void add_dht_counters(node const& dht, counters& c)
|
|
|
|
{
|
|
|
|
int nodes, replacements, allocated_observers;
|
2016-06-20 17:32:06 +02:00
|
|
|
std::tie(nodes, replacements, allocated_observers) = dht.get_stats_counters();
|
2016-06-04 20:04:29 +02:00
|
|
|
|
|
|
|
c.inc_stats_counter(counters::dht_nodes, nodes);
|
|
|
|
c.inc_stats_counter(counters::dht_node_cache, replacements);
|
|
|
|
c.inc_stats_counter(counters::dht_allocated_observers, allocated_observers);
|
|
|
|
}
|
|
|
|
|
2015-04-20 06:52:49 +02:00
|
|
|
} // anonymous namespace
|
|
|
|
|
2006-08-01 17:27:08 +02:00
|
|
|
// class that puts the networking and the kademlia node in a single
|
|
|
|
// unit and connecting them together.
|
2015-05-09 20:06:02 +02:00
|
|
|
dht_tracker::dht_tracker(dht_observer* observer
|
2016-04-24 21:26:28 +02:00
|
|
|
, io_service& ios
|
|
|
|
, send_fun_t const& send_fun
|
2015-05-09 20:06:02 +02:00
|
|
|
, dht_settings const& settings
|
|
|
|
, counters& cnt
|
2016-06-04 01:44:16 +02:00
|
|
|
, dht_storage_interface& storage
|
2016-01-01 15:21:07 +01:00
|
|
|
, entry const& state)
|
2014-07-06 21:18:00 +02:00
|
|
|
: m_counters(cnt)
|
2016-06-04 01:44:16 +02:00
|
|
|
, m_storage(storage)
|
2016-02-12 04:56:52 +01:00
|
|
|
, m_dht(udp::v4(), this, settings, extract_node_id(state, "node-id")
|
2016-06-04 01:44:16 +02:00
|
|
|
, observer, cnt, m_nodes, storage)
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
2016-02-12 04:56:52 +01:00
|
|
|
, m_dht6(udp::v6(), this, settings, extract_node_id(state, "node-id6")
|
2016-06-04 01:44:16 +02:00
|
|
|
, observer, cnt, m_nodes, storage)
|
2015-11-14 06:08:57 +01:00
|
|
|
#endif
|
2016-04-24 21:26:28 +02:00
|
|
|
, m_send_fun(send_fun)
|
2015-05-10 06:54:02 +02:00
|
|
|
, m_log(observer)
|
2016-04-24 21:26:28 +02:00
|
|
|
, m_key_refresh_timer(ios)
|
|
|
|
, m_connection_timer(ios)
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
, m_connection_timer6(ios)
|
|
|
|
#endif
|
2016-04-24 21:26:28 +02:00
|
|
|
, m_refresh_timer(ios)
|
2006-08-01 17:27:08 +02:00
|
|
|
, m_settings(settings)
|
2008-03-24 05:38:43 +01:00
|
|
|
, m_abort(false)
|
2016-04-24 21:26:28 +02:00
|
|
|
, m_host_resolver(ios)
|
2016-01-17 21:09:27 +01:00
|
|
|
, m_send_quota(settings.upload_rate_limit)
|
|
|
|
, m_last_tick(aux::time_now())
|
2006-08-01 17:27:08 +02:00
|
|
|
{
|
2016-01-18 08:21:27 +01:00
|
|
|
m_blocker.set_block_timer(m_settings.block_timeout);
|
|
|
|
m_blocker.set_rate_limit(m_settings.block_ratelimit);
|
2015-11-14 06:08:57 +01:00
|
|
|
|
2016-02-12 04:56:52 +01:00
|
|
|
m_nodes.insert(std::make_pair(m_dht.protocol_family_name(), &m_dht));
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
2016-02-12 04:56:52 +01:00
|
|
|
m_nodes.insert(std::make_pair(m_dht6.protocol_family_name(), &m_dht6));
|
2015-11-14 06:08:57 +01:00
|
|
|
#endif
|
|
|
|
|
2016-06-04 01:44:16 +02:00
|
|
|
update_storage_node_ids();
|
|
|
|
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-11-14 06:08:57 +01:00
|
|
|
m_log->log(dht_logger::tracker, "starting IPv4 DHT tracker with node id: %s"
|
2016-07-29 08:36:15 +02:00
|
|
|
, aux::to_hex(m_dht.nid()).c_str());
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_log->log(dht_logger::tracker, "starting IPv6 DHT tracker with node id: %s"
|
2016-07-29 08:36:15 +02:00
|
|
|
, aux::to_hex(m_dht6.nid()).c_str());
|
2015-11-14 06:08:57 +01:00
|
|
|
#endif
|
2008-11-11 18:51:02 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-07-10 13:34:45 +02:00
|
|
|
dht_tracker::~dht_tracker() = default;
|
2012-06-30 17:30:38 +02:00
|
|
|
|
2016-01-09 19:28:15 +01:00
|
|
|
void dht_tracker::update_node_id()
|
|
|
|
{
|
|
|
|
m_dht.update_node_id();
|
2016-06-04 01:44:16 +02:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_dht6.update_node_id();
|
|
|
|
#endif
|
|
|
|
update_storage_node_ids();
|
2016-01-09 19:28:15 +01:00
|
|
|
}
|
|
|
|
|
2011-11-28 12:11:29 +01:00
|
|
|
// defined in node.cpp
|
2016-01-09 19:28:15 +01:00
|
|
|
void nop();
|
2011-11-28 12:11:29 +01:00
|
|
|
|
2014-02-28 05:02:48 +01:00
|
|
|
void dht_tracker::start(entry const& bootstrap
|
|
|
|
, find_data::nodes_callback const& f)
|
2008-09-02 08:37:40 +02:00
|
|
|
{
|
2006-08-01 17:27:08 +02:00
|
|
|
std::vector<udp::endpoint> initial_nodes;
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
std::vector<udp::endpoint> initial_nodes6;
|
|
|
|
#endif
|
2006-08-01 17:27:08 +02:00
|
|
|
|
|
|
|
if (bootstrap.type() == entry::dictionary_t)
|
|
|
|
{
|
2011-02-25 18:00:36 +01:00
|
|
|
TORRENT_TRY {
|
|
|
|
if (entry const* nodes = bootstrap.find_key("nodes"))
|
|
|
|
read_endpoint_list<udp::endpoint>(nodes, initial_nodes);
|
|
|
|
} TORRENT_CATCH(std::exception&) {}
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
TORRENT_TRY{
|
|
|
|
if (entry const* nodes = bootstrap.find_key("nodes6"))
|
|
|
|
read_endpoint_list<udp::endpoint>(nodes, initial_nodes6);
|
|
|
|
} TORRENT_CATCH(std::exception&) {}
|
|
|
|
#endif
|
2006-08-01 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
2008-10-21 10:45:42 +02:00
|
|
|
error_code ec;
|
2016-01-01 15:21:07 +01:00
|
|
|
refresh_key(ec);
|
2006-08-01 17:27:08 +02:00
|
|
|
|
2013-01-14 03:42:44 +01:00
|
|
|
m_connection_timer.expires_from_now(seconds(1), ec);
|
2007-12-09 05:15:24 +01:00
|
|
|
m_connection_timer.async_wait(
|
2016-05-25 06:31:52 +02:00
|
|
|
std::bind(&dht_tracker::connection_timeout, self(), std::ref(m_dht), _1));
|
2015-11-14 06:08:57 +01:00
|
|
|
|
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_connection_timer6.expires_from_now(seconds(1), ec);
|
|
|
|
m_connection_timer6.async_wait(
|
2016-05-25 06:31:52 +02:00
|
|
|
std::bind(&dht_tracker::connection_timeout, self(), std::ref(m_dht6), _1));
|
2015-11-14 06:08:57 +01:00
|
|
|
#endif
|
2006-08-06 18:36:00 +02:00
|
|
|
|
2008-10-21 10:45:42 +02:00
|
|
|
m_refresh_timer.expires_from_now(seconds(5), ec);
|
2016-05-25 06:31:52 +02:00
|
|
|
m_refresh_timer.async_wait(std::bind(&dht_tracker::refresh_timeout, self(), _1));
|
2014-02-28 05:02:48 +01:00
|
|
|
m_dht.bootstrap(initial_nodes, f);
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_dht6.bootstrap(initial_nodes6, f);
|
|
|
|
#endif
|
2007-02-25 10:42:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void dht_tracker::stop()
|
|
|
|
{
|
2008-03-24 05:38:43 +01:00
|
|
|
m_abort = true;
|
2008-10-21 10:45:42 +02:00
|
|
|
error_code ec;
|
2016-01-01 22:42:23 +01:00
|
|
|
m_key_refresh_timer.cancel(ec);
|
2008-10-21 10:45:42 +02:00
|
|
|
m_connection_timer.cancel(ec);
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_connection_timer6.cancel(ec);
|
|
|
|
#endif
|
2008-10-21 10:45:42 +02:00
|
|
|
m_refresh_timer.cancel(ec);
|
2007-11-11 20:09:29 +01:00
|
|
|
m_host_resolver.cancel();
|
2006-08-01 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
2015-01-04 22:31:02 +01:00
|
|
|
#ifndef TORRENT_NO_DEPRECATE
|
2006-09-05 01:22:21 +02:00
|
|
|
void dht_tracker::dht_status(session_status& s)
|
|
|
|
{
|
2016-06-04 20:04:29 +02:00
|
|
|
s.dht_torrents += int(m_storage.num_torrents());
|
|
|
|
|
|
|
|
s.dht_nodes = 0;
|
|
|
|
s.dht_node_cache = 0;
|
|
|
|
s.dht_global_nodes = 0;
|
|
|
|
s.dht_torrents = 0;
|
|
|
|
s.active_requests.clear();
|
|
|
|
s.dht_total_allocations = 0;
|
|
|
|
|
|
|
|
m_dht.status(s);
|
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_dht6.status(s);
|
|
|
|
#endif
|
2006-09-05 01:22:21 +02:00
|
|
|
}
|
2015-01-04 22:31:02 +01:00
|
|
|
#endif
|
2006-09-05 01:22:21 +02:00
|
|
|
|
2015-01-17 18:02:58 +01:00
|
|
|
void dht_tracker::dht_status(std::vector<dht_routing_bucket>& table
|
|
|
|
, std::vector<dht_lookup>& requests)
|
|
|
|
{
|
2016-06-04 20:04:29 +02:00
|
|
|
m_dht.status(table, requests);
|
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_dht6.status(table, requests);
|
|
|
|
#endif
|
2015-01-17 18:02:58 +01:00
|
|
|
}
|
|
|
|
|
2015-09-17 17:11:46 +02:00
|
|
|
void dht_tracker::update_stats_counters(counters& c) const
|
|
|
|
{
|
2016-06-04 20:04:29 +02:00
|
|
|
const dht_storage_counters& dht_cnt = m_storage.counters();
|
|
|
|
c.set_value(counters::dht_torrents, dht_cnt.torrents);
|
|
|
|
c.set_value(counters::dht_peers, dht_cnt.peers);
|
|
|
|
c.set_value(counters::dht_immutable_data, dht_cnt.immutable_data);
|
|
|
|
c.set_value(counters::dht_mutable_data, dht_cnt.mutable_data);
|
|
|
|
|
|
|
|
c.set_value(counters::dht_nodes, 0);
|
|
|
|
c.set_value(counters::dht_node_cache, 0);
|
|
|
|
c.set_value(counters::dht_allocated_observers, 0);
|
|
|
|
|
|
|
|
add_dht_counters(m_dht, c);
|
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
add_dht_counters(m_dht6, c);
|
|
|
|
#endif
|
2015-09-17 17:11:46 +02:00
|
|
|
}
|
|
|
|
|
2015-11-14 06:08:57 +01:00
|
|
|
void dht_tracker::connection_timeout(node& n, error_code const& e)
|
2006-08-06 18:36:00 +02:00
|
|
|
{
|
2008-03-24 05:38:43 +01:00
|
|
|
if (e || m_abort) return;
|
|
|
|
|
2015-11-14 06:08:57 +01:00
|
|
|
time_duration d = n.connection_timeout();
|
2008-10-21 19:10:11 +02:00
|
|
|
error_code ec;
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
2016-02-12 04:56:52 +01:00
|
|
|
deadline_timer& timer = n.protocol() == udp::v4() ? m_connection_timer : m_connection_timer6;
|
2015-11-14 06:08:57 +01:00
|
|
|
#else
|
|
|
|
deadline_timer& timer = m_connection_timer;
|
|
|
|
#endif
|
|
|
|
timer.expires_from_now(d, ec);
|
2016-05-25 06:31:52 +02:00
|
|
|
timer.async_wait(std::bind(&dht_tracker::connection_timeout, self(), std::ref(n), _1));
|
2006-08-06 18:36:00 +02:00
|
|
|
}
|
|
|
|
|
2008-05-03 18:05:42 +02:00
|
|
|
void dht_tracker::refresh_timeout(error_code const& e)
|
2006-08-01 17:27:08 +02:00
|
|
|
{
|
2008-03-24 05:38:43 +01:00
|
|
|
if (e || m_abort) return;
|
|
|
|
|
2010-01-03 12:08:39 +01:00
|
|
|
m_dht.tick();
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_dht6.tick();
|
|
|
|
#endif
|
2015-01-02 00:24:21 +01:00
|
|
|
|
|
|
|
// periodically update the DOS blocker's settings from the dht_settings
|
|
|
|
m_blocker.set_block_timer(m_settings.block_timeout);
|
|
|
|
m_blocker.set_rate_limit(m_settings.block_ratelimit);
|
|
|
|
|
2008-10-21 19:10:11 +02:00
|
|
|
error_code ec;
|
2010-01-03 12:08:39 +01:00
|
|
|
m_refresh_timer.expires_from_now(seconds(5), ec);
|
2007-12-09 05:15:24 +01:00
|
|
|
m_refresh_timer.async_wait(
|
2016-05-25 06:31:52 +02:00
|
|
|
std::bind(&dht_tracker::refresh_timeout, self(), _1));
|
2006-08-01 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
2016-01-01 15:21:07 +01:00
|
|
|
void dht_tracker::refresh_key(error_code const& e)
|
2006-08-01 17:27:08 +02:00
|
|
|
{
|
2008-03-24 05:38:43 +01:00
|
|
|
if (e || m_abort) return;
|
|
|
|
|
2008-10-21 19:10:11 +02:00
|
|
|
error_code ec;
|
2016-01-01 22:42:23 +01:00
|
|
|
m_key_refresh_timer.expires_from_now(key_refresh, ec);
|
2016-05-25 06:31:52 +02:00
|
|
|
m_key_refresh_timer.async_wait(std::bind(&dht_tracker::refresh_key, self(), _1));
|
2006-08-01 17:27:08 +02:00
|
|
|
|
2016-01-01 15:21:07 +01:00
|
|
|
m_dht.new_write_key();
|
2016-06-04 01:44:16 +02:00
|
|
|
#if TORRENT_USE_IPV6
|
2015-11-14 06:08:57 +01:00
|
|
|
m_dht6.new_write_key();
|
2016-06-04 01:44:16 +02:00
|
|
|
#endif
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2016-01-01 15:21:07 +01:00
|
|
|
m_log->log(dht_logger::tracker, "*** new write key***");
|
2007-05-14 19:49:36 +02:00
|
|
|
#endif
|
2016-01-01 15:21:07 +01:00
|
|
|
}
|
2015-05-08 07:21:26 +02:00
|
|
|
|
2016-06-04 01:44:16 +02:00
|
|
|
void dht_tracker::update_storage_node_ids()
|
|
|
|
{
|
|
|
|
std::vector<sha1_hash> ids;
|
|
|
|
ids.push_back(m_dht.nid());
|
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
ids.push_back(m_dht6.nid());
|
|
|
|
#endif
|
|
|
|
m_storage.update_node_ids(ids);
|
|
|
|
}
|
|
|
|
|
2015-06-25 17:01:36 +02:00
|
|
|
void dht_tracker::get_peers(sha1_hash const& ih
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(std::vector<tcp::endpoint> const&)> f)
|
2015-06-25 17:01:36 +02:00
|
|
|
{
|
2016-08-13 03:31:55 +02:00
|
|
|
std::function<void(std::vector<std::pair<node_entry, std::string> > const&)> empty;
|
2016-06-20 17:32:06 +02:00
|
|
|
m_dht.get_peers(ih, f, empty, false);
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
2016-06-20 17:32:06 +02:00
|
|
|
m_dht6.get_peers(ih, f, empty, false);
|
2015-11-14 06:08:57 +01:00
|
|
|
#endif
|
2015-06-25 17:01:36 +02:00
|
|
|
}
|
|
|
|
|
2014-01-20 07:35:06 +01:00
|
|
|
void dht_tracker::announce(sha1_hash const& ih, int listen_port, int flags
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(std::vector<tcp::endpoint> const&)> f)
|
2006-08-01 17:27:08 +02:00
|
|
|
{
|
2014-01-20 07:35:06 +01:00
|
|
|
m_dht.announce(ih, listen_port, flags, f);
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_dht6.announce(ih, listen_port, flags, f);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
struct get_immutable_item_ctx
|
|
|
|
{
|
2016-07-10 20:27:42 +02:00
|
|
|
explicit get_immutable_item_ctx(int traversals)
|
2015-11-14 06:08:57 +01:00
|
|
|
: active_traversals(traversals)
|
|
|
|
, item_posted(false)
|
|
|
|
{}
|
|
|
|
int active_traversals;
|
|
|
|
bool item_posted;
|
|
|
|
};
|
|
|
|
|
|
|
|
// these functions provide a slightly higher level
|
|
|
|
// interface to the get/put functionality in the DHT
|
2016-08-29 14:31:23 +02:00
|
|
|
void get_immutable_item_callback(item const& it, std::shared_ptr<get_immutable_item_ctx> ctx
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(item const&)> f)
|
2015-11-14 06:08:57 +01:00
|
|
|
{
|
|
|
|
// the reason to wrap here is to control the return value
|
|
|
|
// since it controls whether we re-put the content
|
|
|
|
TORRENT_ASSERT(!it.is_mutable());
|
|
|
|
--ctx->active_traversals;
|
|
|
|
if (!ctx->item_posted && (!it.empty() || ctx->active_traversals == 0))
|
|
|
|
{
|
|
|
|
ctx->item_posted = true;
|
|
|
|
f(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct get_mutable_item_ctx
|
|
|
|
{
|
2016-07-10 20:27:42 +02:00
|
|
|
explicit get_mutable_item_ctx(int traversals) : active_traversals(traversals) {}
|
2015-11-14 06:08:57 +01:00
|
|
|
int active_traversals;
|
|
|
|
item it;
|
|
|
|
};
|
|
|
|
|
2016-08-13 03:31:55 +02:00
|
|
|
void get_mutable_item_callback(item const& it, bool authoritative
|
2016-08-29 14:31:23 +02:00
|
|
|
, std::shared_ptr<get_mutable_item_ctx> ctx
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(item const&, bool)> f)
|
2015-11-14 06:08:57 +01:00
|
|
|
{
|
|
|
|
TORRENT_ASSERT(it.is_mutable());
|
|
|
|
if (authoritative) --ctx->active_traversals;
|
|
|
|
authoritative = authoritative && ctx->active_traversals == 0;
|
|
|
|
if ((ctx->it.empty() && !it.empty()) || (ctx->it.seq() < it.seq()))
|
|
|
|
{
|
|
|
|
ctx->it = it;
|
|
|
|
f(it, authoritative);
|
|
|
|
}
|
|
|
|
else if (authoritative)
|
|
|
|
f(it, authoritative);
|
2006-08-01 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
2015-11-14 06:08:57 +01:00
|
|
|
struct put_item_ctx
|
|
|
|
{
|
2016-07-10 20:27:42 +02:00
|
|
|
explicit put_item_ctx(int traversals)
|
2015-11-14 06:08:57 +01:00
|
|
|
: active_traversals(traversals)
|
|
|
|
, response_count(0)
|
|
|
|
{}
|
|
|
|
|
|
|
|
int active_traversals;
|
|
|
|
int response_count;
|
|
|
|
};
|
|
|
|
|
2016-08-29 14:31:23 +02:00
|
|
|
void put_immutable_item_callback(int responses, std::shared_ptr<put_item_ctx> ctx
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(int)> f)
|
2015-11-14 06:08:57 +01:00
|
|
|
{
|
|
|
|
ctx->response_count += responses;
|
|
|
|
if (--ctx->active_traversals == 0)
|
|
|
|
f(ctx->response_count);
|
|
|
|
}
|
|
|
|
|
2016-08-29 14:31:23 +02:00
|
|
|
void put_mutable_item_callback(item const& it, int responses, std::shared_ptr<put_item_ctx> ctx
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(item const&, int)> cb)
|
2015-11-14 06:08:57 +01:00
|
|
|
{
|
|
|
|
ctx->response_count += responses;
|
|
|
|
if (--ctx->active_traversals == 0)
|
|
|
|
cb(it, ctx->response_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2014-02-24 01:31:13 +01:00
|
|
|
void dht_tracker::get_item(sha1_hash const& target
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(item const&)> cb)
|
2014-02-24 01:31:13 +01:00
|
|
|
{
|
2016-08-29 14:31:23 +02:00
|
|
|
std::shared_ptr<get_immutable_item_ctx>
|
|
|
|
ctx = std::make_shared<get_immutable_item_ctx>((TORRENT_USE_IPV6) ? 2 : 1);
|
2016-05-25 06:31:52 +02:00
|
|
|
m_dht.get_item(target, std::bind(&get_immutable_item_callback, _1, ctx, cb));
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
2016-05-25 06:31:52 +02:00
|
|
|
m_dht6.get_item(target, std::bind(&get_immutable_item_callback, _1, ctx, cb));
|
2015-11-14 06:08:57 +01:00
|
|
|
#endif
|
2014-02-24 01:31:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// key is a 32-byte binary string, the public key to look up.
|
|
|
|
// the salt is optional
|
2016-07-24 00:57:04 +02:00
|
|
|
void dht_tracker::get_item(public_key const& key
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(item const&, bool)> cb
|
2014-02-24 01:31:13 +01:00
|
|
|
, std::string salt)
|
|
|
|
{
|
2016-08-29 14:31:23 +02:00
|
|
|
std::shared_ptr<get_mutable_item_ctx>
|
|
|
|
ctx = std::make_shared<get_mutable_item_ctx>((TORRENT_USE_IPV6) ? 2 : 1);
|
2016-05-25 06:31:52 +02:00
|
|
|
m_dht.get_item(key, salt, std::bind(&get_mutable_item_callback, _1, _2, ctx, cb));
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
2016-05-25 06:31:52 +02:00
|
|
|
m_dht6.get_item(key, salt, std::bind(&get_mutable_item_callback, _1, _2, ctx, cb));
|
2015-11-14 06:08:57 +01:00
|
|
|
#endif
|
2014-02-24 01:31:13 +01:00
|
|
|
}
|
|
|
|
|
2015-11-22 19:00:29 +01:00
|
|
|
void dht_tracker::put_item(entry const& data
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(int)> cb)
|
2014-02-24 01:31:13 +01:00
|
|
|
{
|
|
|
|
std::string flat_data;
|
|
|
|
bencode(std::back_inserter(flat_data), data);
|
2016-07-24 00:57:04 +02:00
|
|
|
sha1_hash const target = item_target_id(flat_data);
|
2014-02-24 01:31:13 +01:00
|
|
|
|
2016-08-29 14:31:23 +02:00
|
|
|
std::shared_ptr<put_item_ctx>
|
|
|
|
ctx = std::make_shared<put_item_ctx>((TORRENT_USE_IPV6) ? 2 : 1);
|
2016-05-25 06:31:52 +02:00
|
|
|
m_dht.put_item(target, data, std::bind(&put_immutable_item_callback
|
2015-11-14 06:08:57 +01:00
|
|
|
, _1, ctx, cb));
|
|
|
|
#if TORRENT_USE_IPV6
|
2016-05-25 06:31:52 +02:00
|
|
|
m_dht6.put_item(target, data, std::bind(&put_immutable_item_callback
|
2015-11-14 06:08:57 +01:00
|
|
|
, _1, ctx, cb));
|
|
|
|
#endif
|
2014-02-24 01:31:13 +01:00
|
|
|
}
|
|
|
|
|
2016-07-24 00:57:04 +02:00
|
|
|
void dht_tracker::put_item(public_key const& key
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(item const&, int)> cb
|
|
|
|
, std::function<void(item&)> data_cb, std::string salt)
|
2014-02-24 01:31:13 +01:00
|
|
|
{
|
2016-08-29 14:31:23 +02:00
|
|
|
std::shared_ptr<put_item_ctx>
|
|
|
|
ctx = std::make_shared<put_item_ctx>((TORRENT_USE_IPV6) ? 2 : 1);
|
2015-11-14 06:08:57 +01:00
|
|
|
|
2016-05-25 06:31:52 +02:00
|
|
|
m_dht.put_item(key, salt, std::bind(&put_mutable_item_callback
|
2015-11-14 06:08:57 +01:00
|
|
|
, _1, _2, ctx, cb), data_cb);
|
|
|
|
#if TORRENT_USE_IPV6
|
2016-05-25 06:31:52 +02:00
|
|
|
m_dht6.put_item(key, salt, std::bind(&put_mutable_item_callback
|
2015-11-14 06:08:57 +01:00
|
|
|
, _1, _2, ctx, cb), data_cb);
|
|
|
|
#endif
|
2014-02-24 01:31:13 +01:00
|
|
|
}
|
2008-05-08 02:22:17 +02:00
|
|
|
|
2015-08-12 06:49:09 +02:00
|
|
|
void dht_tracker::direct_request(udp::endpoint ep, entry& e
|
2016-08-13 03:31:55 +02:00
|
|
|
, std::function<void(msg const&)> f)
|
2014-02-17 06:56:49 +01:00
|
|
|
{
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
if (ep.protocol() == udp::v6())
|
|
|
|
m_dht6.direct_request(ep, e, f);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
m_dht.direct_request(ep, e, f);
|
|
|
|
|
2014-02-17 06:56:49 +01:00
|
|
|
}
|
|
|
|
|
2016-04-24 21:26:28 +02:00
|
|
|
void dht_tracker::incoming_error(error_code const& ec, udp::endpoint const& ep)
|
2006-08-01 17:27:08 +02:00
|
|
|
{
|
2016-04-24 21:26:28 +02:00
|
|
|
if (ec == boost::asio::error::connection_refused
|
|
|
|
|| ec == boost::asio::error::connection_reset
|
|
|
|
|| ec == boost::asio::error::connection_aborted
|
2016-05-24 05:02:52 +02:00
|
|
|
#ifdef _WIN32
|
2016-04-24 21:26:28 +02:00
|
|
|
|| ec == error_code(ERROR_HOST_UNREACHABLE, system_category())
|
|
|
|
|| ec == error_code(ERROR_PORT_UNREACHABLE, system_category())
|
|
|
|
|| ec == error_code(ERROR_CONNECTION_REFUSED, system_category())
|
|
|
|
|| ec == error_code(ERROR_CONNECTION_ABORTED, system_category())
|
2012-09-25 20:57:50 +02:00
|
|
|
#endif
|
2016-04-24 21:26:28 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
m_dht.unreachable(ep);
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_dht6.unreachable(ep);
|
|
|
|
#endif
|
2012-06-22 06:21:20 +02:00
|
|
|
}
|
2016-04-24 21:26:28 +02:00
|
|
|
}
|
2012-06-22 06:21:20 +02:00
|
|
|
|
2016-04-24 21:26:28 +02:00
|
|
|
bool dht_tracker::incoming_packet( udp::endpoint const& ep
|
|
|
|
, char const* buf, int size)
|
|
|
|
{
|
2012-06-22 06:21:20 +02:00
|
|
|
if (size <= 20 || *buf != 'd' || buf[size-1] != 'e') return false;
|
|
|
|
|
2015-01-17 23:06:30 +01:00
|
|
|
m_counters.inc_stats_counter(counters::dht_bytes_in, size);
|
2008-11-02 11:01:04 +01:00
|
|
|
// account for IP and UDP overhead
|
2015-01-17 23:06:30 +01:00
|
|
|
m_counters.inc_stats_counter(counters::recv_ip_overhead_bytes
|
|
|
|
, ep.address().is_v6() ? 48 : 28);
|
|
|
|
m_counters.inc_stats_counter(counters::dht_messages_in);
|
|
|
|
|
2014-01-19 08:44:16 +01:00
|
|
|
if (m_settings.ignore_dark_internet && ep.address().is_v4())
|
|
|
|
{
|
|
|
|
address_v4::bytes_type b = ep.address().to_v4().to_bytes();
|
|
|
|
|
|
|
|
// these are class A networks not available to the public
|
|
|
|
// if we receive messages from here, that seems suspicious
|
2016-06-18 20:01:38 +02:00
|
|
|
static std::uint8_t const class_a[] = { 3, 6, 7, 9, 11, 19, 21, 22, 25
|
2015-07-15 05:15:50 +02:00
|
|
|
, 26, 28, 29, 30, 33, 34, 48, 51, 56 };
|
2014-01-19 08:44:16 +01:00
|
|
|
|
|
|
|
int num = sizeof(class_a)/sizeof(class_a[0]);
|
|
|
|
if (std::find(class_a, class_a + num, b[0]) != class_a + num)
|
2016-01-18 08:21:27 +01:00
|
|
|
{
|
|
|
|
m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
|
2014-01-19 08:44:16 +01:00
|
|
|
return true;
|
2016-01-18 08:21:27 +01:00
|
|
|
}
|
2014-01-19 08:44:16 +01:00
|
|
|
}
|
2008-09-20 19:42:25 +02:00
|
|
|
|
2015-05-10 06:54:02 +02:00
|
|
|
if (!m_blocker.incoming(ep.address(), clock_type::now(), m_log))
|
2016-01-18 08:21:27 +01:00
|
|
|
{
|
|
|
|
m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
|
2014-07-06 21:18:00 +02:00
|
|
|
return true;
|
2016-01-18 08:21:27 +01:00
|
|
|
}
|
2007-12-04 03:53:10 +01:00
|
|
|
|
2008-10-21 19:10:11 +02:00
|
|
|
using libtorrent::entry;
|
|
|
|
using libtorrent::bdecode;
|
2015-05-28 22:36:22 +02:00
|
|
|
|
2012-06-22 06:21:20 +02:00
|
|
|
TORRENT_ASSERT(size > 0);
|
2006-08-01 17:27:08 +02:00
|
|
|
|
2010-10-28 06:01:59 +02:00
|
|
|
int pos;
|
2012-06-22 06:21:20 +02:00
|
|
|
error_code err;
|
2015-03-12 06:20:12 +01:00
|
|
|
int ret = bdecode(buf, buf + size, m_msg, err, &pos, 10, 500);
|
2008-11-11 18:51:02 +01:00
|
|
|
if (ret != 0)
|
2008-10-21 19:10:11 +02:00
|
|
|
{
|
2016-01-18 08:21:27 +01:00
|
|
|
m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-05-28 22:36:22 +02:00
|
|
|
m_log->log_packet(dht_logger::incoming_message, buf, size, ep);
|
2009-09-20 17:21:31 +02:00
|
|
|
#endif
|
2012-06-22 06:21:20 +02:00
|
|
|
return false;
|
2008-10-21 19:10:11 +02:00
|
|
|
}
|
2006-08-01 17:27:08 +02:00
|
|
|
|
2015-03-12 06:20:12 +01:00
|
|
|
if (m_msg.type() != bdecode_node::dict_t)
|
2008-10-21 19:10:11 +02:00
|
|
|
{
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-05-28 22:36:22 +02:00
|
|
|
m_log->log_packet(dht_logger::incoming_message, buf, size, ep);
|
2006-08-01 17:27:08 +02:00
|
|
|
#endif
|
2015-05-30 06:37:12 +02:00
|
|
|
// it's not a good idea to send a response to an invalid messages
|
2012-06-22 06:21:20 +02:00
|
|
|
return false;
|
2008-11-09 01:37:03 +01:00
|
|
|
}
|
2006-08-01 17:27:08 +02:00
|
|
|
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-05-28 22:36:22 +02:00
|
|
|
m_log->log_packet(dht_logger::incoming_message, buf
|
|
|
|
, size, ep);
|
2015-05-16 21:29:49 +02:00
|
|
|
#endif
|
|
|
|
|
2015-03-12 06:20:12 +01:00
|
|
|
libtorrent::dht::msg m(m_msg, ep);
|
2008-10-21 19:10:11 +02:00
|
|
|
m_dht.incoming(m);
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_dht6.incoming(m);
|
|
|
|
#endif
|
2012-06-22 06:21:20 +02:00
|
|
|
return true;
|
2006-08-01 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
2015-04-20 06:52:49 +02:00
|
|
|
namespace {
|
|
|
|
|
2010-01-03 12:08:39 +01:00
|
|
|
void add_node_fun(void* userdata, node_entry const& e)
|
|
|
|
{
|
2015-08-11 02:03:24 +02:00
|
|
|
entry* n = static_cast<entry*>(userdata);
|
2010-01-03 12:08:39 +01:00
|
|
|
std::string node;
|
|
|
|
std::back_insert_iterator<std::string> out(node);
|
2015-07-04 04:33:17 +02:00
|
|
|
write_endpoint(e.ep(), out);
|
2010-01-03 12:08:39 +01:00
|
|
|
n->list().push_back(entry(node));
|
|
|
|
}
|
2015-04-20 06:52:49 +02:00
|
|
|
|
2015-11-14 06:08:57 +01:00
|
|
|
void save_nodes(entry& ret, node const& dht, std::string const& key)
|
|
|
|
{
|
|
|
|
entry nodes(entry::list_t);
|
|
|
|
dht.m_table.for_each_node(&add_node_fun, &add_node_fun, &nodes);
|
|
|
|
bucket_t cache;
|
|
|
|
dht.replacement_cache(cache);
|
|
|
|
for (bucket_t::iterator i(cache.begin())
|
|
|
|
, end(cache.end()); i != end; ++i)
|
|
|
|
{
|
|
|
|
std::string node;
|
|
|
|
std::back_insert_iterator<std::string> out(node);
|
|
|
|
write_endpoint(i->ep(), out);
|
|
|
|
nodes.list().push_back(entry(node));
|
|
|
|
}
|
|
|
|
if (!nodes.list().empty())
|
|
|
|
ret[key] = nodes;
|
|
|
|
}
|
|
|
|
|
2015-04-20 06:52:49 +02:00
|
|
|
} // anonymous namespace
|
2015-05-28 22:36:22 +02:00
|
|
|
|
2006-08-01 17:27:08 +02:00
|
|
|
entry dht_tracker::state() const
|
|
|
|
{
|
|
|
|
entry ret(entry::dictionary_t);
|
2015-11-14 06:08:57 +01:00
|
|
|
save_nodes(ret, m_dht, "nodes");
|
2009-11-10 18:01:05 +01:00
|
|
|
ret["node-id"] = m_dht.nid().to_string();
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
save_nodes(ret, m_dht6, "nodes6");
|
|
|
|
ret["node-id6"] = m_dht6.nid().to_string();
|
|
|
|
#endif
|
2006-08-01 17:27:08 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dht_tracker::add_node(udp::endpoint node)
|
|
|
|
{
|
|
|
|
m_dht.add_node(node);
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_dht6.add_node(node);
|
|
|
|
#endif
|
2006-08-01 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
2010-02-14 08:46:57 +01:00
|
|
|
void dht_tracker::add_router_node(udp::endpoint const& node)
|
2006-09-27 19:20:18 +02:00
|
|
|
{
|
2010-02-14 08:46:57 +01:00
|
|
|
m_dht.add_router_node(node);
|
2015-11-14 06:08:57 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
m_dht6.add_router_node(node);
|
|
|
|
#endif
|
2006-09-27 19:20:18 +02:00
|
|
|
}
|
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
bool dht_tracker::has_quota()
|
|
|
|
{
|
2016-01-17 21:09:27 +01:00
|
|
|
time_point now = clock_type::now();
|
|
|
|
time_duration delta = now - m_last_tick;
|
|
|
|
m_last_tick = now;
|
2016-01-18 08:21:27 +01:00
|
|
|
|
2016-01-17 21:09:27 +01:00
|
|
|
// add any new quota we've accrued since last time
|
2016-06-18 20:01:38 +02:00
|
|
|
m_send_quota += std::uint64_t(m_settings.upload_rate_limit)
|
2016-01-17 21:09:27 +01:00
|
|
|
* total_microseconds(delta) / 1000000;
|
2016-01-18 08:21:27 +01:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2016-01-17 21:09:27 +01:00
|
|
|
return m_send_quota > 0;
|
2014-07-06 21:18:00 +02:00
|
|
|
}
|
|
|
|
|
2016-01-18 06:07:21 +01:00
|
|
|
bool dht_tracker::send_packet(libtorrent::entry& e, udp::endpoint const& addr)
|
2006-08-01 17:27:08 +02:00
|
|
|
{
|
|
|
|
using libtorrent::bencode;
|
2008-12-23 21:04:12 +01:00
|
|
|
|
2011-01-23 03:02:04 +01:00
|
|
|
static char const version_str[] = {'L', 'T'
|
|
|
|
, LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR};
|
|
|
|
e["v"] = std::string(version_str, version_str + 4);
|
|
|
|
|
2009-09-20 02:23:36 +02:00
|
|
|
m_send_buf.clear();
|
|
|
|
bencode(std::back_inserter(m_send_buf), e);
|
2006-08-01 17:27:08 +02:00
|
|
|
|
2016-01-17 21:09:27 +01:00
|
|
|
// 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.
|
|
|
|
|
2016-04-25 23:22:09 +02:00
|
|
|
m_send_quota -= int(m_send_buf.size());
|
2016-01-17 21:09:27 +01:00
|
|
|
|
|
|
|
error_code ec;
|
2016-07-22 18:31:42 +02:00
|
|
|
m_send_fun(addr, span<char const>(&m_send_buf[0]
|
2016-05-02 18:36:21 +02:00
|
|
|
, int(m_send_buf.size())), ec, 0);
|
2016-01-17 21:09:27 +01:00
|
|
|
if (ec)
|
2008-11-09 01:37:03 +01:00
|
|
|
{
|
2015-08-31 19:48:14 +02:00
|
|
|
m_counters.inc_stats_counter(counters::dht_messages_out_dropped);
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-05-28 22:36:22 +02:00
|
|
|
m_log->log_packet(dht_logger::outgoing_message, &m_send_buf[0]
|
2016-04-25 23:22:09 +02:00
|
|
|
, int(m_send_buf.size()), addr);
|
2008-11-09 10:02:06 +01:00
|
|
|
#endif
|
2015-08-31 19:48:14 +02:00
|
|
|
return false;
|
2006-08-06 18:36:00 +02:00
|
|
|
}
|
2014-07-06 21:18:00 +02:00
|
|
|
|
2015-08-31 19:48:14 +02:00
|
|
|
m_counters.inc_stats_counter(counters::dht_bytes_out, m_send_buf.size());
|
|
|
|
// account for IP and UDP overhead
|
|
|
|
m_counters.inc_stats_counter(counters::sent_ip_overhead_bytes
|
|
|
|
, addr.address().is_v6() ? 48 : 28);
|
|
|
|
m_counters.inc_stats_counter(counters::dht_messages_out);
|
2015-05-16 21:29:49 +02:00
|
|
|
#ifndef TORRENT_DISABLE_LOGGING
|
2015-08-31 19:48:14 +02:00
|
|
|
m_log->log_packet(dht_logger::outgoing_message, &m_send_buf[0]
|
2016-04-25 23:22:09 +02:00
|
|
|
, int(m_send_buf.size()), addr);
|
2008-11-10 04:08:29 +01:00
|
|
|
#endif
|
2015-08-31 19:48:14 +02:00
|
|
|
return true;
|
2006-08-01 17:27:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}}
|