improve node-id operations (#693)
improve node-id operations, to operate on 32 bits at a time instead of 8. move out some code into sha1_hash.cpp, from the header file
This commit is contained in:
parent
f56c1f8b2f
commit
077e9bb10c
|
@ -75,6 +75,7 @@ set(sources
|
||||||
proxy_settings
|
proxy_settings
|
||||||
session_stats
|
session_stats
|
||||||
settings_pack
|
settings_pack
|
||||||
|
sha1_hash
|
||||||
socket_io
|
socket_io
|
||||||
socket_type
|
socket_type
|
||||||
socks5_stream
|
socks5_stream
|
||||||
|
|
1
Jamfile
1
Jamfile
|
@ -601,6 +601,7 @@ SOURCES =
|
||||||
session_impl
|
session_impl
|
||||||
session_call
|
session_call
|
||||||
settings_pack
|
settings_pack
|
||||||
|
sha1_hash
|
||||||
socket_io
|
socket_io
|
||||||
socket_type
|
socket_type
|
||||||
socks5_stream
|
socks5_stream
|
||||||
|
|
|
@ -133,81 +133,10 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
// shift left ``n`` bits.
|
// shift left ``n`` bits.
|
||||||
sha1_hash& operator<<=(int n)
|
sha1_hash& operator<<=(int n);
|
||||||
{
|
|
||||||
TORRENT_ASSERT(n >= 0);
|
|
||||||
const int num_words = n / 32;
|
|
||||||
if (num_words >= number_size)
|
|
||||||
{
|
|
||||||
std::memset(m_number, 0, size);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_words > 0)
|
|
||||||
{
|
|
||||||
std::memmove(m_number, m_number + num_words
|
|
||||||
, (number_size - num_words) * sizeof(boost::uint32_t));
|
|
||||||
std::memset(m_number + (number_size - num_words)
|
|
||||||
, 0, num_words * sizeof(boost::uint32_t));
|
|
||||||
n -= num_words * 32;
|
|
||||||
}
|
|
||||||
if (n > 0)
|
|
||||||
{
|
|
||||||
// keep in mind that the uint32_t are stored in network
|
|
||||||
// byte order, so they have to be byteswapped before
|
|
||||||
// applying the shift operations, and then byteswapped
|
|
||||||
// back again.
|
|
||||||
m_number[0] = aux::network_to_host(m_number[0]);
|
|
||||||
for (int i = 0; i < number_size - 1; ++i)
|
|
||||||
{
|
|
||||||
m_number[i] <<= n;
|
|
||||||
m_number[i+1] = aux::network_to_host(m_number[i+1]);
|
|
||||||
m_number[i] |= m_number[i+1] >> (32 - n);
|
|
||||||
m_number[i] = aux::host_to_network(m_number[i]);
|
|
||||||
}
|
|
||||||
m_number[number_size-1] <<= n;
|
|
||||||
m_number[number_size-1] = aux::host_to_network(m_number[number_size-1]);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// shift r ``n`` bits.
|
// shift r ``n`` bits.
|
||||||
sha1_hash& operator>>=(int n)
|
sha1_hash& operator>>=(int n);
|
||||||
{
|
|
||||||
TORRENT_ASSERT(n >= 0);
|
|
||||||
const int num_words = n / 32;
|
|
||||||
if (num_words >= number_size)
|
|
||||||
{
|
|
||||||
std::memset(m_number, 0, size_t(size));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
if (num_words > 0)
|
|
||||||
{
|
|
||||||
std::memmove(m_number + num_words
|
|
||||||
, m_number, (number_size - num_words) * sizeof(boost::uint32_t));
|
|
||||||
std::memset(m_number, 0, num_words * sizeof(boost::uint32_t));
|
|
||||||
n -= num_words * 32;
|
|
||||||
}
|
|
||||||
if (n > 0)
|
|
||||||
{
|
|
||||||
// keep in mind that the uint32_t are stored in network
|
|
||||||
// byte order, so they have to be byteswapped before
|
|
||||||
// applying the shift operations, and then byteswapped
|
|
||||||
// back again.
|
|
||||||
m_number[number_size-1] = aux::network_to_host(m_number[number_size-1]);
|
|
||||||
|
|
||||||
for (int i = number_size - 1; i > 0; --i)
|
|
||||||
{
|
|
||||||
m_number[i] >>= n;
|
|
||||||
m_number[i-1] = aux::network_to_host(m_number[i-1]);
|
|
||||||
m_number[i] |= (m_number[i-1] << (32 - n)) & 0xffffffff;
|
|
||||||
m_number[i] = aux::host_to_network(m_number[i]);
|
|
||||||
}
|
|
||||||
m_number[0] >>= n;
|
|
||||||
m_number[0] = aux::host_to_network(m_number[0]);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// standard comparison operators
|
// standard comparison operators
|
||||||
bool operator==(sha1_hash const& n) const
|
bool operator==(sha1_hash const& n) const
|
||||||
|
@ -230,6 +159,8 @@ namespace libtorrent
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int count_leading_zeroes() const;
|
||||||
|
|
||||||
// returns a bit-wise negated copy of the sha1-hash
|
// returns a bit-wise negated copy of the sha1-hash
|
||||||
sha1_hash operator~() const
|
sha1_hash operator~() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,55 +49,25 @@ namespace libtorrent { namespace dht
|
||||||
// using the kademlia XOR-metric
|
// using the kademlia XOR-metric
|
||||||
node_id distance(node_id const& n1, node_id const& n2)
|
node_id distance(node_id const& n1, node_id const& n2)
|
||||||
{
|
{
|
||||||
node_id ret;
|
return n1 ^ n2;
|
||||||
node_id::iterator k = ret.begin();
|
|
||||||
// TODO: 3 the XORing should be done at full words instead of bytes
|
|
||||||
for (node_id::const_iterator i = n1.begin(), j = n2.begin()
|
|
||||||
, end(n1.end()); i != end; ++i, ++j, ++k)
|
|
||||||
{
|
|
||||||
*k = *i ^ *j;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if: distance(n1, ref) < distance(n2, ref)
|
// returns true if: distance(n1, ref) < distance(n2, ref)
|
||||||
bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref)
|
bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref)
|
||||||
{
|
{
|
||||||
// TODO: 3 the XORing should be done at full words instead of bytes
|
node_id const lhs = n1 ^ ref;
|
||||||
for (node_id::const_iterator i = n1.begin(), j = n2.begin()
|
node_id const rhs = n2 ^ ref;
|
||||||
, k = ref.begin(), end(n1.end()); i != end; ++i, ++j, ++k)
|
return lhs < rhs;
|
||||||
{
|
|
||||||
boost::uint8_t lhs = (*i ^ *k);
|
|
||||||
boost::uint8_t rhs = (*j ^ *k);
|
|
||||||
if (lhs < rhs) return true;
|
|
||||||
if (lhs > rhs) return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
|
// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
|
||||||
// useful for finding out which bucket a node belongs to
|
// useful for finding out which bucket a node belongs to
|
||||||
int distance_exp(node_id const& n1, node_id const& n2)
|
int distance_exp(node_id const& n1, node_id const& n2)
|
||||||
{
|
{
|
||||||
// TODO: 3 the xoring should be done at full words and _builtin_clz() could
|
// TODO: it's a little bit weird to return 159 - leading zeroes. It should
|
||||||
// be used as the last step
|
// probably be 160 - leading zeroes, but all other code in here is tuned to
|
||||||
int byte = node_id::size - 1;
|
// this expectation now, and it doesn't really matter (other than complexity)
|
||||||
for (node_id::const_iterator i = n1.begin(), j = n2.begin()
|
return (std::max)(159 - distance(n1, n2).count_leading_zeroes(), 0);
|
||||||
, end(n1.end()); i != end; ++i, ++j, --byte)
|
|
||||||
{
|
|
||||||
TORRENT_ASSERT(byte >= 0);
|
|
||||||
boost::uint8_t t = *i ^ *j;
|
|
||||||
if (t == 0) continue;
|
|
||||||
// we have found the first non-zero byte
|
|
||||||
// return the bit-number of the first bit
|
|
||||||
// that differs
|
|
||||||
int const bit = byte * 8;
|
|
||||||
for (int b = 7; b >= 0; --b)
|
|
||||||
if (t >= (1 << b)) return bit + b;
|
|
||||||
return bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node_id generate_id_impl(address const& ip_, boost::uint32_t r)
|
node_id generate_id_impl(address const& ip_, boost::uint32_t r)
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2016, Arvid Norberg
|
||||||
|
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/sha1_hash.hpp"
|
||||||
|
#include "libtorrent/aux_/cpuid.hpp"
|
||||||
|
|
||||||
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
int sha1_hash::count_leading_zeroes() const
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
for (int i = 0; i < number_size; ++i)
|
||||||
|
{
|
||||||
|
boost::uint32_t v = aux::network_to_host(m_number[i]);
|
||||||
|
if (v == 0)
|
||||||
|
{
|
||||||
|
ret += 32;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TORRENT_HAS_SSE
|
||||||
|
if (aux::mmx_support)
|
||||||
|
{
|
||||||
|
#ifdef __GNUC__
|
||||||
|
return ret + __builtin_clz(v);
|
||||||
|
#else
|
||||||
|
DWORD pos;
|
||||||
|
_BitScanReverse(&pos, v);
|
||||||
|
return ret + 31 - pos;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
|
||||||
|
static const int MultiplyDeBruijnBitPosition[32] =
|
||||||
|
{
|
||||||
|
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
||||||
|
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
|
||||||
|
};
|
||||||
|
|
||||||
|
v |= v >> 1; // first round down to one less than a power of 2
|
||||||
|
v |= v >> 2;
|
||||||
|
v |= v >> 4;
|
||||||
|
v |= v >> 8;
|
||||||
|
v |= v >> 16;
|
||||||
|
|
||||||
|
return ret + MultiplyDeBruijnBitPosition[
|
||||||
|
static_cast<boost::uint32_t>(v * 0x07C4ACDDU) >> 27];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sha1_hash& sha1_hash::operator<<=(int n)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(n >= 0);
|
||||||
|
const int num_words = n / 32;
|
||||||
|
if (num_words >= number_size)
|
||||||
|
{
|
||||||
|
std::memset(m_number, 0, size);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_words > 0)
|
||||||
|
{
|
||||||
|
std::memmove(m_number, m_number + num_words
|
||||||
|
, (number_size - num_words) * sizeof(boost::uint32_t));
|
||||||
|
std::memset(m_number + (number_size - num_words)
|
||||||
|
, 0, num_words * sizeof(boost::uint32_t));
|
||||||
|
n -= num_words * 32;
|
||||||
|
}
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
// keep in mind that the uint32_t are stored in network
|
||||||
|
// byte order, so they have to be byteswapped before
|
||||||
|
// applying the shift operations, and then byteswapped
|
||||||
|
// back again.
|
||||||
|
m_number[0] = aux::network_to_host(m_number[0]);
|
||||||
|
for (int i = 0; i < number_size - 1; ++i)
|
||||||
|
{
|
||||||
|
m_number[i] <<= n;
|
||||||
|
m_number[i+1] = aux::network_to_host(m_number[i+1]);
|
||||||
|
m_number[i] |= m_number[i+1] >> (32 - n);
|
||||||
|
m_number[i] = aux::host_to_network(m_number[i]);
|
||||||
|
}
|
||||||
|
m_number[number_size-1] <<= n;
|
||||||
|
m_number[number_size-1] = aux::host_to_network(m_number[number_size-1]);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
sha1_hash& sha1_hash::operator>>=(int n)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(n >= 0);
|
||||||
|
const int num_words = n / 32;
|
||||||
|
if (num_words >= number_size)
|
||||||
|
{
|
||||||
|
std::memset(m_number, 0, size_t(size));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
if (num_words > 0)
|
||||||
|
{
|
||||||
|
std::memmove(m_number + num_words
|
||||||
|
, m_number, (number_size - num_words) * sizeof(boost::uint32_t));
|
||||||
|
std::memset(m_number, 0, num_words * sizeof(boost::uint32_t));
|
||||||
|
n -= num_words * 32;
|
||||||
|
}
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
// keep in mind that the uint32_t are stored in network
|
||||||
|
// byte order, so they have to be byteswapped before
|
||||||
|
// applying the shift operations, and then byteswapped
|
||||||
|
// back again.
|
||||||
|
m_number[number_size-1] = aux::network_to_host(m_number[number_size-1]);
|
||||||
|
|
||||||
|
for (int i = number_size - 1; i > 0; --i)
|
||||||
|
{
|
||||||
|
m_number[i] >>= n;
|
||||||
|
m_number[i-1] = aux::network_to_host(m_number[i-1]);
|
||||||
|
m_number[i] |= (m_number[i-1] << (32 - n)) & 0xffffffff;
|
||||||
|
m_number[i] = aux::host_to_network(m_number[i]);
|
||||||
|
}
|
||||||
|
m_number[0] >>= n;
|
||||||
|
m_number[0] = aux::host_to_network(m_number[0]);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/ed25519.hpp"
|
#include "libtorrent/ed25519.hpp"
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#include "test.hpp"
|
#include "test.hpp"
|
||||||
#include "setup_transfer.hpp"
|
#include "setup_transfer.hpp"
|
||||||
|
@ -142,12 +143,11 @@ void lazy_from_entry(entry const& e, bdecode_node& l)
|
||||||
void write_peers(entry::dictionary_type& r, std::set<tcp::endpoint> const& peers)
|
void write_peers(entry::dictionary_type& r, std::set<tcp::endpoint> const& peers)
|
||||||
{
|
{
|
||||||
entry::list_type& pe = r["values"].list();
|
entry::list_type& pe = r["values"].list();
|
||||||
for (std::set<tcp::endpoint>::const_iterator it = peers.begin()
|
for (auto const& p : peers)
|
||||||
; it != peers.end(); ++it)
|
|
||||||
{
|
{
|
||||||
std::string endpoint(18, '\0');
|
std::string endpoint(18, '\0');
|
||||||
std::string::iterator out = endpoint.begin();
|
std::string::iterator out = endpoint.begin();
|
||||||
libtorrent::detail::write_endpoint(*it, out);
|
libtorrent::detail::write_endpoint(p, out);
|
||||||
endpoint.resize(out - endpoint.begin());
|
endpoint.resize(out - endpoint.begin());
|
||||||
pe.push_back(entry(endpoint));
|
pe.push_back(entry(endpoint));
|
||||||
}
|
}
|
||||||
|
@ -1194,70 +1194,6 @@ void do_test_dht(address(&rand_addr)())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// test node-id functions
|
|
||||||
using namespace libtorrent::dht;
|
|
||||||
|
|
||||||
TEST_EQUAL(generate_prefix_mask(0), to_hash("0000000000000000000000000000000000000000"));
|
|
||||||
TEST_EQUAL(generate_prefix_mask(1), to_hash("8000000000000000000000000000000000000000"));
|
|
||||||
TEST_EQUAL(generate_prefix_mask(2), to_hash("c000000000000000000000000000000000000000"));
|
|
||||||
TEST_EQUAL(generate_prefix_mask(11), to_hash("ffe0000000000000000000000000000000000000"));
|
|
||||||
TEST_EQUAL(generate_prefix_mask(17), to_hash("ffff800000000000000000000000000000000000"));
|
|
||||||
TEST_EQUAL(generate_prefix_mask(160), to_hash("ffffffffffffffffffffffffffffffffffffffff"));
|
|
||||||
|
|
||||||
// test kademlia functions
|
|
||||||
|
|
||||||
// distance_exp
|
|
||||||
|
|
||||||
TEST_EQUAL(distance_exp(
|
|
||||||
to_hash("ffffffffffffffffffffffffffffffffffffffff"),
|
|
||||||
to_hash("0000000000000000000000000000000000000000"))
|
|
||||||
, 159);
|
|
||||||
|
|
||||||
TEST_EQUAL(distance_exp(
|
|
||||||
to_hash("ffffffffffffffffffffffffffffffffffffffff"),
|
|
||||||
to_hash("7fffffffffffffffffffffffffffffffffffffff"))
|
|
||||||
, 159);
|
|
||||||
|
|
||||||
TEST_EQUAL(distance_exp(
|
|
||||||
to_hash("ffffffffffffffffffffffffffffffffffffffff"),
|
|
||||||
to_hash("ffffffffffffffffffffffffffffffffffffffff"))
|
|
||||||
, 0);
|
|
||||||
|
|
||||||
TEST_EQUAL(distance_exp(
|
|
||||||
to_hash("ffffffffffffffffffffffffffffffffffffffff"),
|
|
||||||
to_hash("fffffffffffffffffffffffffffffffffffffffe"))
|
|
||||||
, 0);
|
|
||||||
|
|
||||||
TEST_EQUAL(distance_exp(
|
|
||||||
to_hash("8000000000000000000000000000000000000000"),
|
|
||||||
to_hash("fffffffffffffffffffffffffffffffffffffffe"))
|
|
||||||
, 158);
|
|
||||||
|
|
||||||
TEST_EQUAL(distance_exp(
|
|
||||||
to_hash("c000000000000000000000000000000000000000"),
|
|
||||||
to_hash("fffffffffffffffffffffffffffffffffffffffe"))
|
|
||||||
, 157);
|
|
||||||
|
|
||||||
TEST_EQUAL(distance_exp(
|
|
||||||
to_hash("e000000000000000000000000000000000000000"),
|
|
||||||
to_hash("fffffffffffffffffffffffffffffffffffffffe"))
|
|
||||||
, 156);
|
|
||||||
|
|
||||||
TEST_EQUAL(distance_exp(
|
|
||||||
to_hash("f000000000000000000000000000000000000000"),
|
|
||||||
to_hash("fffffffffffffffffffffffffffffffffffffffe"))
|
|
||||||
, 155);
|
|
||||||
|
|
||||||
TEST_EQUAL(distance_exp(
|
|
||||||
to_hash("f8f2340985723049587230495872304958703294"),
|
|
||||||
to_hash("f743589043r890f023980f90e203980d090c3840"))
|
|
||||||
, 155);
|
|
||||||
|
|
||||||
TEST_EQUAL(distance_exp(
|
|
||||||
to_hash("ffff740985723049587230495872304958703294"),
|
|
||||||
to_hash("ffff889043r890f023980f90e203980d090c3840"))
|
|
||||||
, 159 - 16);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// test kademlia routing table
|
// test kademlia routing table
|
||||||
dht_settings s;
|
dht_settings s;
|
||||||
|
@ -2211,7 +2147,7 @@ TORRENT_TEST(dht_dual_stack)
|
||||||
bdecode_node nodes46_keys[5];
|
bdecode_node nodes46_keys[5];
|
||||||
|
|
||||||
ret = verify_message(response, nodes46_desc, nodes46_keys, error_string
|
ret = verify_message(response, nodes46_desc, nodes46_keys, error_string
|
||||||
, sizeof(error_string));
|
, sizeof(error_string));
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
@ -2817,5 +2753,77 @@ TORRENT_TEST(dht_verify_node_address)
|
||||||
TEST_EQUAL(table.size().get<0>(), 1);
|
TEST_EQUAL(table.size().get<0>(), 1);
|
||||||
TEST_EQUAL(nodes.size(), 1);
|
TEST_EQUAL(nodes.size(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(generate_prefix_mask)
|
||||||
|
{
|
||||||
|
// test node-id functions
|
||||||
|
using namespace libtorrent::dht;
|
||||||
|
|
||||||
|
std::vector<std::pair<int, char const*>> const test = {
|
||||||
|
{ 0, "0000000000000000000000000000000000000000" },
|
||||||
|
{ 1, "8000000000000000000000000000000000000000" },
|
||||||
|
{ 2, "c000000000000000000000000000000000000000" },
|
||||||
|
{ 11, "ffe0000000000000000000000000000000000000" },
|
||||||
|
{ 17, "ffff800000000000000000000000000000000000" },
|
||||||
|
{ 37, "fffffffff8000000000000000000000000000000" },
|
||||||
|
{ 160, "ffffffffffffffffffffffffffffffffffffffff" },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto const& i : test)
|
||||||
|
{
|
||||||
|
TEST_EQUAL(generate_prefix_mask(i.first), to_hash(i.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(distance_exp)
|
||||||
|
{
|
||||||
|
// distance_exp
|
||||||
|
|
||||||
|
|
||||||
|
using tst = std::tuple<char const*, char const*, int>;
|
||||||
|
|
||||||
|
std::vector<std::tuple<char const*, char const*, int>> const distance_tests = {
|
||||||
|
tst{ "ffffffffffffffffffffffffffffffffffffffff"
|
||||||
|
, "0000000000000000000000000000000000000000", 159 },
|
||||||
|
|
||||||
|
tst{ "ffffffffffffffffffffffffffffffffffffffff"
|
||||||
|
, "7fffffffffffffffffffffffffffffffffffffff", 159 },
|
||||||
|
|
||||||
|
tst{ "ffffffffffffffffffffffffffffffffffffffff"
|
||||||
|
, "ffffffffffffffffffffffffffffffffffffffff", 0 },
|
||||||
|
|
||||||
|
tst{ "ffffffffffffffffffffffffffffffffffffffff"
|
||||||
|
, "fffffffffffffffffffffffffffffffffffffffe", 0 },
|
||||||
|
|
||||||
|
tst{ "8000000000000000000000000000000000000000"
|
||||||
|
, "fffffffffffffffffffffffffffffffffffffffe", 158 },
|
||||||
|
|
||||||
|
tst{ "c000000000000000000000000000000000000000"
|
||||||
|
, "fffffffffffffffffffffffffffffffffffffffe", 157 },
|
||||||
|
|
||||||
|
tst{ "e000000000000000000000000000000000000000"
|
||||||
|
, "fffffffffffffffffffffffffffffffffffffffe", 156 },
|
||||||
|
|
||||||
|
tst{ "f000000000000000000000000000000000000000"
|
||||||
|
, "fffffffffffffffffffffffffffffffffffffffe", 155 },
|
||||||
|
|
||||||
|
tst{ "f8f2340985723049587230495872304958703294"
|
||||||
|
, "f743589043r890f023980f90e203980d090c3840", 155 },
|
||||||
|
|
||||||
|
tst{ "ffff740985723049587230495872304958703294"
|
||||||
|
, "ffff889043r890f023980f90e203980d090c3840", 159 - 16 },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto const& t : distance_tests)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s %s: %d\n"
|
||||||
|
, std::get<0>(t), std::get<1>(t), std::get<2>(t));
|
||||||
|
|
||||||
|
TEST_EQUAL(distance_exp(
|
||||||
|
to_hash(std::get<0>(t))
|
||||||
|
, to_hash(std::get<1>(t))
|
||||||
|
), std::get<2>(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -110,3 +110,37 @@ TORRENT_TEST(sha1_hash)
|
||||||
TEST_CHECK(h1 == to_hash("0000000070000000000000000000000000000000"));
|
TEST_CHECK(h1 == to_hash("0000000070000000000000000000000000000000"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(count_leading_zeroes)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<char const*, int>> const tests = {
|
||||||
|
{ "ffffffffffffffffffffffffffffffffffffffff", 0 },
|
||||||
|
{ "0000000000000000000000000000000000000000", 160 },
|
||||||
|
{ "fff0000000000000000000000000000000000000", 0 },
|
||||||
|
{ "7ff0000000000000000000000000000000000000", 1 },
|
||||||
|
{ "3ff0000000000000000000000000000000000000", 2 },
|
||||||
|
{ "1ff0000000000000000000000000000000000000", 3 },
|
||||||
|
{ "0ff0000000000000000000000000000000000000", 4 },
|
||||||
|
{ "07f0000000000000000000000000000000000000", 5 },
|
||||||
|
{ "03f0000000000000000000000000000000000000", 6 },
|
||||||
|
{ "01f0000000000000000000000000000000000000", 7 },
|
||||||
|
{ "00f0000000000000000000000000000000000000", 8 },
|
||||||
|
{ "0070000000000000000000000000000000000000", 9 },
|
||||||
|
{ "0030000000000000000000000000000000000000", 10 },
|
||||||
|
{ "0010000000000000000000000000000000000000", 11 },
|
||||||
|
{ "0000000ffff00000000000000000000000000000", 28 },
|
||||||
|
{ "00000007fff00000000000000000000000000000", 29 },
|
||||||
|
{ "00000003fff00000000000000000000000000000", 30 },
|
||||||
|
{ "00000001fff00000000000000000000000000000", 31 },
|
||||||
|
{ "00000000fff00000000000000000000000000000", 32 },
|
||||||
|
{ "000000007ff00000000000000000000000000000", 33 },
|
||||||
|
{ "000000003ff00000000000000000000000000000", 34 },
|
||||||
|
{ "000000001ff00000000000000000000000000000", 35 },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto const& t : tests)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", t.first);
|
||||||
|
TEST_EQUAL(to_hash(t.first).count_leading_zeroes(), t.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue