merged DHT change from RC_0_16

This commit is contained in:
Arvid Norberg 2013-10-13 23:04:40 +00:00
parent b7ae64fd1f
commit 50f051433a
8 changed files with 76 additions and 55 deletions

View File

@ -137,15 +137,21 @@ bootstrapping
------------- -------------
In order to set ones initial node ID, the external IP needs to be known. This In order to set ones initial node ID, the external IP needs to be known. This
is not a trivial problem. With this extension, *all* DHT requests whose node is not a trivial problem. With this extension, *all* DHT responses SHOULD include
ID does not match its IP address MUST be serviced and MUST also include one a *top-level* field called ``ip``, containing a compact binary representation of
extra result value (inside the ``r`` dictionary) called ``ip``. The IP field the requestor's IP and port. That is big endian IP followed by 2 bytes of big endian
contains the raw (big endian) byte representation of the external IP address. port.
This is the same byte sequence used to verify the node ID.
The IP portion is the same byte sequence used to verify the node ID.
It is important that the ``ip`` field is in the top level dictionary. Nodes that
enforce the node-ID will respond with an error message ("y": "e", "e": { ... }),
whereas a node that supports this extension but without enforcing it will respond
with a normal reply ("y": "r", "r": { ... }).
A DHT node which receives an ``ip`` result in a request SHOULD consider restarting A DHT node which receives an ``ip`` result in a request SHOULD consider restarting
its DHT node with a new node ID, taking this IP into account. Since a single node its DHT node with a new node ID, taking this IP into account. Since a single node
can not be trusted, there should be some mechanism of determining whether or can not be trusted, there should be some mechanism to determine whether or
not the node has a correct understanding of its external IP or not. This could not the node has a correct understanding of its external IP or not. This could
be done by voting, or only restart the DHT once at least a certain number of be done by voting, or only restart the DHT once at least a certain number of
nodes, from separate searches, tells you your node ID is incorrect. nodes, from separate searches, tells you your node ID is incorrect.

View File

@ -68,6 +68,7 @@ TORRENT_DECLARE_LOG(node);
#endif #endif
struct traversal_algorithm; struct traversal_algorithm;
struct dht_observer;
struct key_desc_t struct key_desc_t
{ {
@ -295,6 +296,8 @@ public:
rpc_manager m_rpc; rpc_manager m_rpc;
private: private:
dht_observer* m_observer;
table_t m_map; table_t m_map;
dht_immutable_table_t m_immutable_table; dht_immutable_table_t m_immutable_table;
dht_mutable_table_t m_mutable_table; dht_mutable_table_t m_mutable_table;

View File

@ -66,16 +66,13 @@ struct null_observer : public observer
}; };
class routing_table; class routing_table;
struct dht_observer;
class TORRENT_EXTRA_EXPORT rpc_manager class TORRENT_EXTRA_EXPORT rpc_manager
{ {
public: public:
typedef boost::function3<void, address, int, address> external_ip_fun;
rpc_manager(node_id const& our_id rpc_manager(node_id const& our_id
, routing_table& table, udp_socket_interface* sock , routing_table& table, udp_socket_interface* sock);
, dht_observer* observer);
~rpc_manager(); ~rpc_manager();
void unreachable(udp::endpoint const& ep); void unreachable(udp::endpoint const& ep);
@ -118,7 +115,6 @@ private:
node_id m_random_number; node_id m_random_number;
int m_allocated_observers; int m_allocated_observers;
bool m_destructing; bool m_destructing;
dht_observer* m_observer;
}; };
} } // namespace libtorrent::dht } } // namespace libtorrent::dht

View File

@ -47,6 +47,7 @@ namespace libtorrent
TORRENT_EXTRA_EXPORT std::string print_endpoint(tcp::endpoint const& ep); TORRENT_EXTRA_EXPORT std::string print_endpoint(tcp::endpoint const& ep);
TORRENT_EXTRA_EXPORT std::string print_endpoint(udp::endpoint const& ep); TORRENT_EXTRA_EXPORT std::string print_endpoint(udp::endpoint const& ep);
TORRENT_EXTRA_EXPORT std::string address_to_bytes(address const& a); TORRENT_EXTRA_EXPORT std::string address_to_bytes(address const& a);
TORRENT_EXPORT std::string endpoint_to_bytes(udp::endpoint const& ep);
TORRENT_EXTRA_EXPORT void hash_address(address const& ip, sha1_hash& h); TORRENT_EXTRA_EXPORT void hash_address(address const& ip, sha1_hash& h);
namespace detail namespace detail

View File

@ -48,6 +48,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/kademlia/rpc_manager.hpp" #include "libtorrent/kademlia/rpc_manager.hpp"
#include "libtorrent/kademlia/routing_table.hpp" #include "libtorrent/kademlia/routing_table.hpp"
#include "libtorrent/kademlia/node.hpp" #include "libtorrent/kademlia/node.hpp"
#include <libtorrent/kademlia/dht_observer.hpp>
#include "libtorrent/kademlia/refresh.hpp" #include "libtorrent/kademlia/refresh.hpp"
#include "libtorrent/kademlia/find_data.hpp" #include "libtorrent/kademlia/find_data.hpp"
@ -100,7 +101,8 @@ node_impl::node_impl(alert_dispatcher* alert_disp
: m_settings(settings) : m_settings(settings)
, m_id(nid == (node_id::min)() || !verify_id(nid, external_address) ? generate_id(external_address) : nid) , m_id(nid == (node_id::min)() || !verify_id(nid, external_address) ? generate_id(external_address) : nid)
, m_table(m_id, 8, settings) , m_table(m_id, 8, settings)
, m_rpc(m_id, m_table, sock, observer) , m_rpc(m_id, m_table, sock)
, m_observer(observer)
, m_last_tracker_tick(time_now()) , m_last_tracker_tick(time_now())
, m_post_alert(alert_disp) , m_post_alert(alert_disp)
, m_sock(sock) , m_sock(sock)
@ -221,6 +223,28 @@ void node_impl::incoming(msg const& m)
char y = *(y_ent->string_ptr()); char y = *(y_ent->string_ptr());
lazy_entry const* ext_ip = m.message.dict_find_string("ip");
if (ext_ip && ext_ip->string_length() == 4)
{
// this node claims we use the wrong node-ID!
address_v4::bytes_type b;
memcpy(&b[0], ext_ip->string_ptr(), 4);
if (m_observer)
m_observer->set_external_address(address_v4(b)
, m.addr.address());
}
#if TORRENT_USE_IPV6
else if (ext_ip && ext_ip->string_length() == 16)
{
// this node claims we use the wrong node-ID!
address_v6::bytes_type b;
memcpy(&b[0], ext_ip->string_ptr(), 16);
if (m_observer)
m_observer->set_external_address(address_v6(b)
, m.addr.address());
}
#endif
switch (y) switch (y)
{ {
case 'r': case 'r':
@ -657,6 +681,17 @@ void node_impl::incoming_request(msg const& m, entry& e)
return; return;
} }
e["ip"] = endpoint_to_bytes(m.addr);
/*
// if this nodes ID doesn't match its IP, tell it what
// its IP is with an error
// don't enforce this yet
if (!verify_id(id, m.addr.address()))
{
incoming_error(e, "invalid node ID");
return;
}
*/
char const* query = top_level[0]->string_cstr(); char const* query = top_level[0]->string_cstr();
lazy_entry const* arg_ent = top_level[1]; lazy_entry const* arg_ent = top_level[1];
@ -668,11 +703,6 @@ void node_impl::incoming_request(msg const& m, entry& e)
entry& reply = e["r"]; entry& reply = e["r"];
m_rpc.add_our_id(reply); m_rpc.add_our_id(reply);
// if this nodes ID doesn't match its IP, tell it what
// its IP is
if (!verify_id(id, m.addr.address()))
reply["ip"] = address_to_bytes(m.addr.address());
// mirror back the other node's external port // mirror back the other node's external port
reply["p"] = m.addr.port(); reply["p"] = m.addr.port();

View File

@ -46,7 +46,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/kademlia/refresh.hpp> #include <libtorrent/kademlia/refresh.hpp>
#include <libtorrent/kademlia/node.hpp> #include <libtorrent/kademlia/node.hpp>
#include <libtorrent/kademlia/observer.hpp> #include <libtorrent/kademlia/observer.hpp>
#include <libtorrent/kademlia/dht_observer.hpp>
#include <libtorrent/hasher.hpp> #include <libtorrent/hasher.hpp>
#include <libtorrent/time.hpp> #include <libtorrent/time.hpp>
#include <time.h> // time() #include <time.h> // time()
@ -159,8 +158,7 @@ enum { observer_size = max3<
}; };
rpc_manager::rpc_manager(node_id const& our_id rpc_manager::rpc_manager(node_id const& our_id
, routing_table& table, udp_socket_interface* sock , routing_table& table, udp_socket_interface* sock)
, dht_observer* observer)
: m_pool_allocator(observer_size, 10) : m_pool_allocator(observer_size, 10)
, m_sock(sock) , m_sock(sock)
, m_our_id(our_id) , m_our_id(our_id)
@ -169,7 +167,6 @@ rpc_manager::rpc_manager(node_id const& our_id
, m_random_number(generate_random_id()) , m_random_number(generate_random_id())
, m_allocated_observers(0) , m_allocated_observers(0)
, m_destructing(false) , m_destructing(false)
, m_observer(observer)
{ {
std::srand(time(0)); std::srand(time(0));
@ -340,28 +337,6 @@ bool rpc_manager::incoming(msg const& m, node_id* id)
return false; return false;
} }
lazy_entry const* ext_ip = ret_ent->dict_find_string("ip");
if (ext_ip && ext_ip->string_length() == 4)
{
// this node claims we use the wrong node-ID!
address_v4::bytes_type b;
memcpy(&b[0], ext_ip->string_ptr(), 4);
if (m_observer)
m_observer->set_external_address(address_v4(b)
, m.addr.address());
}
#if TORRENT_USE_IPV6
else if (ext_ip && ext_ip->string_length() == 16)
{
// this node claims we use the wrong node-ID!
address_v6::bytes_type b;
memcpy(&b[0], ext_ip->string_ptr(), 16);
if (m_observer)
m_observer->set_external_address(address_v6(b)
, m.addr.address());
}
#endif
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(rpc) << "[" << o->m_algorithm.get() << "] Reply with transaction id: " TORRENT_LOG(rpc) << "[" << o->m_algorithm.get() << "] Reply with transaction id: "
<< tid << " from " << m.addr; << tid << " from " << m.addr;

View File

@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/socket_io.hpp" #include "libtorrent/socket_io.hpp"
#include "libtorrent/address.hpp" #include "libtorrent/address.hpp"
#include "libtorrent/io.hpp" // for write_uint16
#include "libtorrent/hasher.hpp" // for hasher #include "libtorrent/hasher.hpp" // for hasher
namespace libtorrent namespace libtorrent
@ -50,18 +51,18 @@ namespace libtorrent
std::string address_to_bytes(address const& a) std::string address_to_bytes(address const& a)
{ {
#if TORRENT_USE_IPV6 std::string ret;
if (a.is_v6()) std::back_insert_iterator<std::string> out(ret);
{ detail::write_address(a, out);
address_v6::bytes_type b = a.to_v6().to_bytes(); return ret;
return std::string((char*)&b[0], b.size());
} }
else
#endif std::string endpoint_to_bytes(udp::endpoint const& ep)
{ {
address_v4::bytes_type b = a.to_v4().to_bytes(); std::string ret;
return std::string((char*)&b[0], b.size()); std::back_insert_iterator<std::string> out(ret);
} detail::write_endpoint(ep, out);
return ret;
} }
std::string print_endpoint(tcp::endpoint const& ep) std::string print_endpoint(tcp::endpoint const& ep)

View File

@ -48,6 +48,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/bloom_filter.hpp" #include "libtorrent/bloom_filter.hpp"
#include "libtorrent/aux_/session_impl.hpp" #include "libtorrent/aux_/session_impl.hpp"
#include "libtorrent/ip_voter.hpp" #include "libtorrent/ip_voter.hpp"
#include "libtorrent/socket_io.hpp"
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <iostream> #include <iostream>
#include <set> #include <set>
@ -402,6 +403,14 @@ int test_main()
test1.resize(100, true); test1.resize(100, true);
TEST_CHECK(test1.all_set() == true); TEST_CHECK(test1.all_set() == true);
// test address_to_bytes
TEST_EQUAL(address_to_bytes(address_v4::from_string("10.11.12.13")), "\x0a\x0b\x0c\x0d");
TEST_EQUAL(address_to_bytes(address_v4::from_string("16.5.127.1")), "\x10\x05\x7f\x01");
// test endpoint_to_bytes
TEST_EQUAL(endpoint_to_bytes(udp::endpoint(address_v4::from_string("10.11.12.13"), 8080)), "\x0a\x0b\x0c\x0d\x1f\x90");
TEST_EQUAL(endpoint_to_bytes(udp::endpoint(address_v4::from_string("16.5.127.1"), 12345)), "\x10\x05\x7f\x01\x30\x39");
return 0; return 0;
} }