created dht state and session params refactor (#1100)

created dht state and session params refactor
This commit is contained in:
Alden Torres 2016-09-17 09:42:04 -04:00 committed by Arvid Norberg
parent b4da884f29
commit 6c31ea3d44
21 changed files with 478 additions and 167 deletions

View File

@ -124,6 +124,7 @@ set(sources
# -- kademlia --
set(kademlia_sources
dht_state
dht_storage
dos_blocker
dht_tracker

View File

@ -690,6 +690,7 @@ SOURCES =
;
KADEMLIA_SOURCES =
dht_state
dht_storage
dht_tracker
msg

View File

@ -182,6 +182,7 @@ nobase_include_HEADERS = \
extensions/ut_metadata.hpp \
extensions/ut_pex.hpp \
\
kademlia/dht_state.hpp \
kademlia/dht_storage.hpp \
kademlia/dht_tracker.hpp \
kademlia/dht_observer.hpp \

View File

@ -75,6 +75,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/disk_io_job.hpp" // block_cache_reference
#include "libtorrent/peer_class_type_filter.hpp"
#include "libtorrent/kademlia/dht_observer.hpp"
#include "libtorrent/kademlia/dht_state.hpp"
#include "libtorrent/resolver.hpp"
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/extensions.hpp"
@ -113,11 +114,6 @@ namespace libtorrent
class item;
}
struct bencode_map_entry;
typedef std::function<bool(udp::endpoint const& source
, bdecode_node const& request, entry& response)> dht_extension_handler_t;
struct listen_socket_t
{
listen_socket_t()
@ -180,7 +176,10 @@ namespace libtorrent
struct tracker_logger;
#endif
TORRENT_EXPORT std::pair<bencode_map_entry*, int> settings_map();
#ifndef TORRENT_DISABLE_DHT
TORRENT_EXTRA_EXPORT dht_settings read_dht_settings(bdecode_node const& e);
TORRENT_EXTRA_EXPORT entry save_dht_settings(dht_settings const& settings);
#endif
// this is the link between the main thread and the
// thread started to run the main downloader loop
@ -330,10 +329,11 @@ namespace libtorrent
void add_dht_router(std::pair<std::string, int> const& node);
void set_dht_settings(dht_settings const& s);
dht_settings const& get_dht_settings() const { return m_dht_settings; }
void set_dht_state(dht::dht_state const& state);
void set_dht_storage(dht::dht_storage_constructor_type sc);
void start_dht();
void stop_dht();
void start_dht(entry const& startup_state);
void start_dht(dht::dht_state const& startup_state);
bool has_dht() const override;
// this is called for torrents when they are started
@ -928,7 +928,7 @@ namespace libtorrent
, tcp::endpoint bind_ep, int flags, error_code& ec);
#ifndef TORRENT_DISABLE_DHT
entry m_dht_state;
dht::dht_state m_dht_state;
#endif
// this is initialized to the unchoke_interval

View File

@ -0,0 +1,77 @@
/*
Copyright (c) 2016, Arvid Norberg, Alden Torres
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.
*/
#ifndef LIBTORRENT_DHT_STATE_HPP
#define LIBTORRENT_DHT_STATE_HPP
#include <libtorrent/config.hpp>
#include <libtorrent/socket.hpp>
#include <libtorrent/entry.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <vector>
namespace libtorrent
{
struct bdecode_node;
}
namespace libtorrent {
namespace dht
{
// This structure helps to store and load the state
// of the ``dht_tracker``.
// At this moment the library is only a dual stack
// implementation of the DHT. See BEP38_
//
// .. _BEP32: http://bittorrent.org/beps/bep_0032.html
struct TORRENT_EXPORT dht_state
{
dht_state() = default;
// the id of the IPv4 node
node_id nid;
// the id of the IPv6 node
node_id nid6;
// the bootstrap nodes saved from the IPv4 buckets node
std::vector<udp::endpoint> nodes;
// the bootstrap nodes saved from the IPv6 buckets node
std::vector<udp::endpoint> nodes6;
};
TORRENT_EXTRA_EXPORT dht_state read_dht_state(bdecode_node const& e);
TORRENT_EXTRA_EXPORT entry save_dht_state(dht_state const& state);
}}
#endif // LIBTORRENT_DHT_STATE_HPP

View File

@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/traversal_algorithm.hpp>
#include <libtorrent/kademlia/dos_blocker.hpp>
#include <libtorrent/kademlia/dht_state.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/udp_socket.hpp>
@ -71,10 +72,10 @@ namespace libtorrent { namespace dht
, dht_settings const& settings
, counters& cnt
, dht_storage_interface& storage
, entry const& state);
, dht_state const& state);
virtual ~dht_tracker();
void start(entry const& bootstrap
void start(dht_state const& bootstrap
, find_data::nodes_callback const& f);
void stop();
@ -85,7 +86,7 @@ namespace libtorrent { namespace dht
void add_node(udp::endpoint const& node);
void add_router_node(udp::endpoint const& node);
entry state() const;
dht_state state() const;
enum flags_t { flag_seed = 1, flag_implied_port = 2 };
void get_peers(sha1_hash const& ih

View File

@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/settings_pack.hpp"
#include "libtorrent/session_handle.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/kademlia/dht_state.hpp"
#include "libtorrent/kademlia/dht_storage.hpp"
#ifndef TORRENT_NO_DEPRECATE
@ -148,9 +149,16 @@ namespace libtorrent
libtorrent::dht_settings dht_settings;
dht::dht_state dht_state;
dht::dht_storage_constructor_type dht_storage_constructor;
};
// This function helps to construct a ``session_params`` from a
// bencoded data generated by ``session_handle::save_state``
TORRENT_EXPORT session_params read_session_params(bdecode_node const& e
, std::uint32_t flags = 0xffffffff);
// The session holds all state that spans multiple torrents. Among other
// things it runs the network loop and manages all torrents. Once it's
// created, the session object will spawn the main thread that will do all
@ -158,7 +166,7 @@ namespace libtorrent
// torrents to participate in.
//
// You have some control over session configuration through the
// ``session::apply_settings()`` member function. To change one or more
// ``session_handle::apply_settings()`` member function. To change one or more
// configuration options, create a settings_pack. object and fill it with
// the settings to be set and pass it in to ``session::apply_settings()``.
//

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/udp_socket.hpp"
#include "libtorrent/kademlia/dht_tracker.hpp"
#include "libtorrent/kademlia/dht_state.hpp"
#include "libtorrent/performance_counters.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/session_settings.hpp"
@ -109,9 +110,9 @@ TORRENT_TEST(dht_rate_limit)
int const num_packets = 2000;
counters cnt;
entry state;
dht::dht_state state;
std::unique_ptr<lt::dht::dht_storage_interface> dht_storage(dht::dht_default_storage_constructor(dhtsett));
std::shared_ptr<lt::dht::dht_tracker> dht = std::make_shared<lt::dht::dht_tracker>(
auto dht = std::make_shared<lt::dht::dht_tracker>(
&o, dht_ios, std::bind(&udp_socket::send, &sock, _1, _2, _3, _4)
, dhtsett, cnt, *dht_storage, state);

View File

@ -68,14 +68,6 @@ namespace
return sett;
}
sha1_hash to_hash(char const *s) {
std::stringstream hash(s);
sha1_hash ret;
hash >> ret;
TORRENT_ASSERT(!hash.fail());
return ret;
}
std::unique_ptr<dht_storage_interface> create_default_dht_storage(
dht_settings const& sett)
{

View File

@ -4,6 +4,7 @@ lib_LTLIBRARIES = libtorrent-rasterbar.la
if ENABLE_DHT
KADEMLIA_SOURCES = \
kademlia/dht_state.cpp \
kademlia/dht_storage.cpp \
kademlia/dht_tracker.cpp \
kademlia/find_data.cpp \

100
src/kademlia/dht_state.cpp Normal file
View File

@ -0,0 +1,100 @@
/*
Copyright (c) 2016, Arvid Norberg, Alden Torres
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 "libtorrent/kademlia/dht_state.hpp"
#include <libtorrent/bdecode.hpp>
#include <libtorrent/socket_io.hpp>
namespace libtorrent {
namespace dht
{
namespace
{
node_id extract_node_id(bdecode_node const& e, string_view key)
{
if (e.type() != bdecode_node::dict_t) return node_id();
auto nid = e.dict_find_string_value(key);
if (nid.size() != 20) return node_id();
return node_id(nid);
}
entry save_nodes(std::vector<udp::endpoint> const& nodes)
{
entry ret(entry::list_t);
entry::list_type& list = ret.list();
for (auto const& ep : nodes)
{
std::string node;
std::back_insert_iterator<std::string> out(node);
detail::write_endpoint(ep, out);
list.push_back(entry(node));
}
return ret;
}
} // anonymous namespace
dht_state read_dht_state(bdecode_node const& e)
{
dht_state ret;
if (e.type() != bdecode_node::dict_t) return ret;
ret.nid = extract_node_id(e, "node-id");
#if TORRENT_USE_IPV6
ret.nid6 = extract_node_id(e, "node-id6");
#endif
if (bdecode_node const nodes = e.dict_find_list("nodes"))
detail::read_endpoint_list<udp::endpoint>(nodes, ret.nodes);
#if TORRENT_USE_IPV6
if (bdecode_node const nodes = e.dict_find_list("nodes6"))
detail::read_endpoint_list<udp::endpoint>(nodes, ret.nodes6);
#endif
return ret;
}
entry save_dht_state(dht_state const& state)
{
entry ret(entry::dictionary_t);
ret["node-id"] = state.nid.to_string();
entry const nodes = save_nodes(state.nodes);
if (!nodes.list().empty()) ret["nodes"] = nodes;
#if TORRENT_USE_IPV6
ret["node-id6"] = state.nid6.to_string();
entry const nodes6 = save_nodes(state.nodes6);
if (!nodes6.list().empty()) ret["nodes6"] = nodes6;
#endif
return ret;
}
}}

View File

@ -72,15 +72,6 @@ namespace libtorrent { namespace dht
time_duration const key_refresh
= duration_cast<time_duration>(minutes(5));
node_id extract_node_id(entry const& e, std::string const& key)
{
if (e.type() != entry::dictionary_t) return (node_id::min)();
entry const* nid = e.find_key(key);
if (nid == nullptr || nid->type() != entry::string_t || nid->string().length() != 20)
return (node_id::min)();
return node_id(nid->string().c_str());
}
void add_dht_counters(node const& dht, counters& c)
{
int nodes, replacements, allocated_observers;
@ -101,13 +92,13 @@ namespace libtorrent { namespace dht
, dht_settings const& settings
, counters& cnt
, dht_storage_interface& storage
, entry const& state)
, dht_state const& state)
: m_counters(cnt)
, m_storage(storage)
, m_dht(udp::v4(), this, settings, extract_node_id(state, "node-id")
, m_dht(udp::v4(), this, settings, state.nid
, observer, cnt, m_nodes, storage)
#if TORRENT_USE_IPV6
, m_dht6(udp::v6(), this, settings, extract_node_id(state, "node-id6")
, m_dht6(udp::v6(), this, settings, state.nid6
, observer, cnt, m_nodes, storage)
#endif
, m_send_fun(send_fun)
@ -161,28 +152,9 @@ namespace libtorrent { namespace dht
// defined in node.cpp
void nop();
void dht_tracker::start(entry const& bootstrap
void dht_tracker::start(dht_state const& bootstrap
, find_data::nodes_callback const& f)
{
std::vector<udp::endpoint> initial_nodes;
#if TORRENT_USE_IPV6
std::vector<udp::endpoint> initial_nodes6;
#endif
if (bootstrap.type() == entry::dictionary_t)
{
TORRENT_TRY {
if (entry const* nodes = bootstrap.find_key("nodes"))
read_endpoint_list<udp::endpoint>(nodes, initial_nodes);
} TORRENT_CATCH(std::exception&) {}
#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
}
error_code ec;
refresh_key(ec);
@ -198,9 +170,9 @@ namespace libtorrent { namespace dht
m_refresh_timer.expires_from_now(seconds(5), ec);
m_refresh_timer.async_wait(std::bind(&dht_tracker::refresh_timeout, self(), _1));
m_dht.bootstrap(initial_nodes, f);
m_dht.bootstrap(bootstrap.nodes, f);
#if TORRENT_USE_IPV6
m_dht6.bootstrap(initial_nodes6, f);
m_dht6.bootstrap(bootstrap.nodes6, f);
#endif
}
@ -585,40 +557,33 @@ namespace libtorrent { namespace dht
void add_node_fun(void* userdata, node_entry const& e)
{
entry* n = static_cast<entry*>(userdata);
std::string node;
std::back_insert_iterator<std::string> out(node);
write_endpoint(e.ep(), out);
n->list().push_back(entry(node));
auto v = static_cast<std::vector<udp::endpoint>*>(userdata);
v->push_back(e.ep());
}
void save_nodes(entry& ret, node const& dht, std::string const& key)
std::vector<udp::endpoint> save_nodes(node const& dht)
{
entry nodes(entry::list_t);
dht.m_table.for_each_node(&add_node_fun, &add_node_fun, &nodes);
std::vector<udp::endpoint> ret;
dht.m_table.for_each_node(&add_node_fun, &add_node_fun, &ret);
bucket_t cache;
dht.replacement_cache(cache);
for (auto const& b : cache)
{
std::string node;
std::back_insert_iterator<std::string> out(node);
write_endpoint(b.ep(), out);
nodes.list().push_back(entry(node));
ret.push_back(b.ep());
}
if (!nodes.list().empty())
ret[key] = nodes;
return ret;
}
} // anonymous namespace
entry dht_tracker::state() const
dht_state dht_tracker::state() const
{
entry ret(entry::dictionary_t);
save_nodes(ret, m_dht, "nodes");
ret["node-id"] = m_dht.nid().to_string();
dht_state ret;
ret.nid = m_dht.nid();
ret.nodes = save_nodes(m_dht);
#if TORRENT_USE_IPV6
save_nodes(ret, m_dht6, "nodes6");
ret["node-id6"] = m_dht6.nid().to_string();
ret.nid6 = m_dht6.nid();
ret.nodes6 = save_nodes(m_dht6);
#endif
return ret;
}

View File

@ -212,6 +212,7 @@ void node::bootstrap(std::vector<udp::endpoint> const& nodes
for (auto const& n : nodes)
{
if (n.protocol() != protocol()) continue;
#ifndef TORRENT_DISABLE_LOGGING
++count;
#endif
@ -1196,7 +1197,11 @@ node::protocol_descriptor const& node::map_protocol_to_descriptor(udp protocol)
}
TORRENT_ASSERT_FAIL();
#ifndef BOOST_NO_EXCEPTIONS
throw std::out_of_range("unknown protocol");
#else
std::terminate();
#endif
}
} } // namespace libtorrent::dht

View File

@ -287,6 +287,45 @@ namespace libtorrent
// configurations this will give a link error
void TORRENT_CFG() {}
session_params read_session_params(bdecode_node const& e, std::uint32_t const flags)
{
session_params params;
bdecode_node settings;
if (e.type() != bdecode_node::dict_t) return params;
if (flags & session_handle::save_settings)
{
settings = e.dict_find_dict("settings");
if (settings)
{
params.settings = load_pack_from_dict(settings);
}
}
#ifndef TORRENT_DISABLE_DHT
if (flags & session_handle::save_dht_settings)
{
settings = e.dict_find_dict("dht");
if (settings)
{
params.dht_settings = aux::read_dht_settings(settings);
}
}
if (flags & session_handle::save_dht_state)
{
settings = e.dict_find_dict("dht state");
if (settings)
{
params.dht_state = dht::read_dht_state(settings);
}
}
#endif
return params;
}
void session::start(session_params params, io_service* ios)
{
bool const internal_executor = ios == nullptr;
@ -308,8 +347,11 @@ namespace libtorrent
}
#endif
set_dht_settings(params.dht_settings);
set_dht_storage(params.dht_storage_constructor);
#ifndef TORRENT_DISABLE_DHT
m_impl->set_dht_settings(params.dht_settings);
m_impl->set_dht_state(std::move(params.dht_state));
m_impl->set_dht_storage(params.dht_storage_constructor);
#endif
m_impl->start_session(std::move(params.settings));

View File

@ -195,6 +195,82 @@ namespace libtorrent {
namespace aux {
#ifndef TORRENT_DISABLE_DHT
dht_settings read_dht_settings(bdecode_node const& e)
{
dht_settings sett;
if (e.type() != bdecode_node::dict_t) return sett;
bdecode_node val;
val = e.dict_find_int("max_peers_reply");
if (val) sett.max_peers_reply = val.int_value();
val = e.dict_find_int("search_branching");
if (val) sett.search_branching = val.int_value();
val = e.dict_find_int("max_fail_count");
if (val) sett.max_fail_count = val.int_value();
val = e.dict_find_int("max_torrents");
if (val) sett.max_torrents = val.int_value();
val = e.dict_find_int("max_dht_items");
if (val) sett.max_dht_items = val.int_value();
val = e.dict_find_int("max_peers");
if (val) sett.max_peers = val.int_value();
val = e.dict_find_int("max_torrent_search_reply");
if (val) sett.max_torrent_search_reply = val.int_value();
val = e.dict_find_int("restrict_routing_ips");
if (val) sett.restrict_routing_ips = (val.int_value() != 0);
val = e.dict_find_int("restrict_search_ips");
if (val) sett.restrict_search_ips = (val.int_value() != 0);
val = e.dict_find_int("extended_routing_table");
if (val) sett.extended_routing_table = (val.int_value() != 0);
val = e.dict_find_int("aggressive_lookups");
if (val) sett.aggressive_lookups = (val.int_value() != 0);
val = e.dict_find_int("privacy_lookups");
if (val) sett.privacy_lookups = (val.int_value() != 0);
val = e.dict_find_int("enforce_node_id");
if (val) sett.enforce_node_id = (val.int_value() != 0);
val = e.dict_find_int("ignore_dark_internet");
if (val) sett.ignore_dark_internet = (val.int_value() != 0);
val = e.dict_find_int("block_timeout");
if (val) sett.block_timeout = val.int_value();
val = e.dict_find_int("block_ratelimit");
if (val) sett.block_ratelimit = val.int_value();
val = e.dict_find_int("read_only");
if (val) sett.read_only = (val.int_value() != 0);
val = e.dict_find_int("item_lifetime");
if (val) sett.item_lifetime = val.int_value();
return sett;
}
entry save_dht_settings(dht_settings const& settings)
{
entry e;
entry::dictionary_type& dht_sett = e.dict();
dht_sett["max_peers_reply"] = settings.max_peers_reply;
dht_sett["search_branching"] = settings.search_branching;
dht_sett["max_fail_count"] = settings.max_fail_count;
dht_sett["max_torrents"] = settings.max_torrents;
dht_sett["max_dht_items"] = settings.max_dht_items;
dht_sett["max_peers"] = settings.max_peers;
dht_sett["max_torrent_search_reply"] = settings.max_torrent_search_reply;
dht_sett["restrict_routing_ips"] = settings.restrict_routing_ips;
dht_sett["restrict_search_ips"] = settings.restrict_search_ips;
dht_sett["extended_routing_table"] = settings.extended_routing_table;
dht_sett["aggressive_lookups"] = settings.aggressive_lookups;
dht_sett["privacy_lookups"] = settings.privacy_lookups;
dht_sett["enforce_node_id"] = settings.enforce_node_id;
dht_sett["ignore_dark_internet"] = settings.ignore_dark_internet;
dht_sett["block_timeout"] = settings.block_timeout;
dht_sett["block_ratelimit"] = settings.block_ratelimit;
dht_sett["read_only"] = settings.read_only;
dht_sett["item_lifetime"] = settings.item_lifetime;
return e;
}
#endif // TORRENT_DISABLE_DHT
void session_impl::init_peer_class_filter(bool unlimited_local)
{
// set the default peer_class_filter to use the local peer class
@ -552,31 +628,12 @@ namespace aux {
#ifndef TORRENT_DISABLE_DHT
if (flags & session::save_dht_settings)
{
entry::dictionary_type& dht_sett = e["dht"].dict();
dht_sett["max_peers_reply"] = m_dht_settings.max_peers_reply;
dht_sett["search_branching"] = m_dht_settings.search_branching;
dht_sett["max_fail_count"] = m_dht_settings.max_fail_count;
dht_sett["max_torrents"] = m_dht_settings.max_torrents;
dht_sett["max_dht_items"] = m_dht_settings.max_dht_items;
dht_sett["max_peers"] = m_dht_settings.max_peers;
dht_sett["max_torrent_search_reply"] = m_dht_settings.max_torrent_search_reply;
dht_sett["restrict_routing_ips"] = m_dht_settings.restrict_routing_ips;
dht_sett["restrict_search_ips"] = m_dht_settings.restrict_search_ips;
dht_sett["extended_routing_table"] = m_dht_settings.extended_routing_table;
dht_sett["aggressive_lookups"] = m_dht_settings.aggressive_lookups;
dht_sett["privacy_lookups"] = m_dht_settings.privacy_lookups;
dht_sett["enforce_node_id"] = m_dht_settings.enforce_node_id;
dht_sett["ignore_dark_internet"] = m_dht_settings.ignore_dark_internet;
dht_sett["block_timeout"] = m_dht_settings.block_timeout;
dht_sett["block_ratelimit"] = m_dht_settings.block_ratelimit;
dht_sett["read_only"] = m_dht_settings.read_only;
dht_sett["item_lifetime"] = m_dht_settings.item_lifetime;
e["dht"] = save_dht_settings(m_dht_settings);
}
if (m_dht && (flags & session::save_dht_state))
{
e["dht state"] = m_dht->state();
e["dht state"] = dht::save_dht_state(m_dht->state());
}
#endif
@ -605,57 +662,21 @@ namespace aux {
#ifndef TORRENT_DISABLE_DHT
bool need_update_dht = false;
if (flags & session::save_dht_settings)
if (flags & session_handle::save_dht_settings)
{
settings = e->dict_find_dict("dht");
if (settings)
{
bdecode_node val;
val = settings.dict_find_int("max_peers_reply");
if (val) m_dht_settings.max_peers_reply = val.int_value();
val = settings.dict_find_int("search_branching");
if (val) m_dht_settings.search_branching = val.int_value();
val = settings.dict_find_int("max_fail_count");
if (val) m_dht_settings.max_fail_count = val.int_value();
val = settings.dict_find_int("max_torrents");
if (val) m_dht_settings.max_torrents = val.int_value();
val = settings.dict_find_int("max_dht_items");
if (val) m_dht_settings.max_dht_items = val.int_value();
val = settings.dict_find_int("max_peers");
if (val) m_dht_settings.max_peers = val.int_value();
val = settings.dict_find_int("max_torrent_search_reply");
if (val) m_dht_settings.max_torrent_search_reply = val.int_value();
val = settings.dict_find_int("restrict_routing_ips");
if (val) m_dht_settings.restrict_routing_ips = (val.int_value() != 0);
val = settings.dict_find_int("restrict_search_ips");
if (val) m_dht_settings.restrict_search_ips = (val.int_value() != 0);
val = settings.dict_find_int("extended_routing_table");
if (val) m_dht_settings.extended_routing_table = (val.int_value() != 0);
val = settings.dict_find_int("aggressive_lookups");
if (val) m_dht_settings.aggressive_lookups = (val.int_value() != 0);
val = settings.dict_find_int("privacy_lookups");
if (val) m_dht_settings.privacy_lookups = (val.int_value() != 0);
val = settings.dict_find_int("enforce_node_id");
if (val) m_dht_settings.enforce_node_id = (val.int_value() != 0);
val = settings.dict_find_int("ignore_dark_internet");
if (val) m_dht_settings.ignore_dark_internet = (val.int_value() != 0);
val = settings.dict_find_int("block_timeout");
if (val) m_dht_settings.block_timeout = val.int_value();
val = settings.dict_find_int("block_ratelimit");
if (val) m_dht_settings.block_ratelimit = val.int_value();
val = settings.dict_find_int("read_only");
if (val) m_dht_settings.read_only = (val.int_value() != 0);
val = settings.dict_find_int("item_lifetime");
if (val) m_dht_settings.item_lifetime = val.int_value();
m_dht_settings = read_dht_settings(settings);
}
}
if (flags & session::save_dht_state)
if (flags & session_handle::save_dht_state)
{
settings = e->dict_find_dict("dht state");
if (settings)
{
m_dht_state = settings;
m_dht_state = dht::read_dht_state(settings);
need_update_dht = true;
}
}
@ -663,7 +684,7 @@ namespace aux {
#ifndef TORRENT_NO_DEPRECATE
bool need_update_proxy = false;
if (flags & session::save_proxy)
if (flags & session_handle::save_proxy)
{
settings = e->dict_find_dict("proxy");
if (settings)
@ -702,7 +723,7 @@ namespace aux {
}
#endif
if (flags & session::save_settings)
if (flags & session_handle::save_settings)
{
settings = e->dict_find_dict("settings");
if (settings)
@ -5579,7 +5600,7 @@ namespace aux {
}
}
void session_impl::start_dht(entry const& startup_state)
void session_impl::start_dht(dht::dht_state const& startup_state)
{
INVARIANT_CHECK;
@ -5590,7 +5611,7 @@ namespace aux {
m_dht_storage = m_dht_storage_constructor(m_dht_settings);
m_dht = std::make_shared<dht::dht_tracker>(
static_cast<dht_observer*>(this)
static_cast<dht::dht_observer*>(this)
, m_io_service
, std::bind(&session_impl::send_udp_packet, this, false, _1, _2, _3, _4)
, m_dht_settings
@ -5628,6 +5649,11 @@ namespace aux {
m_dht_settings = settings;
}
void session_impl::set_dht_state(dht::dht_state const& state)
{
m_dht_state = state;
}
void session_impl::set_dht_storage(dht::dht_storage_constructor_type sc)
{
m_dht_storage_constructor = sc;
@ -5636,14 +5662,20 @@ namespace aux {
#ifndef TORRENT_NO_DEPRECATE
entry session_impl::dht_state() const
{
if (!m_dht) return entry();
return m_dht->state();
return m_dht ? dht::save_dht_state(m_dht->state()) : entry();
}
void session_impl::start_dht_deprecated(entry const& startup_state)
{
m_settings.set_bool(settings_pack::enable_dht, true);
start_dht(startup_state);
std::vector<char> tmp;
bencode(std::back_inserter(tmp), startup_state);
bdecode_node e;
error_code ec;
if (tmp.empty() || bdecode(&tmp[0], &tmp[0] + tmp.size(), e, ec) != 0)
return;
start_dht(dht::read_dht_state(e));
}
#endif

View File

@ -102,6 +102,13 @@ sha1_hash rand_hash()
return ret;
}
sha1_hash to_hash(char const* s)
{
sha1_hash ret;
aux::from_hex({s, 40}, (char*)&ret[0]);
return ret;
}
#if TORRENT_USE_IPV6
address rand_v6()
{
@ -1001,6 +1008,14 @@ tcp::endpoint ep(char const* ip, int port)
return ret;
}
udp::endpoint uep(char const* ip, int port)
{
error_code ec;
udp::endpoint ret(address::from_string(ip, ec), std::uint16_t(port));
TEST_CHECK(!ec);
return ret;
}
libtorrent::address addr(char const* ip)
{
lt::error_code ec;

View File

@ -60,6 +60,7 @@ EXPORT libtorrent::tcp::endpoint rand_tcp_ep();
EXPORT libtorrent::udp::endpoint rand_udp_ep(libtorrent::address(&rand_addr)() = rand_v4);
EXPORT libtorrent::sha1_hash rand_hash();
EXPORT libtorrent::sha1_hash to_hash(char const* s);
EXPORT std::map<std::string, std::int64_t> get_counters(libtorrent::session& s);
@ -112,6 +113,7 @@ EXPORT void stop_proxy(int port);
EXPORT void stop_all_proxies();
EXPORT libtorrent::tcp::endpoint ep(char const* ip, int port);
EXPORT libtorrent::udp::endpoint uep(char const* ip, int port);
EXPORT libtorrent::address addr(char const* ip);
EXPORT libtorrent::address_v4 addr4(char const* ip);
#if TORRENT_USE_IPV6

View File

@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/session.hpp"
#include "libtorrent/kademlia/node.hpp" // for verify_message
#include "libtorrent/bencode.hpp"
#include "libtorrent/bdecode.hpp"
#include "libtorrent/socket_io.hpp" // for hash_address
#include "libtorrent/broadcast_socket.hpp" // for supports_ipv6
#include "libtorrent/performance_counters.hpp" // for counters
@ -63,13 +64,6 @@ using namespace std::placeholders;
namespace {
sha1_hash to_hash(char const* s)
{
sha1_hash ret;
aux::from_hex({s, 40}, (char*)&ret[0]);
return ret;
}
void get_test_keypair(public_key& pk, secret_key& sk)
{
aux::from_hex({"77ff84905a91936367c01360803104f92432fcd904a43511876df5cdf3e7e548", 64}, pk.bytes.data());
@ -3375,6 +3369,43 @@ TORRENT_TEST(compare_ip_cidr)
#endif
}
TORRENT_TEST(dht_state)
{
dht_state s;
s.nid = to_hash("0000000000000000000000000000000000000001");
s.nodes.push_back(uep("1.1.1.1", 1));
s.nodes.push_back(uep("2.2.2.2", 2));
// not important that IPv6 is disabled here
s.nid6 = to_hash("0000000000000000000000000000000000000002");
s.nodes6.push_back(uep("3.3.3.3", 3));
s.nodes6.push_back(uep("4.4.4.4", 4));
entry const e = save_dht_state(s);
std::vector<char> tmp;
bencode(std::back_inserter(tmp), e);
bdecode_node n;
error_code ec;
int r = bdecode(&tmp[0], &tmp[0] + tmp.size(), n, ec);
TEST_CHECK(!r);
dht_state const s1 = read_dht_state(n);
TEST_EQUAL(s1.nid, s.nid);
TEST_CHECK(s1.nodes == s.nodes);
TEST_EQUAL(s1.nid6, s.nid6);
TEST_CHECK(s1.nodes6 == s.nodes6);
// empty
bdecode_node n1;
dht_state const s2 = read_dht_state(n1);
TEST_EQUAL(s2.nid, node_id());
TEST_CHECK(s2.nodes.empty());
TEST_EQUAL(s2.nid6, node_id());
TEST_CHECK(s2.nodes6.empty());
}
// TODO: test obfuscated_get_peers
#else

View File

@ -68,13 +68,6 @@ namespace
return sett;
}
sha1_hash to_hash(char const *s) {
std::stringstream hash(s);
sha1_hash ret;
hash >> ret;
return ret;
}
bool g_storage_constructor_invoked = false;
std::unique_ptr<dht_storage_interface> dht_custom_storage_constructor(

View File

@ -41,13 +41,6 @@ POSSIBILITY OF SUCH DAMAGE.
using namespace libtorrent;
sha1_hash to_hash(char const* s)
{
sha1_hash ret;
aux::from_hex({s, 40}, (char*)&ret[0]);
return ret;
}
address_v4 v4(char const* str)
{
error_code ec;

View File

@ -33,9 +33,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/extensions.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/bdecode.hpp"
#include "libtorrent/hex.hpp"
#include "settings.hpp"
#include "test.hpp"
#include "setup_transfer.hpp"
using namespace libtorrent;
using namespace libtorrent::dht;
@ -95,6 +99,52 @@ TORRENT_TEST(custom_dht_storage)
TEST_CHECK(ses.is_dht_running() == true);
TEST_EQUAL(g_storage_constructor_invoked, true);
}
TORRENT_TEST(dht_state)
{
settings_pack p = settings();
p.set_bool(settings_pack::enable_dht, true);
dht_settings sett;
sett.max_dht_items = 10000;
sett.max_peers = 20000;
dht_state s;
s.nid = to_hash("0000000000000000000000000000000000000001");
s.nodes.push_back(uep("1.1.1.1", 1));
s.nodes.push_back(uep("2.2.2.2", 2));
// not important that IPv6 is disabled here
s.nid6 = to_hash("0000000000000000000000000000000000000002");
s.nodes6.push_back(uep("3.3.3.3", 3));
s.nodes6.push_back(uep("4.4.4.4", 4));
session_params params(p);
params.dht_settings = sett;
params.dht_state = s;
lt::session ses1(params);
TEST_CHECK(ses1.is_dht_running() == true);
entry e;
ses1.save_state(e);
std::vector<char> tmp;
bencode(std::back_inserter(tmp), e);
bdecode_node n;
error_code ec;
int r = bdecode(&tmp[0], &tmp[0] + tmp.size(), n, ec);
TEST_CHECK(!r);
session_params params1 = read_session_params(n);
TEST_EQUAL(params1.dht_settings.max_dht_items, 10000);
TEST_EQUAL(params1.dht_settings.max_peers, 20000);
// not a chance the nid will be the fake initial ones
TEST_CHECK(params1.dht_state.nid != s.nid);
#if TORRENT_USE_IPV6
TEST_CHECK(params1.dht_state.nid6 != s.nid6);
#endif
}
#endif
#ifndef TORRENT_DISABLE_EXTENSIONS