support IPv6 in node_entry and m_ips
This commit is contained in:
parent
b5ecfa4f91
commit
11fa4f3e47
|
@ -55,10 +55,10 @@ struct TORRENT_EXTRA_EXPORT node_entry
|
||||||
void timed_out() { if (pinged() && timeout_count < 0xfe) ++timeout_count; }
|
void timed_out() { if (pinged() && timeout_count < 0xfe) ++timeout_count; }
|
||||||
int fail_count() const { return pinged() ? timeout_count : 0; }
|
int fail_count() const { return pinged() ? timeout_count : 0; }
|
||||||
void reset_fail_count() { if (pinged()) timeout_count = 0; }
|
void reset_fail_count() { if (pinged()) timeout_count = 0; }
|
||||||
udp::endpoint ep() const { return udp::endpoint(address_v4(a), p); }
|
udp::endpoint ep() const { return endpoint; }
|
||||||
bool confirmed() const { return timeout_count == 0; }
|
bool confirmed() const { return timeout_count == 0; }
|
||||||
address addr() const { return address_v4(a); }
|
address addr() const { return endpoint.address(); }
|
||||||
int port() const { return p; }
|
int port() const { return endpoint.port; }
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
time_point first_seen;
|
time_point first_seen;
|
||||||
|
@ -69,8 +69,7 @@ struct TORRENT_EXTRA_EXPORT node_entry
|
||||||
|
|
||||||
node_id id;
|
node_id id;
|
||||||
|
|
||||||
address_v4::bytes_type a;
|
union_endpoint endpoint;
|
||||||
boost::uint16_t p;
|
|
||||||
|
|
||||||
// the average RTT of this node
|
// the average RTT of this node
|
||||||
boost::uint16_t rtt;
|
boost::uint16_t rtt;
|
||||||
|
|
|
@ -73,6 +73,23 @@ struct routing_table_node
|
||||||
bucket_t live_nodes;
|
bucket_t live_nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ip_set
|
||||||
|
{
|
||||||
|
void insert(address addr);
|
||||||
|
size_t count(address addr);
|
||||||
|
void erase(address addr);
|
||||||
|
|
||||||
|
bool operator==(ip_set const& rh)
|
||||||
|
{
|
||||||
|
return m_ip4s == rh.m_ip4s && m_ip6s == rh.m_ip6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// these must be multisets because there can be multiple routing table
|
||||||
|
// entries for a single IP when restrict_routing_ips is set to false
|
||||||
|
boost::unordered_multiset<address_v4::bytes_type> m_ip4s;
|
||||||
|
boost::unordered_multiset<address_v6::bytes_type> m_ip6s;
|
||||||
|
};
|
||||||
|
|
||||||
// differences in the implementation from the description in
|
// differences in the implementation from the description in
|
||||||
// the paper:
|
// the paper:
|
||||||
//
|
//
|
||||||
|
@ -256,9 +273,8 @@ private:
|
||||||
|
|
||||||
// these are all the IPs that are in the routing
|
// these are all the IPs that are in the routing
|
||||||
// table. It's used to only allow a single entry
|
// table. It's used to only allow a single entry
|
||||||
// per IP in the whole table. Currently only for
|
// per IP in the whole table.
|
||||||
// IPv4
|
ip_set m_ips;
|
||||||
boost::unordered_multiset<address_v4::bytes_type> m_ips;
|
|
||||||
|
|
||||||
// constant called k in paper
|
// constant called k in paper
|
||||||
int m_bucket_size;
|
int m_bucket_size;
|
||||||
|
|
|
@ -38,6 +38,71 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
struct union_address
|
||||||
|
{
|
||||||
|
union_address()
|
||||||
|
{
|
||||||
|
*this = address();
|
||||||
|
}
|
||||||
|
|
||||||
|
union_address(address const& a)
|
||||||
|
{
|
||||||
|
*this = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
union_address& operator=(address const& a)
|
||||||
|
{
|
||||||
|
#if TORRENT_USE_IPV6
|
||||||
|
v4 = a.is_v4();
|
||||||
|
if (v4)
|
||||||
|
addr.v4 = a.to_v4().to_bytes();
|
||||||
|
else
|
||||||
|
addr.v6 = a.to_v6().to_bytes();
|
||||||
|
#else
|
||||||
|
addr.v4 = a.to_v4().to_bytes();
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(union_address const& rh) const
|
||||||
|
{
|
||||||
|
#if TORRENT_USE_IPV6
|
||||||
|
if (v4 != rh.v4) return false;
|
||||||
|
if (v4)
|
||||||
|
return addr.v4 == rh.addr.v4;
|
||||||
|
else
|
||||||
|
return addr.v6 == rh.addr.v6;
|
||||||
|
#else
|
||||||
|
return addr.v4 == rh.addr.v4;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(union_address const& rh) const
|
||||||
|
{
|
||||||
|
return !(*this == rh);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator address() const
|
||||||
|
{
|
||||||
|
#if TORRENT_USE_IPV6
|
||||||
|
if (v4) return address(address_v4(addr.v4));
|
||||||
|
else return address(address_v6(addr.v6));
|
||||||
|
#else
|
||||||
|
return address(address_v4(addr.v4));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TORRENT_UNION addr_t
|
||||||
|
{
|
||||||
|
address_v4::bytes_type v4;
|
||||||
|
#if TORRENT_USE_IPV6
|
||||||
|
address_v6::bytes_type v6;
|
||||||
|
#endif
|
||||||
|
} addr;
|
||||||
|
#if TORRENT_USE_IPV6
|
||||||
|
bool v4:1;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
struct union_endpoint
|
struct union_endpoint
|
||||||
{
|
{
|
||||||
|
@ -58,75 +123,35 @@ namespace libtorrent
|
||||||
|
|
||||||
union_endpoint& operator=(udp::endpoint const& ep)
|
union_endpoint& operator=(udp::endpoint const& ep)
|
||||||
{
|
{
|
||||||
#if TORRENT_USE_IPV6
|
addr = ep.address();
|
||||||
v4 = ep.address().is_v4();
|
|
||||||
if (v4)
|
|
||||||
addr.v4 = ep.address().to_v4().to_bytes();
|
|
||||||
else
|
|
||||||
addr.v6 = ep.address().to_v6().to_bytes();
|
|
||||||
#else
|
|
||||||
addr.v4 = ep.address().to_v4().to_bytes();
|
|
||||||
#endif
|
|
||||||
port = ep.port();
|
port = ep.port();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator udp::endpoint() const
|
operator udp::endpoint() const
|
||||||
{
|
{
|
||||||
#if TORRENT_USE_IPV6
|
return udp::endpoint(addr, port);
|
||||||
if (v4) return udp::endpoint(address_v4(addr.v4), port);
|
|
||||||
else return udp::endpoint(address_v6(addr.v6), port);
|
|
||||||
#else
|
|
||||||
return udp::endpoint(address_v4(addr.v4), port);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
union_endpoint& operator=(tcp::endpoint const& ep)
|
union_endpoint& operator=(tcp::endpoint const& ep)
|
||||||
{
|
{
|
||||||
#if TORRENT_USE_IPV6
|
addr = ep.address();
|
||||||
v4 = ep.address().is_v4();
|
|
||||||
if (v4)
|
|
||||||
addr.v4 = ep.address().to_v4().to_bytes();
|
|
||||||
else
|
|
||||||
addr.v6 = ep.address().to_v6().to_bytes();
|
|
||||||
#else
|
|
||||||
addr.v4 = ep.address().to_v4().to_bytes();
|
|
||||||
#endif
|
|
||||||
port = ep.port();
|
port = ep.port();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
libtorrent::address address() const
|
libtorrent::address address() const
|
||||||
{
|
{
|
||||||
#if TORRENT_USE_IPV6
|
return addr;
|
||||||
if (v4) return address_v4(addr.v4);
|
|
||||||
else return address_v6(addr.v6);
|
|
||||||
#else
|
|
||||||
return address_v4(addr.v4);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
operator tcp::endpoint() const
|
operator tcp::endpoint() const
|
||||||
{
|
{
|
||||||
#if TORRENT_USE_IPV6
|
return tcp::endpoint(addr, port);
|
||||||
if (v4) return tcp::endpoint(address_v4(addr.v4), port);
|
|
||||||
else return tcp::endpoint(address_v6(addr.v6), port);
|
|
||||||
#else
|
|
||||||
return tcp::endpoint(address_v4(addr.v4), port);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_UNION addr_t
|
union_address addr;
|
||||||
{
|
|
||||||
address_v4::bytes_type v4;
|
|
||||||
#if TORRENT_USE_IPV6
|
|
||||||
address_v6::bytes_type v6;
|
|
||||||
#endif
|
|
||||||
} addr;
|
|
||||||
boost::uint16_t port;
|
boost::uint16_t port;
|
||||||
#if TORRENT_USE_IPV6
|
|
||||||
bool v4:1;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,7 @@ namespace libtorrent { namespace dht
|
||||||
, bool pinged)
|
, bool pinged)
|
||||||
: last_queried(pinged ? aux::time_now() : min_time())
|
: last_queried(pinged ? aux::time_now() : min_time())
|
||||||
, id(id_)
|
, id(id_)
|
||||||
, a(ep.address().to_v4().to_bytes())
|
, endpoint(ep)
|
||||||
, p(ep.port())
|
|
||||||
, rtt(roundtriptime & 0xffff)
|
, rtt(roundtriptime & 0xffff)
|
||||||
, timeout_count(pinged ? 0 : 0xff)
|
, timeout_count(pinged ? 0 : 0xff)
|
||||||
{
|
{
|
||||||
|
@ -54,8 +53,7 @@ namespace libtorrent { namespace dht
|
||||||
node_entry::node_entry(udp::endpoint ep)
|
node_entry::node_entry(udp::endpoint ep)
|
||||||
: last_queried(min_time())
|
: last_queried(min_time())
|
||||||
, id(0)
|
, id(0)
|
||||||
, a(ep.address().to_v4().to_bytes())
|
, endpoint(ep)
|
||||||
, p(ep.port())
|
|
||||||
, rtt(0xffff)
|
, rtt(0xffff)
|
||||||
, timeout_count(0xff)
|
, timeout_count(0xff)
|
||||||
{
|
{
|
||||||
|
@ -67,7 +65,6 @@ namespace libtorrent { namespace dht
|
||||||
node_entry::node_entry()
|
node_entry::node_entry()
|
||||||
: last_queried(min_time())
|
: last_queried(min_time())
|
||||||
, id(0)
|
, id(0)
|
||||||
, p(0)
|
|
||||||
, rtt(0xffff)
|
, rtt(0xffff)
|
||||||
, timeout_count(0xff)
|
, timeout_count(0xff)
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,15 +58,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
using boost::uint8_t;
|
using boost::uint8_t;
|
||||||
|
|
||||||
#if BOOST_VERSION <= 104700
|
|
||||||
namespace boost {
|
|
||||||
size_t hash_value(libtorrent::address_v4::bytes_type ip)
|
|
||||||
{
|
|
||||||
return boost::hash_value(*reinterpret_cast<boost::uint32_t*>(&ip[0]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace libtorrent { namespace dht
|
namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
|
@ -89,6 +80,30 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ip_set::insert(address addr)
|
||||||
|
{
|
||||||
|
if (addr.is_v4())
|
||||||
|
m_ip4s.insert(addr.to_v4().to_bytes());
|
||||||
|
else
|
||||||
|
m_ip6s.insert(addr.to_v6().to_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ip_set::count(address addr)
|
||||||
|
{
|
||||||
|
if (addr.is_v4())
|
||||||
|
return m_ip4s.count(addr.to_v4().to_bytes());
|
||||||
|
else
|
||||||
|
return m_ip6s.count(addr.to_v6().to_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ip_set::erase(address addr)
|
||||||
|
{
|
||||||
|
if (addr.is_v4())
|
||||||
|
erase_one(m_ip4s, addr.to_v4().to_bytes());
|
||||||
|
else
|
||||||
|
erase_one(m_ip6s, addr.to_v6().to_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
routing_table::routing_table(node_id const& id, int bucket_size
|
routing_table::routing_table(node_id const& id, int bucket_size
|
||||||
, dht_settings const& settings
|
, dht_settings const& settings
|
||||||
, dht_logger* log)
|
, dht_logger* log)
|
||||||
|
@ -514,8 +529,8 @@ void routing_table::remove_node(node_entry* n
|
||||||
&& n < &bucket->replacements[0] + bucket->replacements.size())
|
&& n < &bucket->replacements[0] + bucket->replacements.size())
|
||||||
{
|
{
|
||||||
int idx = n - &bucket->replacements[0];
|
int idx = n - &bucket->replacements[0];
|
||||||
TORRENT_ASSERT(m_ips.count(n->a) > 0);
|
TORRENT_ASSERT(m_ips.count(n->addr()) > 0);
|
||||||
erase_one(m_ips, n->a);
|
m_ips.erase(n->addr());
|
||||||
bucket->replacements.erase(bucket->replacements.begin() + idx);
|
bucket->replacements.erase(bucket->replacements.begin() + idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,8 +539,8 @@ void routing_table::remove_node(node_entry* n
|
||||||
&& n < &bucket->live_nodes[0] + bucket->live_nodes.size())
|
&& n < &bucket->live_nodes[0] + bucket->live_nodes.size())
|
||||||
{
|
{
|
||||||
int idx = n - &bucket->live_nodes[0];
|
int idx = n - &bucket->live_nodes[0];
|
||||||
TORRENT_ASSERT(m_ips.count(n->a) > 0);
|
TORRENT_ASSERT(m_ips.count(n->addr()) > 0);
|
||||||
erase_one(m_ips, n->a);
|
m_ips.erase(n->addr());
|
||||||
bucket->live_nodes.erase(bucket->live_nodes.begin() + idx);
|
bucket->live_nodes.erase(bucket->live_nodes.begin() + idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,7 +597,7 @@ routing_table::add_node_status_t routing_table::add_node_impl(node_entry e)
|
||||||
if (e.id == m_id) return failed_to_add;
|
if (e.id == m_id) return failed_to_add;
|
||||||
|
|
||||||
// do we already have this IP in the table?
|
// do we already have this IP in the table?
|
||||||
if (m_ips.count(e.addr().to_v4().to_bytes()) > 0)
|
if (m_ips.count(e.addr()) > 0)
|
||||||
{
|
{
|
||||||
// this exact IP already exists in the table. It might be the case
|
// this exact IP already exists in the table. It might be the case
|
||||||
// that the node changed IP. If pinged is true, and the port also
|
// that the node changed IP. If pinged is true, and the port also
|
||||||
|
@ -688,7 +703,7 @@ routing_table::add_node_status_t routing_table::add_node_impl(node_entry e)
|
||||||
j->timeout_count = 0;
|
j->timeout_count = 0;
|
||||||
j->update_rtt(e.rtt);
|
j->update_rtt(e.rtt);
|
||||||
e = *j;
|
e = *j;
|
||||||
erase_one(m_ips, j->addr().to_v4().to_bytes());
|
m_ips.erase(j->addr());
|
||||||
rb.erase(j);
|
rb.erase(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,7 +752,7 @@ ip_ok:
|
||||||
{
|
{
|
||||||
if (b.empty()) b.reserve(bucket_size_limit);
|
if (b.empty()) b.reserve(bucket_size_limit);
|
||||||
b.push_back(e);
|
b.push_back(e);
|
||||||
m_ips.insert(e.addr().to_v4().to_bytes());
|
m_ips.insert(e.addr());
|
||||||
return node_added;
|
return node_added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,9 +777,9 @@ ip_ok:
|
||||||
{
|
{
|
||||||
// j points to a node that has not been pinged.
|
// j points to a node that has not been pinged.
|
||||||
// Replace it with this new one
|
// Replace it with this new one
|
||||||
erase_one(m_ips, j->addr().to_v4().to_bytes());
|
m_ips.erase(j->addr());
|
||||||
*j = e;
|
*j = e;
|
||||||
m_ips.insert(e.addr().to_v4().to_bytes());
|
m_ips.insert(e.addr());
|
||||||
return node_added;
|
return node_added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,9 +798,9 @@ ip_ok:
|
||||||
{
|
{
|
||||||
// i points to a node that has been marked
|
// i points to a node that has been marked
|
||||||
// as stale. Replace it with this new one
|
// as stale. Replace it with this new one
|
||||||
erase_one(m_ips, j->addr().to_v4().to_bytes());
|
m_ips.erase(j->addr());
|
||||||
*j = e;
|
*j = e;
|
||||||
m_ips.insert(e.addr().to_v4().to_bytes());
|
m_ips.insert(e.addr());
|
||||||
return node_added;
|
return node_added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,9 +908,9 @@ ip_ok:
|
||||||
|
|
||||||
if (j != b.end() && (force_replace || j->rtt > e.rtt))
|
if (j != b.end() && (force_replace || j->rtt > e.rtt))
|
||||||
{
|
{
|
||||||
erase_one(m_ips, j->addr().to_v4().to_bytes());
|
m_ips.erase(j->addr());
|
||||||
*j = e;
|
*j = e;
|
||||||
m_ips.insert(e.addr().to_v4().to_bytes());
|
m_ips.insert(e.addr());
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
if (m_log)
|
if (m_log)
|
||||||
{
|
{
|
||||||
|
@ -940,13 +955,13 @@ ip_ok:
|
||||||
// less reliable than this one, that has been pinged
|
// less reliable than this one, that has been pinged
|
||||||
j = std::find_if(rb.begin(), rb.end(), boost::bind(&node_entry::pinged, _1) == false);
|
j = std::find_if(rb.begin(), rb.end(), boost::bind(&node_entry::pinged, _1) == false);
|
||||||
if (j == rb.end()) j = rb.begin();
|
if (j == rb.end()) j = rb.begin();
|
||||||
erase_one(m_ips, j->addr().to_v4().to_bytes());
|
m_ips.erase(j->addr());
|
||||||
rb.erase(j);
|
rb.erase(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rb.empty()) rb.reserve(m_bucket_size);
|
if (rb.empty()) rb.reserve(m_bucket_size);
|
||||||
rb.push_back(e);
|
rb.push_back(e);
|
||||||
m_ips.insert(e.addr().to_v4().to_bytes());
|
m_ips.insert(e.addr());
|
||||||
return node_added;
|
return node_added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1140,13 +1155,13 @@ void routing_table::node_failed(node_id const& nid, udp::endpoint const& ep)
|
||||||
// has never responded at all, remove it
|
// has never responded at all, remove it
|
||||||
if (j->fail_count() >= m_settings.max_fail_count || !j->pinged())
|
if (j->fail_count() >= m_settings.max_fail_count || !j->pinged())
|
||||||
{
|
{
|
||||||
erase_one(m_ips, j->addr().to_v4().to_bytes());
|
m_ips.erase(j->addr());
|
||||||
b.erase(j);
|
b.erase(j);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
erase_one(m_ips, j->a);
|
m_ips.erase(j->addr());
|
||||||
b.erase(j);
|
b.erase(j);
|
||||||
|
|
||||||
// sort by RTT first, to find the node with the lowest
|
// sort by RTT first, to find the node with the lowest
|
||||||
|
@ -1277,7 +1292,7 @@ void routing_table::find_node(node_id const& target
|
||||||
#if TORRENT_USE_INVARIANT_CHECKS
|
#if TORRENT_USE_INVARIANT_CHECKS
|
||||||
void routing_table::check_invariant() const
|
void routing_table::check_invariant() const
|
||||||
{
|
{
|
||||||
boost::unordered_multiset<address_v4::bytes_type> all_ips;
|
ip_set all_ips;
|
||||||
|
|
||||||
for (table_t::const_iterator i = m_buckets.begin()
|
for (table_t::const_iterator i = m_buckets.begin()
|
||||||
, end(m_buckets.end()); i != end; ++i)
|
, end(m_buckets.end()); i != end; ++i)
|
||||||
|
@ -1285,12 +1300,13 @@ void routing_table::check_invariant() const
|
||||||
for (bucket_t::const_iterator j = i->replacements.begin();
|
for (bucket_t::const_iterator j = i->replacements.begin();
|
||||||
j != i->replacements.end(); ++j)
|
j != i->replacements.end(); ++j)
|
||||||
{
|
{
|
||||||
all_ips.insert(j->addr().to_v4().to_bytes());
|
all_ips.insert(j->addr());
|
||||||
}
|
}
|
||||||
for (bucket_t::const_iterator j = i->live_nodes.begin();
|
for (bucket_t::const_iterator j = i->live_nodes.begin();
|
||||||
j != i->live_nodes.end(); ++j)
|
j != i->live_nodes.end(); ++j)
|
||||||
{
|
{
|
||||||
all_ips.insert(j->addr().to_v4().to_bytes());
|
TORRENT_ASSERT(j->addr().is_v4() == i->live_nodes.begin()->addr().is_v4());
|
||||||
|
all_ips.insert(j->addr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue