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; }
|
||||
int fail_count() const { return 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; }
|
||||
address addr() const { return address_v4(a); }
|
||||
int port() const { return p; }
|
||||
address addr() const { return endpoint.address(); }
|
||||
int port() const { return endpoint.port; }
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
time_point first_seen;
|
||||
|
@ -69,8 +69,7 @@ struct TORRENT_EXTRA_EXPORT node_entry
|
|||
|
||||
node_id id;
|
||||
|
||||
address_v4::bytes_type a;
|
||||
boost::uint16_t p;
|
||||
union_endpoint endpoint;
|
||||
|
||||
// the average RTT of this node
|
||||
boost::uint16_t rtt;
|
||||
|
|
|
@ -73,6 +73,23 @@ struct routing_table_node
|
|||
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
|
||||
// the paper:
|
||||
//
|
||||
|
@ -256,9 +273,8 @@ private:
|
|||
|
||||
// these are all the IPs that are in the routing
|
||||
// table. It's used to only allow a single entry
|
||||
// per IP in the whole table. Currently only for
|
||||
// IPv4
|
||||
boost::unordered_multiset<address_v4::bytes_type> m_ips;
|
||||
// per IP in the whole table.
|
||||
ip_set m_ips;
|
||||
|
||||
// constant called k in paper
|
||||
int m_bucket_size;
|
||||
|
|
|
@ -38,6 +38,71 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -58,75 +123,35 @@ namespace libtorrent
|
|||
|
||||
union_endpoint& operator=(udp::endpoint const& ep)
|
||||
{
|
||||
#if TORRENT_USE_IPV6
|
||||
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
|
||||
addr = ep.address();
|
||||
port = ep.port();
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator udp::endpoint() const
|
||||
{
|
||||
#if TORRENT_USE_IPV6
|
||||
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
|
||||
return udp::endpoint(addr, port);
|
||||
}
|
||||
|
||||
union_endpoint& operator=(tcp::endpoint const& ep)
|
||||
{
|
||||
#if TORRENT_USE_IPV6
|
||||
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
|
||||
addr = ep.address();
|
||||
port = ep.port();
|
||||
return *this;
|
||||
}
|
||||
|
||||
libtorrent::address address() const
|
||||
{
|
||||
#if TORRENT_USE_IPV6
|
||||
if (v4) return address_v4(addr.v4);
|
||||
else return address_v6(addr.v6);
|
||||
#else
|
||||
return address_v4(addr.v4);
|
||||
#endif
|
||||
return addr;
|
||||
}
|
||||
|
||||
operator tcp::endpoint() const
|
||||
{
|
||||
#if TORRENT_USE_IPV6
|
||||
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
|
||||
return tcp::endpoint(addr, port);
|
||||
}
|
||||
|
||||
TORRENT_UNION addr_t
|
||||
{
|
||||
address_v4::bytes_type v4;
|
||||
#if TORRENT_USE_IPV6
|
||||
address_v6::bytes_type v6;
|
||||
#endif
|
||||
} addr;
|
||||
union_address addr;
|
||||
boost::uint16_t port;
|
||||
#if TORRENT_USE_IPV6
|
||||
bool v4:1;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,7 @@ namespace libtorrent { namespace dht
|
|||
, bool pinged)
|
||||
: last_queried(pinged ? aux::time_now() : min_time())
|
||||
, id(id_)
|
||||
, a(ep.address().to_v4().to_bytes())
|
||||
, p(ep.port())
|
||||
, endpoint(ep)
|
||||
, rtt(roundtriptime & 0xffff)
|
||||
, timeout_count(pinged ? 0 : 0xff)
|
||||
{
|
||||
|
@ -54,8 +53,7 @@ namespace libtorrent { namespace dht
|
|||
node_entry::node_entry(udp::endpoint ep)
|
||||
: last_queried(min_time())
|
||||
, id(0)
|
||||
, a(ep.address().to_v4().to_bytes())
|
||||
, p(ep.port())
|
||||
, endpoint(ep)
|
||||
, rtt(0xffff)
|
||||
, timeout_count(0xff)
|
||||
{
|
||||
|
@ -67,7 +65,6 @@ namespace libtorrent { namespace dht
|
|||
node_entry::node_entry()
|
||||
: last_queried(min_time())
|
||||
, id(0)
|
||||
, p(0)
|
||||
, rtt(0xffff)
|
||||
, timeout_count(0xff)
|
||||
{
|
||||
|
|
|
@ -58,15 +58,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
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
|
||||
|
@ -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
|
||||
, dht_settings const& settings
|
||||
, dht_logger* log)
|
||||
|
@ -514,8 +529,8 @@ void routing_table::remove_node(node_entry* n
|
|||
&& n < &bucket->replacements[0] + bucket->replacements.size())
|
||||
{
|
||||
int idx = n - &bucket->replacements[0];
|
||||
TORRENT_ASSERT(m_ips.count(n->a) > 0);
|
||||
erase_one(m_ips, n->a);
|
||||
TORRENT_ASSERT(m_ips.count(n->addr()) > 0);
|
||||
m_ips.erase(n->addr());
|
||||
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())
|
||||
{
|
||||
int idx = n - &bucket->live_nodes[0];
|
||||
TORRENT_ASSERT(m_ips.count(n->a) > 0);
|
||||
erase_one(m_ips, n->a);
|
||||
TORRENT_ASSERT(m_ips.count(n->addr()) > 0);
|
||||
m_ips.erase(n->addr());
|
||||
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;
|
||||
|
||||
// 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
|
||||
// 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->update_rtt(e.rtt);
|
||||
e = *j;
|
||||
erase_one(m_ips, j->addr().to_v4().to_bytes());
|
||||
m_ips.erase(j->addr());
|
||||
rb.erase(j);
|
||||
}
|
||||
|
||||
|
@ -737,7 +752,7 @@ ip_ok:
|
|||
{
|
||||
if (b.empty()) b.reserve(bucket_size_limit);
|
||||
b.push_back(e);
|
||||
m_ips.insert(e.addr().to_v4().to_bytes());
|
||||
m_ips.insert(e.addr());
|
||||
return node_added;
|
||||
}
|
||||
|
||||
|
@ -762,9 +777,9 @@ ip_ok:
|
|||
{
|
||||
// j points to a node that has not been pinged.
|
||||
// Replace it with this new one
|
||||
erase_one(m_ips, j->addr().to_v4().to_bytes());
|
||||
m_ips.erase(j->addr());
|
||||
*j = e;
|
||||
m_ips.insert(e.addr().to_v4().to_bytes());
|
||||
m_ips.insert(e.addr());
|
||||
return node_added;
|
||||
}
|
||||
|
||||
|
@ -783,9 +798,9 @@ ip_ok:
|
|||
{
|
||||
// i points to a node that has been marked
|
||||
// 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;
|
||||
m_ips.insert(e.addr().to_v4().to_bytes());
|
||||
m_ips.insert(e.addr());
|
||||
return node_added;
|
||||
}
|
||||
|
||||
|
@ -893,9 +908,9 @@ ip_ok:
|
|||
|
||||
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;
|
||||
m_ips.insert(e.addr().to_v4().to_bytes());
|
||||
m_ips.insert(e.addr());
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (m_log)
|
||||
{
|
||||
|
@ -940,13 +955,13 @@ ip_ok:
|
|||
// less reliable than this one, that has been pinged
|
||||
j = std::find_if(rb.begin(), rb.end(), boost::bind(&node_entry::pinged, _1) == false);
|
||||
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);
|
||||
}
|
||||
|
||||
if (rb.empty()) rb.reserve(m_bucket_size);
|
||||
rb.push_back(e);
|
||||
m_ips.insert(e.addr().to_v4().to_bytes());
|
||||
m_ips.insert(e.addr());
|
||||
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
|
||||
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);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
erase_one(m_ips, j->a);
|
||||
m_ips.erase(j->addr());
|
||||
b.erase(j);
|
||||
|
||||
// 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
|
||||
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()
|
||||
, 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();
|
||||
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();
|
||||
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